Динамическое создание экземпляра без генериков - PullRequest
8 голосов
/ 06 февраля 2010

Я хотел бы понять, почему не работает следующее:

public class HelloClass {

    private class MyClass
    {
        public MyClass() 
        {
           System.out.println ("Oh heck this is me!");   
        }
    }

    public Object newInstance (Object o)
    {
        try {
            // java.lang.InstantiationException here
            return o.getClass().newInstance();        
        } catch (Exception e) {
            e.printStackTrace(System.out);
            return null;
        }
    }

    public void run()
    {
        MyClass m = new MyClass();  
        Object o = newInstance(m);
    }

    public static void main(String[] args) 
    {
        HelloClass hd = new HelloClass();
        hd.run();
    }
}

Я знаю правильный способ достижения этого путем объявления аргумента newInstance классом , но хотел бы понять, почему этого нельзя сделать, как указано выше.

UPD: вот исключение, которое я получаю:

java.lang.InstantiationException: HelloClass$MyClass
    at java.lang.Class.newInstance0(Class.java:340)
    at java.lang.Class.newInstance(Class.java:308)
    at HelloClass.newInstance(HelloClass.java:14)
    at HelloClass.run(HelloClass.java:24)
    at HelloClass.main(HelloClass.java:30)

Ответы [ 4 ]

6 голосов
/ 06 февраля 2010

Конструкторы для внутренних классов имеют скрытый первый аргумент, который вы должны предоставить при использовании отражения. Передайте экземпляр внешнего класса.

Вместо

return o.getClass().newInstance();

использование:

return o.getClass().getConstructor(getClass()).newInstance(this);
1 голос
/ 06 февраля 2010

Очень хороший вопрос!

Это потому, что у внутреннего класса есть неявный аргумент в каждом конструкторе - его внешний класс. Следовательно, у него нет конструктора по умолчанию.

Чтобы получить его экземпляр, вы должны создать его экземпляр, передав в качестве аргумента внешний класс.

 Constructor constructor = o.getClass().getConstructor(HelloClass.class);
 return constructor.newInstance(this);
1 голос
/ 06 февраля 2010

Кажется, проблема в том, что это нестатический класс-член, так как он работает как в случае, если вы объявите MyClass как статический, так и в том случае, если вы сделаете его классом верхнего уровня. Хотя я не совсем уверен, почему.

0 голосов
/ 06 февраля 2010

Метод newInstance в объекте Class работает только для конкретного класса с конструктором без аргументов.

Если вы измените MyClass на статический, он будет соответствовать требованиям и код будет работать. Как таковой, он имеет неявный конструктор с внешним объектом в качестве параметра и не имеет конструктора без аргументов.

Вы можете заставить свой собственный метод newInstance работать, используя метод newInstance конструктора:

public Object newInstance (Object o)
{
    try {
        final Constructor<? extends Object> constructor =
                     o.getClass().getConstructor(this.getClass());
        return constructor.newInstance(this);
    } catch (Exception e) {
        e.printStackTrace(System.out);
        return null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...