클래스 이름과 호출 생성자를 사용하여 인스턴스 만들기


312

클래스 이름 (동적)이 주어진 특정 클래스의 인스턴스를 만들고 매개 변수를 생성자에 전달하는 방법이 있습니까?

다음과 같은 것 :

Object object = createInstance("mypackage.MyClass","MyAttributeValue");

"MyAttributeValue"의 생성자에 대한 인수는 어디에 있습니까 MyClass?

답변:


497

예, 다음과 같습니다.

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });

물론 단일 문자열 매개 변수에서만 작동하지만 쉽게 수정할 수 있습니다.

클래스 이름은 네임 스페이스를 포함하여 정규화 된 이름이어야합니다. 중첩 클래스의 경우 1 달러를 사용해야합니다 (컴파일러가 사용하는 방식). 예를 들면 다음과 같습니다.

package foo;

public class Outer
{
    public static class Nested {}
}

이를 위해 Class객체 를 얻으 려면가 필요합니다 Class.forName("foo.Outer$Nested").


5
newInstance()varargs 메서드 (와 마찬가지로 GetConstructor())이므로 명시 적 Object배열 생성이 필요하지 않습니다 .
Joachim Sauer

18
@Joachim : varargs라는 것을 알고 있지만 Object[]인수가 있을 때 까다로울 수 있으므로이 경우 명시 적으로 배열을 만드는 것을 선호합니다.
Jon Skeet

2
clazz.getConstructor (String.class); 왜 String.class입니까?
Umair A.

2
@Neutralizer : 예,하지만 역동적 일 필요가없는 질문에 대답하고있었습니다.
Jon Skeet

3
@ JonSkeet 나는 당신이 어디에서 왔는지 이해하지만, 그렇게 간단하지는 않습니다-나는 문서를 보았지만 혼란 스러웠지만 그것을 테스트하고 작동하면-작동했습니다-그러나 작동하지 않으면 문제가 구성 부족이나 내 문제로 인한 것인지 확실하지 않은 경우가 많았습니다. 종종 간단한 질문을 할 때 사람들은 유용한 도움을주는 유용한 음식을 먹습니다. 그렇기 때문에 "그렇게 작동 할 것입니다." 하지만 지금은 이해가
안된다는

97

원하는 클래스 Class.forName()Class객체 를 얻는 데 사용할 수 있습니다 .

그런 다음을 사용 getConstructor()하여 원하는 Constructor객체 를 찾으십시오 .

마지막으로 newInstance()해당 객체를 호출 하여 새 인스턴스를 가져옵니다.

Class<?> c = Class.forName("mypackage.MyClass");
Constructor<?> cons = c.getConstructor(String.class);
Object object = cons.newInstance("MyAttributeValue");

81

반사를 사용할 수 있습니다

return Class.forName(className).getConstructor(String.class).newInstance(arg);

3
기본 생성자를 사용하는 경우 String.class 매개 변수 값을 제거하십시오. 예 : return Class.forName (className) .getConstructor (). newInstance (arg);
Vijay Kumar

21
@VijayKumar 제 생각에는 Class.forName(className).getConstructor().newInstance();;)
Peter Lawrey

14

클래스에 빈 생성자가 하나만있는 경우 (예 : Activity 또는 Fragment 등, Android 클래스) :

Class<?> myClass = Class.forName("com.example.MyClass");    
Constructor<?> constructor = myClass.getConstructors()[0];

2
이것이 나를 도왔습니다. Constructor<?> ctor = clazz.getConstructor(String.class)나를 위해 작동하지 않는 것 같습니다.
Leo C Han

8

(즉) getConstructor(String.lang)생성자를 사용할 때는 public으로 선언해야합니다. 그렇지 않으면 a NoSuchMethodException가 발생합니다.

비공개 생성자 에 액세스 하려면 대신 (즉) 사용해야합니다 getDeclaredConstructor(String.lang).



4

Class<?>생성자 인수를 전달 하여 Java로 객체를 만드는 매우 간단한 방법 :

