무계 와일드카드 - [OOP & Java#10]

나는 아래의 문장에서 범용과 경계가 있는 어댑터를 토론했다.


비록 나는 범형과 어댑터의 대부분 기초 지식을 소개했지만, 여전히 일부 분야는 더욱 주목하고 토론해야 한다.본문에서 나는 무계 어댑터에 관한 미묘한 점을 쓰고 싶다.

동기


이 주제를 둘러싼 일반적인 질문은 다음과 같습니다.
  • List<?>List<Object> 사이에는 어떤 차이가 있습니까?
  • List<?>List<? extends Object> 사이에는 어떤 차이가 있습니까?
  • 반환 유형은 ? 또는 List<?>?

  • p, 비록 나는 예시에서 List<?> 를 사용했지만, 나는 모든 가능한 범주 유형, 예를 들어 ImmutableList<?> 이라는 사용자 정의 범주 유형을 가리킨다.

    문제 1


    What is the difference between List<?> and List<Object> ?


    우리가 어댑터와 범주를 이야기할 때, 우리의 중점은 항상 유형과 유형이 안전하다.이러한 실현을 사용하는 목적은 다태성을 허용하는 것이다.
    우리가 어댑터가 있을 때, 우리는'any'라는 단어를 생각할 수 있다.List<?>는 가능한 모든 종류의 목록입니다.유형은 알 수 없지만 어떤 유형이든 바꿀 수 있고 표현식이 유효하다는 것을 알고 있습니다.?의 상황은 그렇지 않다.불변성으로 인해 단편적인 유형의 관계는 범용에 적용되지 않는다.
    // This works
    Number[] myArr = new Integer[]();
    
    // This does not work
    List<Number> myDemo = new List<Integer>();
    
    매개변수 선언에 나타나면 다음과 같은 뚜렷한 차이가 있습니다.
    // example method declaration
    void test(ArrayList<?> myList) {}
    
    // example method declaration
    void test2(ArrayList<Object> myList) {}
    
    // this works
    test(new ArrayList<Integer>());
    
    // this works
    test(new ArrayList<Object>());
    
    // this does not work
    test2(new ArrayList<Integer>());
    
    // this works
    test2(new ArrayList<Object>());
    
  • 방법List<Object>은 모든 종류의 목록을 받아들일 수 있다
  • 방법test 유형test2만 받아들일 수 있는 목록
  • Object 다음과 같은 경우에 유용할 수 있습니다.
  • 클래스에서 제공하는 기능만 사용합니다.
  • 작업은 유형 매개 변수에 의존하지 않습니다. 예를 들어 List<?> 정적 방법: Object 또는 List.
  • 문제 2


    What is the difference between List<?> and List<? extends Object> ?


    내가 무계 어댑터를 연구한 후에야 나는 비로소 상술한 상황을 깨달았다.
  • 목록모든 유형의 목록을 표시하는 경계가 없음
  • 목록?확장 대상 > 경계가 있습니다. 대상으로부터 확장된 모든 종류의 목록을 나타냅니다.자바의 모든 클래스가 대상 클래스의 하위 클래스라고 가정하면 여기서도 어떤 종류를 사용할 수 있습니다.
  • 앞의 예를 보면 그들은 모두 같은 목적을 가지고 있는 것 같다.
    void test(ArrayList<?> myList) {}
    
    void test2(ArrayList<? extends Object> myList) {}
    
    // this works
    test(new ArrayList<Integer>());
    
    // this works
    test(new ArrayList<Object>());
    
    // this works
    test2(new ArrayList<Integer>());
    
    // this works
    test2(new ArrayList<Object>());
    
    기사 Java Generics 에서 언급한 차이점은 다음과 같습니다.

    Reifiable types are those whose type is not erased at compile time. In other words, a non-reifiable type's runtime representation will have less information than its compile-time counterpart, because some of it'll get erased. The only exception to this rule is unbounded wildcard types.


    범용 유형은 실행할 때 삭제됩니다.이것은 List.size이 번역된 후에 원시 유형List.clear이 되었다는 것을 의미한다.단, 번역 후 List<Integer>List 로 유지됩니다.만약 우리가 범용 유형에 대한 정보를 가지고 있다면, 우리는 그것에 대해 응용할 수 있다List<?>.
    그래서
  • List<?> 복구 불가능, 실행 중 instanceof 으로 변경됩니다.
  • List<? extends Object>는 복구 가능하며 운행 시 List 로 변경됩니다.
  • // this compiles
    // allowed to use instanceof on unbounded wildcards
    List aList = new ArrayList<Integer>();
    aList instanceof List<?>;
    
    // this does not compile
    // not allowed to use instanceof on bounded wildcards
    aList instanceof List<? extends Object>;
    
    나는 이 차이가 현저하지 않다고 생각하지만, 더 많이 알아도 무방하다:)

    질문


    Can return types be ? or List<?>?


    갑골문Java tutorial에 따르면

    Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards.


    그래서 가능하지만 추천하지 않습니다.실제로 반환 유형 List<?> 또는 List<?> 에 문제가 있습니다.
  • 용도?
  • 반환 유형을 List<?> 로 선언하면 컴파일 오류가 발생합니다.
    test.java:27: error: illegal start of type
        public ? test() {
    error: invalid method declaration; return type required
        public ? test() {
    
  • 용도?
  • 만약 우리가 확실히 이런 방법을 가지고 이 대상을 되돌려준다면, 우리는 어떤 목표 유형으로 그것을 받아들일 수 있습니까?
    // method declaration
    public List<?> test() { return new ArrayList<Integer>();}
    
    // this does not work
    // error: incompatible types: java.util.List<capture#1 of ?> 
    // cannot be converted to java.util.List<java.lang.Integer>
    List<Integer> ls  = test(); 
    
    // this works but may be of little use
    List<?> ls = test(); // does compile
    
    반환된 객체가 실제로는 ? 인 것을 알고 있더라도 List<?> 는 특정 유형(예: List<Integer> 에 할당할 수 없습니다.따라서 목록의 항목에 대해 List<?> 관련 방법을 사용할 수 없습니다.우리는 일반적인 어댑터를 블랙박스로 사용할 수 있는 장점을 얻었지만, 그 후에 우리는 그것을 조작할 능력을 잃었다.

    참고

  • ArrayList Java API
  • Stackoverflow - ? vs object
  • Unbounded Wildcards
  • Java Generics
  • 좋은 웹페이지 즐겨찾기