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接口;
scala的()运算,会转化为调用伴生对象的apply()方法, case class C会为C$生成apply()方法,里面调用了C的构造方法;
之所以说是调用了C$的apply()而不是C的apply(),原因前面也说过, scala层对C这个标识符(即类名)的使用都会转化为java层的C$;