通过new创建对象
会创建几个完全不相同的对象
实体类:
package cn.xiaov.creatobject;
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试类
package cn.xiaov.creatobject;
/**
* @ClassName TestByNew
* @Description: 测试通过new产生对象
* @author: RiceBall
* @date: 2020/4/12 17:04
*/
public class TestByNew {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
System.out.println(p1==p2); //false
}
}
通过克隆创建对象
浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制
实现clone方法的步骤
(1)克隆对象实现Cloneable接口
(2)重写Object类中的clone()方法,重写时需要定义成public
(3)在重写方法中,调用super.clone()
浅克隆
实体类:
package cn.xiaov.creatobject;
public class Person implements Cloneable {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:
package cn.xiaov.creatobject;
/**
* @ClassName TestByShallowClone
* @Description: 测试浅克隆产生新的对象
* @author: RiceBall
* @date: 2020/4/12 17:13
*/
public class TestByShallowClone {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("张三", 12);
Person p2 = (Person) p1.clone();
System.out.println(p1 == p2); //false
System.out.println(p2); //Person{name='张三', age=12}
p2.setName("李四");
System.out.println(p1); //Person{name='张三', age=12}
System.out.println(p2); //Person{name='李四', age=12}
}
}
但是这仅仅是局限于浅克隆,当条件改变时,比如Person类增加一个成员变量Car car
package cn.xiaov.creatobject;
public class Car implements Cloneable {
private int high;
private String name;
public Car() {
}
public Car(int high, String name) {
this.high = high;
this.name = name;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Car{" +
"hight=" + high +
", name='" + name + '\'' +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
此时改造后的Person类如下:
package cn.xiaov.creatobject;
public class Person implements Cloneable {
private String name;
private int age;
private Car car;
public Person() {
}
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:
package cn.xiaov.creatobject;
/**
* @ClassName TestByShallowClone
* @Description: 测试浅克隆产生新的对象
* @author: RiceBall
* @date: 2020/4/12 17:13
*/
public class TestByShallowClone {
public static void main(String[] args) throws CloneNotSupportedException {
Car car =new Car(120,"BYD");
Person p1 = new Person("张三", 12,car);
Person p2 = (Person) p1.clone();
System.out.println(p1 == p2); //false
System.out.println(p2); //Person{name='张三', age=12, car=Car{high=120, name='BYD'}}
p2.getCar().setName("Bentley");
System.out.println(p1); //Person{name='张三', age=12, car=Car{high=120, name='Bentley'}}
System.out.println(p2); //Person{name='张三', age=12, car=Car{high=120, name='Bentley'}}
}
}
惊讶的发现:虽然只改变了p2的carName,但是p1的也跟着改变了,这显然不是我们需要的。
从这里就可以引入深克隆了。
深克隆
需要解决上面的问题,必须使用深克隆。
我们只需要在Person中修改clone()就好了,修改成如下:
@Override
public Object clone() throws CloneNotSupportedException {
//return super.clone();
Person obj = null;
obj= (Person)super.clone();
Car car = (Car)obj.getCar().clone();
obj.setCar(car);
return obj;
}
测试类:
package cn.xiaov.creatobject;
/**
* @ClassName TestByShallowClone
* @Description: 测试浅克隆产生新的对象
* @author: RiceBall
* @date: 2020/4/12 17:13
*/
public class TestByShallowClone {
public static void main(String[] args) throws CloneNotSupportedException {
Car car =new Car(120,"BYD");
Person p1 = new Person("张三", 12,car);
Person p2 = (Person) p1.clone();
System.out.println(p1 == p2); //false
System.out.println(p2); //Person{name='张三', age=12, car=Car{high=120, name='BYD'}}
p2.getCar().setName("Bentley");
System.out.println(p1); //Person{name='张三', age=12, car=Car{high=120, name='BYD'}}
System.out.println(p2); //Person{name='张三', age=12, car=Car{high=120, name='Bentley'}}
}
}
这样就是修改p2的car而不会改变p1的car了。
通过序列化和反序列化创建对象
对象必须实现Serializable接口,将对象以流的形式序列化存入文件中,然后反序列化读出,实现克隆对象。
实体类:
package cn.xiaov.creatobject;
import java.io.Serializable;
public class People implements Serializable {
private static final long serialVersionUID = 1276556512891407167L;
private String name;
private Cat cat;
public People() {
}
public People(String name, Cat cat) {
this.name = name;
this.cat = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", cat=" + cat +
'}';
}
}
package cn.xiaov.creatobject;
import java.io.Serializable;
public class Cat implements Serializable {
private static final long serialVersionUID = -3714996400599377283L;
private int height;
private String name;
public Cat() {
}
public Cat(int height, String name) {
this.height = height;
this.name = name;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Cat{" +
"height=" + height +
", name='" + name + '\'' +
'}';
}
}
SerializableUtil工具类:
package cn.xiaov.creatobject;
import java.io.*;
/**
* @ClassName SerializableUtil
* @Description: 序列化和反序列化产生对象的工具类
* @author: RiceBall
* @date: 2020/4/12 18:15
*/
public class SerializableUtil {
private SerializableUtil() {
throw new AssertionError();
}
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bin);
return (T) ois.readObject();
}
}
测试类:
package cn.xiaov.creatobject;
public class TestBySerializable {
public static void main(String[] args) throws Exception {
Cat cat = new Cat(12, "小花");
People p1 = new People("张三", cat);
People p2 = SerializableUtil.clone(p1);
System.out.println(p1==p2); //false
System.out.println(p2); //People{name='张三', cat=Cat{height=12, name='小花'}}
p2.getCat().setName("小红");
System.out.println(p1); //People{name='张三', cat=Cat{height=12, name='小花'}}
System.out.println(p2); //People{name='张三', cat=Cat{height=12, name='小红'}}
}
}
通过反射产生对象
实体类使用上面的People和Cat
测试类如下:
package cn.xiaov.creatobject;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @ClassName TestByReflection
* @Description: 测试通过反射创建对象
* @author: RiceBall
* @date: 2020/4/12 19:42
*/
public class TestByReflection {
public static void main(String[] args) throws ClassNotFoundException,
IllegalAccessException, InstantiationException, NoSuchMethodException,
InvocationTargetException {
Cat cat = new Cat(12, "小花");
Class<?> c = Class.forName("cn.xiaov.creatobject.People");
//直接使用newInstance()方法创建对象 调用无参构造
People p1 = (People) c.getDeclaredConstructor().newInstance();
//p1.setName("张三");
//p1.setCat(cat);
//通过反射调用普通方法
Method setName = c.getDeclaredMethod("setName", String.class);
Method setCat = c.getDeclaredMethod("setCat", Cat.class);
setName.invoke(p1, "王五");
setCat.invoke(p1, cat);
System.out.println(p1); //People{name='王五', cat=Cat{height=12, name='小花'}}
//通过有参构造器创建对象
Constructor<?> constructor = c.getDeclaredConstructor(String.class, Cat.class);
People p2 = (People) constructor.newInstance("李四", cat);
System.out.println(p2); //People{name='李四', cat=Cat{height=12, name='小花'}}
}
}
备注:
Java9之后,newInstance()方法过时,改用:
//被废弃的方法
//aClass.newInstance()
//更新后的使用
aClass.getDeclaredConstructor().newInstance();