programing

일반 클래스의 정적 메서드?

prostudy 2022. 4. 24. 09:38
반응형

일반 클래스의 정적 메서드?

자바에서는 다음과 같은 것을 갖고 싶다.

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

하지만 나는 이해한다.

정전기 방지 유형 T를 정적으로 참조할 수 없음

나는 기본적인 용도를 넘어서는 제네릭을 이해하지 못하기 때문에 그것을 잘 이해할 수 없다.내가 그 주제에 대해 인터넷에서 많은 정보를 찾을 수 없었던 것은 도움이 되지 않는다.

이와 유사한 방법으로 그러한 사용이 가능한지 누군가 명확히 할 수 있는가?또한, 왜 나의 원래 시도는 성공하지 못했을까?

정적 메서드나 정적 필드에는 클래스의 일반 유형 매개 변수를 사용할 수 없다.클래스의 형식 매개 변수는 인스턴스 메서드와 인스턴스 필드에만 해당된다.정적 필드 및 정적 메서드의 경우, 클래스의 모든 인스턴스, 심지어 다른 유형 매개변수의 인스턴스 간에 공유되므로 특정 유형 매개변수에 의존할 수 없다.

당신의 문제가 클래스의 유형 매개변수를 사용하는 것을 요구해서는 안 될 것 같다.네가 하고자 하는 일을 좀 더 자세히 설명한다면, 우리가 더 나은 방법을 찾을 수 있도록 도와줄 수 있을 거야.

는 자바가 T유형을 인스턴스화할 때까지요

아마도 당신은 전화를 걸어 정적 메소드를 실행할 수 있을 것이다.Clazz<T>.doit(something)그럴 수 없는 것처럼 들리는데

다른 방법은 형식 매개 변수를 방법 자체에 넣는 것이다.

static <U> void doIt(U object)

U에 대한 올바른 제한은 없지만 없는 것보다는 낫지...

나는 이 같은 문제에 부딪쳤다.다음에 대한 소스 코드를 다운로드하여 답을 찾았다.Collections.sort자바 틀에서내가 사용한 답은 '그것'을 넣는 것이었다.<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
}

이 구문은 아직 언급되지 않은 것 같다(논의 없는 방법을 원하는 경우):

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

그리고 통화:

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

이게 누군가에게 도움이 되길 바래.

선언할 때 일반적 방법에 대한 구문을 사용하여 원하는 것을 할 수 있다.doIt()( ()의)<T>사이에static그리고voiddoIt()):

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.supps.datamanager's 를어.클래즈$KC'!!!
그 섹시한 'class com.supps.datamanager's 를어.클래즈$SunshineBand'!!!

그것은 오류에서 정확하게 언급되었다: 당신은 정전기형 T를 정적으로 언급할 수 없다.그 이유는 유형 매개변수 때문이다.T예를 들어, 형식 인수 중 하나로 대체될 수 있다.Clazz<String>또는Clazz<integer>properties의 비정적 된다. 그러나 정적 필드/방법들은 클래스의 모든 비정적 객체에 의해 공유된다.

다음 발췌문은 의사로부터 인용된다.

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

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

    // ...
}

형식 매개 변수의 정적 필드가 허용되면 다음 코드가 혼동될 수 있다.

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

정적 필드 os는 전화, 호출기, pc로 공유되기 때문에 실제 os의 유형은 무엇인가?스마트폰, 호출기, 태블릿PC가 동시에 될 수 없다.따라서 형식 매개 변수의 정적 필드를 생성할 수 없다.

크리스가 답변에서 올바르게 지적했듯이, 당신은 이 경우 클래스가 아닌 메소드에 타입 파라미터를 사용할 필요가 있다.다음과 같이 쓸 수 있다.

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

정적 변수는 클래스의 모든 인스턴스에서 공유되므로예를 들어 다음 코드가 있는 경우

class Class<T> {
  static void doIt(T object) {
    // using T here 
  }
}

