매개 변수 유형의 객체 인스턴스화


89

다음과 같은 템플릿 클래스가 있습니다.

class MyClass<T>
{
    T field;
    public void myMethod()
    {
       field = new T(); // gives compiler error
    }
}

내 클래스에서 T의 새 인스턴스를 만들려면 어떻게해야합니까?

답변:


86

타입 삭제 한 후에 대해 알려진 모든이 T가 어떤 서브 클래스이다 Object. 인스턴스를 만들려면 몇 가지 팩토리를 지정해야합니다.T .

한 가지 접근 방식은 다음을 사용할 수 있습니다 Supplier<T>.

class MyClass<T> {

  private final Supplier<? extends T> ctor;

  private T field;

  MyClass(Supplier<? extends T> ctor) {
    this.ctor = Objects.requireNonNull(ctor);
  }

  public void myMethod() {
    field = ctor.get();
  }

}

사용법은 다음과 같습니다.

MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);

또는 Class<T>개체를 제공 한 다음 반사를 사용할 수 있습니다.

class MyClass<T> {

  private final Constructor<? extends T> ctor;

  private T field;

  MyClass(Class<? extends T> impl) throws NoSuchMethodException {
    this.ctor = impl.getConstructor();
  }

  public void myMethod() throws Exception {
    field = ctor.newInstance();
  }

}

어떤 패키지 Supplier에 있습니까? `MyClass (Class <? extends T> impl)`는`throws NoSuchMethodException`을 선언해야 컴파일됩니다. 귀하의 답변은 불행히도 Java 초보자에게 친숙하지 않습니다.
purucat

@ user927387java.util.function.Supplier
에릭슨

Supplier <T>는 가치있는 곳에 Java 8, JFTR이 필요합니다.
Fran Marzoa

14

또 다른 비 반사 접근 방식은 하이브리드 빌더 / 추상 팩토리 패턴을 사용하는 것입니다.

Effective Java에서 Joshua Bloch는 Builder 패턴을 자세히 살펴보고 일반적인 Builder 인터페이스를 옹호합니다.

public interface Builder<T> {
  public T build();
}

콘크리트 빌더는이 인터페이스를 구현할 수 있으며 외부 클래스는 콘크리트 빌더를 사용하여 필요에 따라 빌더를 구성 할 수 있습니다. 빌더는 MyClass에 Builder<T>.

이 패턴을 사용하면 생성자 매개 변수가 있거나 추가 구성이 필요한 T경우에도 의 새 인스턴스를 가져올 수 T있습니다. 물론 Builder를 MyClass로 전달할 방법이 필요합니다. MyClass에 아무것도 전달할 수 없으면 Builder와 Abstract Factory가 종료됩니다.


12

이것은 당신이 찾고있는 것보다 더 무겁지만 작동 할 것입니다. 이 방법을 사용하면 호출 될 때마다 메서드에 전달하는 대신 생성 될 때 MyClass에 팩토리를 삽입하는 것이 더 합리적입니다.

interface MyFactory<T> 
{
    T newObject();
}

class MyClass<T> 
{
    T field;
    public void myMethod(MyFactory<T> factory)
    {
       field = factory.newObject()
    }
}

1
훌륭하고 비반 사적인 접근 방식; 반사는 항상 옵션이 아닙니다. myMethod는 MyFactory <? 확장 T>, 맞죠?
erickson

1
좋은 호출-myMethod ()에서 T 유형의 개체와 T의 하위 클래스를 만들 수 있도록 팩토리에 경계가있는 와일드 카드를 배치하고 싶을 것입니다.
Dan Hodge


-3

classOfT 클래스

        try {
            t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
        } catch (Exception e) {
            e.printStackTrace();
        }

2
그 classOfT 클래스는 어디에 선언되어 있습니까?
Fran Marzoa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.