By adding to @EntryLevelDev's answer, you can use javap
to see what really happened.
1.scala
class Test(val str: String){
}
step1. scalac 1.scala
step2. javap Test
Compiled from "1.scala"
public class Test {
public java.lang.String str();
public Test(java.lang.String);
}
2.scala :
class Test2(str: String){
}
step1. scalac 2.scala
step2. javap Test2
Compiled from "1.scala"
public class Test1 {
public Test1(java.lang.String);
}
So when you add val, scala generates a method by the argument's name, and is made public so is visible from outside.