Roger Keays
Roger Keays

Reputation: 3227

Is kotlin.String really a java.lang.String?

I'm interested to know how kotlin.String is implemented, since it reports itself as a java.lang.String, yet has more methods available (according to ki autocompletion) even accounting for extension methods:

[34] kotlin.String().javaClass
res17: Class<String> = class java.lang.String

[35] "10".javaClass
res18: Class<String> = class java.lang.String

[36] "10".toLong()
res19: Long = 10

[37] java.lang.String("10").javaClass
res20: Class<String> = class java.lang.String

[38] java.lang.String("10").toLong()
ERROR Unresolved reference. None of the following candidates is 
applicable because of receiver type mismatch: 
public inline fun String.toLong(): Long defined in kotlin.text
public inline fun String.toLong(radix: Int): Long defined in 
kotlin.text (Line_39.kts:1:24)

Is kotlin.String really a java.lang.String?

Upvotes: 1

Views: 917

Answers (2)

Roger Keays
Roger Keays

Reputation: 3227

To expand on the other comments posted here, it looks like kotlin.String is not a java.lang.String, but it does compile to one, according to the java/kotlin type mapping. So even though the runtime class is the same, the compiler treats them differently. Since the toLong extension method is implemented on kotlin.String, it is not available for java.lang.String.

You can pull the same trick in reverse:

[71] fun java.lang.String.zero(): Long = 0
[72] java.lang.String().zero()
res36: Long = 0

but this extension method is not available for a kotlin.String, even though it compiles to a java.lang.String.

[73] "kotlin string".javaClass
res37: Class<String> = class java.lang.String
[74] "kotlin string".zero()
ERROR Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
public final fun String.zero(): Long defined in Line_72 (Line_75.kts:1:17)

To further complicate the matter, a java.lang.String is normally loaded as a kotlin.String unless you give the fully qualified name.

[0] java.lang.String("12345").toLong()
ERROR Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: 
public inline fun String.toLong(): Long defined in kotlin.text
public inline fun String.toLong(radix: Int): Long defined in kotlin.text (Line_1.kts:1:27)

[1] java.lang.String("12345").substring(0).toLong()
res0: Long = 12345

So the answer is no, a kotlin.String is not a java.lang.String. They are interoperable because they compile to the same class, but the compiler still distinguishes between them.

Related question: does Any == Object

Upvotes: 1

sidereal
sidereal

Reputation: 1120

Kotlin supports adding functionality to classes without extending the class, via extensions: https://kotlinlang.org/docs/extensions.html

You can see String.toLong is added along with many other extensions to base Java classes via the kotlin.text package here: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/

Upvotes: 3

Related Questions