不使用new运算符实例化对象

12
在一次Java面试中,被问到以下问题:

Java中是否有一种不使用new运算符实例化对象的方法?我回答他说没有其他实例化对象的方法。但是他问我在Java中如何使用xml文件中的配置来实例化对象(在Spring框架中)。我回答他,Spring内部使用reflection utilsnew运算符创建对象。但是面试官对我的回答并不满意。

我看到这个链接很有用,但一个或另一个内部方法中都会间接地涉及new操作符。

真的有没有一种不使用new运算符在Java中实例化对象的方法?

你可以通过反射/newInstance、克隆(clone())和(反)序列化((de)serialization)等方式创建一个对象,我相信还有其他几种方法我没有想到。 - Durandal
8个回答

15
你可以使用Java反射API来完成。这就是Spring框架中的依赖注入的工作方式(从xml实例化对象)。
Class<YourClass> c = YourClass.class;
YourClass instance = c.newInstance();

此外,考虑到枚举是一种特殊类,因此枚举实例的创建不需要使用new运算符。
public enum YourEnum { X, Y }

1
糟糕,但是@Arun说:*。我说,内部Spring使用反射工具使用新运算符创建对象。 - Andremoniy
Class theClass = Class.forName("a.b.c.YourClass"); YourClass c = (YourClass) theClass.newInstance();类 theClass = Class.forName("a.b.c.YourClass"); YourClass c = (YourClass) theClass.newInstance(); - arcy
@sanbhat:http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance() - Arun

12
以下形式的数组初始化器没有明确使用new关键字。
int ia[][] = { {1, 2}, null };

通过自动装箱,这将创建一个对象...

Integer big = 9999;

最后,以下结果将在程序生命周期的某个地方创建对象 :-)

String s = "a literal";
enum Counting { ONE, TWO, FOUR, THREE_SIR }
Class c = String.class;

(而且有很多使用库方法或本地代码的方法来实现它)


在纯Java中,任何创建新对象的操作都会涉及到new字节码或3个new array字节码之一,这可能包括我的所有示例。

有趣的是,Object.clone()ObjectInputStream.readObject()都使用了“神奇”的机制来创建实例,不涉及上述字节码,并且不以正常方式调用构造函数。


1
使用"a literal"String.class,既不涉及new也不涉及newarray字节码。相反,使用了ldc指令。在当今的Java环境中,由于字符串连接或lambda表达式,情况变得更加复杂... - Holger

7

您可以使用JDBC的方式

Class.forName("YOURCLASSNAME").newInstance()

2
   import java.io.FileInputStream;
   import java.io.FileOutputStream;
   import java.io.ObjectInputStream;
   import java.io.ObjectOutputStream;
   import java.io.Serializable;

   public class ObjectCreateDifferentWays {

       public static void main(String[] args) throws Exception {
           ///1st Way with newInstance()
           Class cls = Class.forName("Student");
           Student ob1 = (Student) cls.newInstance();
           ob1.display();
                                      
           ///2nd Way with new Operator
           Student ob2 = new Student();
           ob2.display();

           //3rd Way with clone
           Student ob3 = (Student) ob2.clone();
           ob3.display();


           //4th Way with Deserialization
           FileOutputStream out = new FileOutputStream("file.txt");
           ObjectOutputStream obOut = new ObjectOutputStream(out);
           obOut.writeObject(ob2);
           obOut.flush();

           FileInputStream fIn = new FileInputStream("file.txt");
           ObjectInputStream obIn = new ObjectInputStream(fIn);

           Student ob4 = (Student) obIn.readObject();
           ob4.display();
       }
   }


   class Student implements Cloneable, Serializable {
       public void display() throws Exception {
           System.out.println("Display ");
       }@
       Override
       protected Object clone() throws CloneNotSupportedException {
           return super.clone();
       }
   }

在Java中创建对象的方式有多种

1) newInstance() method
2) new operator
3) clone() method
4) Deserialization

2
你可以使用 clone 方法创建对象的副本而无需使用 new 运算符。
clone 用于创建对象的副本。在使用 Object 的 clone 方法时,应注意以下几点:
  • 对于每个想要克隆的类,都要实现 "Cloneable" 接口。如果一个类没有实现 "Cloneable" 接口,则 clone 方法将抛出 "CloneableNotSupportedException" 异常。这个接口不包含任何方法,只是一个标记接口。

String 类的示例:

String sample = new String();

现在我们不会使用new运算符,而是创建一个新对象

String sampleClone = sample.clone();

您可以使用 Class.forName() 方法。 public static Class<?> forName(String className) throws ClassNotFoundException 返回与给定字符串名称相对应的类或接口的 Class 对象。
示例 -- Class exampleClass = Class.forName(yourtClass);
阅读 官方文档

1
但我猜这似乎在内部使用了新操作符。http://javapapers.com/core-java/java-clone-shallow-copy-and-deep-copy/ - Arun
@Arun clone创建一个相同类的新实例,并将所有字段复制到新实例中并返回它。没有任何地方写明它在内部使用new运算符。 - Nikhil Agrawal

1
你可以在不调用 new 的情况下反序列化一个对象。
好的,你需要在 FileInputStream 和 ObjectInputStream 上调用 new,但我认为这是合理使用。
 FileInputStream fis = new FileInputStream("myClassInstance.ser");
 ObjectInputStream ois = new ObjectInputStream(fis);
 MyClass myObject = (MyClass)ois.readObject();

0

在不使用new运算符的情况下,只有三种标准方法可以实例化一个类,它们如下:

  1. newInstance()
  2. clone()
  3. 反序列化

我至少能想到另外两种方法……除了我回答中展示的五种示例之外。因此,你所说的“只有三种标准方法”有些偏差。 - Stephen C

0
据我所知,Class.newInstance()和Constructor.newInstance()在内部不使用new关键字。
创建实例的其他方法,也可以不使用new关键字:
  • Object.clone()
  • Serialization

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接