How to convert Any to Int in Kotlin - kotlin

I have an attribute in my model defined as above that in some cases contain an Int.
var value: Any?
I know that I can do it if I cast first to String and then to Int
value.toString().toInt() // works
Is there a way of doing it by skipping casting into a String before?
When I try to cast directly to into an Int I get this error
FATAL EXCEPTION: main
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

The problem is that you were attempting to cast directly from a String to an Int with value as Int.
This isn't working because, as the exception is telling you, value contains a String, and a String cannot be coerced into an Int. The fact that this String represents an integer doesn't matter, as it would need to be parsed into an Int. That precisely is what the toInt() method does.
The reason you must cast to a String first is because toInt() is an extension method on String, and value is of type Any?. This means that you can't call toInt() directly on value because it doesn't know that it contains a String at compile time, even though it does at runtime. If you wanted to skip this step, you could also use smart casts by checking the type first:
if (value is String) {
value.toInt()
}
You can find a bit more info on smart casts and other Kotlin type casting here: https://kotlinlang.org/docs/reference/typecasts.html#smart-casts
This also may be pointing to an underlying design problem. You expect that this will sometimes contain an Int, but as we can see here whatever is setting this value in your model is setting it to a String containing that number. Do you expect this value to truly be able to contain many different types, or are you only expect Int and String? If the latter, then it would possibly be a better design decision to make this a String rather than an Any?. That would prevent unexpected/unhandled types from being provided, and make the model less ambiguous to anyone looking at or using it.

This is the way I do it:
val myInt = value as? Int ?: defaultValue
This will try to convert value to an int, but if it fails, will use defaultValue instead.

We can use Kotlin's toInt() or toIntOrNull() method to convert from String to Int type. For example:
fun giveString(): String {
return "12"
}
fun giveInt(): Int {
return giveString().toInt() // here we are casting return type to Int
}
Below we are casting return tye to Int if the string is not convertible, will return null
fun giveNullableInt(): Int? {
return giveString().toIntOrNull()
}

Related

Kotlin Nullable with .toString() understanding Kotlin null safe

So i'm playing around will nullables and null safe in Kotlin to try understand it better.
var stringNull : String? = null
println(stringNull.toString())
println(stringNull?.lowercase())
Both of these return "null" so I'm just trying to figure out what the difference between String and String? is in practical terms. Is the "nullness" of the String not stored in the String Class itself? is it the method, such as toString() or lowerCase(), that is handling the "nullness" passed to it by an operator and not the String class itself? it's hard to see what's happening here in terms of the literal data that is being passed around. how is the value of "null", as in no data, being parsed into a string value of "null"?
The reason println(stringNull.toString()) prints null is because Kotlin decided to create an extension function on Any? called toString() over here.
If you try
class SomeClass {
fun foo() {}
}
fun main() {
val some: SomeClass? = null
println(some?.foo())
println(some.foo())
}
The compiler will complain with Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type SomeClass?
toString is just a very special function so they decided to add it on every type, hence the Any?
P.S
Also, I would recommend to use val by default (even when playing around) and only use var if you really really need to.
Is the "nullness" of the String not stored in the String Class itself?
If I understand your question correctly, that is correct, String is itself not nullable. String? is the nullable version of String.
is it the method, such as toString() or lowerCase(), that is handling the "nullness" passed to it by an operator and not the String class itself?
Among toString and lowerCase, only toString handles nulls. We can see this from their signatures:
public fun Any?.toString(): String
// ^^^^
// nullable type
public expect fun String.lowercase(): String
// ^^^^^^
// non-nullable type
In the internal implementation of toString, you can imagine that there is a bit of logic that says "if the instance is null, return "null"".
lowercase cannot be called on a nullable string directly, and will give you a compiler error if you try to do that. This is why you have to use the ?. safe navigation operator to call it on stringNull. This will check if stringNull is null before calling lowercase, and if it is found that stringNull is null, lowercase won't actually be called, and the whole expression stringNull?.lowercase() evaluates to null. Therefore, "null" is printed.
(And I think I just answered your last question)
stringNull.toString() calls the following extension function:
/**
* Returns a string representation of the object. Can be called with a null receiver, in which case
* it returns the string "null".
*/
public fun Any?.toString(): String
stringNull?.lowercase() call the following extension function:
/**
* Returns a copy of this string converted to lower case using Unicode mapping rules of the invariant locale.
*
* This function supports one-to-many and many-to-one character mapping,
* thus the length of the returned string can be different from the length of the original string.
*
* #sample samples.text.Strings.lowercase
*/
#SinceKotlin("1.5")
#WasExperimental(ExperimentalStdlibApi::class)
public expect fun String.lowercase(): String
So while the two calls both return null, it's two different function calls.

Why do I get this? Kotlin: Type mismatch: inferred type is String? but String was expected

When I try to run this code:
fun main() {
val input: String = readLine()
val outputs = input.toCharArray()
for (i in 0 until input.length) {
print("${outputs[i]}${outputs[i]}")
}
}
I get this Error:(2, 25) Kotlin: Type mismatch: inferred type is String? but String was expected.
How do I fix that?
The readLine() function returns a String? (nullable String).
Return the line read or null if the input stream is redirected to a file and the end of file has been reached.
There is no end of File in the console inputs so there's no need to worry about nulls. You can use the unsafe call operator !! to cast it to a non null value String.
val input: String = readLine()!!
In Kotlin, calling a function on a nullable type using only the dot operator is a compilation error as it could cause a null pointer exception. In order to avoid this kind of error, the compiler forces you to check if your reference is not null. It is also possible to use the safe call operator ?.. I recommend you to read the excellent Kotlin documentation about the subject: Null Safety.
If you have started using Kotlin, I also recommend you to start writing your code in a more declarative/functional way. Look how it is possible to accomplish what you want in a much simpler way:
fun main() {
val input = readLine()
input?.toCharArray()?.forEach { print(it) }
}

