前几天与同事谈过此事.
显而易见的是使用构造函数,但还有其他方法吗?
在java中创建对象有四种不同的方法:
一.使用new
关键字
这是在java中创建对象的最常用方法.几乎99%的对象都是以这种方式创建的.
MyObject object = new MyObject();
乙.使用Class.forName()
如果我们知道类的名称并且它是否有公共默认构造函数,我们可以用这种方式创建一个对象.
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
Ç.使用clone()
clone()可用于创建现有对象的副本.
MyObject anotherObject = new MyObject(); MyObject object = (MyObject) anotherObject.clone();
d.使用object deserialization
对象反序列化只不过是从序列化形式创建对象.
ObjectInputStream inStream = new ObjectInputStream(anInputStream ); MyObject object = (MyObject) inStream.readObject();
你可以在这里阅读
有各种方法:
通过Class.newInstance
.
通过Constructor.newInstance
.
通过反序列化(使用最派生的非可序列化基类的no-args构造函数).
通过Object.clone
(不调用构造函数).
通过JNI(应该调用构造函数).
通过任何其他方法new
为您调用.
我猜你可以将类加载描述为创建新对象(例如interned String
s).
作为声明中初始化的一部分的文字数组(没有数组的构造函数).
"varargs"(...
)方法调用中的数组(没有数组的构造函数).
非编译时间常量字符串连接(在典型的实现中恰好产生至少四个对象).
导致运行时创建和抛出异常.例如throw null;
或"".toCharArray()[0]
.
当然,哦,原始拳击(除非缓存).
JDK8应该有lambda(基本上是简洁的匿名内部类),它们被隐式转换为对象.
为了完整性(和PaŭloEbermann),new
关键字也有一些语法.
在Java语言中,创建对象的唯一方法是通过调用其构造函数,无论是显式还是隐式.使用反射导致对构造函数方法的调用,反序列化使用反射来调用构造函数,工厂方法将调用包装到构造函数以抽象实际构造,而克隆同样是包装构造函数调用.
是的,您可以使用反射创建对象.例如,String.class.newInstance()
将为您提供一个新的空String对象.
在Java中创建对象有五种不同的方法,
1.使用new
关键字 →构造函数调用
Employee emp1 = new Employee();
2.使用newInstance()
Class
→构造函数的方法调用
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee") .newInstance();
它也可以写成
Employee emp2 = Employee.class.newInstance();
3.使用newInstance()
Constructor
→构造函数的方法调用
Constructorconstructor = Employee.class.getConstructor(); Employee emp3 = constructor.newInstance();
4.使用clone()
方法 →没有构造函数调用
Employee emp4 = (Employee) emp3.clone();
5.使用反序列化 →没有构造函数调用
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj")); Employee emp5 = (Employee) in.readObject();
前三个方法new
关键字都newInstance()
包含构造函数调用,但后来两个克隆和反序列化方法创建对象而不调用构造函数.
所有上述方法都有不同的字节码与它们相关,阅读不同的方式来创建Java中的对象,例如示例和更详细的描述,例如所有这些方法的字节码转换.
然而,人们可以争辩说创建数组或字符串对象也是创建对象的一种方式,但这些事情仅对某些类更具体,并由JVM直接处理,而我们可以使用这5种方式创建任何类的对象.
克隆和反序列化.
你也可以使用
Object myObj = Class.forName("your.cClass").newInstance();
如果您是java新手,应该注意这一点,每个对象都继承自Object
protected native clone clone()抛出CloneNotSupportedException;
此外,您可以将数据反序列化为对象.这不是通过类构造函数!
更新:感谢汤姆在你的评论中指出这一点!迈克尔也进行了实验.
它遍历派生最多的非可序列化超类的构造函数.
当该类没有no-args构造函数时,在反序列化时抛出InvalidClassException.
请参阅Tom的答案以获得对所有情况的完整处理;-)
是否还有其他方法可以在java中创建对象而不使用"new"关键字
有一种对象,它不能由普通的实例创建机制(调用构造函数)构造:数组.数组是用.创建的
A[] array = new A[len];
要么
A[] array = new A[] { value0, value1, value2 };
正如Sean在评论中所说,这在语法上类似于构造函数调用,并且在内部它只是分配和零初始化(或使用显式内容初始化,在第二种情况下)一个内存块,带有一些标头来指示类型和长度.
将参数传递给varargs-method时,也会隐式创建(并填充)数组.
第四种方式
A[] array = (A[]) Array.newInstance(A.class, len);
当然,克隆和反序列化也适用于此.
标准API中有许多方法可以创建数组,但实际上它们都使用这些方法中的一种(或多种).
其他方式,如果我们是详尽无遗的.
在Oracle JVM上是Unsafe.allocateInstance(),它在不调用构造函数的情况下创建实例.
使用字节码操作,你可以添加代码anewarray
,multianewarray
,newarray
或new
.可以使用诸如ASM或BCEL之类的库来添加这些.Oracle的Java附带了一个版本的bcel.同样,这不会调用构造函数,但您可以将构造函数称为单独调用.