programing tip

Java : 유형 매개 변수로 개인 생성자에 액세스

itbloger 2020. 11. 12. 07:59
반응형

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")using 리플렉션을 어떻게 구성 합니까?

대답

jtahlborn의 답변을 기반으로 다음과 같이 작동합니다.

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);
    }   
}

클래스를 가져 와서 T의 하한이있는 단일 인수 (이 경우 Object)를 사용하는 생성자를 찾고, 생성자가 액세스 할 수 있도록 ( setAccessible메소드 사용) 마지막으로 원하는 인수로 호출해야합니다.


getDeclaredConstructors생성자를 가져올 때 사용 하고 private이므로 접근성을 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);

개인 생성자가 인수를 취하지 않으면 새 인스턴스를 생성하는 동안 문제를 가져옵니다.이 경우 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 : 내 블로그의 "Eager Initialization"및 "Singleton Violation by reflection": http://sanjaymadnani.wordpress.com/2014/04/14/singleton-design-pattern-in-java/


As @ArtB said you could use dp4j.com, if you know the constructor you want to use at compile-time. On the project homepage there's an example of just that, accessing a Singleton constructor.

Instead of JUnit's @Test annotate the method in which to inject the Reflection with @Reflect:

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

To see the reflection generated code use -Averbose=true argument as in this answer.


If Junit Test Class (in Test Folder) has the same package name as of Actual Class, then from Junit Test case, we can call all private methods to test, without any additional library like dp4j.


There is a library for JUnit (dp4j) that automatically inserts code for accessing private methods. That may be of use.


At first I was getting NoSuchMethodException using reflection.

Use this:

Constructor<TestClass> constructor= (Constructor<TestClass>) TestClass.class.getDeclaredConstructors()[0];

참고URL : https://stackoverflow.com/questions/5629706/java-accessing-private-constructor-with-type-parameters

반응형