Java에서 이름으로 클래스를 인스턴스화하는 방법이 있습니까?


102

나는 질문으로보고 있었다 : 이름 을 가질 때 클래스를 인스턴스화하는 방법을 설명하는 문자열 이름 에서 클래스를 인스턴스화하십시오. Java로 수행하는 방법이 있습니까? 패키지 이름과 클래스 이름을 갖게되며 특정 이름을 가진 개체를 만들 수 있어야합니다.


우리 는 클래스를 인스턴스화 하고 결과는 객체 (또는 : instance )입니다.
안드레아스 돌크

1
대답은 '예,하지만 난 당신이 요청해야한다고 생각 하면 그것 좋은 아이디어입니다. 큰 힘 (반성)에는 큰 책임이 따르며 그 결과를 이해하고 고려한 경우에만 사용해야합니다.
c1moore

답변:


238

두 가지 방법:

방법 1-인수가없는 생성자가있는 클래스에만 해당

클래스에 인수가없는 생성자가있는 경우 메서드를 사용하여 Class객체를 가져오고이 메서드를 사용하여 인스턴스를 만들 수 있습니다 (이 메서드는 Java의 확인 된 예외를 무효화 할 수 있기 때문에 종종 악의적 인 것으로 간주됩니다 ).Class.forName()newInstance()

예를 들면 :

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

방법 2

클래스에 인수가없는 생성자가없는 경우에도 작동하는 더 안전한 방법은 클래스 개체를 쿼리하여 해당 Constructor개체 를 가져오고이 개체에 대한 newInstance()메서드를 호출하는 것입니다.

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

두 방법 모두 반사라고 합니다. 일반적으로 다음과 같은 것을 포함하여 발생할 수있는 다양한 예외를 포착해야합니다.

  • JVM이 클래스를 찾을 수 없거나로드 할 수 없습니다.
  • 인스턴스화하려는 클래스에 올바른 종류의 생성자가 없습니다.
  • 생성자 자체에서 예외가 발생했습니다.
  • 호출하려는 생성자가 공개되지 않았습니다.
  • 보안 관리자가 설치되어 반사가 발생하지 않습니다.

안녕하세요,에서 객체를 생성 한 후 newInstance()다시 자신의 객체로 캐스트 할 수 있습니까?
GMsoF 2014 년

@Simon 보안 관리자에 대해 자세히 설명하거나 조언 해 줄 수 있습니까?

나는 이것을 이해하지 못한다. 다른 디렉토리에있는 알 수없는 파일의 클래스에 액세스하고 싶습니다. 경로 / 파일의 이름 만 문자열로 가지고 있습니다. 문자열 "dir / unkonwn.java". Class.forName ( "dir / unknown")을 호출하면 오류가 발생합니다.
john ktejik

어떻게 캐스트 instance할 수 com.foo.MyClass있습니까? 주어진 com.foo.MyClass은 단지 문자열
Sanket9394

14
MyClass myInstance = (MyClass) Class.forName("MyClass").newInstance();

15
클래스에 매개 변수없는 생성자가 없거나 (다른 생성자가있는 경우), 매개 변수없는 생성자가 액세스 할 수없는 경우에는 작동하지 않는다는 점을 언급 할 가치가 있습니다.
Dawood ibn Kareem

3

use Class.forName ( "클래스의 문자열 이름") .newInstance ();

Class.forName("A").newInstance();

이로 인해 A라는 클래스가 초기화됩니다.


패키지 이름이 추가되어 있어도 작동하지 않습니다. :(
trusktr

3

를 사용하여 인스턴스를 생성하기 위해 클래스의 정규화 된 이름을 더 쉽게 얻으려면 메서드를 Class.forName(...)사용할 수 있습니다 Class.getName(). 다음과 같은 것 :

class ObjectMaker {
    // Constructor, fields, initialization, etc...
    public Object makeObject(Class<?> clazz) {
        Object o = null;

        try {
            o = Class.forName(clazz.getName()).newInstance();
        } catch (ClassNotFoundException e) {
            // There may be other exceptions to throw here, 
            // but I'm writing this from memory.
            e.printStackTrace();
        }

        return o;
    }
}

그런 다음 전달하는 클래스로 돌아가는 객체를 캐스팅 할 수 있습니다 makeObject(...).

Data d = (Data) objectMaker.makeObject(Data.class);

1
당신은 단순히 그때 clazz.newInstance()대신 할 수 없습니까 ? getNamefromName
user276648 dec.

1

자바 리플렉션 사용

새 객체 생성 생성자를 호출하는 것은 새 객체를 생성하는 것과 동일하기 때문에 생성자에 대한 메서드 호출과 동일한 것은 없습니다 (가장 정확하게 말하면 새 객체를 생성하려면 메모리 할당과 객체 생성이 모두 포함됨). 따라서 이전 예제와 가장 가까운 것은 다음과 같습니다.

import java.lang.reflect.*;

   public class constructor2 {
      public constructor2()
      {
      }

      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }

      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

지정된 매개 변수 유형을 처리하는 생성자를 찾고이를 호출하여 객체의 새 인스턴스를 만듭니다. 이 접근 방식의 가치는 컴파일 시간이 아닌 실행 시간에 생성자 조회 및 호출을 사용하여 순전히 동적이라는 것입니다.



0
String str = (String)Class.forName("java.lang.String").newInstance();

0

이런 식으로 작동합니다 ...

String name = "Test2";//Name of the class
        Class myClass = Class.forName(name);
        Object o = myClass.newInstance();

0

사용하여 newInstance()직접 자바 8. 추천되지 않습니다 당신 사용할 필요가 Class.getDeclaredConstructor(...).newInstance(...)해당 예외.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.