Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中创建对象有哪些不同的方法?_Java - Fatal编程技术网

在Java中创建对象有哪些不同的方法?

在Java中创建对象有哪些不同的方法?,java,Java,前几天我和一个同事谈过这件事 使用构造函数是显而易见的,但是还有什么其他方法呢?和。反射: someClass.newInstance(); 具体取决于您所说的“创建”是什么意思,但其他一些是: 克隆法 反序列化 反射类.newInstance 反射构造函数对象 在Java语言中,创建对象的唯一方法是通过显式或隐式调用其构造函数。使用反射导致调用构造函数方法,反序列化使用反射调用构造函数,工厂方法包装调用构造函数以抽象实际构造,克隆类似于包装构造函数调用。从API用户的角度来看,构造函数的另一

前几天我和一个同事谈过这件事

使用构造函数是显而易见的,但是还有什么其他方法呢?

和。

反射:

someClass.newInstance();

具体取决于您所说的“创建”是什么意思,但其他一些是:

克隆法 反序列化 反射类.newInstance 反射构造函数对象
在Java语言中,创建对象的唯一方法是通过显式或隐式调用其构造函数。使用反射导致调用构造函数方法,反序列化使用反射调用构造函数,工厂方法包装调用构造函数以抽象实际构造,克隆类似于包装构造函数调用。

从API用户的角度来看,构造函数的另一种替代方法是静态工厂方法,如BigInteger.valueOf,不过对于API作者和real来说,对象仍然是使用构造函数创建的。

还有ClassLoader.loadClassstring,但这并不常用


如果你想成为这方面的律师,数组在技术上是对象,因为数组的.length属性。因此初始化数组会创建一个对象。

是的,可以使用反射创建对象。例如,String.class.newInstance将为您提供一个新的空字符串对象。

您还可以使用

 Object myObj = Class.forName("your.cClass").newInstance();
MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();
MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object
Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();

反思也能帮你完成这项工作

SomeClass anObj = SomeClass.class.newInstance();

是创建类的新实例的另一种方法。在这种情况下,您还需要处理可能引发的异常。

如果您是java新手,应该注意到这一点,每个对象都继承自对象

受保护的本机对象克隆引发CloneNotSupportedException

此外,还可以将数据反序列化为对象。这不是通过类构造函数实现的

更新:感谢Tom在您的评论中指出这一点!迈克尔也做了实验

它经过最派生的不可序列化超类的构造函数。 当该类没有参数构造函数时,反序列化时会引发InvalidClassException

关于所有病例的完整处理,请参见Tom的答案-

如果现有对象实现可克隆,则还可以克隆该对象

Foo fooClone = fooOriginal.clone (); 

有多种方式:

通过Class.newInstance。 通过Constructor.newInstance。 通过反序列化,使用派生最多的不可序列化基类的无参数构造函数。 通过Object.clone不调用构造函数。 通过JNI应该调用构造函数。 通过任何其他方法为您调用新的。 我想您可以将类加载描述为创建新对象,例如插入字符串。 在声明中作为初始化的一部分的文字数组没有数组的构造函数。 varargs中的数组。。。方法不调用数组的构造函数。 在典型的实现中,非编译时常量字符串串联至少会生成四个对象。 导致运行时创建并引发异常。例如抛出空值;或者.toCharArray[0]。 当然,还有原语的装箱,除非缓存。 JDK8应该具有lambda本质上简洁的匿名内部类,这些类被隐式转换为对象。 为了完整性和Paŭlo Ebermann,还有一些新关键字的语法。 使用新运算符从而调用构造函数 使用反射clazz.newInstance再次调用构造函数。或者通过clazz.getConstructor…newInstance。。再次使用构造函数,但您可以选择哪一个 通过调用对象类的构造函数来总结答案(一种主要方法)


更新:另一个答案列出了两种不涉及使用构造函数的方法-反序列化和克隆

在java中创建对象有四种不同的方法:

A.使用新关键字 这是在java中创建对象最常用的方法。几乎99%的对象都是以这种方式创建的

 MyObject object = new MyObject();
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
MyObject object = new MyObject();//normal way
MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();
Employee object = new Employee();
B.使用Class.forName 如果我们知道类的名称&如果它有一个公共的默认构造函数,我们可以用这种方式创建一个对象

 MyObject object = new MyObject();
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
MyObject object = new MyObject();//normal way
MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();
Employee object = new Employee();
C.使用克隆 克隆可用于创建现有对象的副本

MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();
MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object
Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();
D.使用对象反序列化 对象反序列化只不过是从其序列化形式创建对象

ObjectInputStream inStream = new ObjectInputStream(anInputStream );
MyObject object = (MyObject) inStream.readObject();
ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();
// Create Object5
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("");
ObjectOutputStream oout = new ObjectOutputStream(out);

// write something in the file
oout.writeObject(object3);
oout.flush();

// create an ObjectInputStream for the file we created before
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("crunchify.txt"));
Employee object5 = (Employee) ois.readObject();

您可以从中读取它们。

