本文为《Java Coding Problems》49-57题,问题涉及Objects, Immutability, and Switch Expressions (共18题 40-57)。
问题:写一个不可变的类
思路:
不可变类的几个要点:
final
标注,防止继承。private final
的,只在构造器中初始化一次。public
的包含所有字段的构造器,或者提供一个工厂方法。getter
方法。setter
方法。代码如下:
public final class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
}
问题:如果不可变类包含一个可变的对象,那如何保持类的不可变性?
思路:在构造方法和可变对象的getter
中进行对象拷贝。
代码如下:
// 这是个可变对象
class Radius {
int start;
int end;
}
public final class Point {
private final double x;
private final double y;
// 这是个可变对象的字段
private final Radius radius;
private Radius cloneRadius(Radius radius) {
Radius clone = new Radius();
clone.start = radius.start;
clone.end = radius.end;
return clone;
}
public Point(double x, double y, Radius radius) {
this.x = x;
this.y = y;
// 在构造不可变对象的时候,复制这个可变对象
this.radius = cloneRadius(radius);
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public Radius getRadius() {
// 在返回可变对象的时候,复制可变对象
return cloneRadius(radius);
}
}
问题:当类的字段特别多时,且部分字段可选,提供一个全字段构造器不太方便,使用Builder模式更加合理。
代码如下:
public final class Point {
private final double x;
private final double y;
private final String description;
private Point(PointBuilder pointBuilder) {
this.x = pointBuilder.getX();
this.y = pointBuilder.getY();
this.description = pointBuilder.getDescription();
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public String getDescription() {
return description;
}
public static final class PointBuilder {
private final double x;
private final double y;
// description是可选的
private String description;
public PointBuilder(double x, double y) {
this.x = x;
this.y = y;
}
public PointBuilder description(String description) {
this.description = description;
return this;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public String getDescription() {
return description;
}
public Point build() {
return new Point(this);
}
}
}
问题:不可变对象初始化后就不能再改变了,所以需要防止错误的初始化。
思路:JSR 380
使得可以通过注解进行字段校验。Hibernate Validator提供了一些annotations,比如@NotNull
, @Min
, @Max
, @Size
, @Email
。在创建不可变对象的时候进行校验,如果校验失败,则初始化失败。
问题:如何复制一个对象。
思路:复制对象有很多种方式,例如:
new
一个新对象,把字段拷贝过去。Cloneable
接口,重写clone()
方法(记得调用super.clone()
)。C++
中的复制构造函数。clone
库,如Cloner
。toString
问题:为什么要重写toString
方法,如何合理的重写?
思路:toString
方法在打印一个对象时被调用,是debug
,记录log
时不可缺少的方法。但由于toString
方法的默认实现只是返回对象的hashCode
,不利于对象展示,所以需要重写。
一般而言,toString
应包含对象的所有字段,但要注意剔除敏感数据,比如用户密码等。
问题:JDK12
提供了Switch
表达式。
思路:略。
问题:JDK12
允许Switch
语句中一个case有多个选项。
思路:略
问题:JDK12
提供了Switch
表达式,其每一个case都可以返回一个值,case后面可以是语句块。
思路:略。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。