создание универсального объекта Java в анонимном подклассе - PullRequest
2 голосов
/ 19 января 2012

Я играл с анонимными подклассами и нашел проблему, которую не могу обойти.

РЕДАКТИРОВАТЬ: проблема решена благодаря Томасу, весь рабочий код находится на pastebin ( Foo.java ; FooTest.java )

2 Классы;Foo и FooTest ... Сначала код:

class Foo {

    public Foo () {}

    public void whichClassAmI () {
        System.out.println(this.getClass());                                                 
    }

    public void say () {
        System.out.println("Foo says: nothing");                                             
    }   

    public <T extends Foo> T getAnotherFoo () {                                              

        try {                                                                                
            Class<? extends Foo> c = this.getClass();                                        
            T r = (T)(c.getConstructor().newInstance());                                     
            return r;                                                                        
        } catch (Exception e) {                                                              
            throw new RuntimeException(e);                                                   
        }
    }                                                                                        

}

_

class FooTest {                                                                              

    public static String stuff = "";                                                         

    public static void main (String[] args) {                                                

        Foo f1 = new Foo();                                                                  

        // instance of anon subclass                                                         
        Foo f2 = new Foo(){                                                                  
            public void say () {                                                             
                System.out.println("Modded Foo says: " + stuff);                             
            }                                                                                
        };                                                                                   

        f1.whichClassAmI();                                                                  
        f2.whichClassAmI();                                                                  

        stuff = "stuff";                                                                     
        f1.say();                                                                            
        f2.say();                                                                            

        Foo f3 = f1.getAnotherFoo();                                                         
        f3.say();                                                                            

        Foo f4 = f2.getAnotherFoo(); // <-- exception here
    }

}

Таким образом, этот код компилируется с предупреждением о небезопасной операции, запускается и выдает исключение;вывод:

Note: Foo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
class Foo
class FooTest$1
Foo says: nothing
Modded Foo says: stuff
Foo says: nothing
Exception in thread "main" java.lang.RuntimeException: java.lang.NoSuchMethodException: FooTest$1.<init>()
    at Foo.getAnotherFoo(Foo.java:20)
    at FooTest.main(FooTest.java:23)
Caused by: java.lang.NoSuchMethodException: FooTest$1.<init>()
    at java.lang.Class.getConstructor0(Class.java:2723)
    at java.lang.Class.getConstructor(Class.java:1674)
    at Foo.getAnotherFoo(Foo.java:17)
    ... 1 more

что я не понимаю:

  1. f2 класс FooTest $ 1, и этот класс, кажется, не расширяет Foo

  2. , если (1) верно, почему «Класс c = [...]» может быть установлен с помощью FooTest $ 1

  3. , если (1) является ложными (2) работает правильно, почему он не находит метод?

1 Ответ

4 голосов
/ 19 января 2012

To 1): f2 относится к типу FooTest$1, который расширяет Foo, но не печатается, вы просто получаете текущий класс и никаких суперклассов или интерфейсов.

To 2):Так как 1) ложно, здесь нет вопроса:)

To 3): Проблема в том, что анонимному внутреннему классу FooTest$1 необходим внешний экземпляр FooTest для создания.Вызов конструктора через отражение попытался бы создать новый экземпляр без включающего экземпляра FooTest, и такой метод недоступен (т. Е. Метод, который создает экземпляр внутреннего класса без экземпляравключающий класс).

Вам нужно получить конструктор, который принимает экземпляр включающего класса в качестве параметра.Для получения дополнительной информации посмотрите на этот вопрос: Можно ли создать экземпляр вложенного класса с помощью Java Reflection?

Редактировать :

Я снова прочитал ваш код и мне стыдно, что я пропустил это: класс FooTest$1 на самом деле является статическим внутренним классом, поскольку он создается в методе static main.Таким образом, у него нет конструктора, принимающего экземпляр класса.

Однако, поскольку вы создаете класс и его встроенный конструктор, этот конструктор не является общедоступным.Таким образом, getClass().getConstructor() не вернет его (этот класс будет возвращать только открытые конструкторы. В этом случае вы должны использовать getClass().getDeclaredConstructor(). То же самое верно для полей и методов, только для записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...