简体   繁体   English

在 Java 中创建对象的所有不同方法是什么?

[英]What are all the different ways to create an object in Java?

Had a conversation with a coworker the other day about this.前几天和同事讨论了这个问题。

There's the obvious using a constructor, but what are the other ways there?使用构造函数很明显,但其他方法是什么?

There are four different ways to create objects in java:在java中有四种不同的方式来创建对象:

A .一个 Using new keyword使用new关键字
This is the most common way to create an object in java.这是在java中创建对象最常见的方式。 Almost 99% of objects are created in this way.几乎 99% 的对象都是以这种方式创建的。

 MyObject object = new MyObject();

B . Using Class.forName()使用Class.forName()
If we know the name of the class & if it has a public default constructor we can create an object in this way.如果我们知道类的名称并且它有一个公共默认构造函数,我们就可以通过这种方式创建一个对象。

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

C . C. Using clone()使用clone()
The clone() can be used to create a copy of an existing object. clone() 可用于创建现有对象的副本。

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

D . D. Using object deserialization使用object deserialization
Object deserialization is nothing but creating an object from its serialized form.对象反序列化只不过是从其序列化形式创建对象。

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

You can read them from here .您可以从这里阅读它们。

There are various ways:有多种方式:

  • Through Class.newInstance .通过Class.newInstance
  • Through Constructor.newInstance .通过Constructor.newInstance
  • Through deserialisation (uses the no-args constructor of the most derived non-serialisable base class).通过反序列化(使用最派生的不可序列化基类的无参数构造函数)。
  • Through Object.clone ( does not call a constructor ).通过Object.clone不调用构造函数)。
  • Through JNI (should call a constructor).通过JNI(应该调用一个构造函数)。
  • Through any other method that calls a new for you.通过任何其他为您调用new方法的方法。
  • I guess you could describe class loading as creating new objects (such as interned String s).我猜您可以将类加载描述为创建新对象(例如实习String )。
  • A literal array as part of the initialisation in a declaration (no constructor for arrays).作为声明中初始化的一部分的文字数组(没有数组的构造函数)。
  • The array in a "varargs" ( ... ) method call (no constructor for arrays). "varargs" ( ... ) 方法调用中的数组(没有数组的构造函数)。
  • Non-compile time constant string concatenation (happens to produce at least four objects, on a typical implementation).非编译时常量字符串连接(在典型的实现中至少产生四个对象)。
  • Causing an exception to be created and thrown by the runtime.导致运行时创建和抛出异常。 For instance throw null;例如throw null; or "".toCharArray()[0] ."".toCharArray()[0]
  • Oh, and boxing of primitives (unless cached), of course.哦,当然还有原语的装箱(除非缓存)。
  • JDK8 should have lambdas (essentially concise anonymous inner classes), which are implicitly converted to objects. JDK8 应该有 lambdas(本质上是简洁的匿名内部类),它们被隐式转换为对象。
  • For completeness (and Paŭlo Ebermann), there's some syntax with the new keyword as well.为了完整性(和 Paŭlo Ebermann),还有一些带有new关键字的语法。

Within the Java language, the only way to create an object is by calling its constructor, be it explicitly or implicitly.在 Java 语言中,创建对象的唯一方法是调用其构造函数,无论是显式还是隐式。 Using reflection results in a call to the constructor method, deserialization uses reflection to call the constructor, factory methods wrap the call to the constructor to abstract the actual construction and cloning is similarly a wrapped constructor call.使用反射导致调用构造函数方法,反序列化使用反射调用构造函数,工厂方法包装对构造函数的调用以抽象实际构造,克隆类似地包装构造函数调用。

Yes, you can create objects using reflection.是的,您可以使用反射创建对象。 For example, String.class.newInstance() will give you a new empty String object.例如, String.class.newInstance()会给你一个新的空 String 对象。

There are five different ways to create an object in Java,在 Java 中有五种不同的方法来创建对象,

1. Using new keyword → constructor get called 1. 使用new关键字→ 构造函数被调用

Employee emp1 = new Employee();

2. Using newInstance() method of Class → constructor get called 2.使用newInstance()的方法Class →构造函数被调用

Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee")
                                .newInstance();

It can also be written as也可以写成

Employee emp2 = Employee.class.newInstance();

3. Using newInstance() method of Constructor → constructor get called 3.使用Constructor newInstance()方法→constructor被调用

Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();

4. Using clone() method → no constructor call 4. 使用clone()方法→ 没有构造函数调用

Employee emp4 = (Employee) emp3.clone();

5. Using deserialization → no constructor call 5.使用反序列化→无构造函数调用

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();

First three methods new keyword and both newInstance() include a constructor call but later two clone and deserialization methods create objects without calling the constructor.前三个方法new关键字和newInstance()包含构造函数调用,但后面的两个克隆和反序列化方法在不调用构造函数的情况下创建对象。

