Does Kotlin have primitive types? - kotlin

Does Kotlin have primitive types?. When I declare the variable: val myAge: Int = 18 then the myAge variable stores the actual values is 18 or stores the addresses of the objects in the memory?. If Int is primitive type then why we can use its method like myAge.minus(10)?

No... and yes.
Kotlin doesn't have primitive type (I mean you cannot declare primitive directly). It uses classes like Int, Float as an object wrapper for primitives.
When kotlin code is converted to jvm code, whenever possible, "primitive object" is converted to java primitive.
In some cases this cannot be done. Those cases are, for example, collection of "primitives". For example, List<Int> cannot contains primitive. So, compiler knows when it can convert object to primitive. And, again, it's very similar to java:
List<Integer> numbers = new ArrayList<>;
numbers.add(0); // <-- you use primitive, but in fact, JVM will convert this primitive to object.
numbers.add(new Integer(0)); // <-- We don't need do that.
Also, when you declare "nullable primitive" it is never converted to primitive (what is kind of obvious, as primitive cannot be null). In java it works very similar:
int k = null; // No way!
Integer kN = null; // That's OK.
One more thing - what docs are saying about it?
For Common, JVM, JS
Represents a 32-bit signed integer. On the JVM, non-nullable values of this type are represented as values of the primitive type int.
For Native
Represents a 32-bit signed integer.
#see: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/index.html
So, the last conclusion. Kotlin doesn't have primitive types out of the box. You treat all objects like objects. Converting to primitive is done at some lower level than code. This design is caused to keep compatibility with JVM.
I did a little deep dive and published it on medium. For interested: https://medium.com/#przemek.materna/kotlin-is-not-primitive-primitives-in-kotlin-and-java-f35713fda5cd

Short answer - yes and depends on the declaration.
val myAge: Int = 18 // this is primitive
val myAge2: Int? = 18 // this is not
There's a very informative video about that
https://www.youtube.com/watch?v=Ta5wBJsC39s

On the Java platform, numbers are physically stored as JVM primitive types, unless we need a nullable number reference (e.g. Int?) or generics are involved. In the latter cases numbers are boxed.
Note that boxing of numbers does not necessarily preserve identity:
val a: Int = 10000
println(a === a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA === anotherBoxedA) // !!!Prints 'false'!!!
Note "===" used to compare reference ....
On the other hand, it preserves equality:
val a: Int = 10000
println(a == a) // Prints 'true'
val boxedA: Int? = a
val anotherBoxedA: Int? = a
println(boxedA == anotherBoxedA) // Prints 'true'

Related

What is the difference between intArrayOf() and arrayOf()?

In some sources I read that the first creates an array of elements of primitive type Int, and the second of packed Integer, in others that in Kotlin there are no primitive types, and it is the same. I haven't found any consensus, I'd be grateful if someone could explain.
Googled and read the book Kotlin in Actions
arrayOf produce an object of class Array<T>. As you initialize array using this function, primitive values that you provide as arguments are being boxed. In other words, primitive integer value 1 will be converted to the object of type Int with value 1.
val array = arrayOf(1, 2, 3) // array's type is Array<Int>
intArrayOf is a function to create object of type IntArray. This class does not have boxing overhead. Therefore values that you provide are not being boxed.
val array = intArrayOf(1, 2, 3) // array's type is IntArray
Note that both classes IntArray and Array<T> have no inheritance relation. But they contain same set of methods and properties.
IntArray represents primitive type arrays, which are designed specifically to prevent deriving array type from provided elements and avoid boxing overhead.
However, if you are calling get method on IntArray, you will get value of type Int, same as when you call get on Array<Int>.
intArrayOf() and arrayOf() are both functions in Kotlin for creating arrays. The main difference between the two functions is the type of elements that the resulting arrays can hold.
intArrayOf() is used to create an array of primitive Int values, while arrayOf() is used to create an array of objects, such as String, Float, or other object types.
Here's an example of using intArrayOf():
val intArray = intArrayOf(1, 2, 3, 4, 5)
And here's an example of using arrayOf():
val stringArray = arrayOf("A", "B", "C")
Note that while intArrayOf() creates an array of primitive Int values, arrayOf() creates an array of Int objects, which are reference types. This means that the elements in the array created by arrayOf() are objects that can have different values, while the elements in the array created by intArrayOf() are primitive values that cannot have different values.

Referential vs Structural equality in Kotlin in case of strings

