When converting a java code into Kotlin, the
public MayData[] getDataArray() {
return new MayData[0];
}
changed to
fun getDataArray(): Array<MyData> {
return arrayOfNulls<MyData>(0)
}
but I got an error:
Error:(50, 16) Type mismatch: inferred type is Array<MyData?> but Array<MyData> was expected
it has to add the ‘?’
fun getDataArray(): Array<MyData?> {
return arrayOfNulls<MyData>(0)
}
what does the ‘?’ mean with the template type?
arrayOfNulls returns an array of objects, initialized with null values. The '?' means that the object may be null.
return arrayOfNulls<MyData>(0)
What this line means:
arrayOfNulls Return an array of N elements (zero in your case), but fill it with null
<MyData> The Data-Type is MyData, which is NOT nullable
So you create an array with null values (even if the size is zero) but the DataType is not nullable:
Two solutions:
// zero elements in the array but not nullable
fun getDataArray(): Array<MyData> {
return arrayOf()
}
// array with nullable data-type
fun getDataArray(): Array<MyData?> {
return arrayOfNulls<MyData?>(0)
}
T is a generic. ? marks a type as nullable. In Kotlin you make a distinction between types that can be null, and those that cannot.
Since in Java all types except the atomic ones (int, long, float...) can be null you need to add the ? operator to deal with this case as well.
You need to know that In Kotlin every class can be used in two variants: a nullable and a non-nullable one. For example, the class String can be used for the String or the String? type, the former one meaning "not null" and the latter one meaning "nullable".
The <> chars introduce a "generic type", e.g. for an Array<String> this means, that this Array can only hold objects of type String, whereas Array<String?> means it can hold instances of String and null on top of that.
As your making use of arrayOfNulls the function's return type will be Array<MyData?>, which is why the compiler complains:
inferred type is Array but Array was expected
Blockquote
In order to fix that, you can either make your function return the nullable version, like you already did or you do not use arrayOfNulls, when you're sure you don't want to include nulls in your array.
fun getDataArray(): Array<MyData?> {
return arrayOfNulls<MyData>(0)
}
or
fun getDataArray(): Array<MyData> {
return arrayOf<MyData>()
}
Related
I want to know the difference between String? and String! in Kotlin.
I search on kotlinlang.org but did not find any information.
Kotlin's type system differentiates between nullable and non-nullable types. In that context, String? is a nullable type while String would be the corresponding non-nullable type.
When working with Java libraries, the compiler is not always able to identify whether a type is nullable or not, since Java does not have that differentiation. Such types will then show up as "platform type" String!, meaning (basically): "I have no idea if this can be null but I'll treat it as non-nullable for now".
If you have control over the corresponding Java library, Kotlin supports various annotations to help distinguish between types, otherwise it is up to you as developer to explicitly assign either a nullable or a non-nullable type e.g. upon variable declaration to avoid running into NullPointerExceptions at runtime.
I'll try to answer with some sample code.
1. String?
This means this string is nullable.
Example 1: Use it in the type definition.
fun testStringTypes() {
// When initializing stringA, we can set null as the value
var stringA: String? = null
// And we can also set it to a meaningful string
stringA = "Hello"
// Then we can still set it back to null
stringA = null
}
Example 2: a variance of String?
fun testStringTypes() {
var stringA: String? = null
stringA = "Hello"
stringA = null
val lenOfStringA = stringA?.length ?: 0
}
So here is a brief description about what this val lenOfStringA = stringA?.length ?: 0 means:
Because stringA is defined as nullable;
stringA?.length means, access to the length property only if stringA is not null;
Because if, when stringA is null and if the code still tries to access to length (like in Java), the program will throw a NullPointerException. stringA? a question mark here, is to avoid this, which is called SafeCalls.
2. String!
This is platform types.
Copy from the link above:
As mentioned above, platform types can't be mentioned explicitly in the program, so there's no syntax for them in the language. Nevertheless, the compiler and IDE need to display them sometimes (for example, in error messages or parameter info), so there is a mnemonic notation for them:
I think (correct me if I was wrong), this makes sense when working with Java, because String in Java can be null, in other words, when accessing it from Kotlin, we don't know it is null or not. So String! is kind of a reminder to developer: Hey! Attention, this variable could be null.
Example 3, work with Java method from Kotlin:
// In Java:
public class PlatformTypeTest {
public String returnSomeStringCouldBeNull() {
return null;
}
}
And let's call this method in Kotlin.
fun testStringTypes() {
val someStringFromJava = PlatformTypeTest().returnSomeStringCouldBeNull()
}
fun testStringTypes() {
val someStringFromJava = PlatformTypeTest().returnSomeStringCouldBeNull()
someStringFromJav
}
As we can see from above two screenshots, IDE is reminding us this String from Java can be null.
And for String!, we can access it in different ways:
fun main() {
val someStringFromJava = PlatformTypeTest().returnSomeStringCouldBeNull()
var lenOfString = someStringFromJava?.length ?: 0
// lenOfString = someStringFromJava.length // NullPointerException
// lenOfString = someStringFromJava!!.length // NullPointerException
println(lenOfString)
}
With code snippet above, it works fine with var lenOfString = someStringFromJava?.length ?: 0, but the other two ways will cause NPE, as explained at above.
String? is a nullable type.
String! is a platform type platform type.
From Kotlin website:
Nullable Types Example:
val nullable: String? = item // allowed, always works
val notNull: String = item // allowed, may fail at runtime
Platform Types Example:
- T! means "T or T?",
- (Mutable)Collection<T>! means "Java collection of T may be mutable or not, may be nullable or not",
- Array<(out) T>! means "Java array of T (or a subtype of T), nullable or not"
Why the following code failed to compile with the error:
"Type mismatch: inferred type is String? but Comparable<String?>! was expected
What does it mean the '!' after the brackets? And why it says that infered type is String
if it defiently MutableList<String?>? ?
The code:
private fun createAllGamesList(gamesPerCountriesMap: MutableMap<String?, MutableMap<Long, MutableList<AllScoresGameObj>>>?)
:List<BaseDataItem>
{
var countriesNameSet = gamesPerCountriesMap?.keys
var countriesNameList = countriesNameSet?.toMutableList()
Collections.sort(countriesNameList)
countriesNameList?.let{
}
}
Just want to point out that using the Java class Collections in Kotlin is kind of discouraged since the Kotlin standard library has built-in functions that can do the same tasks in ways that fit Kotlin-style syntax better, has better nullability handling, and can be more performant when they use inline lambdas.
For instance, you wouldn't be running into the weird type Comparable<String?>! if using Kotlin's sort() or sortedBy(). The ! symbol after a type means it's maybe nullable and maybe not because the Java code doesn't specify either way.
In Kotlin, you can call sort() directly on your MutableList (it's an extension function) if it has a Comparable type. You'll still run into the problem that String? is not a Comparable<String?>, but you can do custom sorting using compareBy and thenBy to create a Comparator:
countriesNameList.sortedWith(
compareBy<String?> { it ?: "" } // lambda returns String, which is Comparable
.thenBy { it == null } // Sort between empty Strings and null values by returning a Boolean (another Comparable
)
The problem is that countriesNameList is a list of nullable Strings. That is, its type is MutableList<String?>, and not MutableList<String>.
Collections.sort() requires that the collection's type implement Comparable<T>, but String? does not implement Comparable<String?>. I imagine this is because it is not obvious where null values would fall in the natural ordering of String? elements.
This is very easy to observe with the following code:
val list: MutableList<String?> = mutableListOf("hello", "world")
Collections.sort(list)
If I change the type specification to not include the ?, the problem goes away:
val list: MutableList<String> = mutableListOf("hello", "world")
Collections.sort(list)
You can work around this by providing your own comparator:
Collections.sort(countriesNameList) { lhs, rhs -> customCompare(lhs, rhs) }
private fun customCompare(lhs: String?, rhs: String?): Int = when {
lhs == null && rhs == null -> 0
lhs == null -> 1
rhs == null -> -1
else -> lhs.compareTo(rhs)
}
I'm creating one function in Kotlin. It validates email and password fields. I want to apply email and password should not be null. #NotNull kinda annotation here.
Does anyone know how to do this in Kotlin? So the caller cannot send the null value.
private fun isEmailAndPasswordValid(email: String, password: String): Boolean {
if (email.isEmpty()) return false
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) return false
if (password.isEmpty()) return false
return true
}
Kotlin differentiates all types by nullable and not-nullable. For example, the class String can be used for the type String, which is not nullable, and the type String?, which IS nullable, i.e. could hold null.
In your example no nullable types are used, so you’re all good - no additional annotation needed.
The documentation should be studied for further information.
The Kotlin language is by default null-safe so when creating a new variable it can't be null, but when you want a nullable variable you can add The exclamation mark to specify that it can be null for Example String?, Int? ...
Not Nullable
var a: String = "bachiri"
a = null // compilation error
Nullable Type
var a: String? = "bachiri"
a = null // OK
and bare in mind if you want to call a function on the nullable Type you should use eighter the check for null variable(1) or use the safe calls(2)
Kotlin has build-in null safety. String is a non-null type while String? is a nullable type. So, isEmailAndPasswordValid(email: String, password: String) will enforce the value passed to it is non-null.
When I check the Kotlin documentation, I can see that a String variable can't be set to null, unless you declare it can be, and your compiler will raise an error.
For example, a regular variable of type String can not hold null
https://kotlinlang.org/docs/reference/null-safety.html
I've written a function to perform a database query. I want it to return null if it cannot fetch any result.
fun getServiceCharge(model: String): ServiceChargeMasterList {
val unique = VideoconApplication.daoSession.serviceChargeMasterListDao.queryBuilder().where(ServiceChargeMasterListDao.Properties.ModelCategory.eq(model)).unique()
if (unique != null)
return unique
else
return null!!
}
It gives me kotlin.KotlinNullPointerException.
Can anyone tell me how can I solve this?
Just specify your return type as ServiceChargeMasterList? and return null. The !! operator is very ugly to use.
You don't even have to use that if statement if your unique() method return and optional (or Java object). In that case, you method could look like this:
fun getServiceCharge(model: String): ServiceChargeMasterList? {
return VideoconApplication.daoSession.serviceChargeMasterListDao.queryBuilder().where(ServiceChargeMasterListDao.Properties.ModelCategory.eq(model)).unique()
}
Use this
fun getServiceCharge(model: String): ServiceChargeMasterList? =
VideoconApplication.
daoSession.
serviceChargeMasterListDao.
queryBuilder().
where(ServiceChargeMasterListDao.Properties.ModelCategory.eq(model)).
unique()
Explanation
In Kotlin, there are optional types. If you return ServiceChargeMasterList, you say to the compiler that you will never return null. If you want to return null, you have to add ? sign at the end of the type which indicates that you can return an instance of ServiceChargeMasterList or null.
The operator !! can be explained in Java as
//Kotlin
variable!!
//Java
if (variable == null)
throw new kotlin.NullPointerException();
Your method’s return type does not allow null to be returned. You need to change it to it’s nullable versionServiceChargeMasterList? (nullability denoted by the question mark).
The not-null assertion operator !! should only be used in very rare cases because it tries to transform nullable types into non-nullable types and might throw a NullPointerException when invoked on null.
Your code null!! is the perfect demonstration for this.
Instead of applying safe operators like in nullableVar?.foo(), this operator is used like this: nullableVar!!.foo().
In your case though, the !! operator is the wrong choice. If your method is really supposed to return null, change the return type.
open fun getProfile() : ProfileModel? {
if (MyApplication.sharedPreference.getString("profile","")!=null){
var profileModel : ProfileModel = Profile()
return profileModel
}
return null
}
add ? after your return type then return null it works
I'm new to Kotlin and I don't know why compiler complains about this code:
data class Test(var data : String = "data")
fun test(){
var test: Test? = Test("")
var size = test?.data.length
}
Compiler complains with test?.data.length, it says that I should do: test?.data?.length. But data variable is String, not String?, so I don't understand why I have to put the ? when I want to check the length.
The expression test?.data.length is equivalent to (test?.data).length, and the test?.data part is nullable: it is either test.data or null. Therefore it is not null-safe to get its length, but instead you should use the safe call operator again: test?.data?.length.
The nullability is propagated through the whole calls chain: you have to write these chains as a?.b?.c?.d?.e (which is, again, equivalent to (((a?.b)?.c)?.d)?.e), because, if one of the left parts is null, the rest of the calls cannot be performed as if the value is not-null.
If you don't want to use safe call before each non-nullable component of the call chain, you can get the result of the first safe call into a new variable with the standard extension functions run or let:
// `this` is non-nullable `Test` inside lambda
val size = test?.run { data.length }
// or: `it` is non-nullable `Test` inside lambda
val size = test?.let { it.data.length }
Note that size is still nullable Int? here.