All above methods have different bytecode associated with them, Read Different ways to create objects in Java with Example for examples and more detailed description eg bytecode conversion of all these methods.以上所有方法都有不同的字节码与之相关联,请阅读在 Java 中创建对象的不同方法和示例,以及更详细的描述,例如所有这些方法的字节码转换。

However one can argue that creating an array or string object is also a way of creating the object but these things are more specific to some classes only and handled directly by JVM, while we can create an object of any class by using these 5 ways.然而有人会说,创建数组或字符串对象也是创建对象的一种方式,但这些东西只针对某些类,由JVM直接处理,而我们可以使用这5种方式创建任何类的对象。

你也可以使用

 Object myObj = Class.forName("your.cClass").newInstance();

This should be noticed if you are new to java, every object has inherited from Object如果您是 Java 新手,应该注意这一点,每个对象都继承自 Object

protected native Object clone() throws CloneNotSupportedException;受保护的本机对象 clone() 抛出 CloneNotSupportedException;

Also, you can de-serialize data into an object.此外,您可以数据反序列化为对象。 This doesn't go through the class Constructor !这不会通过类构造函数!


UPDATED : Thanks Tom for pointing that out in your comment !更新:感谢汤姆在您的评论中指出这一点! And Michael also experimented.迈克尔也进行了实验。

It goes through the constructor of the most derived non-serializable superclass.它通过最派生的不可序列化超类的构造函数。
And when that class has no no-args constructor, a InvalidClassException is thrown upon de-serialization.当该类没有无参数构造函数时,反序列化时会抛出 InvalidClassException。

Please see Tom's answer for a complete treatment of all cases ;-)请参阅 Tom 的回答以了解所有情况的完整处理 ;-)
is there any other way of creating an object without using "new" keyword in java 有没有其他方法可以在java中不使用“new”关键字来创建对象

There is a type of object, which can't be constructed by normal instance creation mechanisms (calling constructors): Arrays .有一类对象,不能通过普通的实例创建机制(调用构造函数)来构造:数组 Arrays are created with数组是用

 A[] array = new A[len];

or要么

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

As Sean said in a comment, this is syntactically similar to a constructor call and internally it is not much more than allocation and zero-initializing (or initializing with explicit content, in the second case) a memory block, with some header to indicate the type and the length.正如肖恩在评论中所说,这在语法上类似于构造函数调用,在内部,它只不过是分配和零初始化(或在第二种情况下使用显式内容初始化)内存块,并带有一些标头来指示类型和长度。

When passing arguments to a varargs-method, an array is there created (and filled) implicitly, too.将参数传递给可变参数方法时,也会隐式创建(并填充)一个数组。

A fourth way would be第四种方式是

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

Of course, cloning and deserializing works here, too.当然,克隆和反序列化在这里也有效。

There are many methods in the Standard API which create arrays, but they all in fact are using one (or more) of these ways.标准 API 中有许多创建数组的方法,但实际上它们都使用其中一种(或多种)方法。

Other ways if we are being exhaustive.其他方式,如果我们是详尽无遗的。

  • On the Oracle JVM is Unsafe.allocateInstance() which creates an instance without calling a constructor.在 Oracle JVM 上是 Unsafe.allocateInstance(),它在不调用构造函数的情况下创建一个实例。
  • Using byte code manipulation you can add code to anewarray , multianewarray , newarray or new .使用字节码操作,您可以将代码添加到anewarraymultianewarraynewarraynew These can be added using libraries such as ASM or BCEL.这些可以使用诸如 ASM 或 BCEL 之类的库添加。 A version of bcel is shipped with Oracle's Java. bcel 的一个版本随 Oracle 的 Java 一起提供。 Again this doesn't call a constructor, but you can call a constructor as a seperate call.同样,这不会调用构造函数,但您可以将构造函数作为单独的调用来调用。

Reflection will also do the job for you.反思也会为你完成这项工作。

SomeClass anObj = SomeClass.class.newInstance();

is another way to create a new instance of a class.是另一种创建类的新实例的方法。 In this case, you will also need to handle the exceptions that might get thrown.在这种情况下,您还需要处理可能抛出的异常。

  • using the new operator (thus invoking a constructor)使用new运算符(从而调用构造函数)
  • using reflection clazz.newInstance() (which again invokes the constructor).使用反射clazz.newInstance() (再次调用构造函数)。 Or by clazz.getConstructor(..).newInstance(..) (again using a constructor, but you can thus choose which one)或者通过clazz.getConstructor(..).newInstance(..) (再次使用构造函数,但您可以因此选择哪一个)

To summarize the answer - one main way - by invoking the constructor of the object's class.总结答案 - 一种主要方式 - 通过调用对象类的构造函数。

