Java创建对象的5种方式
哔哩哔哩链接:https://www.bilibili.com/video/BV1Bu411U7Ya?spm_id_from=333.999.0.0&vd_source=7c5f1f4c039688f19024d50ef51aaed1
1.Student类
static class Student implements Serializable, Cloneable {
private String id;
private String name;
private Integer age;
public Student() {
}
public Student(String id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
2.java创建对象的5种方式
// java创建对象的5种方式
@Test
public void createObject() {
System.out.println(createStudent01());
System.out.println(createStudent02());
System.out.println(createStudent03());
System.out.println(createStudent04());
System.out.println(createStudent05());
}
// 1.通过new xxx()调用构造方法创建对象
private Student createStudent01() {
return new Student(UUID.randomUUID().toString(), "zhangsan", 20);
}
// 2.通过反射,调用xxx.getClass().newInstance()创建对象
private Student createStudent02() {
try {
// 得到一个空的对象
Student student = Student.class.newInstance();
student.setId(UUID.randomUUID().toString());
student.setName("lisi");
student.setAge(22);
return student;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
// 3.通过反射,调用construct.newInstance()创建对象
private Student createStudent03() {
// 获取Student类对应的class字节码对象
Class<Student> studentClass = Student.class;
Constructor<Student> constructor = null;
try {
// 获取Student类中有参构造方法
constructor = studentClass.getConstructor(String.class, String.class, Integer.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Student wanwu = null;
try {
// 创建对象
wanwu = constructor.newInstance(UUID.randomUUID().toString(), "wanwu", 25);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return wanwu;
}
// 4.通过xxx.clone()克隆方式创建(需要实现Cloneable接口,重写clone方法)
public Student createStudent04(){
Student student = new Student(UUID.randomUUID().toString(), "zhaoliu", 26);
try {
Student clone = (Student)student.clone();
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
// 5.通过序列化,反序列化创建对象(需要实现Serializable接口)
public Student createStudent05(){
Student student = new Student(UUID.randomUUID().toString(), "tianqi", 27);
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("E:\\student.txt"));
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("E:\\student.txt"));
// 调用输出流将student对象序列化到E:\student.txt
objectOutputStream.writeObject(student);
// 从E:\student.txt文件中反序列化出student对象
Student object = (Student)objectInputStream.readObject();
return object;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
3.浅克隆与深克隆
哔哩哔哩链接:https://www.bilibili.com/video/BV1Sa41127pU?spm_id_from=333.999.0.0&vd_source=7c5f1f4c039688f19024d50ef51aaed1
3.1.浅克隆
Teacher
package com.bilibili.juc.clone;
public class Teacher {
private Integer pkid;
private String name;
public Teacher() {
}
public Teacher(Integer pkid, String name) {
this.pkid = pkid;
this.name = name;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"pkid=" + pkid +
", name='" + name + '\'' +
'}';
}
}
Student
package com.bilibili.juc.clone;
public class Student implements Cloneable{
private double weight;
private Integer pkid;
private String name;
// 持有一个教师对象的引用
private Teacher teacher;
public Student(double weight, Integer pkid, String name, Teacher teacher) {
this.weight = weight;
this.pkid = pkid;
this.name = name;
this.teacher = teacher;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"weight=" + weight +
", pkid=" + pkid +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
浅克隆测试
// 浅拷贝演示
@org.junit.jupiter.api.Test
public void qianTest() throws CloneNotSupportedException {
Teacher teacher = new Teacher(1, "黄老师");
// 浅拷贝之前的对象
Student student = new Student(50.00, 1, "张三", teacher);
// 浅拷贝之后的对象
Student student1 = (Student) student.clone();
System.out.println(student == student1);
System.out.println(student.getTeacher() == student1.getTeacher());
System.out.println("浅拷贝前teacher的hashcode:" + student.getTeacher().hashCode());
System.out.println("浅拷贝后teacher新对象的hashcode:" + student1.getTeacher().hashCode());
System.out.println("克隆之前student学生的老师:" + student.getTeacher().getName());
// 将克隆后的对象student1的老师姓名改为张老师,导致旧student的老师姓名也被修改
student1.getTeacher().setName("张老师");
System.out.println("克隆之前的student学生:" + student);
System.out.println("克隆之后的student1学生:" + student1);
}
3.2.深克隆
Teacher2
package com.bilibili.juc.clone;
public class Teacher2 implements Cloneable{
private Integer pkid;
private String name;
public Teacher2() {
}
public Teacher2(Integer pkid, String name) {
this.pkid = pkid;
this.name = name;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"pkid=" + pkid +
", name='" + name + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Student2
package com.bilibili.juc.clone;
public class Student2 implements Cloneable{
private double weight;
private Integer pkid;
private String name;
// 持有一个教师对象的引用
private Teacher2 teacher;
public Student2(double weight, Integer pkid, String name, Teacher2 teacher) {
this.weight = weight;
this.pkid = pkid;
this.name = name;
this.teacher = teacher;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher2 getTeacher() {
return teacher;
}
public void setTeacher(Teacher2 teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"weight=" + weight +
", pkid=" + pkid +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
Student2 student = null;
student = (Student2) super.clone();
// 拷贝teacher对象
student.teacher = (Teacher2)this.teacher.clone();
return student;
}
}
深克隆测试
// 深拷贝演示
@org.junit.jupiter.api.Test
public void shenTest() throws CloneNotSupportedException {
Teacher2 teacher = new Teacher2(1, "黄老师");
// 深拷贝之前的对象
Student2 student = new Student2(50.00, 1, "张三", teacher);
// 深拷贝之后的对象
Student2 student1 = (Student2) student.clone();
System.out.println(student == student1);
System.out.println(student.getTeacher() == student1.getTeacher());
System.out.println("深拷贝前teacher的hashcode:" + student.getTeacher().hashCode());
System.out.println("深拷贝后teacher新对象的hashcode:" + student1.getTeacher().hashCode());
System.out.println("克隆之前student学生的老师:" + student.getTeacher().getName());
// 将克隆后的对象student1的老师姓名改为张老师,因为是深拷贝,旧student的老师姓名不会被修改
student1.getTeacher().setName("张老师");
System.out.println("克隆之前的student学生:" + student);
System.out.println("克隆之后的student1学生:" + student1);
}
3.3.通过序列化实现深克隆
Teacher3
package com.bilibili.juc.clone;
import java.io.Serializable;
public class Teacher3 implements Serializable {
private Integer pkid;
private String name;
public Teacher3() {
}
public Teacher3(Integer pkid, String name) {
this.pkid = pkid;
this.name = name;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Teacher{" +
"pkid=" + pkid +
", name='" + name + '\'' +
'}';
}
}
Student3
package com.bilibili.juc.clone;
import java.io.*;
public class Student3 implements Serializable {
private double weight;
private Integer pkid;
private String name;
// 持有一个教师对象的引用
private Teacher3 teacher;
public Student3(double weight, Integer pkid, String name, Teacher3 teacher) {
this.weight = weight;
this.pkid = pkid;
this.name = name;
this.teacher = teacher;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
public Integer getPkid() {
return pkid;
}
public void setPkid(Integer pkid) {
this.pkid = pkid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Teacher3 getTeacher() {
return teacher;
}
public void setTeacher(Teacher3 teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Student{" +
"weight=" + weight +
", pkid=" + pkid +
", name='" + name + '\'' +
", teacher=" + teacher +
'}';
}
// 通过序列化实现深拷贝
public Student3 deepCloneBySerializable() {
Student3 student = null;
ByteArrayOutputStream byteArrayOutputStream = null;
ObjectOutputStream objectOutputStream = null;
ByteArrayInputStream byteArrayInputStream = null;
ObjectInputStream objectInputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);//对象序列化
objectOutputStream.writeObject(this);
byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
objectInputStream = new ObjectInputStream(byteArrayInputStream);
//对象的反序列化
student = (Student3) objectInputStream.readObject();
return student;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (null != objectInputStream) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != byteArrayInputStream) {
try {
byteArrayInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != objectOutputStream) {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != byteArrayOutputStream) {
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
通过序列化实现深克隆测试
@org.junit.jupiter.api.Test
public void searilizableTest() throws CloneNotSupportedException {
Teacher3 teacher = new Teacher3(1, "黄老师");
// 深拷贝之前的对象
Student3 student = new Student3(50.00, 1, "张三", teacher);
// 深拷贝之后的对象
Student3 student1 = (Student3) student.deepCloneBySerializable();
System.out.println(student == student1);
System.out.println(student.getTeacher() == student1.getTeacher());
System.out.println("深拷贝前teacher的hashcode:" + student.getTeacher().hashCode());
System.out.println("深拷贝后teacher新对象的hashcode:" + student1.getTeacher().hashCode());
System.out.println("克隆之前student学生的老师:" + student.getTeacher().getName());
// 将克隆后的对象student1的老师姓名改为张老师,因为是深拷贝,旧student的老师姓名不会被修改
student1.getTeacher().setName("张老师");
System.out.println("克隆之前的student学生:" + student);
System.out.println("克隆之后的student1学生:" + student1);
}
3.4 不实现深克隆
Attachment:
package com.bilibili.juc.sheng;
import java.io.Serializable;
public class Attachment implements Serializable {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
YuelyLog :
package com.bilibili.juc.sheng;
import java.io.Serializable;
public class YuelyLog implements Serializable,Cloneable {
private Attachment attachment;
private String name;
private String date;
@Override
protected YuelyLog clone() throws CloneNotSupportedException {
return (YuelyLog)super.clone();
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
ShengTest :
package com.bilibili.juc.sheng;
import java.io.IOException;
import java.util.Date;
public class ShengTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
Attachment attachment = new Attachment();
attachment.setName("wj");
YuelyLog yuelyLog = new YuelyLog();
yuelyLog.setAttachment(attachment);
yuelyLog.setDate(new Date().toString());
yuelyLog.setName("dn");
System.out.println("yelyLog:name="+(yuelyLog.getAttachment().getName()));
YuelyLog clone = yuelyLog.clone();
clone.getAttachment().setName("clone");
System.out.println("yelyLog:name="+(yuelyLog.getAttachment().getName()));
}
}
输出结果:
yelyLog:name=wj
yelyLog:name=clone
说明在修改浅拷贝队形的同时原对象也发生了变化,这是一种非常危险的事情,如果处理不当,对全局性的变量或者原对象进项操作会引起大bug
其实我们拷贝一个对象就是希望他是独立的,可操作的,不会因为修改他而引起原对象发生变化。
通过序列化实现深拷贝
public class YuelyLog implements Serializable,Cloneable {
private Attachment attachment;
private String name;
private String date;
@Override
protected YuelyLog clone() throws CloneNotSupportedException {
return (YuelyLog)super.clone();
}
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
/**
* 使用序列化技术实现深拷贝
* @return
*/
public YuelyLog deepClone() throws IOException,ClassNotFoundException{
//将对象写入流中
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
//从流中取出
ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
return (YuelyLog)objectInputStream.readObject();
}
}
之后将YuelyLog clone = yuelyLog.clone();改为YuelyLog clone = yuelyLog.deepClone();
代码如下:
package com.bilibili.juc.sheng;
import java.io.IOException;
import java.util.Date;
public class ShengTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, CloneNotSupportedException {
Attachment attachment = new Attachment();
attachment.setName("wj");
YuelyLog yuelyLog = new YuelyLog();
yuelyLog.setAttachment(attachment);
yuelyLog.setDate(new Date().toString());
yuelyLog.setName("dn");
System.out.println("yelyLog:name="+(yuelyLog.getAttachment().getName()));
YuelyLog clone = yuelyLog.deepClone();
clone.getAttachment().setName("clone");
System.out.println("yelyLog:name="+(yuelyLog.getAttachment().getName()));
}
}
输出结果:
yelyLog:name=wj
yelyLog:name=wj
在这里强调一点,当然如果你能保证在拷贝对象后,你只是对拷贝对象成员变量为基本类型和String类型进行操作,可以使用浅拷贝,像对复杂对象操作,我们一般使用深拷贝,或者对非基本类型单独实现拷贝进行修改。业务中灵活掌握。
4.方法重载和重写的区别
哔哩哔哩链接:https://www.bilibili.com/video/BV1sS4y1j7tX?spm_id_from=333.999.0.0&vd_source=7c5f1f4c039688f19024d50ef51aaed1
5.String s = new String(“abc”)创建了几个对象
public class NewString {
public static void main(String[] args) {
// 在方法执行过程中,根据字节码指令,往栈里写入数据或提取数据,即入栈/出栈。某些字节码指令把值压入操作数栈,其余指令将操作数取出栈。
// 1.在字符串常量池中创建了一个“abc”的字符串常量
// 2.把字符串常量“abc”的值压入到操作数栈中
// 3.把栈中的元素存入到局部变量表索引为1的位置
// 4.方法返回
String abc = "abc";
}
}
public class NewString {
public static void main(String[] args) {
// 1.创建一个新的实例
// 2.复制栈中的元素并把复制的值压入到操作数栈中
// 3.在字符串常量池中创建了一个“abc”的字符串常量
// 4.把字符串常量“abc”的值压入到操作数栈中
// 5.调用String构造方法,
// 6.把栈中的元素存入到局部变量表索引为1的位置
// 7.方法返回
String abc = new String("abc");
}
}
public class NewString {
public static void main(String[] args) {
// 1.在字符串常量池中创建了一个“abc”的字符串常量
// 2.把栈中的元素存入到局部变量表索引为1的位置
// 3.创建一个新的实例
// 4.复制栈中的元素并把复制的值压入到操作数栈中
// 5.由于之前已经创建了“abc”字符串常量池,即“abc”已经在字符串常量池中存在,直接获取#2(abc在字符串常量池中)的地址
// 6.调用String构造方法
// 7.把栈中的元素存入到局部变量表索引为2的位置
// 8.方法返回
String ABC = "abc";
String abc = new String("abc");
}
}
喜欢请关注我
至此,我们的Java创建对象的5种方式以及浅克隆与深克隆的区别
就讲解完成了。喜欢我的话可以关注我的微信公众号我爱学习呀嘻嘻
,不定期分享各类资源哦。