1:Java创建对象的方式和使用范围
创建方式 | 调用机制 | 使用场景 |
new 关键字创建 | 实例化调用了构造函数 | 对象最通用、常规,简单的方法 适用于任何可通过构造器来实例化对象的地方。 |
Class类的newInstance方法 | 实例化调用了构造函数 | newInstance()是实现IOC、反射、面对接口编程和依赖倒置等技术常用方式,一般用于设计框架 例如spring 框架的 对象实例化等。利用类路径进行对象实例化。 |
Contructor 的 newInstance()方法 | 实例化调用了构造函数 | newInstance()是实现IOC、反射、面对接口编程和依赖倒置等技术常用方式,一般用于设计框架 例如spring 框架的 对象实例化等。利用类路径进行对象实例化。 这种 方式比class 方式用得更多,因为class 方式也是调用contructor构造器。并且这种方式可以是无参和有参都可以,class则 只有一种 无参构造器。 |
clone()方法 | 无构造函数调用 | 如果想创建一个对象新的副本,保持对象初始状态完全相同,但是随后又可以改变新的副本的对象 的属性和值则此时适用 |
deserialization | 无构造函数调用 | 提及反序列化时需要理解序列化,所谓序列化:即将一个对象用一串字符表示。因此,序列化可以看成是为了把对象存储在磁盘上或者是从磁盘上读出来并重建对象而把对象扁平化的一种方式。反序列化是把对象从扁平状态转化成活动对象的相反的步骤。 |
1.1: new 关键字创建
package com;
public class Student {
public static void main(String[] args) {
Book book = new Book();
System.out.println(book.getBookName());
}
}
package com;
public class Book {
private String bookName;
private String bookNum;
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookNum() {
return bookNum;
}
public void setBookNum(String bookNum) {
this.bookNum = bookNum;
}
}
1.2: Class类的newInstance方法 和 Contructor 的 newInstance() 从如下图种 java.lang.reflect可看出
该创建对象使用反射技术,所以一般用于设计框架阶段使用
package com;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Student {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//通过class newIstance() 该对象只能是无参构造器
Book book1 = Book.class.newInstance();
//通过Constructor newIstance 实例化对象 此时该对象可以是无参或者有参都行
Constructor constructor = Book.class.getConstructor();
Book emp3 = (Book) constructor.newInstance();
}
}
1.3: clone()方法创建 需要实现Cloneable 创建对象时效率要高于使用new来创建
package com;
import java.lang.reflect.Constructor;
import java.util.List;
public class Student {
public static void main(String[] args) throws CloneNotSupportedException {
Book book = new Book();
book.setBookName("数学");
book.setBookNum(1);
List<Book> list = new ArrayList<Book>();
for(int i =0 ;i<6;i++){
Book b2 = (Book) book.clone();
b2.setBookNum(i);
list.add(b2);
}
System.out.println(list.toString());
}
}
package com;
public class Book implements Cloneable{
private String bookName;
private Integer bookNum;
public Book(String name) {
this.bookName = name;
if (name.length() != 0) {
bookName = name.substring(0, 1);
bookName += "abc";
}
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public Integer getBookNum() {
return bookNum;
}
public void setBookNum(Integer bookNum) {
this.bookNum = bookNum;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Book{" +
"bookName='" + bookName + '\'' +
", bookNum=" + bookNum +
'}';
}
}
输出结果::::
[Book{bookName='数学', bookNum=0}, Book{bookName='数学', bookNum=1}, Book{bookName='数学', bookNum=2}, Book{bookName='数学', bookNum=3}, Book{bookName='数学', bookNum=4}, Book{bookName='数学', bookNum=5}]
输出哈希值:
460141958
1163157884
1956725890
356573597
1735600054
21685669
1614008253363
clone时间差40
1614008253403
new时间差50
从输出结果可看出 克隆对象具备原有对象的值,但是可以改变原有对象的默写属性 其中地址也不一样。
在某个对象中无构造函数时创建对象 少了没有差异,大于100000时new 效率高,在有参构造器中做操作时
clone效率明显,所以轻量级对象创建使用new 否则其他使用clone()
1.4:deserialization 生成对象
串行化(serialization)是指将一个对象的当前状态转换成字节流(a stream of bytes)的过程,而反串行化(deserialization)则指串行化过程的逆过程,将字节流转换成一个对象,
package com.qxkj;
import java.io.Serializable;
public class Employ implements Serializable {
private static final long serialVersionUID = 1L;
private int age; // will persist
private String name; // will persist
// transient 为Java保留字,告诉JVM以transient宣告的基本型态(primitive type)或物
// 件(object)变量不要序列化,例如敏感性数据像是密码等。
private transient String pwd; // will not persist
public Employ() {
}
public Employ(int age, String name,String pwd) {
this.age = age;
this.name = name;
this.pwd=pwd;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
package com.qxkj;
import java.io.*;
/**
* @author Administrator
* @title: TestSerializable
* @projectName day_test_project
* @description: TODO
* @date 2021/2/22 002223:48
*/
public class TestSerializable {
private static File f = null;
//串行化
public static void serialization() {
f = new File("D://t.m");
try {
if (f.exists())
f.delete();
f.createNewFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Employ p = new Employ(10, "xplq", "123456");
try {
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream(f));
out.writeObject(p);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//反串行化
public static void deserialization() {
if (!f.exists())
return;
try {
ObjectInputStream input = new ObjectInputStream(
new FileInputStream(f.getPath()));
try {
Employ p = (Employ) input.readObject();
System.out.println(p.getName());
System.out.println(p.getAge());
System.out.println(p.getPwd());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//测试
public static void main(String[] args) {
TestSerializable.serialization();
TestSerializable.deserialization();
}
}
输出结果
李四
50
null
数学
密码为null 是因为ransient 为Java保留字,告诉JVM以transient宣告的基本型态(primitive type)或物
// 件(object)变量不要序列化,例如敏感性数据像是密码等。