scala主构造函数不生成字段

时间:2017-01-10 04:17:35

标签: scala

这是scala代码

class Dog(name:String, age:Int) {
   println("Dog is created!")
   def sayHello() = println(s"My name is $name, I am $age years old")
}

反编译生成的类文件,如下所示。

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) })));
 }
}

只有一个字段“name”,但没有“age”字段。为什么呢?

2 个答案:

答案 0 :(得分:1)

多奇怪,因为当我反编译上面的代码时,我得到了这个。

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!");
    }
}

通过查看此信息,您可以看到nameage } {/ 1}}和private类字段均可用

在构造函数中,您可以看到为finalname分配了值,然后print语句正在运行。

我从age

在线反编译了上述代码

希望这能让你怀疑。

答案 1 :(得分:0)

我按以下方式编译/反汇编了您的代码段(在使用Scala 2.12.1和Java 1.8.0_112的Mac上):

$ 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

这导致以下输出包含nameage的私人最终成员:

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);
}

那么你是如何编译/反编译你的代码的呢?

在您的问题中,您撰写了关于字段的文章。实际上在你的情况下那些不是字段,它们是简单的类参数。它们仅由构造函数使用。如果您明确使用val关键字,那么这将是一个字段。

如果您希望这些参数是可通过dog.agedog.name访问的真实字段,请写下以下内容:

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")
}

作为替代方案,您可以使用类似的案例类:

case class Dog(name:String, age:Int) {
  println("Dog is created!")
  def sayHello() = println(s"My name is $name, I am $age years old")
}

有关详细信息,请查看 Scala编程一书中的Functional Objects章节。

编辑:我刚尝试使用JD-GUI反编译同一个类文件。这导致失踪的私人age班级成员:

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) })));
    }
}

因此,javap工作以来这可能是JD中的一个错误。我创建了一个ticket on github。但我怀疑他们会解决它。 JD-GUI项目的最后一次提交是一年多以前的事了......