[java] 제네릭 클래스의 정적 메소드?

Java에서는 다음과 같은 것을 갖고 싶습니다.

class Clazz<T> {
  static void doIt(T object) {
    // ...
  }
}

그러나 나는 얻는다

비 정적 유형 T에 대한 정적 참조를 만들 수 없습니다

기본 용도 이외의 제네릭을 이해하지 못하므로 이해가되지 않습니다. 인터넷에서 주제에 관한 많은 정보를 찾을 수 없었습니다.

비슷한 방식으로 그러한 사용이 가능한지 누군가가 분명히 말할 수 있습니까? 또한, 원래의 시도가 실패한 이유는 무엇입니까?



답변

정적 메소드 또는 정적 필드에는 클래스의 일반 유형 매개 변수를 사용할 수 없습니다. 클래스의 유형 매개 변수는 인스턴스 메소드 및 인스턴스 필드에만 적용됩니다. 정적 필드와 정적 메서드의 경우 클래스의 모든 인스턴스, 다른 유형 매개 변수의 인스턴스간에 공유되므로 특정 유형 매개 변수에 의존 할 수 없습니다.

문제가 클래스의 type 매개 변수를 사용해야하는 것처럼 보이지 않습니다. 당신이하려는 일을 더 자세하게 설명한다면, 우리는 당신이 그것을하는 더 좋은 방법을 찾도록 도울 수 있습니다.


답변

Java는 T유형을 인스턴스화 할 때까지 무엇을 알지 못합니다 .

어쩌면 호출하여 정적 메소드를 실행할 수 Clazz<T>.doit(something)있지만 할 수없는 것처럼 들립니다.

일을 처리하는 다른 방법은 type 매개 변수를 메서드 자체에 넣는 것입니다.

static <U> void doIt(U object)

U에 대한 올바른 제한은 없지만 아무것도 아닌 것보다 낫습니다 ….


답변

나는이 같은 문제에 부딪쳤다. Collections.sortJava 프레임 워크에서 소스 코드를 다운로드하여 답변을 찾았습니다 . 내가 사용한 대답 <T>은 클래스 정의가 아닌 메소드에 제네릭 을 넣는 것이 었습니다 .

그래서 이것은 효과가 있었다 :

public class QuickSortArray  {
    public static <T extends Comparable> void quickSort(T[] array, int bottom, int top){
//do it
}

}

물론 위의 답변을 읽은 후에는 이것이 일반적인 클래스를 사용하지 않고 수용 가능한 대안이라는 것을 깨달았습니다.

public static void quickSort(Comparable[] array, int bottom, int top){
//do it
}


답변

메소드를 선언 할 때 일반 메소드의 구문을 사용하여 원하는 것을 수행 할 수 있습니다 doIt()( 의 메소드 서명 <T>사이에 staticvoid메소드 서명에 추가됨 doIt()).

class Clazz<T> {
  static <T> void doIt(T object) {
    // shake that booty
  }
}

Eclipse 편집기에서 Cannot make a static reference to the non-static type T오류 없이 위의 코드를 수락 한 다음 다음 작업 프로그램으로 확장했습니다 (약식 연령에 적합한 문화 참조로 완료).

public class Clazz<T> {
  static <T> void doIt(T object) {
    System.out.println("shake that booty '" + object.getClass().toString()
                       + "' !!!");
  }

  private static class KC {
  }

  private static class SunshineBand {
  }

  public static void main(String args[]) {
    KC kc = new KC();
    SunshineBand sunshineBand = new SunshineBand();
    Clazz.doIt(kc);
    Clazz.doIt(sunshineBand);
  }
}

콘솔을 실행할 때 다음 줄을 콘솔에 인쇄합니다.

그 전리품을 흔들어 ‘class com.eclipseoptions.datamanager.Clazz $ KC’!!!
그 전리품을 흔들어 ‘class com.eclipseoptions.datamanager.Clazz $ SunshineBand’!!!


답변

이 구문은 아직 언급되지 않았다고 생각합니다 (인수가없는 메소드를 원할 경우).

class Clazz {
  static <T> T doIt() {
    // shake that booty
  }
}

그리고 전화 :

String str = Clazz.<String>doIt();

이것이 누군가를 돕기를 바랍니다.


답변

그것은 제대로 오류에서 언급 한 : 당신이 비 정적 T 형식에 대한 정적 참조를 만들 수없는 이유는 유형 매개 변수입니다 T유형 인수 등의로 대체 될 수 Clazz<String>또는 Clazz<integer>등 그러나 정적 필드 / 메소드는 모든 비에서 공유 클래스의 정적 객체.

다음 발췌 내용은 문서 에서 발췌 한 것입니다 .

클래스의 정적 필드는 클래스의 모든 비 정적 객체가 공유하는 클래스 수준 변수입니다. 따라서 매개 변수 유형의 정적 필드는 허용되지 않습니다. 다음 클래스를 고려하십시오.

public class MobileDevice<T> {
    private static T os;

    // ...
}

매개 변수 유형의 정적 필드가 허용 된 경우 다음 코드가 혼동됩니다.

MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();

정적 필드 os는 phone, pager 및 pc에서 공유되므로 실제 os 유형은 무엇입니까? 스마트 폰, 호출기 및 TabletPC 일 수는 없습니다. 따라서 매개 변수 유형의 정적 필드를 작성할 수 없습니다.

chris의 대답 에서 올바르게 지적 했듯이이 경우 클래스가 아닌 메소드와 함께 유형 매개 변수를 사용해야합니다. 다음과 같이 작성할 수 있습니다.

static <E> void doIt(E object) 


답변

다음과 같은 것이 당신을 더 가깝게 할 것입니다

class Clazz
{
   public static <U extends Clazz> void doIt(U thing)
   {
   }
}

편집 : 자세한 내용으로 업데이트 된 예

public abstract class Thingo
{

    public static <U extends Thingo> void doIt(U p_thingo)
    {
        p_thingo.thing();
    }

    protected abstract void thing();

}

class SubThingoOne extends Thingo
{
    @Override
    protected void thing()
    {
        System.out.println("SubThingoOne");
    }
}

class SubThingoTwo extends Thingo
{

    @Override
    protected void thing()
    {
        System.out.println("SuThingoTwo");
    }

}

public class ThingoTest
{

    @Test
    public void test()
    {
        Thingo t1 = new SubThingoOne();
        Thingo t2 = new SubThingoTwo();

        Thingo.doIt(t1);
        Thingo.doIt(t2);

        // compile error -->  Thingo.doIt(new Object());
    }
}