结论
case class
又称样例类,可用于DTO(序列化特性),模式匹配(unapply特性).
作为一种语法糖,在定义之后会隐式获得很多经典的方法.
1. case class与case object
无参数时,使用case object
;
有参数时,使用case class
.case object
比参数为()
的case class
少apply
和unapply
方法.
2. 类参数
类参数默认作为private final
的类成员.
同时自动生成一个同名public
方法以获取它的值.
3. 伴生对象
apply
方法和unapply
方法:case class
会自动生成一个伴生对象(object
),作为当前作用域的一个单例,同时在里面实现了apply
方法,可以使用apply
方法或者括号函数()
创建对象.(也可以依旧使用new
关键字)
由于有unapply
方法实现,因此可以用于模式匹配.
4. 序列化特性
详情
1. 用IDE查看class文件
假如写这么一个scala文件:
1 | package learn |
编译后生成的class文件会有两个:
1 | TestCaseClass$.class |
用IDE打开TestCaseClass.class
是:
1 | package learn |
可见定义case class
后,自动会继承AnyRef
,加上Product
和Serializable
的trait
.
另一个内部类文件TestCaseClass$.class
虽然用ide打开为空,但看文件大小1180,可见并不是空文件.
2. 反编译
使用javap -p -c -s TestCaseClass.class
查看,过滤掉看不懂的部分和常量池里的各种符号引用,大致能发现如下内容:
类签名
1
public class learn.TestCaseClass implements scala.Product,scala.Serializable
可见本质上是实现Product和Serializable的接口.(加上默认实现)
方法:
1
2
3
4
5
6
7
8
9
10
11
12public static boolean unapply(learn.TestCaseClass);
public static learn.TestCaseClass apply();
public learn.TestCaseClass copy();
public java.lang.String productPrefix();
public int productArity();
public java.lang.Object productElement(int);
public scala.collection.Iterator<java.lang.Object> productIterator();
public boolean canEqual(java.lang.Object);
public int hashCode();
public java.lang.String toString();
public boolean equals(java.lang.Object);
public learn.TestCaseClass();注意到
unapply
和apply
方法是static
的,说明会自动生成一个伴生对象,并添加这两个方法.(static
方法在object
里)
反编译内部类:
- 类签名:可见
1
public final class learn.TestCaseClass$ extends scala.runtime.AbstractFunction0<learn.TestCaseClass> implements scala.Serializable
case class
其实也是作为一个Function
存在的,如果把源码改动一下加上参数:1
2package learn
case class TestCaseClass(xyz:String)
则这里的类签名变为:
1 | public final class learn.TestCaseClass$ extends scala.runtime.AbstractFunction1<java.lang.String, learn.TestCaseClass> implements scala.Serializable |
此外由于类参数没有加限定,默认变成了val
,因此类参数是private final
的:
1 | private final java.lang.String xyz |
其中AbstractFuction
是一个抽象类,源码为:
1 | abstract class AbstractFunction0[@specialized(Specializable.Primitives) +R] extends Function0[R] {} |
- 方法签名:
1
2
3
4
5public static {};// 3: invokespecial #15 // Method "<init>":()V
public final java.lang.String toString();
public learn.TestCaseClass apply();
public boolean unapply(learn.TestCaseClass);
public java.lang.Object apply();