Why does lateinit work on Object type but not primitive type? - kotlin

This answer says that Object types use the null value on lateinits of Object type. Can someone elaborate on this? What do they mean by "uses the null value"?
Furthermore it says "For primitive types, there is no such value" - why is there no

On the JVM, which was historically the first platform targeted by Kotlin, there is a distinction between the primitive types and classes, or object types.
They have different runtime representations: a primitive value is stored directly in the field, which can only hold one of the corresponding primitive type values (e.g. only true and false for boolean) and has no special representation for a missing value. In comparison, a class-typed field stores an indirect reference to an instance that is allocated somewhere in the heap, and a class-typed field can hold a special null reference that doesn't point to any instance.
The Kotlin lateinit properties are compiled to a single field and they internally use the null value to indicate that the property has not yet been initialized. As primitive-typed JVM fields can't have a null value, Kotlin doesn't allow lateinit properties of types that are normally mapped to Java primitives, as that would require a different representation, and no acceptable solution existed, as the other answer says.
Instead, you can use by Delegates.notNull() to achieve similar behavior with the mapped types.

Related

Why does casting to a generic work without an instance of that type?

I've created 2 kotlin methods: one to check a type and another to cast an object. They look like:
fun Any?.isOfType(type: Class<*>): Boolean{
return type.isInstance(this)
// return `this is T` does NOT work.
}
and
fun <T> Any?.castToType(): T {
return this as T
// Works, albeit with a warning.
}
I've read some posts on generics and erasures, but I can't get over what seems to be a discrepancy.
Why is it that checking for the type of an object cannot be done with generics, but casting to a generic can?
The question is why:
fun <T> Any?.castToType() = this as T // compiles with warning
"hello".castToType<Int>()
"works" but this won't even compile:
fun <T> Any?.isOfType() = this is T // won't compile
"hello".isOfType<Int>()
Actually both don't really work. In both cases the type is erased at runtime. So why does one compile and the other doesn't?
this is T cannot work at runtime since the type of T is unknown and thus the compiler has to reject it.
this as T on the other hand might work:
"hello".castToType<Int>() // no runtime error but NOP
"hello".castToType<Int>().minus(1) // throws ClassCastException
2.0.castToType<Int>().minus(1) // no runtime error, returns 1
In some cases it works, in others it throws an exception. Now every unchecked cast can either succeed or lead to runtime exceptions (with or without generic types) so it makes sense to show a warning instead of a compile error.
Summary
unchecked casts with generic types are no different from unchecked casts without generic types, they are dangerous but a warning is sufficient
type checks with generic types on the other hand are impossible at runtime
Addendum
The official documentation explains type erasure and why is-checks with type arguments can't succeed at runtime:
At runtime, the instances of generic types do not hold any information about their actual type arguments. The type information is said to be erased. For example, the instances of Foo and Foo<Baz?> are erased to just Foo<*>.
Due to the type erasure, there is no general way to check whether an instance of a generic type was created with certain type arguments at runtime, and the compiler prohibits such is-checks such as ints is List or list is T (type parameter)
(https://kotlinlang.org/docs/generics.html#type-erasure)
In my own words: I can't check whether A is B if I don't know what B is. If B is a class I can check against an instance of that class (that's why type.isInstance(this) works) but if B is a generic type, the runtime has no information on it (it was erased by the compiler).
This isn't about casting vs checking; it's about using generics vs class objects.
The second example is generic; it uses T as a type parameter. Unfortunately, because generics are implemented using type erasure, this means that the type isn't available at runtime (because it has been erased, and replaced by the relevant upper bound — Any? in this case). This is why operations such as type checking or casting to a type parameter can be unsafe and give compilation warnings.
The first example, though, doesn't use a type parameter; instead, it uses a parameter which is called type, but is a Class object, representing a particular class. This is a value which is provided at runtime, just like any other method parameter, and so you can call methods such as cast() and isInstance() to handle some type issues at runtime. However, they're closely related to reflection, and have some of the same disadvantages, such as fragility, ugly code, and limited compile-time checks.
(Kotlin code often uses KClass objects instead of Java Class objects, but the principle is the same.)
It may be worth highlighting the difference between class and type, which are related but subtly different. For example, String is both a class and a type, while String? is another type derived from the same class. LinkedList is a class, but not a type (because it needs a type parameter); LinkedList<Int> is a type.
Types can of course be derived from interfaces as well as from classes, e.g. Runnable, or MutableList<Int>.
This is relevant to the question, because generics use type parameters, while Class objects represent classes.

How to check if a Kotlin type (KClass) is basic (primitive), or not, at runtime (e.g. Reflection API)?

Kotlin specification states basic types as "Some types can have a special internal representation - for example, numbers, characters and booleans can be represented as primitive values at runtime". https://kotlinlang.org/docs/basic-types.html
Yet, I am not figuring out any way to know if the Type representation in Kotlin, i.e. instance of KClass is a basic type, or not?
Scope
We need to parse and convert String values to strongly typed instances and for "basic types" we want to use the corresponding to<basic type> auxiliary method, like Java valueOf or boxing.

Combine JsonDeserialize#contentAs with JsonDeserialize#contentConverter or JsonDeserialize#contentUsing for custom deserialization

In JsonDeserialize annotation documentation the contentAs field is supposed to define the "Concrete type to deserialize content".
I tried to use this in combination, with either a Converter (via contentConverter field of the same annotation) or a JsonDeserializer (via contentUsing field of the same annotation), by extending either StdConverter or StdDeserializer, respectively, in an attempt to create an agnostic custom deserializer.
I cannot find a way to access the JsonDeserialize#contentAs information inside any of these two classes.
I am aware that the classes I extend from have a type parameter, I just put an Object class there. Documentation states
contentAs Concrete type to deserialize content (elements of a Collection/array, values of Maps) values as, instead of type otherwise declared. Must be a subtype of declared type; otherwise an exception may be thrown by deserializer.
Apparently I am applying the #JsonDeserializer annotation on a Collection of some persistable Class. I want to deserialize each such object, solely by knowing its id. Well, if I could only get that very type I defined in the #JsonDeserializer#contentAs field...
Can anyone tell me if this is possible anyhow?
I managed to implement the agnostic deserializer withou the use of #JsonDeserializer#contentAs after all.
After reading the javadocs of com.fasterxml.jackson.databind.JsonDeserializer I concluded that my custom deserializer should implement the com.fasterxml.jackson.databind.deser.ContextualDeserializer interface.
Inside the implementation of ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property)
I could finally get access to the class type of the content of the collection, which I applied the #JsonDeserialize annotation on,
by calling:
ctxt.getContextualType().getRawClass()
NOTE that the same call inside the implementation of com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) returned null, hence the need of the aforementioned interface.
All I had to do then is store the returned class in a member field (of type Class< ? >) of the custom deserializer and use it in the execution of JsonDeserializer#deserialize()
The only thing that remains to check is whether an instance of this custom deserializer is shared between threads. I only did some minor checks; I used the same implementation for two different collections of different types. I observed that ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) was called once (among multiple deserialization invokations), for each distinct type that was going to be deserialized. After checking during debugging, it seems that the same deserializer object is used for the same type. In my case, since what I store in the member field is this type itself, I don't mind if the same deserializer is used for the same java type to be deserialized because they should contain the same value. So we 're clear on this aspect as well.
EDIT: It appears all I have to do is update the com.fasterxml.jackson.databind.deser.std.StdDeserializer#_valueClass value to the now known class. Since it is final and since the ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) returns a JsonSerializer object, which is actually used,
instead of returning "this" serializer I can create a new one, passing the discovered class in the constructor, which actually sets the StdDeserializer#_valueClass to the class I actually want, and I'm all set!
Finally, NOTE that I didn't have to use the #JsonDeserializer#contentAs annotationfield as I get the value from the ctxt.getContextualType().getRawClass() statement inside ContextualDeserializer#createContextual(DeserializationContext ctxt, BeanProperty property) implementation

What's the difference between an object and a data object?

The other day I noticed that I sometimes put data in front of objects and other times not:
object A
data object B
What's the difference between an object and a data object?
The fact that data is allowed on an object declaration is in fact a bug (KT-6486) which should be fixed.
data is an annotation which causes the compiler to generate equals, hashCode, toString, copy and componentN functions. It doesn't make much sense when applied to an object declaration for two reasons:
An object declaration cannot have a constructor, and all these functions work based on properties defined in the primary constructor.
There's only one instance of any object at runtime.
So no componentN functions would be generated, copy can't work, and the generated equals/hashCode/toString implementations will be equivalent to the default ones from Any which are based on identity.

Nullable Type in ATL COM

I am working on the data access in C++ ATL/COM.
How do you pass a nullable type (e.g. nullable integer) in an interface???
In ATL/C++ in in interfaces (IDL) you don't have nullable classes and support in language constructs (<type>? in C#). Nullable is basically the type itself and an extra BOOL indicating whether we currently have NULL or not.
One can implement a relatively simple template class to look - to extend possible - similarly to C# Nullable. On the interface this will be either two arguments, or as you discovered you can use VARIANT type since it already embeds payload value and .vt member indicating type. VT_NULL constant is what it says for itslef - the value of the whole variant is null.