What can `Nothing` be used for?

I am specifically asking for the non-nullable type Nothing.
I do know that Nothing? allows us to, for example, filter null to make an overload unambiguous, but I'm struggling to think of instances where Nothing would be useful.
Nothing? can have exactly one value, null. So Nothing can have exactly no value. What's the point? Why not simply use Unit?
1. Nothing is the counterpart to Any?
Just as Any? is the base type of any other type, Nothing is the sub type of any other type (even the nullable ones).
Knowing this it becomes clear that s will be of type String in the following example, given name is a String?.
val s = name ?: throw IllegalArgumentException("Name required")
The throw expression returns Nothing, and the common base type of String and Nothing is String. That's what we want, because that's the type we want to work with.
If we would use Unit instead of Nothing the common base type would be Any, which is certainly not what we want, because it would require a cast to String afterward.
That makes sense too, because if the exception will be thrown execution cannot continue there, thus s wouldn't be used any further anyway.
2. Nothing marks code locations that can never be reached
fun foo() {
throw IllegalArgumentException("...")
println("Hey") // unreachable code
}
3. Type inference
If null is used to initialize a value of an inferred type and there's no other information to determine a more specific type, the inferred type will be Nothing?.
val x = null // 'x' has type `Nothing?`
val l = listOf(null) // 'l' has type `List<Nothing?>
Further reading
Nothing is used to tell the compiler that it will never return. For example,
fun main() {
var name: String? = null
val notNullName = name ?: fail("name was null")
println(notNullName)
}
fun fail(message: String): Nothing {
throw RuntimeException(message)
}
fun infiniteLoop(): Nothing {
while (true) {
// Nothingness
}
}

Smart cast does not cast String? to String after !value.isNullOrBlank()

I want to add to the list objects only if they have all fields, and try this code:
data class Response(val id: String, val name: String)
val list = mutableListOf<Response>()
val id : String? = "test_id"
val name : String? = "test_name"
if (!id.isNullOrBlank() and !name.isNullOrBlank()) {
list.add(Response(id, name)) // Type mismatch. Required String, Found String?
}
But I got an error: Type mismatch. Required String, Found String?
What is the correct (and compact) way to do it?
As a recommendation: always try to use && instead of bitwise and to evaluate your conditions. Seldomly is there any reason to use a bitwise and (there are some use-cases, but in most cases you just want to have a short-circuiting evaluation of your conditions, even more so if there is some complex calculation/service calls within one of the functions).
From what I see and expect the smart cast should work, even more so because && already does work. I didn't find any appropriate or matching issue, so you may want to open a new ticket for this.
Note also that the smart cast should work due to the Kotlin contract defined in isNullOrBlank which basically checks whether the value underneath is null so it might be related to the evaluation of the contracts, and/or the inlining of the function and/or something of the former combined with the bitwise and.
An alternative approach I usually like to do, without involving smart casts:
val id : String = getId()?.takeIf { it.isNotBlank() } ?: return
val name : String = getName()?.takeIf { it.isNotBlank() } ?: return
list.add(Response(id, name))
Here you verify the value while you get it and abort if you cannot use it.

Difference between Any type and Generics in Kotlin

Suppose I have the following function definition.
fun<T> parse(a: Any): T = when (a) {
is String -> a
else -> false
}
I guessed it should be valid. However, the IntelliJ IDEA linter shows a type mismatch error
That being said, I would change the return type of my parse function to Any, right? So that, what is the difference between using Any type and Generics in Kotlin? In which cases should use each of those?
I did read the following question but not understood at all about star-projection in Kotlin due to the fact I am quite new.
Your return type it defined as T, but there is nothing assuring that T and a:Any are related. T may be more restrictive than Any, in which case you can't return a boolean or whatever you provided for a.
The following will work, by changing the return type from T to Any:
fun<T> parse(a: Any): Any = when (a) {
is String -> a
else -> false
}
Any alternate option, if you really want to return type T:
inline fun<reified T> parse(a: Any): T? = when (a) {
is T -> a
else -> null
}
Your example does not use T and thus it's nonsense to make it generic anyways.
Think about this: As a client you put something into a function, e.g. an XML-ByteArray which the function is supposed to parse into an Object. Calling the function you do not want to have it return Any (Casting sucks) but want the function return the type of the parsed object. THIS can be achieved with generics:
fun <T> parse(xml: ByteArray): T {
val ctx: JAXBContext = JAXBContext.newInstance()
val any = ctx.createUnmarshaller().unmarshal(ByteArrayInputStream(xml))
return any as T
}
val int = parse<Int>("123".toByteArray())
val string = parse<String>("123".toByteArray())
Look at the method calls: You tell with generics what type is expected to be returned. The code is not useful and only supposed to give you an idea of generics.
I guessed it should be valid
Why would it be? You return a String in one branch and a Boolean in the other. So the common type for the entire when expression is Any and that's what the compiler (and IDEA) says is "found". Your code also says it should be T (which is "required").
Your generic method should work for any T, e.g. for Int, but Any isn't a subtype of Int and so the code isn't valid.
So that, what is the difference between using Any type and Generics in Kotlin?
This is like asking "what is the difference between using numbers and files": they don't have much in common in the first place. You use generics to write code which can work with all types T (or with all types satisfying some constraint); you use Any when you want the specific type Any.