Reputation: 1
Here is the scala code
class Dog(name:String, age:Int) {
println("Dog is created!")
def sayHello() = println(s"My name is $name, I am $age years old")
}
decompile the generated class file as below.
import scala.Predef.;
import scala.StringContext;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
@ScalaSignature(bytes="\006\001=2A!\001\002\001\023\t\031Ai\\4\013\005\r!\021\001C2iCB$XM\035\034\013\005\0251\021!B6d[2\004(\"A\004\002\007\r|Wn\001\001\024\005\001Q\001CA\006\017\033\005a!\"A\007\002\013M\034\027\r\\1\n\005=a!AB!osJ+g\r\003\005\022\001\t\005\t\025!\003\023\003\021q\027-\\3\021\005MQbB\001\013\031!\t)B\"D\001\027\025\t9\002\"\001\004=e>|GOP\005\00331\ta\001\025:fI\0264\027BA\016\035\005\031\031FO]5oO*\021\021\004\004\005\t=\001\021\t\021)A\005?\005\031\021mZ3\021\005-\001\023BA\021\r\005\rIe\016\036\005\006G\001!\t\001J\001\007y%t\027\016\036 \025\007\025:\003\006\005\002'\0015\t!\001C\003\022E\001\007!\003C\003\037E\001\007q\004C\003+\001\021\0051&\001\005tCfDU\r\0347p)\005a\003CA\006.\023\tqCB\001\003V]&$\b")
public class Dog
{
private final String name;
public Dog(String name, int age)
{
Predef..MODULE$.println("Dog is created!");
}
public void sayHello()
{
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "My name is ", ", I am ", " years old" })).s(Predef..MODULE$.genericWrapArray(new Object[] { this.name, BoxesRunTime.boxToInteger(this.age) })));
}
}
There is only a field "name", but there is no "age" field. Why?
Upvotes: 0
Views: 125
Reputation: 54322
I compiled/disassembled your code snippet the following way (on a Mac with Scala 2.12.1 and Java 1.8.0_112):
$ echo > Dog.scala <<EOF
class Dog(name:String, age:Int) {
println("Dog is created!")
def sayHello() = println(s"My name is $name, I am $age years old")
}
EOF
$ scalac Dog.scala && javap -private Dog.class
That results into the following output which contains both private final class members for name
and age
:
Compiled from "Dog.scala"
public class Dog {
private final java.lang.String name;
private final int age;
public void sayHello();
public Dog(java.lang.String, int);
}
So how did you compile/decompile your code?
In your question you wrote about fields. Actually in your case those are not fields, they are simple class parameters. They are only used by the constructor. It would be a field if you use the val
keyword explicitly.
In case you want those parameters to be real fields accessible via dog.age
and dog.name
, write the following:
class Dog(val name:String, val age:Int) {
println("Dog is created!")
def sayHello() = println(s"My name is $name, I am $age years old")
}
As an alternative you could use a case class like:
case class Dog(name:String, age:Int) {
println("Dog is created!")
def sayHello() = println(s"My name is $name, I am $age years old")
}
For more details please have a look at the Functional Objects chapter in the Programming in Scala book.
EDIT: I just tried to decompile the same class file with the JD-GUI. That lead into the missing private age
class member:
import scala.Predef.;
import scala.StringContext;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
@ScalaSignature(bytes="\006\001-2A!\001\002\001\013\t\031Ai\\4\013\003\r\tq\001P3naRLhh\001\001\024\005\0011\001CA\004\013\033\005A!\"A\005\002\013M\034\027\r\\1\n\005-A!AB!osJ+g\r\003\005\016\001\t\005\t\025!\003\017\003\021q\027-\\3\021\005=1bB\001\t\025!\t\t\002\"D\001\023\025\t\031B!\001\004=e>|GOP\005\003+!\ta\001\025:fI\0264\027BA\f\031\005\031\031FO]5oO*\021Q\003\003\005\t5\001\021\t\021)A\0057\005\031\021mZ3\021\005\035a\022BA\017\t\005\rIe\016\036\005\006?\001!\t\001I\001\007y%t\027\016\036 \025\007\005\032C\005\005\002#\0015\t!\001C\003\016=\001\007a\002C\003\033=\001\0071\004C\003'\001\021\005q%\001\005tCfDU\r\0347p)\005A\003CA\004*\023\tQ\003B\001\003V]&$\b")
public class Dog
{
private final String name;
public Dog(String name, int age)
{
Predef..MODULE$.println("Dog is created!");
}
public void sayHello()
{
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[])new String[] { "My name is ", ", I am ", " years old" })).s(Predef..MODULE$.genericWrapArray(new Object[] { this.name, BoxesRunTime.boxToInteger(this.age) })));
}
}
So probably this is a bug in JD since javap
worked. I created a ticket on github. But I doubt that they will fix it. The last commit on the JD-GUI project was more than a year ago...
Upvotes: 0
Reputation: 2294
Thats Strange because when I decompiled the above code I got this.
import scala.Predef;
import scala.StringContext;
import scala.collection.Seq;
import scala.collection.mutable.WrappedArray;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
@ScalaSignature(bytes="\u0006\u0001\u001d2A!\u0001\u0002\u0001\u000b\t\u0019Ai\\4\u000b\u0003\r\tq\u0001P3naRLhh\u0001\u0001\u0014\u0005\u00011\u0001CA\u0004\u000b\u001b\u0005A!\"A\u0005\u0002\u000bM\u001c\u0017\r\\1\n\u0005-A!AB!osJ+g\r\u0003\u0005\u000e\u0001\t\u0005\t\u0015!\u0003\u000f\u0003\u0011q\u0017-\\3\u0011\u0005=\u0011bBA\u0004\u0011\u0013\t\t\u0002\"\u0001\u0004Qe\u0016$WMZ\u0005\u0003'Q\u0011aa\u0015;sS:<'BA\t\t\u0011!1\u0002A!A!\u0002\u00139\u0012aA1hKB\u0011q\u0001G\u0005\u00033!\u00111!\u00138u\u0011\u0015Y\u0002\u0001\"\u0001\u001d\u0003\u0019a\u0014N\\5u}Q\u0019Qd\b\u0011\u0011\u0005y\u0001Q\"\u0001\u0002\t\u000b5Q\u0002\u0019\u0001\b\t\u000bYQ\u0002\u0019A\f\t\u000b\t\u0002A\u0011A\u0012\u0002\u0011M\f\u0017\u0010S3mY>$\u0012\u0001\n\t\u0003\u000f\u0015J!A\n\u0005\u0003\tUs\u0017\u000e\u001e")
public class Dog {
private final String name;
private final int age;
public void sayHello() {
Predef..MODULE$.println((Object)new StringContext((Seq)Predef..MODULE$.wrapRefArray((Object[])new String[]{"My name is ", ", I am ", " years old"})).s((Seq)Predef..MODULE$.genericWrapArray((Object)new Object[]{this.name, BoxesRunTime.boxToInteger((int)this.age)})));
}
public Dog(String name, int age) {
this.name = name;
this.age = age;
Predef..MODULE$.println((Object)"Dog is created!");
}
}
By looking at this you can see that both name
and age
class fields are available with private
and final
In the constructor you can see that name
, age
are assigned there values and then the print statement is working.
I decompiled the above code online from http://www.javadecompilers.com/
Hope this clears you doubt.
Upvotes: 1