0

I noticed that the hashcode of Char-values is exactly the ID they have in ASCII, for example:

println('a'.hashCode()) //is 97

Is this true by contract and where can I see the implementation for this? The class Any.kt doesn't contain the implementation and Char.kt does neither.

Moritz Groß
  • 1,352
  • 12
  • 30

1 Answers1

1

I noticed that the hashcode of Char-values is exactly the ID they have in ASCII […]

That is impossible. ASCII only has 128 values, but Kotlin Char has 65536, so clearly, a Char cannot have their ASCII value as their hashcode, because 99.8% of them don't have an ASCII value.

Is this true by contract

No, it is not. The contract for kotlin.Char.hashCode() is:

fun hashCode(): Int

Returns a hash code value for the object. The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
  • If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result.

That is the whole contract. There is nothing about a relationship with ASCII.

and where can I see the implementation for this? The class Any.kt doesn't contain the implementation and Char.kt does neither.

I am assuming types like kotlin.Char or kotlin.Int are not actually implemented as Kotlin objects but as compiler intrinsics for performance reasons. For example, I would expect 42 to be a JVM int on the JVM platform and an ECMAScript number on the ECMAScript platform, and not implemented as a full-blown object with object header, instance variable table, class pointer, etc.

As it so happens, Kotlin's contract for hashCode() matches the contract for pretty much every other language as well, so I would expect that they as much as possible re-use the underlying platform's implementation. (In fact, I would suspect that is precisely the reason for designing the contract this way.)

Even for Kotlin/Native, it makes sense to map kotlin.Int to a native machine integer int_fast32_t or int32_t type.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • On the JVM, `Char` and `Int` (along with `Boolean`, `Byte`, `Short`, `Long`, `Float`, and `Double`) are compiled down to [primitive values](https://kotlinlang.org/docs/tutorials/kotlin-for-py/primitive-data-types-and-their-limitations.html) where possible — but it's not always possible, e.g. where they need to be nullable, used as generic types in collections, or for interoperability with Java objects.  In those cases, the values are ‘boxed’ into wrapper objects; see [this question](https://stackoverflow.com/questions/57408327/does-kotlin-have-primitive-types)… (contd) – gidds Jun 27 '20 at 12:40
  • It may well be that Sun deliberately chose the hash codes of those wrappers to match the primitive values, to reduce one of the gotchas with autoboxing.  (There are several more, though.)  But if it ain't in the contract, then you shouldn't rely on it. – gidds Jun 27 '20 at 12:42