scala case 之类与对象

简介

本文主要介绍case class与普通class的一些区别。以及case classcase object的异同点。

case classclass的区别

Person.scala源码,运行后生成Person$.classPerson.class两个文件。

1
2
3
4
5
6
7
8
case class Person(age:Int, name:String)

object Person {
def main(args: Array[String]): Unit = {
val person = Person(25,"stm")
println(person.toString)
}
}

Person.class反编译如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import scala.Function1;
import scala.Option;
import scala.Product;

package com.stm.datastructures.caseClass;

class;
import scala.Serializable;
import scala.Tuple2;
import scala.collection.Iterator;
import scala.reflect.ScalaSignature;
import scala.runtime.BoxesRunTime;
import scala.runtime.ScalaRunTime.;
import scala.runtime.Statics;

@ScalaSignature
public class Person
implements Product, Serializable {
private final int age;
private final String name;

public Person(int age, String name) {
Product.class.$init$(this);
}

public boolean equals(Object x$1) {
if (this != x$1) {
Object localObject = x$1;
int i;
if ((localObject instanceof Person)) {
i = 1;
} else {
i = 0;
}
if (i == 0) {
break label96;
}
Person localPerson = (Person) x$1;
if (age() == localPerson.age()) {
str = localPerson.name();
String tmp54_44 = name();
if (tmp54_44 == null) {
tmp54_44;
if (str == null) {
break label75;
}
tmpTernaryOp = tmp54_44;
break label88;
}
}
}
}

public String toString() {
return ScalaRunTime..MODULE$._toString(this);
}

public int hashCode() {
int i = -889275714;
i = Statics.mix(i, age());
i = Statics.mix(i, Statics.anyHash(name()));
return Statics.finalizeHash(i, 2);
}

public boolean canEqual(Object x$1) {
return x$1 instanceof Person;
}

public Iterator<Object> productIterator() {
return ScalaRunTime..MODULE$.typedProductIterator(this);
}

public Object productElement(int x$1) {
int i = x$1;
switch (i) {
default:
throw new IndexOutOfBoundsException(BoxesRunTime.boxToInteger(x$1).toString());
case 1:
break;
}
return BoxesRunTime.boxToInteger(age());
}

public int productArity() {
return 2;
}

public String productPrefix() {
return "Person";
}

public String copy$default$2() {
return name();
}

public int copy$default$1() {
return age();
}

public Person copy(int age, String name) {
return new Person(age, name);
}

public String name() {
return this.name;
}

public int age() {
return this.age;
}

public static Function1<Object, Function1<String, Person>> curried() {
return Person..MODULE$.curried();
}

public static Function1<Tuple2<Object, String>, Person> tupled() {
return Person..MODULE$.tupled();
}

public static Person apply(int paramInt, String paramString) {
return Person..MODULE$.apply(paramInt, paramString);
}

public static Option<Tuple2<Object, String>> unapply(Person paramPerson) {
return Person..MODULE$.unapply(paramPerson);
}
}

Person$.class编译如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import scala.Option;
import scala.Serializable;
import scala.Some;
import scala.Tuple2;
import scala.runtime.AbstractFunction2;
import scala.runtime.BoxesRunTime;

public final class Person$
extends AbstractFunction2<Object, String, Person>
implements Serializable {
public static final MODULE$;

private Person$() {
MODULE$ = this;
}

private Object readResolve() {
return MODULE$;
}

public Option<Tuple2<Object, String>> unapply(Person x$0) {
return x$0 == null ? None..MODULE$:
new Some(new Tuple2(BoxesRunTime.boxToInteger(x$0.age()), x$0.name()));
}

public Person apply(int age, String name) {
return new Person(age, name);
}

public final String toString() {
return "Person";
}

static {
new ();
}
}

Student.scala源码,运行后生成Student$.classStudent.class两个文件。

1
2
3
4
5
6
7
8
class Student(val age:Int, val name:String){}

object Student{
def main(args: Array[String]): Unit = {
val stu = new Student(25, "stm")
println(stu)
}
}

Student.class反编译如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import scala.reflect.ScalaSignature;

@ScalaSignature
public class Student {
private final int age;
private final String name;

public Student(int age, String name) {
}

public String name() {
return this.name;
}

public int age() {
return this.age;
}

public static void main(String[] paramArrayOfString) {
Student..MODULE$.main(paramArrayOfString);
}
}

Student$.class反编译如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import scala.Predef.;

public final class Student$ {
public static final MODULE$;

static {
new ();
}

public void main(String[] args) {
Student stu = new Student(25, "stm");
Predef..MODULE$.println(stu);
}

private Student$() {
MODULE$ = this;
}
}

从编译结果,可以看出一下几点:

  1. 生成了apply方法,可以直接把对象当做方法使用。

    1
    val person = Person(25,"stm")
  2. 继承了ProductSerializable

  3. agename是用final修饰的。
  4. 默认实现了toString
  5. 实现了name()age()方法。(参数列表中的参数都隐式获得一个val作为前缀)

    1
    2
    println(person1.age) //25
    println(person1.name) //stm
  6. 重写了equals方法,比较structure而不是reference:

    1
    2
    3
    val person1 = Person(25, "stm")
    val person2 = Person(25, "stm")
    println(person1 == person2) //true

case objectcase class区别

  1. case object反编译后没有applyunapply方法,因为caes object没有参数。

总结

  1. case classcase object本质没区别,有参使用case class,无参使用case object;
  2. case classcase object增加了继承和方法。
  3. case classcase object支持模式匹配。