存在一种类型的对象,它不能由调用构造函数的常规实例创建机制构造:数组。数组是用

 A[] array = new A[len];

正如Sean在一篇评论中所说,这在语法上类似于构造函数调用,在内部,它只不过是分配和零初始化或使用显式内容初始化,在第二种情况下是内存块,带有一些头来指示类型和长度

将参数传递给varargs方法时,也会创建一个数组并隐式填充

第四种方法是

 A[] array = (A[]) Array.newInstance(A.class, len);
当然,克隆和des 我也在这里工作


标准API中有许多创建数组的方法,但实际上它们都在使用这些方法中的一种或多种。

如果我们详尽无遗的话,还有其他方法

在Oracle JVM上是不安全的。allocateInstance在不调用构造函数的情况下创建实例。 使用字节码操作,您可以向anewarray、multianewarray、newarray或new添加代码。可以使用诸如ASM或BCEL之类的库来添加它们。Oracle的Java附带了一个bcel版本。同样,这不会调用构造函数,但可以作为单独的调用调用构造函数。
在Java中创建对象有五种不同的方法:

1.使用“new”关键字: 这是在Java中创建对象最常用的方法。几乎99%的对象都是以这种方式创建的

 MyObject object = new MyObject();
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
MyObject object = new MyObject();//normal way
MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();
Employee object = new Employee();
2.采用工厂法: 例如:

3.通过使用克隆概念: 通过使用克隆,克隆可用于创建现有对象的副本

MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();
MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object
Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();
4.使用“Class.forName”: 如果我们知道类的名称&如果它有一个公共的默认构造函数,我们可以用这种方式创建一个对象

 MyObject object = new MyObject();
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
MyObject object = new MyObject();//normal way
MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();
Employee object = new Employee();
例如:

5.使用对象反序列化: 对象反序列化只不过是从其序列化形式创建对象

ObjectInputStream inStream = new ObjectInputStream(anInputStream );
MyObject object = (MyObject) inStream.readObject();
ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();
// Create Object5
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("");
ObjectOutputStream oout = new ObjectOutputStream(out);

// write something in the file
oout.writeObject(object3);
oout.flush();

// create an ObjectInputStream for the file we created before
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("crunchify.txt"));
Employee object5 = (Employee) ois.readObject();

我们可以通过5种方式创建对象:

新接线员 通过反射,例如Class.forName后跟Class.newInstance 工厂法 通过克隆 通过反射api
我们还可以通过以下方式创建对象:-

String s ="Hello";
没有人讨论过它。

方法1

使用新关键字。这是在java中创建对象最常用的方法。几乎99%的对象都是以这种方式创建的

 MyObject object = new MyObject();
MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();
MyObject object = new MyObject();//normal way
MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();
Employee object = new Employee();
方法2

使用Class.forName。Class.forName为您提供了类对象,它对反射很有用。这个对象拥有的方法是由Java定义的,而不是由编写类的程序员定义的。每门课都一样。在上调用newInstance将为您提供该类的实例,即调用class.forNameExampleClass.newInstance相当于调用new ExampleClass,您可以在其上调用该类定义的方法、访问可见字段等

Employee object2 = (Employee) Class.forName(NewEmployee).newInstance();
Class.forName将始终使用调用方的类加载器,而ClassLoader.loadClass可以指定不同的类加载器。我相信Class.forName也会初始化加载的类,而ClassLoader.loadClass方法不会立即初始化,直到第一次使用它时才会初始化

另一条必须是:

Java:线程状态介绍及示例 简单Java枚举示例

方法3

使用克隆。克隆可用于创建现有对象的副本

MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();
MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object
Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();
方法4

使用newInstance方法

Object object4 = Employee.class.getClassLoader().loadClass(NewEmployee).newInstance();
方法5

使用对象反序列化。对象反序列化只不过是从其序列化形式创建对象

ObjectInputStream inStream = new ObjectInputStream(anInputStream );
MyObject object = (MyObject) inStream.readObject();
ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();
// Create Object5
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("");
ObjectOutputStream oout = new ObjectOutputStream(out);

// write something in the file
oout.writeObject(object3);
oout.flush();

// create an ObjectInputStream for the file we created before
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("crunchify.txt"));
Employee object5 = (Employee) ois.readObject();

在Java中创建对象有五种不同的方法

一,。使用新关键字→ 调用构造函数

Employee emp1 = new Employee();
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
                                .newInstance();
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
二,。使用类的newInstance方法→ 调用构造函数

Employee emp1 = new Employee();
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
                                .newInstance();
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
它也可以写成

Employee emp2 = Employee.class.newInstance();
三,。使用构造函数的newInstance方法→ 调用构造函数

Employee emp1 = new Employee();
Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
                                .newInstance();
Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
五,。使用反序列化→ 没有构造函数调用

Employee emp4 = (Employee) emp3.clone();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
前三个方法new关键字和两个newInstance都包含构造函数调用,但后面两个克隆和反序列化方法在不调用构造函数的情况下创建对象

以上所有方法都有与其相关的不同字节码,请阅读示例和更详细的说明,例如所有这些方法的字节码转换