사례 1 :- 여기 에이 Main클래스 의 작은 코드가 있습니다 .

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Main {

    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

        // Get class name as string.
        String myClassName = Base.class.getName();
        // Create class of type Base.
        Class<?> myClass = Class.forName(myClassName);
        // Create constructor call with argument types.
        Constructor<?> ctr = myClass.getConstructor(String.class);
        // Finally create object of type Base and pass data to constructor.
        String arg1 = "My User Data";
        Object object = ctr.newInstance(new Object[] { arg1 });
        // Type-cast and access the data from class Base.
        Base base = (Base)object;
        System.out.println(base.data);
    }

}

그리고, 여기에 있습니다 Base클래스 구조는 :

public class Base {

    public String data = null;

    public Base() 
    {
        data = "default";
        System.out.println("Base()");
    }

    public Base(String arg1) {
        data = arg1;
        System.out.println("Base("+arg1+")");
    }

}

사례 2 :- 여러 인수와 복사 생성자를 사용하여 생성자를 유사하게 코딩 할 수 있습니다. 예를 들어, Base생성자에 매개 변수로 3 개의 인수를 전달 하면 클래스에서 생성자를 작성하고 위와 같이 코드를 변경해야합니다.

Constructor<?> ctr = myClass.getConstructor(String.class, String.class, String.class);
Object object = ctr.newInstance(new Object[] { "Arg1", "Arg2", "Arg3" }); 

그리고 여기 Base 클래스는 어떻게 생겼을까 요?

public class Base {

    public Base(String a, String b, String c){
        // This constructor need to be created in this case.
    }   
}

참고 :- 코드에서 처리해야하는 다양한 예외를 처리하는 것을 잊지 마십시오.


또 다른 방법은 기존 Java 객체를 clone ()하는 것입니다. 기존 Java 오브젝트의 사본이 작성됩니다. 이 경우 Deep copy 또는 Shallow copy 개념도 처리해야합니다.
Rahul Raina

2

누구나 싱글 톤 패턴을 따르는 클래스에도 불구하고 클래스의 인스턴스를 만드는 방법을 찾고 있다면 여기에 방법이 있습니다.

// Get Class instance
Class<?> clazz = Class.forName("myPackage.MyClass");

// Get the private constructor.
Constructor<?> cons = clazz.getDeclaredConstructor();

// Since it is private, make it accessible.
cons.setAccessible(true);

// Create new object. 
Object obj = cons.newInstance();

이것은 개인 생성자를 사용하여 싱글 톤 패턴을 구현하는 클래스에서만 작동합니다.


1

생성 된 객체 내에서 메소드를 호출 할 수도 있습니다.

첫 번째 constractor를 호출하여 생성 된 객체에서 첫 번째 메소드를 호출하여 객체 인스턴트를 생성 할 수 있습니다.

    Class<?> c = Class.forName("mypackage.MyClass");
    Constructor<?> ctor = c.getConstructors()[0];
    Object object=ctor.newInstance(new Object[]{"ContstractorArgs"});
    c.getDeclaredMethods()[0].invoke(object,Object... MethodArgs);

첫 번째 생성자가 String매개 변수로 사용 된다는 것을 어떻게 알 수 있습니까? 생성자 순서를 변경할 때 약간 지저분해진다
Farid

클래스 문서에서 @Farid
하템 바다 위

여전히 getConstructor(ClassName.class)더 낫습니다. 생성자의 순서가 클래스에서 변경 되더라도 수동으로 위치를 찾을 필요가 없습니다.
Farid

@Farid-c.getDeclaredMethods () [0] .invoke (object, Object ... MethodArgs); 경우에 따라 특수 생성자를 지정하지만 이것이 필요할 수도 있지만 옳습니다.
Hatem Badawi

1

또 다른 유용한 답변. getConstructor (params) .newInstance (args)는 어떻게 사용합니까?

return Class.forName(**complete classname**)
    .getConstructor(**here pass parameters passed in constructor**)
    .newInstance(**here pass arguments**);

필자의 경우 클래스 생성자는 Webdriver를 매개 변수로 사용하므로 아래 코드에서 사용됩니다.

return Class.forName("com.page.BillablePage")
    .getConstructor(WebDriver.class)
    .newInstance(this.driver);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.