【问题标题】:Instantiate objects without using new operator在不使用 new 运算符的情况下实例化对象
【发布时间】:2013-05-17 10:52:55
【问题描述】:

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

在 java 中有没有不使用new 运算符来实例化对象的方法?我回复他说没有其他的实例化方式。但他问我如何使用 java 中的 xml 文件中的配置实例化 java 中的对象(在 spring 框架中)。我说过,spring 在内部使用reflection utils 来创建一个带有new 运算符的对象。但面试官并不相信我的回答。

我看到this link 很有用,但有一个new 运算符间接参与其中一种或其他内部方法。

真的有办法在java中不使用new操作符来实例化对象吗?

【问题讨论】:

  • 你可以通过反射/newInstance、clone()和(de)serialization创建一个没有new的对象。我敢肯定还有一些我没有想到的。

标签: java xml new-operator objectinstantiation


【解决方案1】:

您可以使用Java Reflection API 进行操作。这就是 Spring 框架的 DI 的工作方式(从 xml 实例化对象)。

Class<YourClass> c = YourClass.class;
YourClass instance = c.newInstance();

另外, 考虑到enumspecial class,枚举的实例是在不使用new 运算符的情况下创建的。

public enum YourEnum { X, Y }

【讨论】:

  • 糟糕,但@Arun 说:。我说过,spring 在内部使用反射工具来创建一个带有 new 运算符的对象。
  • 类 theClass = Class.forName("a.b.c.YourClass"); YourClass c = (YourClass) theClass.newInstance();
【解决方案2】:

以下形式的数组初始值设定项不明确使用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() 都使用“魔术”机制来创建不涉及上述字节码的实例,并且不以正常方式调用构造函数。

【讨论】:

    【解决方案3】:

    你可以使用jdbc的方式

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

    【讨论】:

      【解决方案4】:

      您可以使用clone 方法创建对象的副本,而无需使用 new 运算符。

      克隆用于制作对象的副本。在使用 Object 的 clone 方法时有一些注意事项。

      • 为每个要克隆的类实现“可克隆”接口。如果一个类没有实现“Cloneable”接口,clone方法会抛出“CloneableNotSupportedException”。该接口不包含任何方法。它只是一个标记界面。

      字符串类示例

      String sample = new String();
      

      现在我们不打算使用 new 操作符,我们将创建一个新对象

      String sampleClone = sample.clone();
      

      其他你可以使用的Class.forName()

      public static Class forName(String className) 抛出 ClassNotFoundException

      返回与具有给定字符串名称的类或接口关联的 Class 对象。

      示例 -- 类 exampleClass = Class.forName(yourtClass);

      阅读官方文档

      http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName%28java.lang.String%29

      【讨论】:

      【解决方案5】:
         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() 方法 2) 新运营商 3) clone() 方法 4) 反序列化

      【讨论】:

        【解决方案6】:

        您可以在不调用 new 的情况下反序列化对象。

        好的,您必须在FileInputStreamObjectInputStream 上致电new,但我认为这是合理使用。

         FileInputStream fis = new FileInputStream("myClassInstance.ser");
         ObjectInputStream ois = new ObjectInputStream(fis);
         MyClass myObject = (MyClass)ois.readObject();
        

        【讨论】:

          【解决方案7】:

          AFAIK、Class.newInstance() 和 Constructor.newInstance() 内部不使用 new 关键字。

          其他不使用new关键字创建实例的方法:

          • Object.clone()
          • 序列化

          【讨论】:

            【解决方案8】:

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

            1. newInstance()
            2. 克隆()
            3. 反序列化

            【讨论】:

            • 我可以想到至少 2 种其他方式......除了我的答案中作为示例显示的 5 种其他方式之外。所以你的“只有三种标准方式”有点离题了。
            猜你喜欢
            • 2021-07-02
            • 1970-01-01
            • 1970-01-01
            • 2011-11-08
            • 1970-01-01
            • 2011-04-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多