然而,有人可能会争辩说,创建数组或字符串对象也是创建对象的一种方式,但这些事情只针对某些类,由JVM直接处理,而我们可以使用这5种方式创建任何类的对象。

如果我使用这5种方式,它会要求我将其包含在try/catch块中。是的,在许多情况下,可以抛出异常。请参阅JavaDoc for newInstance以了解可能出现的问题。@stacker:您能解释一下这与创建新对象有什么关系吗?谢谢。@ryanprayogo clone将返回一个新对象,即使该对象是调用clone的对象的克隆,并且实际上是在不调用构造函数的情况下创建新对象的唯一方法。它确实通过一个构造函数—最派生的不可序列化超类的无参数构造函数。@Tom Oh wow—我不知道然后做了一点实验。显然,当最派生的不可序列化超类没有无参数构造函数时,它会导致InvalidClassException被序列化到流中,并在反序列化时抛出!!-这有多奇怪?实际上只有两种方法存在:使用new、clone或reflection调用构造函数,以及不调用构造函数的反序列化。@AlexR:Object.clone也不调用构造函数。由于这似乎是顶部的答案,您能否将数组的创建作为子案例添加到A和B中?有关详细信息,请参见我的答案

序列化确实会调用构造函数,只是不是最派生的类型。您还应该提到构造函数类,它概括了class.newInstance。您也应该添加正常的方式:-@Paŭlo Ebermann,这太老派了,太不酷了。我假设这个问题的意思是使用构造函数,尽管上面提到的大多数(但不是全部)都使用/a构造函数。实际上,只有3种真正的方法可以做到这一点,对此我添加了注释,但您遗漏了一种:java.misc.Unsafe.allocateInstance。尽管出于许多原因,这是令人讨厌的。实际上,反序列化不使用无参数构造函数。在引擎罩下,它使用了allocateInstance或等效的黑魔法。最好的答案是JNIAllocObject。不调用构造函数。3和4是同一机制的不同别名。尽管您不能定义数组构造函数,但除此之外,该机制是同一个新关键字。Array.newInstance是唯一的新机制here@Sean:这是同一个关键词,但我敢说这是一个完全不同的内部机制。当然,这是真的。但另一方面,数组创建的不同版本在内部几乎相同。刚刚意识到你的答案是2011年的。抱歉挑起了一些旧东西:-@Sean:没问题,我利用这个机会做了一些语法修正。干得好,这里没有人讨论数组!4仅当您还没有该类时才需要Class.forName,而在所有其他情况下都需要该类。它也不需要no-args构造函数:如果知道正确的参数,可以通过多种方法调用任何公共构造函数。您至少忽略了另外两种方法。2工厂方法只是获取对象的一种模式。但是在内部它使用了新的关键字来创建对象。为什么这么多人说工厂方法创建对象,你们从哪里学来的?Class.forName加载一个类而不是创建一个对象。reflection?当然你们指的是反射。你们将如何从工厂方法创建对象,内部实现可能再次使用新的关键字对吗?你为什么要反省两次?如果你真的给出一些例子,这会更有意义。这是一种创建原始数据类型的方法,它只是Java在幕后提供的一种灵活性,不使用新关键字。这与新关键字相同。Madhusudan,仅供参考,在new operator的帮助下,对象应始终存储在堆中,而在本例中,Hello是一个应存储在字符串池中的对象。字符串是一个类而不是一个基本数据类型。这不会创建一个对象。它将引用指定给现有对象。该对象已由编译器和类加载器创建。不要对非代码的文本使用代码格式。还有比这些更多的方法。阅读其他答案。”几乎99%都是猜测。嗨,EJP,很抱歉这个错误…我说这是一种创建对象的方法,但没有说这是正确的方法。这只是一个模型。很抱歉,我是alearner,新的StackOverflow不正确。反序列化不显式或隐式调用类的构造函数。我不应该编写“其构造函数”和“构造函数”,而应该编写“构造函数”和“构造函数”。在反序列化的情况下,始终调用第一个适用的无参数构造函数。默认克隆实现不调用任何构造函数。如果这是我的克隆方法实现,请返回super.clone;。如果有疑问,请查看语言规范12.5新类实例的创建15.9类实例创建表达式只有3个:普通c-tor New关键字、克隆和不安全的.allocateInstanceClass。其余的人称之为其中之一。反射被编译为c-tor调用,反序列化为Unsafe.allocateInstanceClass。您可以创建自己的API,最终将调用其中一个。@bestsss-Unsafe是Java的一个特定于实现的详细信息,在规范中没有提到。完全可以构建一个兼容的Java实现,该实现不使用编译反射,而是使用新的、克隆的代码,或者不安全。allocateInstance。您可以检查链接,loadClassString name返回的结果类对象是对象,但不是该类的对象。若给出示例,那个么我们可以在整个java库中找到许多这样的示例,但这些示例是特定于类的。请检查并披露任何信息,不要将本网站用作通过发布来推广您的网站的方式。看见