有5种显式地创建对象的方式:
1、用new语句创建对象,这是最常用的创建对象的方式。
2、运用反射手段,调用Java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。Class.forName()
3、调用对象的clone()方法。
4、调用ClassLoader类加载器
5、运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法.
下面演示了5种方式创建对象的过程。
package com.youcl.demo; public class Customer implements Cloneable{ private String name; private int age; public Customer() { System.out.println("默认构造"); } public Customer(String name, int age) { this.name = name; this.age = age; System.out.println("参数构造"); } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Customer)) return false; final Customer other = (Customer) o; if (this.name.equals(other.name) && this.age == other.age) return true; else return false; } public String toString() { return "name=" + name + ",age=" + age; } public static void main(String args[]) throws Exception { // 运用反射手段创建Customer对象 Class objClass = Class.forName("com.youcl.demo.Customer"); Customer c1 = (Customer) objClass.newInstance(); // 会调用Customer类的默认构造方法 System.out.println("c1: " + c1); // 打印name=unknown,age=0 // 用new语句创建Customer对象 Customer c2 = new Customer("Tom", 20); System.out.println("c2: " + c2); // 打印name=tom,age=20 // 运用克隆手段创建Customer对象,测试发现要实现Cloneable接口 Customer c3 = (Customer) c2.clone(); // 不会调用Customer类的构造方法 System.out.println("c2==c3 : " + (c2 == c3)); // 打印false System.out.println("c2.equals(c3) : " + c2.equals(c3)); // 打印true System.out.println("c3: " + c3); // 打印name=tom,age=20 } }
以上程序的打印结果如下:
默认构造 c1: name=null,age=0 参数构造 c2: name=Tom,age=20 c2==c3 : false c2.equals(c3) : true c3: name=Tom,age=20
从以上打印结果看出,用new语句或Class对象的newInstance()方法创建Customer对象时,都会执行Customer类的构造方法,而用对象的clone()方法创建Customer对象时,不会执行Customer类的构造方法。(区别)
ClassLoader 类加载器方式
这种方法其实跟Class.forName()有点类似,但有所区别,Class.forName()默认会将类装载到JVM并完成初始化(执行static块并对static变量赋值),而使用loadClass()方式则不会进行初始化。当然,两者在加载完类之后都要通过newInstance()才能创建对象。
package com.youcl.demo; public class TestClass { String msg; void test() { System.out.println("Hello World"); } public static void main(String args[]) throws Exception { TestClass object = (TestClass) TestClass.class.getClassLoader().loadClass("com.youcl.demo.TestClass").newInstance(); object.test(); } }
反序列化方式示例
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class TestClass implements Serializable { String msg; void test() { System.out.println(msg); } public static void main(String args[]) throws Exception { TestClass object = new TestClass(); // 修改对象中的变量值 object.msg = "Hello World"; // 将对象保存成文件 FileOutputStream fos = new FileOutputStream("d://test.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(object); // 从文件读取对象 FileInputStream fis = new FileInputStream("d://test.txt"); ObjectInputStream ois = new ObjectInputStream(fis); TestClass desObject = (TestClass) ois.readObject(); desObject.test(); } } 输出 Hello World
反序列化文件查看示例值
除了以上5种显式地创建对象的方式以外,在程序中还可以隐含地创建对象,包括以下几种情况:
1、对于java命令中的每个命令行参数,Java虚拟机都会创建相应的String对象,并把它们组织到一个String数组中,再把该数组作为参数传给程序入口main(String args[])方法。
2、程序代码中的String类型的直接数对应一个String对象,例如:
String s1="Hello"; String s2="Hello"; //s2和s1引用同一个String对象 String s3=new String("Hello"); System.out.println(s1==s2); //打印true System.out.println(s1==s3); //打印false
执行完以上程序,内存中实际上只有两个String对象,一个是直接数,由Java虚拟机隐含地创建,还有一个通过new语句显式地创建。
3、字符串操作符“+”的运算结果为一个新的String对象。例如:
String s1="H"; String s2=" ello"; String s3=s1+s2; //s3引用一个新的String对象 System.out.println(s3=="Hello"); //打印false System.out.println(s3.equals("Hello")); //打印true
4、当Java虚拟机加载一个类时,会隐含地创建描述这个类的Class实例.
内容总结自开发经验,如有不对之处还请留言指出,感谢!