Update: Another answer listed two ways that do not involve using a constructor - deseralization and cloning.更新:另一个答案列出了两种不涉及使用构造函数的方法 - 去序列化和克隆。

There are FIVE different ways to create objects in Java:在 Java 中有五种不同的方法来创建对象:

1. Using `new` keyword: 1. 使用`new`关键字:

This is the most common way to create an object in Java.这是在 Java 中创建对象的最常见方法。 Almost 99% of objects are created in this way.几乎 99% 的对象都是以这种方式创建的。

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

2. By Using Factory Method: 2. 使用工厂方法:

ClassName ObgRef=ClassName.FactoryMethod();

Example:例子:

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

3. By Using Cloning Concept: 3.通过使用克隆概念:

By using clone() , the clone() can be used to create a copy of an existing object.通过使用clone()clone()可用于创建现有对象的副本。

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

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

If we know the name of the class & if it has a public default constructor we can create an object in this way.如果我们知道类的名称并且它有一个公共默认构造函数,我们就可以通过这种方式创建一个对象。

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

Example:例子:

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

5. Using object deserialization: 5. 使用对象反序列化:

Object deserialization is nothing but creating an object from its serialized form.对象反序列化只不过是从其序列化形式创建对象。

ObjectInputStreamName inStream = new ObjectInputStreamName(anInputStream );
MyObjectName object = (MyObjectNmae) inStream.readObject();

反射:

someClass.newInstance();

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

Foo fooClone = fooOriginal.clone (); 

Method 1方法一

Using new keyword.使用新关键字。 This is the most common way to create an object in java.这是在java中创建对象最常见的方式。 Almost 99% of objects are created in this way.几乎 99% 的对象都是以这种方式创建的。

Employee object = new Employee();

Method 2方法二

Using Class.forName().使用 Class.forName()。 Class.forName() gives you the class object, which is useful for reflection. Class.forName() 为您提供类对象,这对于反射很有用。 The methods that this object has are defined by Java, not by the programmer writing the class.该对象具有的方法是由 Java 定义的,而不是由编写类的程序员定义的。 They are the same for every class.它们对每个班级都是一样的。 Calling newInstance() on that gives you an instance of that class (ie callingClass.forName("ExampleClass").newInstance() it is equivalent to calling new ExampleClass()), on which you can call the methods that the class defines, access the visible fields etc.在其上调用 newInstance() 为您提供该类的实例(即,调用 Class.forName("ExampleClass").newInstance() 等效于调用 new ExampleClass()),您可以在该实例上调用该类定义的方法,访问可见字段等。

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

Class.forName() will always use the ClassLoader of the caller, whereas ClassLoader.loadClass() can specify a different ClassLoader. Class.forName() 将始终使用调用者的 ClassLoader,而 ClassLoader.loadClass() 可以指定不同的 ClassLoader。 I believe that Class.forName initializes the loaded class as well, whereas the ClassLoader.loadClass() approach doesn't do that right away (it's not initialized until it's used for the first time).我相信 Class.forName 也会初始化加载的类,而 ClassLoader.loadClass() 方法不会立即这样做(直到第一次使用它才会初始化)。

Another must read:另一个必读:

Java: Thread State Introduction with Example Simple Java Enum Example Java:线程状态介绍与示例简单 Java 枚举示例

Method 3方法三

Using clone().使用克隆()。 The clone() can be used to create a copy of an existing object. clone() 可用于创建现有对象的副本。

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

Method 4方法四

Using newInstance() method使用 newInstance() 方法

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

Method 5方法五

Using Object Deserialization.使用对象反序列化。 Object Deserialization is nothing but creating an object from its serialized form.对象反序列化只不过是从其序列化形式创建对象。

// 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();

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

Depends exactly what you mean by create but some other ones are:完全取决于您所说的创建,但其他一些是:

  • Clone method克隆方法
  • Deserialization反序列化
  • Reflection (Class.newInstance())反射(Class.newInstance())
  • Reflection (Constructor object)反射(构造函数对象)

there is also ClassLoader.loadClass(string) but this is not often used.还有 ClassLoader.loadClass(string) 但这并不经常使用。

and if you want to be a total lawyer about it, arrays are technically objects because of an array's .length property.如果你想成为一个全面的律师,数组在技术上是对象,因为数组的 .length 属性。 so initializing an array creates an object.所以初始化一个数组会创建一个对象。

We can create an objects in 5 ways:我们可以通过 5 种方式创建对象:

  1. by new operator新运营商
  2. by reflection (eg Class.forName() followed by Class.newInstance())通过反射(例如 Class.forName() 后跟 Class.newInstance())
  3. by factory method按工厂方法
  4. by cloning通过克隆
  5. by reflection api通过反射api

We can also create the object in this way:-我们也可以通过这种方式创建对象:-

String s ="Hello";

Nobody has discuss it.没有人讨论过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM