183

前几天和同事讨论过这个问题。

使用构造函数很明显,但是还有其他方法吗?

4

22 回答 22

291

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

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

 MyObject object = new MyObject();

。使用Class.forName()
如果我们知道类的名称并且如果它有一个公共的默认构造函数,我们可以通过这种方式创建一个对象。

MyObject object = (MyObject) Class.forName("subin.rnd.MyObject").newInstance();

C. _ 使用clone()
clone() 可用于创建现有对象的副本。

MyObject anotherObject = new MyObject();
MyObject object = (MyObject) anotherObject.clone();

D. _ 使用object deserialization
对象反序列化只不过是从其序列化形式创建一个对象。

ObjectInputStream inStream = new ObjectInputStream(anInputStream );
MyObject object = (MyObject) inStream.readObject();

您可以从这里阅读它们。

于 2011-02-24T12:26:43.660 回答
68

有多种方式:

  • 通过Class.newInstance.
  • 通过Constructor.newInstance.
  • 通过反序列化(使用最派生的不可序列化基类的无参数构造函数)。
  • 通过Object.clone不调用构造函数)。
  • 通过 JNI(应该调用构造函数)。
  • 通过任何其他为您调用 a 的方法new
  • 我想您可以将类加载描述为创建新对象(例如 interned String)。
  • 作为声明中初始化的一部分的文字数组(没有数组的构造函数)。
  • “varargs”( ...) 方法调用中的数组(没有数组的构造函数)。
  • 非编译时常量字符串连接(在典型实现中发生至少四个对象)。
  • 导致运行时创建和抛出异常。例如throw null;"".toCharArray()[0]
  • 哦,当然还有原语装箱(除非缓存)。
  • JDK8 应该有 lambdas(本质上是简洁的匿名内部类),它们被隐式转换为对象。
  • 为了完整性(和 Paŭlo Ebermann),new关键字也有一些语法。
于 2010-01-20T17:44:48.640 回答
25

在 Java 语言中,创建对象的唯一方法是调用其构造函数,无论是显式的还是隐式的。使用反射导致调用构造函数方法,反序列化使用反射调用构造函数,工厂方法包装对构造函数的调用以抽象实际构造,克隆同样是包装的构造函数调用。

于 2008-09-18T19:01:35.440 回答
13

是的,您可以使用反射创建对象。例如,String.class.newInstance()会给你一个新的空字符串对象。

于 2010-01-20T16:40:00.003 回答
11

在 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→构造函数的方法被调用

Constructor<Employee> constructor = 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 种方式创建任何类的对象。

于 2016-11-19T05:55:29.760 回答
9

克隆反序列化

于 2008-09-18T18:35:52.163 回答
6

你也可以使用

 Object myObj = Class.forName("your.cClass").newInstance();
于 2010-01-20T16:41:47.457 回答
6

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

受保护的本机对象 clone() 抛出 CloneNotSupportedException;

于 2010-01-20T16:44:36.763 回答
6

此外,您可以将数据反序列化为对象。这不通过类 Constructor !


更新:感谢汤姆在您的评论中指出这一点!迈克尔也进行了实验。

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

请参阅汤姆的回答以了解所有情况的完整处理;-)
是否有任何其他方法可以在不使用 java 中的“new”关键字的情况下创建对象

于 2010-01-20T17:03:35.847 回答
6

有一种对象,不能通过普通的实例创建机制(调用构造函数)来构造:数组。数组是用

 A[] array = new A[len];

或者

 A[] array = new A[] { value0, value1, value2 };

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

将参数传递给可变参数方法时,也会隐式创建(并填充)数组。

第四种方法是

 A[] array = (A[]) Array.newInstance(A.class, len);

当然,克隆和反序列化也适用于此。

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

于 2011-02-24T12:52:25.560 回答
5

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

  • 在 Oracle JVM 上是 Unsafe.allocateInstance() ,它在不调用构造函数的情况下创建实例。
  • 使用字节码操作,您可以将代码添加到anewarray、或. 这些可以使用 ASM 或 BCEL 等库添加。Oracle 的 Java 附带了一个 bcel 版本。同样,这不会调用构造函数,但您可以将构造函数作为单独的调用来调用。multianewarraynewarraynew
