创建和销毁对象——遇到多个构造器参数时考虑使用构建器
参考资料:《Effective Java》、https://blog.csdn.net/zxd1435513775/article/details/83016670、https://www.jianshu.com/p/e3832c06e32c
基础回顾
1.重叠构造器是什么?
当一个类中有很多成员变量,不同的变量组成不同功能的构造器。这时候就可以使用重叠构造器。
如下代码:
public class EJ01_02 { private String Name; private int Age; private double Height; private String Gender; private int Year; //这个构造器只需要Name、Age参数 public EJ01_02(String Name,int Age){ this.Name=Name; this.Age=Age; } //这个构造器只需要Name、Height参数 public EJ01_02(String Name,double Height){ this.Name=Name; this.Height=Height; } //这个构造器只需要Name、Height、Year参数 public EJ01_02(String Name,String Gender,int Year){ this.Name=Name; this.Gender=Gender; this.Year=Year; } //这个构造器需要所有参数 public EJ01_02(String Name,int Age,double Height,String Gender,int Year){ this.Name=Name; this.Age=Age; this.Height=Height; this.Gender=Gender; this.Year=Year; } }
上面这段代码只有五个参数,而且还没写出所有组合就看上去有点多余。如果参数多起来,代码看上去可以说是非常糟糕。
而且组合多了后,一些类型相同的参数,如果顺序不对的话编译器并不会报错,但是运行时可能出现不可预估的错误。
下面要说到的构建器很好的解决了这个问题。
2.JavaBeans模式是什么?
当有多个可选的构造器参数除了上面的方法外,还有第二个方法,就是JavaBeans模式。
在这种模式下,先调用一个无参构造器来创建对象,然后调用setter方法来设置开发者需要用到的参数。
代码如下:
class JavaBeans_Demo { private String Name; private int Age; private double Height; private String Gender; private int Year; //无参构造器 public JavaBeans_Demo(){ } //Setters public void setName(String val){Name=val;} public void setAge(int val){Age=val;} public void setHeight(double val){Height=val;} public void setGender(String val){Gender=val;} public void setYear(int val){Year=val;} }
class EJ01_02_Test{ public static void main(String args[]){ //创建对象 JavaBeans_Demo jb=new JavaBeans_Demo(); //设置需要的参数 jb.setName("张三"); jb.setAge(18); jb.setGender("女"); } }
虽然上面的代码看上去比第一种更灵活,但是在构造过程中可能处于不一致的状态。
比如:两个线程同时对jb对象进行操作,可能A线程还没赋值完毕,B线程就开始获取属性,或者甚至两个线程的都进行赋值操作,后赋值的会覆盖前面的设置。
为了避免上面的情况发生,开发者还得确保它们的线程安全。
构建器——建造者(Builder)模式
首先看下面的代码:
class JavaBuilder_Demo { private String Name; private int Age; private double Height; private String Gender; private int Year; public JavaBuilder_Demo(Builder builder) { Name=builder.Name; Age=builder.Age; Height=builder.Height; Gender=builder.Gender; Year=builder.Year; } //静态内部类 public static class Builder{ private String Name; private int Age; private double Height; private String Gender; private int Year; public Builder name(String val){ Name=val; return this; } public Builder age(int val){ Age=val; return this; } public Builder height(double val){ Height=val; return this; } public Builder Gender(String val){ Gender=val; return this; } public Builder Year(int val){ Year=val; return this; } public JavaBuilder_Demo build(){ return new JavaBuilder_Demo(this); } } }
class EJ01_02_Test2{ public static void main(String args[]){ //创建对象并在创建对象时就设置了参数,这样就不会出不一致的问题 JavaBuilder_Demo jb=new JavaBuilder_Demo.Builder().name("张三").age(18).Gender("女").build(); } }
上面代码中,有几个要点:
1.需要写一个静态的内部类,在调用的时候,静态内部类里的构造器可以设置必须的参数。
2.return this的意思是返回实际调用这个方法的实例化对象。
3.为什么需要静态内部类,因为可以创建对象的时候就可以选择性的选择自己需要用到的属性,而不用在创建完对象后类似JavaBeans那样去设置属性值。