case class, object的底层实现

本文深入探讨Scala中class、object及caseclass之间的关系与转换原理,解析这些元素如何在Java中实现,包括单例模式、成员变量处理及方法调用等关键细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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也不可同时定义;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值