My current understanding of structural equality is that it compares the type and the content.
For Referential equality, it compares the address of the two objects. Also, in the case of a primitive type of var, it will print true if the content is the same.
According to the doc here --> numbers, characters and booleans can be represented as primitive values at runtime - but to the user, they look like ordinary classes.
So String should be treated as objects at runtime.
But I get true when comparing referentially two strings that have the same content.
fun main(){
val name1 = "123"
val name2 = "123"
println(name1 == name2) //true, structural equality which is same type and same content (same as equals)
// checks if left and right are same object --> referential equality
var name3 = "123"
println(name1 === name3) //true ????????
// should print false. String is basic type and not primitve
var Arr: IntArray = intArrayOf(1,2,3)
var Arr2: IntArray = intArrayOf(1,2,3)
println(Arr === Arr2) // prints false, arrays are basic type
}
Also, why doesn't equality in kotlin of both types differentiates between val and var? They are two different types of objects at their core.
Can someone point out where am I going wrong with this? I might be missing something pretty obvious here.
So as far as string referential equality check goes, I think it does the same thing as Java in that it adds everything to the string constant pool.
Here is the thread for referential string comparison in java (done by ==) -
What makes reference comparison (==) work for some strings in Java?
For Val vs Var the answer by #Tenfour04 below explains the logic.
val and var are not different types of objects. They are references, not objects at all. They have nothing to do with the behavior of the objects they are referring to. When you compare two objects, the types of variables and properties that are referencing them is not a factor whatsoever. When you call equals on one object, the runtime only uses the reference to find the object in memory. Only then is its function called.

Kotlin type mismatch: required Array<Int?>? but found Array<Int>

Here's my Foo data class definition
data class Foo(
var fooArg: Array<Int?>? = null,
)
And here's the call to it:
val bar: Array<Int> = arrayOf(1,2,3)
val foo = Foo(fooArg = bar)
But this gives an error type mismatch: required Array<Int?>? but found Array<Int>
I am confused, it is expecting a nullable type, and I provide it with a non-null value, how is that type mismatch?
You declared bar as Array<Int>. Non-null types are not compatible with nullable types*. Change it to Array<Int?> and it will work:
val bar: Array<Int?> = arrayOf(1,2,3)
val foo = Foo(fooArg = bar)
Or alternatively:
val bar = arrayOf<Int?>(1, 2, 3)
*I think the correct thing to say is that arrays are invariant on the type parameter. But I get lost every time I try to understand it properly. 🤯
Adam's answer covers the solution, but it's also worth mentioning why what you're doing doesn't work. Java uses call-site variance annotations, unlike most other languages in existence. Kotlin takes the more traditional approach of using declaration-site variance annotations. That means that, when declaring a class which takes generic arguments, the writer of the class decides how it behaves with respect to subtypes.
Now, Int is a subtype of Int?. Namely, every Int is an Int?, but the reverse is not true. The question is: is Array<Int> a subtype of Array<Int?>? Well, covariant types such as List<T> preserve subtyping, so List<Int> is actually a subtype of List<Int?>. If you replace your example in the question with lists rather than arrays, everything works.
On the other hand, Array<T> is an invariant type. We can both read and write to an array, so it's never safe to upcast or downcast the type parameter. If we could, then the following would typecheck.
// Doesn't compile, for good reason
val myHealthyArray: Array<Int> = arrayOf(1);
val myScaryNullableArray: Array<Int?> = myHealthyArray;
myScaryNullableArray[0] = null;
Now my perfectly innocent myHealthyArray variable has a null in it that the type Array<Int> can't account for. That's contrary to everything Kotlin stands for, so it's disallowed on principle.
If you're only ever going to be using this data structure for reading, not writing, consider using List<T> or something covariant, which better describes the type of your function and also allows the subtyping relationships to work more fully.

toString() in Kotlin - wrong output

