Каква е разликата между новия оператор и Class.newInstance()?

Каква е разликата между оператора new и Class.forName(...).newInstance()? И двамата създават екземпляри на клас и не съм сигурен каква е разликата между тях.


person i2ijeya    schedule 06.01.2011    source източник
comment
или Class.forName(...).getConstructor(...).newInstance(...)   -  person viavad    schedule 10.06.2019


Отговори (10)


Операторът new създава нов обект от тип, който е известен статично (по време на компилиране) и може да извика всеки конструктор на обекта, който се опитвате да създадете. Това е предпочитаният начин за създаване на обект - бърз е и JVM прави много агресивни оптимизации върху него.

Class.forName().newInstance() е динамична конструкция, която търси клас с конкретно име. По-бавно е от използването на new, защото типът на обекта не може да бъде твърдо кодиран в байт кода и защото JVM може да трябва да извърши проверка на разрешенията, за да гарантира, че имате правомощията да създадете обект. Освен това е частично опасно, защото винаги използва конструктор с нулев аргумент и ако обектът, който се опитвате да създадете, няма нулев конструктор, той хвърля изключение.

Накратко, използвайте new, ако знаете по време на компилиране какъв е типът на обекта, който искате да създадете. Използвайте Class.forName().newInstance(), ако не знаете какъв тип обект ще правите.

person templatetypedef    schedule 06.01.2011
comment
Това е популярен въпрос за интервю и това е страхотен отговор... благодаря - person Soumyadip Das; 06.08.2012
comment
можете да получите конструктори, които изискват аргументи и да ги използвате за инстанциране на обект чрез API за отражение. - person Manjunath Maruthi; 08.01.2015
comment
Само бележка, ClassNotFoundException е отметнато, така че не можете да компилирате това: try { optlib.SomeClass obj = new optlib.SomeClass(); } catch (ClassNotFoundException e) {}. В този случай трябва да използвате Class.forName().newInstance(). - person Dávid Horváth; 14.12.2016
comment
безупречен отговор! - person Gaurav; 17.10.2019

Class.forName("your class name").newInstance() е полезен, ако трябва да създавате класове динамично, защото не е необходимо да кодирате твърдо името на класа, за да създадете обект.

Представете си сценарий, при който зареждате класове динамично от отдалечен източник. Ще знаете имената им, но не можете да ги импортирате по време на компилиране. В този случай не можете да използвате new за създаване на нови екземпляри. Това е (една от причините), поради която Java предлага метода newInstance().

person Andreas Dolk    schedule 06.01.2011
comment
Страхотен!! Това е полезен отговор!! - person Emad Aghayi; 30.12.2015

Class.forName може да извиква само конструктора по подразбиране (без параметри) и името на класа може да бъде предоставено по време на изпълнение, напр. името на db-драйвера, прочетено от конфигурационен файл.

person stacker    schedule 06.01.2011
comment
Това не е вярно, можете да получите конструктори, които изискват аргументи и да ги използвате, за да създадете обект чрез API за отражение. Методът newInstance обаче специално извиква конструктора no-arg и изисква той да бъде видим и достъпен. Отговорът на templatetypedef е най-пълният/правилен и информативен. - person LINEMAN78; 06.01.2011

Основната разлика е, че Class.forName('your class name').newInstance() е динамичен, тъй като типът не трябва да бъде твърдо кодиран в кода.

person fastcodejava    schedule 10.05.2013

Class.forName("your class name").newInstance() се използва, когато искате да получите екземпляр от клас, който работи подобно на new, но е полезен, когато искате да получите екземпляр от клас в jar файл или отдалечен сървър и не можете да импортирате това по време на компилиране.

пример: Class.forName("YOUR JDBC DRIVER").newInstance(), не можете да импортирате JDBC класа по време на компилация.

person Emad Aghayi    schedule 30.12.2015
comment
Примерът с JDBC всъщност не е много добър, необходимостта от извикване на newInstance() съществува само за някои ранни версии на MySQL JDBC драйвера. - person Mark Rotteveel; 02.10.2016

Class.forName('myClass').newInstance() зарежда класа, ако вече не е зареден. Тук той извиква първоначалния конструктор и изпълнява само статичната част на конструктора.

Операторът new се използва за инициализиране на нови обекти.

Можете да създадете много екземпляри както от оператора new, така и от Class.forName(), разликата е, че вторият път, когато създадете newInstance(), статичните блокове няма да се инициализират.

Добър пример за Class.forName('myClass).newInstance() е JDBC драйверът

Class.forName("com.mysql.JDBC.Driver").newInstance()
person Nipuna    schedule 06.01.2011
comment
Какво ще стане, ако използвам Class‹myClass› inst1 = (Class‹myClass›)Class.forName('myClass).getInstance()...... Class‹myClass› inst2 = (Class‹myClass›)Class.forName(' myClass).getInstance().............. Това ще направи множество инстанции правилни. - person i2ijeya; 06.01.2011
comment
Ами не намирам метод getInstance(). Вие ли? - person Nipuna; 06.01.2011
comment
Примерът с JDBC всъщност не е много добър, необходимостта от извикване на newInstance() съществува само за някои ранни версии на MySQL JDBC драйвера. - person Mark Rotteveel; 02.10.2016

Class.forName ще направи търсене, за да намери обекта Class за YourClass.

Използването на новия оператор трябва да бъде същото като YourClass.class.newInstance().

person Zeki    schedule 06.01.2011

Въпреки че и двата ефективно правят едно и също нещо, трябва да използвате оператора new, вместо да правите Class.forName('class').getInstance(). Последният използва API за отражение, за да търси класа по време на изпълнение. Чрез използването на новия оператор VM ще знае предварително, че искате да използвате този клас и по този начин да бъдете по-ефективни.

person salexander    schedule 06.01.2011

Да приемем com.statckoverflow.Test

Class.forName - Ще зареди тестовия клас и ще върне обекта на Class клас, който съдържа метаданните на тестовия клас като име, пакет, конструктор, анотации, методи, полета.

newInstance() - Използва се за инстанциране на нови обекти с помощта на Java Reflection. Вътрешният конструктор на нулев параметър ще бъде извикан в класа Test. Това означава, че Class клас обект ще създаде Test клас обект чрез извикване на конструктора на нулев параметър. Можем да използваме отражението за подробности за Test клас. Като конструктори, методи и т.н.

new оператор - Създава новия обект за класа, който инстанцира Class и може да извиква техните конструктори.

person Kanchan Kumar    schedule 13.10.2017

Ако няма конструктор с нулев аргумент на обект, той също ще създаде обект и няма да хвърля никакви изключения, моля, намерете кодовите фрагменти по-долу.

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();
}
person user2364795    schedule 09.05.2013