인스턴스가 생성된 후에만 T를 사용할 수 있다.그러나 정적 방법은 인스턴스를 사용하기 전에 사용할 수 있다.따라서 일반 유형 매개변수는 정적 방법 및 변수 내에서 참조할 수 없다.

클래스에 대한 일반 유형을 지정하면 JVM은 클래스의 인스턴스만 가지고 있고 정의는 없다는 것을 알고 있다.각 정의에는 매개 변수화된 유형만 있다.

제네릭은 C++의 템플릿처럼 작동하므로 먼저 클래스를 인스턴스화한 다음 지정된 유형을 가진 함수를 사용하십시오.

또한 간단히 말하면, 그것은 제네릭의 "삭제" 속성 때문에 일어난다.그 말은 우리가 정의내리지만ArrayList<Integer>그리고ArrayList<String>컴파일 시 그것은 두 가지 다른 콘크리트 유형으로 유지되지만, 실행 시 JVM은 일반 유형을 지우고 두 클래스 대신 하나의 ArrayList 클래스만 만든다.그래서 우리가 일반에 대한 정적 유형 방법이나 어떤 것을 정의할 때, 그것은 그 일반의 모든 인스턴스에 의해 공유된다, 제 예에서 그것은 양쪽 모두에 의해 공유된다.ArrayList<Integer>그리고ArrayList<String>.그래서 에러가 생기는 겁니다.클래스의 일반 형식 매개 변수는 정적 컨텍스트에서 허용되지 않음!

@Rivenhill의 BD: 이 오래된 질문이 작년에 다시 주목을 받았기 때문에, 단지 토론을 위해서 조금 더 진행합시다.너의 몸은doIt방법은 아무 것도 하지 않는다.T-전혀 특이하다.여기 있다:

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

모든 유형의 변수를 완전히 삭제한 후 코드만 입력하면 됨

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

좋아. 하지만 원래의 문제로 다시 돌아가자.클래스 선언의 첫 번째 유형 변수는 중복이다.그 방법에서 두 번째 방법만 있으면 된다.다시 시작하지만 아직 최종 답은 아니다.

public class Clazz  {
  static <T extends Saying> void doIt(T object) {
    System.out.println("shake that booty "+ object.say());
  }

  public static void main(String args[]) {
    Clazz.doIt(new KC());
    Clazz.doIt(new SunshineBand());
  }
}
// Output:
// KC
// Sunshine

interface Saying {
      public String say();
}

class KC implements Saying {
      public String say() {
          return "KC";
      }
}

class SunshineBand implements Saying {
      public String say() {
          return "Sunshine";
      }
}

하지만, 다음 버전은 똑같은 방식으로 작동하기 때문에, 아무것도 아닌 것에 대해 너무 야단이다.메서드 파라미터의 인터페이스 타입만 있으면 된다.어디에도 활자 변수가 보이지 않는다.그게 정말 원래의 문제였을까?

public class Clazz  {
  static void doIt(Saying object) {
    System.out.println("shake that booty "+ object.say());
  }

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

interface Saying {
      public String say();
}

class KC implements Saying {
      public String say() {
          return "KC";
      }
}

class SunshineBand implements Saying {
      public String say() {
          return "Sunshine";
      }
}

T는 정적 방법의 범위에 있지 않기 때문에 정적 방법에서는 T를 사용할 수 없다.정적 메서드에 대해 다른 유형 매개 변수를 정의하십시오.이렇게 쓰고 싶다.

class Clazz<T> {

  static <U> void doIt(U object) {
    // ...
  }

}

예를 들면 다음과 같다.

public class Tuple<T> {

    private T[] elements;

    public static <E> Tuple<E> of(E ...args){
        if (args.length == 0) 
             return new Tuple<E>();
        return new Tuple<E>(args);
    }

    //other methods
}

참조URL: https://stackoverflow.com/questions/936377/static-method-in-a-generic-class

반응형