I have written some codes for printing out objects in array with toString()
but by using Option1 println(path.toString())
Output is [LRunningpath;#27973e9b
which is not what i want. Then i replace it with Option2 as follow
var i=0
for(i in 0 until path.size)
println(path[i].toString())
which is correct.
My questions are,
why Option 1 don't work?
what does the output in Option 1 mean?
any advice to avoid the same situation in the future?
Any hints is very appreciated. Thank you for the kindness.
my codes are as below:
fun main() {
println("Warming up")
val input1 = Runningpath("in Forest", 2000, "some houses")
val input2 = Runningpath("at lake", 1500, "a school")
val path = arrayOf(input1, input2 )
println(path.toString())
/* var i=0
for(i in 0 until path.size)
println(path[i].toString())
*/
}
class Runningpath(val name: String, val length: Int, val spot: String){
override fun toString(): String= "The Path $name ($length m) is near $spot"
}
Short answer: in most cases, it's better to use lists instead of arrays.
Arrays are mostly for historical reasons, for compatibility, and for implementing low-level data structures.  In Kotlin, you sometimes need them for interoperability with Java, and for handling vararg arguments.  But other than those, lists have many advantages.
The problem is that on the JVM, an array is very different from all other objects.  It has only the methods inherited from Object, and doesn't override those.  (And you can't create your own subclasses to override or add to them.)
In particular, it has the toString() method from Object.  That gives a code indicating the type — here [ for an array, L indicating that each element is a reference, Runningpath giving the type of reference, ; and # separators, and a hex representation of the array's hash code, which may be its address in memory or some other unique number.
So if you want some other way of displaying an array, you'll have to do it ‘manually’.
Other problems with arrays on the JVM result from them having run-time typing — they were part of Java long before generics were added, and interoperate badly with generics (e.g. you can't create an array of a generic type) — and being both mutable and covariant (and hence not type-safe in some cases).
Lists, like other Collections and data structures, are proper objects: they have methods such as toString(), which you can override; they can have generic type parameters; they're type-safe; they can have many implementations, including subclasses; and they're much better supported by the standard library and by many third-party libraries too.
So unless you have a particular need (vararg processing, Java interoperability, or a dire need to save every possible byte of memory), life will go easier if you use lists instead of arrays!
You can use the joinToString for that:
println(path.joinToString("\n"))
The joinToString() is actually available for both the List and the Array, but I'd recommend using the List as you'd have immutability and many other extensions on that, that will help your on manipulating the datas.

Kotlin how to declare chained fields with same data type

In other programming languages like Java if you want to chain fields, you do like: String a, b, c, d;
Is it possible to chain fields in Kotlin too, like val a, b, c, d?
here doesn`t provide any info
No, Kotlin does not support declaration of multiple variable in a statement.
Kotlin has learned some good lessons from Java. One of that is variable declaration. Though Java support multiple variable declaration in a line, Oracle's Java Guidelines says use only one declaration per line.
Following is mentioned in Oracle Java Standard:
One declaration per line is recommended since it encourages commenting. In other words,
int level; // indentation level
int size; // size of table
is preferred over
int level, size;
In absolutely no case should variables and functions be declared on the same line. Example:
long dbaddr, getDbaddr(); // WRONG!
Do not put different types on the same line. Example:
int foo, fooarray[]; //WRONG!
Note: The examples above use one space between the type and the identifier. Another
acceptable alternative is to use tabs, e.g.:
int level; // indentation level
int size; // size of table
Object currentEntry; // currently selected table entry
Refer this link for Oracle convention: http://www.oracle.com/technetwork/java/codeconventions-150003.pdf. Page no. 14 > Declarations.
There has been some huge debates on this topic of type of declaration should be used for Java. So Kotlin just removed that as an option.
First, Kotlin is a null-safety language which means you can't declare fields without initializing them, and Kotlin has no default value for any types even if it is nullable, but there is an exception for the primitive array, e.g:IntArray(size) the default value likes as java are 0. So you can't write the form of the field declaration as in Java, for example:
//Java
private String a,b,c;// they are `null` by default.
private val a:String? // error: property must be initialized
Secondly, If you are concerned about the definition of fields/variables, they are totally different. the field/variable type is declared at the right-side, which means you can't declare a unified fields/variables in Kotlin at all, so it doesn't make sense in Kotlin, for example:
//Java
String a,b;
//Kotlin
val a, b;
// ^---^--- how to declare the variables type?
// v-- just more than one `val` after introduce the variable types
val a:String; val b:String;
Finally, field is a heavy component in Kotlin. when you declare a field in Java it is merely a field, no more. but in Kotlin when you declare a field, it maybe a property/field. and a property has getter/backing field(?)/setter(?), for example:
// java
String a; //just a field
// kotlin
var a:String = "a" // has a backing field, getter & setter
private var b:String = "b" // it is just a field
#JvmField var c:String = "c"
// ^--- it is a field but it has getter/setter in reflect
// e.g: this::c.getter & this::c.setter