【问题标题】:What is the difference between the new operator and Class.newInstance()?new 运算符和 Class.newInstance() 有什么区别?
【发布时间】:2011-01-06 06:27:53
【问题描述】:

new 运算符和Class.forName(...).newInstance() 有什么区别?它们都创建了一个类的实例,我不确定它们之间有什么区别。

【问题讨论】:

  • 或 Class.forName(...).getConstructor(...).newInstance(...)

标签: java reflection new-operator


【解决方案1】:

new 运算符创建一个静态已知类型的新对象(在编译时),并且可以在您尝试创建的对象上调用任何构造函数。这是创建对象的首选方式 - 它速度快,并且 JVM 对其进行了大量积极优化。

Class.forName().newInstance() 是一个动态构造,用于查找具有特定名称的类。它比使用new 慢,因为对象的类型不能硬编码到字节码中,并且因为JVM 可能必须进行权限检查以确保您有权创建对象。它也是部分不安全的,因为它总是使用零参数构造函数,如果您尝试创建的对象没有空值构造函数,它会引发异常。

简而言之,如果您在编译时知道要创建的对象类型是什么,请使用new。如果您不知道要制作什么类型的对象,请使用Class.forName().newInstance()

【讨论】:

  • 这是一个流行的面试问题,这是一个很好的答案......谢谢
  • 您可以获取需要参数的构造函数,并使用它们通过反射api实例化一个对象。
  • 请注意,ClassNotFoundException 已选中,因此您无法编译:try { optlib.SomeClass obj = new optlib.SomeClass(); } catch (ClassNotFoundException e) {}。在这种情况下,您必须使用Class.forName().newInstance()
  • 完美答案!
【解决方案2】:

Class.forName("your class name").newInstance() 在您需要动态实例化类时很有用,因为您不必硬编码类名来创建对象。

想象一个从远程源动态加载类的场景。您将知道它们的名称,但无法在编译时导入它们。在这种情况下,您不能使用 new 创建新实例。这就是 Java 提供 newInstance() 方法的(一个原因)。

【讨论】:

  • 太棒了!!这是有用的回应!
【解决方案3】:

Class.forName 只能调用默认构造函数(不带参数)和 可以在运行时提供类名,例如从配置文件中读取的 db-driver 名称。

【讨论】:

  • 这是不正确的,您可以获取需要参数的构造函数并使用它们通过反射 api 实例化对象。但是 newInstance 方法专门调用无参数构造函数并要求它是可见和可访问的。 templatetypedef 的答案是最完整/正确且信息量最大的。
【解决方案4】:

主要区别在于Class.forName('your class name').newInstance() 是动态的,因为类型不需要硬编码到代码中。

【讨论】:

    【解决方案5】:

    Class.forName("your class name").newInstance() 用于从类中获取实例,类似于new,但当你想从 jar 文件或远程服务器中的类中获取实例并且 无法在编译时导入它。

    例如:Class.forName("YOUR JDBC DRIVER").newInstance(),您不能在编译时导入 JDBC 类。

    【讨论】:

    • JDBC的例子其实不是很好,调用newInstance()的必要性只存在于一些早期版本的MySQL JDBC驱动中。
    【解决方案6】:

    Class.forName('myClass').newInstance() 会加载尚未加载的类。这里它调用初始构造函数并且只执行构造函数的静态部分。

    new 运算符用于初始化新对象。

    您可以从new 运算符和Class.forName() 创建许多实例,区别在于您第二次创建newInstance() 静态块时不会被初始化。

    Class.forName('myClass).newInstance() 的一个很好的例子是 JDBC 驱动程序

    Class.forName("com.mysql.JDBC.Driver").newInstance()
    

    【讨论】:

    • 如果我使用 Class inst1 = (Class)Class.forName('myClass).getInstance()...... Class inst2 = (Class)Class.forName('myClass).getInstance().......这将使多个实例正确。
    • 好吧,我没有找到 getInstance() 方法。你呢?
    • JDBC的例子其实不是很好,调用newInstance()的必要性只存在于一些早期版本的MySQL JDBC驱动中。
    【解决方案7】:

    Class.forName 将查找 Class 对象以查找 YourClass

    使用new操作符应该和YourClass.class.newInstance()一样。

    【讨论】:

      【解决方案8】:

      虽然两者都有效地做同样的事情,但您应该使用 new 运算符而不是 Class.forName('class').getInstance()。后者使用反射 API 在运行时查找类。通过使用 new 运算符,VM 将事先知道您想要使用该类,从而提高效率。

      【讨论】:

        【解决方案9】:

        假设com.statckoverflow.Test

        Class.forName - 它将加载 Test 类并返回 Class 类对象,其中包含 Test 类的元数据,如名称、包、构造函数、注释、方法、字段。

        newInstance() - 用于使用 Java 反射实例化新对象。 Test 类将调用内部零参数构造函数。这意味着Class类对象将通过调用零参数构造函数来创建Test类对象,Test类的细节可以使用反射。比如构造函数、方法等。

        new 运算符 - 为实例化 Class 的类创建新对象,并可以调用它们的构造函数。

        【讨论】:

          【解决方案10】:

          如果一个对象没有零参数构造函数,它也会创建一个对象并且不会抛出任何异常,请看下面的代码sn-ps。

          try {
              Class o = Class.forName("com.myCompany.MyClass");
          
              Constructor m = o.getConstructor(Integer.class,String.class);
              m.newInstance(new Integer(0),new String(""));
          
          } catch (ClassNotFoundException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (InstantiationException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (SecurityException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (NoSuchMethodException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (IllegalArgumentException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (InvocationTargetException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          

          【讨论】:

            猜你喜欢
            • 2011-05-24
            • 1970-01-01
            • 2022-06-10
            • 2018-08-02
            • 2011-03-16
            • 2013-06-05
            • 2018-08-16
            • 2012-10-10
            相关资源
            最近更新 更多