public class CloneableTest implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
public static void main(String[] args) throws CloneNotSupportedException { CloneableTest c1 = new CloneableTest(); CloneableTest c2 = (CloneableTest) c1.clone(); } }
运行后没有报错。现在把 implements Cloneable 去掉。
1 2 3 4 5 6 7 8 9 10 11 12
public class CloneableTest { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
public static void main(String[] args) throws CloneNotSupportedException { CloneableTest c1 = new CloneableTest(); CloneableTest c2 = (CloneableTest) c1.clone();
} }
运行后抛出 CloneNotSupportedException:
1 2 3 4
Exception in thread "main" java.lang.CloneNotSupportedException: com.cmower.baeldung.interface1.CloneableTest at java.base/java.lang.Object.clone(Native Method) at com.cmower.baeldung.interface1.CloneableTest.clone(CloneableTest.java:6) at com.cmower.baeldung.interface1.CloneableTest.main(CloneableTest.java:11)
Writer writer = new Writer(); System.out.println(writer.toString());
输出结果如下所示:
1
Writer{name='null', age=0}
name 是字符串类型,所以默认值为 null,age 为 int 类型,所以默认值为 0。
让我们为 Writer 类主动加一个无参的构造方法:
1 2 3 4
public Writer() { this.name = ""; this.age = 0; }
构造方法也是一个方法,只不过它没有返回值,默认返回创建对象的类型。需要注意的是,当前构造方法没有参数,它被称为无参构造方法。如果我们没有主动创建无参构造方法的话,编译器会隐式地自动添加一个无参的构造方法。这就是为什么,一开始虽然没有构造方法,却可以使用 new Writer() 创建对象的原因,只不过,所有的字段都被初始化成了默认值。
接下来,让我们添加一个有参的构造方法:
1 2 3 4
public Writer(String name, int age) { this.name = name; this.age = age; }
现在,我们创建 Writer 对象的时候就可以通过对字段值初始化值了。
1 2
Writer writer1 = new Writer("沉默王二",18); System.out.println(writer1.toString());
来看一下打印结果:
1
Writer{name='沉默王二', age=18}
可以根据字段的数量添加不同参数数量的构造方法,比如说,我们可以单独为 name 字段添加一个构造方法:
1 2 3
public Writer(String name) { this.name = name; }
为了能够兼顾 age 字段,我们可以通过 this 关键字调用其他的构造方法:
1 2 3
public Writer(String name) { this(name,18); }
把作者的年龄都默认初始化为 18。如果需要使用父类的构造方法,还可以使用 super 关键字,手册后面有详细的介绍。
没错,就是多出来的那个 public Pig() {},参数是空的,方法体是空的。我们可以通过 new 关键字利用这个构造方法来创建一个对象,代码如下所示:
Pig pig = new Pig(); 当然了,我们也可以主动添加带参的构造方法。
1 2 3 4 5 6 7 8 9 10 11
public class Pig { private String color;
public Pig(String color) { this.color = color; }
public void eat() { System.out.println("吃"); } }
这时候,再查看反编译后的字节码时,你会发现缺省的无参构造方法消失了——和源代码一模一样。
1 2 3 4 5 6 7 8 9 10 11
public class Pig { private String color;
public Pig(String color) { this.color = color; }
public void eat() { System.out.println("吃"); } }
这意味着无法通过 new Pig() 来创建对象了——编译器会提醒你追加参数。
比如说你将代码修改为 new Pig(“纯白色”),或者添加无参的构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public class Pig { private String color;
public Pig(String color) { this.color = color; }
public Pig() { }
public void eat() { System.out.println("吃"); } }
使用无参构造方法创建的对象状态默认值为 null(color 字符串为引用类型),如果是基本类型的话,默认值为对应基本类型的默认值,比如说 int 为 0,更详细的见下图。
(图片中有一处错误,boolean 的默认值为 false)
接下来,我们来创建多个 Pig 对象,它的颜色各不相同。
1 2 3 4 5 6 7
public class PigTest { public static void main(String[] args) { Pig pigNoColor = new Pig(); Pig pigWhite = new Pig("纯白色"); Pig pigBlack = new Pig("纯黑色"); } }