First, 'well its not even java.lang.String' statement is not quite correct. Plain String
name comes from type alias defined in Predef
object:
type String = java.lang.String
and insides of Predef
are imported in every Scala source, hence you use String
instead of full java.lang.String
, but in fact they are the same.
java.lang.String
is very special class treated by JVM in special way. As @pagoda_5b said, it is declared as final
, it is not possible to extend it (and this is good in fact), so Scala library provides a wrapper (RichString
) with additional operations and an implicit conversion String -> RichString
available by default.
However, there is slightly different situation with Integer
, Character
, Boolean
etc. You see, even though String
is treated specially by JVM, it still a plain class whose instances are plain objects. Semantically it is not different from, say, List
class.
There is another situation with primitive types. Java int
, char
, boolean
types are not classes, and values of these types are not objects. But Scala is fully object-oriented language, there are no primitive types. It would be possible to use java.lang.{Integer,Boolean,...}
everywhere where you need corresponding types, but this would be awfully inefficient because of boxing.
Because of this Scala needed a way to present Java primitive types in object-oriented setting, and so scala.{Int,Boolean,...}
classes were introduced. These types are treated specially via Scala compiler - scalac generates code working with primitives when it encounters one of these classes. They also extend AnyVal
class, which prevents you from using null
as a value for these types. This approach solves the problem with efficiency, leaves java.lang.{Integer,Boolean,...}
classes available where you really need boxing, and also provides elegant way to use primitives of another host system (e.g. .NET runtime).