case class, object的底层实现

来源:互联网 发布:关键词排列组合软件 编辑:程序博客网 时间:2024/05/01 23:35

object和class的关系

class O{    def func() {        O.func();println("No!")    }}object O{    def func() {println("O!")    }}
都定义了func()方法,但是实际上不冲突;

上述代码转化为java的结果:

public final class O${    public static final  MODULE$;    static    {        new ();    }    public void func()    {        Predef..MODULE$.println("O!");    }    private O$() {        MODULE$ = this;    }}public class O{    public void func()    {        O..MODULE$.func();        Predef..MODULE$.println("No!");    }}

可看出:

    1 实际上会产生2个类, 分别是O和O$;

    2 O$是单例类, MODULE$是单例对象;

    3 对伴生对象O的调用,都会转化为对O$.MODULE$的调用;

class A{  var a = 2; //和object A有同名的变量,这种情况下,不会为java的A类生成static int a的静态变量;}object A{  def func() {    println("O A")  }  var a = 1; }

Java的代码如下:

public class A{  private int a = 2;  public static void func() { A..MODULE$.func(); }   public int a() { return this.a; }   public void a_$eq(int x$1) { this.a = x$1; }}public final class A${  public static final  MODULE$;  private int a;  static  {    new ();  }  public void func()  {    Predef..MODULE$.println("O A");  }  public int a() { return this.a; }   public void a_$eq(int x$1) { this.a = x$1; }  private A$() {    MODULE$ = this;    this.a = 1;  }}

1 scala类的任何成员变量,在java都是private的,且都会生成相应的存取方法, 且set方法命名: xxx_$eq.
2 A类没有定义func()方法,所以为A类生成了func()方法,里面直接调用A$类的同名方法,这样A类的对象等于就有了func()方法.
3 scala中,对A.a的调用,都会转化为对A$的方法的调用;
4 如果object A中声明了a, class A没有声明a,则会在java层为A生成static int a的变量和存取方法,但是不会被调用到;

5 如果object A中声明了a, class A也声明了a,则就不会在java层为A生成static int a;

6 若只定义了object A, 没有定义class A, 则java层也会生成class A,但是不可用;

上面4,5其实都无所谓,因为第3条才是根本, 即对A.a的调用, 都会直接route到对A$的方法的调用;

class B{  var x = 10;}case object B{  def func() {    println("O B")  }  var b = 1;}
转化为的java代码:

public class B{  private int x = 10;  public static boolean canEqual(Object paramObject) { return B..MODULE$.canEqual(paramObject); }   public static Iterator<Object> productIterator() { return B..MODULE$.productIterator(); }   public static Object productElement(int paramInt) { return B..MODULE$.productElement(paramInt); }   public static int productArity() { return B..MODULE$.productArity(); }   public static String productPrefix() { return B..MODULE$.productPrefix(); }   public static void b_$eq(int paramInt) { B..MODULE$.b_$eq(paramInt); }   public static int b() { return B..MODULE$.b(); }   public static void func() { B..MODULE$.func(); }   public int x() { return this.x; }   public void x_$eq(int x$1) { this.x = x$1; }}public final class B$  implements Product, Serializable{  public static final  MODULE$;  private int b;  static  {    new ();  }  public void func()  {    Predef..MODULE$.println("O B");  }  public int b() { return this.b; }   public void b_$eq(int x$1) { this.b = x$1; }  public String productPrefix()  {    return "B"; }   public int productArity() { return 0; }   public Object productElement(int x$1) { int i = x$1; throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString()); }   public Iterator<Object> productIterator() { return ScalaRunTime..MODULE$.typedProductIterator(this); }   public boolean canEqual(Object x$1) { return x$1 instanceof ; }   public int hashCode() { return 66; }   public String toString() { return "B"; }   private Object readResolve() { return MODULE$; }   private B$() { MODULE$ = this; Product.class.$init$(this);    this.b = 1;  }}

case class和class的关系

case class C(c1: Int){  var c = c1;}
转化为的java代码:

public class C  implements Product, Serializable{  private final int c1;  private int c;  public static Option<Object> unapply(C paramC)  {    return C..MODULE$.unapply(paramC);  }  public static C apply(int paramInt)  {    return C..MODULE$.apply(paramInt);  }  public static <A> Function1<Object, A> andThen(Function1<C, A> paramFunction1)  {    return C..MODULE$.andThen(paramFunction1);  }  public static <A> Function1<A, C> compose(Function1<A, Object> paramFunction1)  {    return C..MODULE$.compose(paramFunction1);  }  public int c1()  {    return this.c1; }   public int c() { return this.c; }  public int copy$default$1()  {    return c1(); }   public void c_$eq(int x$1) { this.c = x$1; }  public C copy(int c1)  {    return new C(c1); }   public String productPrefix() { return "C"; }   public int productArity() { return 1; }   public Object productElement(int x$1) { int i = x$1; switch (i) { default:      throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());    case 0: } return BoxesRunTime.boxToInteger(c1()); }   public Iterator<Object> productIterator() { return ScalaRunTime..MODULE$.typedProductIterator(this); }   public boolean canEqual(Object x$1) { return x$1 instanceof C; }   public int hashCode() { int i = -889275714; i = Statics.mix(i, c1()); return Statics.finalizeHash(i, 1); }   public String toString() { return ScalaRunTime..MODULE$._toString(this); }  public boolean equals(Object x$1)  {    C localC;    if (this != x$1) { Object localObject = x$1;      int i;      if ((localObject instanceof C)) i = 1; else i = 0; if (i == 0) break label64; localC = (C)x$1; } label64: return ((c1() == localC.c1()) && (localC.canEqual(this)) ? 1 : 0) != 0; }   public C(int c1) { Product.class.$init$(this);    this.c = c1;  }}

最后总结

class D   --------->  只会生成class D类
object A  --------->  生成A和A$, 但是A无意义,都是A$的转发,且不能被调用(因为scala层认为没有定义class A,编译不通过);
case class C ------>  生成C和C$; 定义了C$的apply()方法;

case object B ----->  生成B和B$; 同样,B是B$的转发,且不可用; B$实现了Serializable接口;


case class C声明后,之所以可以不用new操作符: var c = C(),是因为:
scala的()运算,会转化为调用伴生对象的apply()方法, case class C会为C$生成apply()方法,里面调用了C的构造方法;

之所以说是调用了C$的apply()而不是C的apply(),原因前面也说过, scala层对C这个标识符(即类名)的使用都会转化为java层的C$;


class class C和class C不可同时定义;同理, case object C和object C也不可同时定义;

0 0
原创粉丝点击