于 2011-02-24T14:10:48.597 回答
4

反射:

someClass.newInstance();
于 2008-09-18T18:37:19.397 回答
4

反射也将为您完成这项工作。

SomeClass anObj = SomeClass.class.newInstance();

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

于 2010-01-20T16:44:13.443 回答
4
  • 使用new运算符(因此调用构造函数)
  • 使用反射clazz.newInstance()(再次调用构造函数)。或者通过clazz.getConstructor(..).newInstance(..)(再次使用构造函数,但您可以选择哪一个)

总结答案 - 一种主要方式 - 通过调用对象类的构造函数。

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

于 2011-02-24T12:23:26.173 回答
4

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

1.使用`new`关键字:

这是在 Java 中创建对象的最常用方法。几乎 99% 的对象都是以这种方式创建的。

MyObject object = new MyObject();//normal way

2.通过使用工厂方法:

ClassName ObgRef=ClassName.FactoryMethod();

例子:

RunTime rt=Runtime.getRunTime();//Static Factory Method

3. 通过使用克隆概念:

通过使用clone()clone()可用于创建现有对象的副本。

MyObjectName anotherObject = new MyObjectName();
MyObjectName object = anotherObjectName.clone();//cloning Object

4. 使用`Class.forName()`:

如果我们知道类的名称并且如果它有一个公共的默认构造函数,我们可以通过这种方式创建一个对象。

MyObjectName object = (MyObjectNmae) Class.forName("PackageName.ClassName").newInstance();

例子:

String st=(String)Class.forName("java.lang.String").newInstance();

5.使用对象反序列化:

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

ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();
于 2011-05-14T07:35:03.133 回答
3

您还可以克隆现有对象(如果它实现了 Cloneable)。

Foo fooClone = fooOriginal.clone (); 
于 2010-01-20T17:08:27.540 回答
2

方法一

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

Employee object = new Employee();

方法二

使用 Class.forName()。Class.forName() 为您提供类对象,这对反射很有用。该对象具有的方法是由 Java 定义的,而不是由编写类的程序员定义的。它们对于每个班级都是一样的。调用 newInstance() 会为您提供该类的实例(即,callingClass.forName("ExampleClass").newInstance() 相当于调用 new ExampleClass()),您可以在其上调用该类定义的方法,访问可见字段等。

Employee object2 = (Employee) Class.forName(NewEmployee).newInstance();

Class.forName() 将始终使用调用者的 ClassLoader,而 ClassLoader.loadClass() 可以指定不同的 ClassLoader。我相信 Class.forName 也会初始化加载的类,而 ClassLoader.loadClass() 方法不会立即执行此操作(直到第一次使用它才初始化)。

另一个必须阅读:

Java:带有示例的线程状态介绍简单的Java枚举示例

方法三

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

Employee secondObject = new Employee();
Employee object3 = (Employee) secondObject.clone();

方法四

使用 newInstance() 方法

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

方法五

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

// 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();
于 2015-07-09T09:28:11.947 回答
0

从 API 用户的角度来看,构造函数的另一种替代方法是静态工厂方法(如 BigInteger.valueOf()),尽管对于 API 作者(并且在技术上是“真实的”),对象仍然是使用构造函数创建的。

于 2008-09-18T20:10:37.740 回答
-1

完全取决于您创建的意思,但其他一些是:

  • 克隆方法
  • 反序列化
  • 反射 (Class.newInstance())
  • 反射(构造函数对象)
于 2008-09-18T18:40:20.200 回答
-2

还有 ClassLoader.loadClass(string) 但这并不经常使用。

如果你想成为一个完整的律师,由于数组的 .length 属性,数组在技术上是对象。所以初始化一个数组会创建一个对象。

于 2008-09-18T20:20:11.100 回答
-3

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

  1. 由新运营商
  2. 通过反射(例如 Class.forName() 后跟 Class.newInstance())
  3. 通过工厂方法
  4. 通过克隆
  5. 通过反射api
于 2011-08-26T13:26:55.340 回答
-5

我们也可以这样创建对象:-

String s ="Hello";

没有人讨论它。

于 2014-06-24T06:39:12.517 回答