Подтвердить что ты не робот

Java: доступ к частному конструктору с параметрами типа

Это продолжение этого вопроса о частных конструкторах java.

Предположим, что у меня есть следующий класс:

class Foo<T>
{
    private T arg;
    private Foo(T t) {
        // private!
        this.arg = t;
    }   

    @Override
    public String toString() {
        return "My argument is: " + arg;
    }   
}

Как бы я построил new Foo("hello") с помощью отражения?

ANSWER

На основе jtahlborn answer, следующие работы:

public class Example {
    public static void main(final String[] args) throws Exception {
        Constructor<Foo> constructor;
        constructor = Foo.class.getDeclaredConstructor(Object.class);
        constructor.setAccessible(true);
        Foo<String> foo = constructor.newInstance("arg1");
        System.out.println(foo);
    }   
}
4b9b3361

Ответ 1

вам нужно будет получить класс, найти конструктор, который принимает один аргумент с нижней границей T (в данном случае Object), заставить конструктор быть доступным (используя метод setAccessible) и, наконец, вызвать с нужным аргументом.

Ответ 2

Удостоверьтесь, что вы используете getDeclaredConstructors при получении конструктора и устанавливаете его доступность к true с его частной.

Что-то вроде этого должно работать.

Constructor<Foo> constructor= (Constructor<Foo>) Foo.class.getDeclaredConstructors()[0];
constructor.setAccessible(true); 
Foo obj = constructor.newInstance("foo"); 
System.out.println(obj);

Обновление

Если вы хотите использовать getDeclaredConstructor, передайте Object.class в качестве аргумента, который переводит на общий T.

Class fooClazz = Class.forName("path.to.package.Foo");
Constructor<Foo> constructor = fooClazz.getDeclaredConstructor(Object.class);
constructor.setAccessible(true); 
Foo obj = constructor.newInstance("foo"); 
System.out.println(obj);

Ответ 3

Хорошо, если частный конструктор не принимает никаких аргументов, мы получаем проблему при создании нового экземпляра, в этом случае после setAccessible true мы не можем создать объект. Даже construct.newInstance(null); не будет создавать объект без конструктора аргументов.

мы можем создать объект ниже кода с использованием отражения:

public class Singleton {

    private static Singleton instance = new Singleton();

    /* private constructor */
    private Singleton() {}

    public static Singleton getDefaultInstance() {
        return instance;
    }
}

Да, мы можем создать объект выше класса.

// reflection concept to get constructor of a Singleton class.  
Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();

// change the accessibility of constructor for outside a class object creation.  
constructor.setAccessible(true);

// creates object of a class as constructor is accessible now.  
Singleton secondOb = constructor.newInstance();

// close the accessibility of a constructor.
constructor.setAccessible(false);

Вы можете обратиться: Пример 2: "Яркая инициализация" и "Синглтонное нарушение отражением" в моем блоге: http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/

Ответ 4

Как @ArtB сказал, что вы можете использовать dp4j.com, , если знаете конструктор, который вы хотите использовать во время компиляции. На главной странице проекта есть пример именно этого, доступ к конструктору Singleton.

Вместо JUnit @Test аннотируйте метод, в котором нужно ввести Reflection с помощью @Reflect:

public class Example {
    @com.dp4j.Reflect
    public static void main(final String[] args){
        Foo<String> foo = new Foo("hello");
        System.out.println(foo);
    }   
}

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

Ответ 5

Если класс тестирования Junit (в тестовой папке) имеет то же имя пакета, что и для Actual Class, то из теста Junit Test мы можем вызвать все частные методы для тестирования без какой-либо дополнительной библиотеки, такой как dp4j.

Ответ 6

Существует библиотека для JUnit (dp4j), которая автоматически вставляет код для доступа к приватным методам. Это может быть полезно.