범용-[OOP&Java#5]

18241 단어 oopjavacomputerscience
이것은 이해하기 어려운 개념이지만, 앞의 몇 편의 문장의 기본 사상을 연결시키고, 자바에서 더욱 간결한 유형 의식 이미지를 나타낸다.
지난 글에서 나는 물건을 소장품에 넣는 필요성에 대해 이야기했다.Python에서는 목록에 정수, 문자열 등을 저장합니다. 자바에서는 기본 모듈이 형식에 따라 특정한 유형의 대상을 저장합니다.
int[] arrayOfInts = new int[2];
String[] arrayOfStrings = new String[2];
그때 파이톤에서 정수와 문자열을 같은 용기에 자유롭게 넣을 수 있을 것 같다고 말했다.나는 또 다른 자유도를 놓쳤다.컨테이너의 컨텐트 유형을 동일하게 유지하면서 Python에서 먼저 일반 목록을 만든 다음 정수 목록으로 사용할지 문자열 목록으로 사용할지 결정할 수 있습니다.Java에서 기본 배열은 유형 선언으로 작성되며 이후에 변경되지 않습니다.이것이 바로 우리가 모조약을 필요로 하는 이유다.

진화하다
서랍이 하나 있다고 가정해 봐.서랍 안에 많은 물건을 넣을 수 있다.조리가 없는 사람으로서 서랍에 라벨을 붙여서 특정한 물품만을 겨냥하고 싶지 않다(한 서랍은 옷을 넣고, 다른 서랍은 서류를 넣는 등).Java에서는 컴파일할 때 유형을 선언해야 하기 때문에 다음 방법을 사용할 수 있습니다.

A drawer can contain an Object.


class Drawer {
  Object obj;
  Drawer(Object obj) {
    this.obj = obj;
  }

  Object get() {
    return this.obj;
  }
}
이제 서랍을 만들 수 있습니다. 컴파일러가 서랍에 무엇을 넣었는지 신경 쓰지 않는 것 같습니다.
// store a shirt into the drawer
Drawer drawer = new Drawer("shirt");
// store integers into the drawer
Drawer drawer = new Drawer(123);

drawer.get() // returns an "Object"
서랍에서 물건을 어떻게 꺼내요?현재 서랍에 저장된 모든 물건은 Object 유형이 될 것이다.서랍에서 물건을 꺼낼 때마다 유형 전환을 책임져야 한다.
Java에서는 컴파일할 때 최소한 런타임 전에 객체가 할 수 있는 작업을 결정합니다.이것은 서랍에서 꺼낸 대상에 대한 어떤 방법도 유형과 호환되어야 한다는 것을 의미한다.만약 항목의 유형이 Object이라면 컴파일러는 Object급의 조작만 안전하게 실행할 수 있다. 예를 들어 toString().
Drawer drawer = new Drawer("shirt");
Drawer drawer = new Drawer(123);

// ERROR: incompatible types: .. Object cannot be converted to String
String shirt = drawer.get();

// Error: ClassCastException Integer cannot be String
String shirt = (String)drawer.get();

Drawer drawer = new Drawer("shirt");
// SAFE: type cast Object to String before assignment
String shirt = (String)drawer.get();
이상에서 두 문제를 설명하였다.
  • 다른 방법이 호출될 수 있도록 서랍에서 꺼낸 항목을 정확한 형식으로 입력해야 합니다.
  • 제1점 때문에 유형 변환이 없는 방법을 사용하면 cannot find symbol 오류가 발생할 수 있습니다.이것은 컴파일러가 말한 "나는 이런 방법이 이런 유형의 대상에 적용될 줄 몰랐다."
  • // ERROR: what I get out is an Object, which does not
    // have a 'length()' method
    new Drawer("string").get().length()
    
    // ERROR: order of casting is wrong
    (String)(new Drawer("string").get()).length()
    
    // SAFE
    ((String)new Drawer("string").get()).length()
    
    이런 방법은 서투르고 잘못되기 쉬워서 서랍에서 물건을 꺼낼 때마다 목적지에서 타자를 쳐야 한다.

    모조약의 탄생
    위 예에서 언급한 문제 및 요구 사항을 해결하기 위해 다음을 수행합니다.
  • 서랍은 옷, 파일 등을 보관하는 용기가 될 수 있고 유형에 따라 유사한 종류만 정의할 필요가 없다.
  • 서랍은 강제 타자를 피하기 위해 물건을 꺼내고 글씨체를 보존하는 것을 허용해야 한다.
  • 편리하지만 서랍은 가능한 한 컴파일러를 이용하여 유형 검사를 해야 한다.
  • 그래서 우리는 다음과 같은 생각을 하게 되었다.
  • '제조'과정에서 어떤 종류의 물품이 서랍에 들어갔는지 설명하지 마세요.
  • 템플릿 시스템의 자유가 있습니다.자리 표시자를 넣고 실제 사용 과정에서 자리 표시자를 실제 값으로 바꿉니다.
  • 범형에 대해서는
  • 클래스/인터페이스/방법 정의에 유형 매개 변수를 포함합니다.
  • 자리 표시자 유형 매개변수는 배치 위치에 따라 클래스/메서드와 같은 다양한 범위에 배치됩니다.
  • 잠시 후, 구체적인 유형 매개 변수로 유형 매개 변수를 대체하여 다태성을 나타낼 것입니다.
  • Terminology: type parameters and type arguments


    // the "T" and "U" below are type parameters
    // generic class declaration
    class Car<T> {}
    // generic method declaration
    public static <U> void doThis(U item) {}
    
    // The "String" below is a type argument
    new Car<String>();
    
    범형으로 서랍을 재정의하다
    class Drawer<T> {
      T obj;
      Drawer(T obj) {
        this.obj = obj;
      }
      T get() {
        return this.obj;
      }
    }
    
    위의 클래스 정의에서 우리는 T에서 <>를 정의했는데 이것은 우리가'자리 차지 문자'를 정의했다는 것을 의미한다.알파벳 'T' 는 매우 간단합니다. 'U', 'O' 등 다른 문자열로 변경할 수 있습니다. 이런 의미에서 'T' 는 변수로 볼 수 있으며, 나중에 지정할 유형을 저장할 수 있습니다.자리 표시자가 여러 개 있을 수 있습니다.

    Java의 일반 유형 매개변수 이름
    성함

    E
    원소.
    K
    열쇠.
    다섯
    가치관
    N
    번호
    T
    타입
    현재 검색 대상은 매우 쉽다.
    // PREVIOUSLY
    Drawer drawer = new Drawer("string");
    ((String)drawer.get()).length()
    
    // CURRENT
    Drawer<String> drawer = new Drawer<String>("string");
    drawer.get().length()
    
    클래스 정의 중의 유형 매개 변수의 사상에 따라 우리는 방법에 대해 같은 조작을 집행할 수 있다.
    // type parameter | return type | method name | method arguments
    <U> Drawer<U> customDrawer(U obj) {
      return new Drawer<U>(obj);
    }
    
    범용 방법에 대해 유형 매개 변수의 작용역은 방법 자체이다.만약 이 방법이 일반 클래스에 있다면, 이 방법의 유형 매개 변수는 이 클래스의 유형 매개 변수와 무관하다.
    우리도 범형 방법을 범형류에 넣을 수 있다.다시 한 번 주의하지만, 이 두 종류의 매개 변수는 서로 다른 범위 내에 있다.
    class Drawer<T> {
      T obj;
      Drawer(T obj) {
        this.obj = obj;
      }
      T get() {
        return this.obj;
      }
      static <U> Drawer<U> customDrawer(U u) {
        return new Drawer<U>(u);
      }
    }
    
    // calling the static method like this
    Drawer<Integer> drawer = Drawer.customDrawer(123);
    drawer.get() // outputs 123
    

    자동 포장 및 분리
    일반적으로 자바가 원시 데이터 형식을 인용 형식으로 자동으로 처리하는 방법에 대한 토론은 자바 과정의 초기에 소개되었다.모조약은 이 개념을 재검토했다.
  • 범형은 인용 형식만 형식 매개 변수로 받아들인다.
  • // ERROR, does not accept primitive types
    Drawer<int> drawer = new Drawer<int>(123);
    
  • 일반 지원 기본 데이터 유형과 참고 데이터 유형 간의 표준 자동 포장 및 해체 행위
  • // auto-boxing
    Drawer<Interger> drawer = new Drawer<Integer>(123);
    
    // retrieve the Integer within the drawer 
    Integer x = drawer.get();
    
    // auto-unboxing
    int x = drawer.get();
    

    유형 차이
    협방차
    역변했어
    변하지 않았어
    하위 유형 관계
    보존
    거꾸로 했어
    보류도 역전도 없다
    이런 전문 어휘를 두려워하지 말고 예를 들어 봅시다.
    협방차

    A subclass relationship can be extended to complex data types such as Array.


    // since Integer is a subtype/subclass of Object
    Object o = new Integer(123);
    // this relationship is preserved in Java arrays
    Object[] arr = new int[1];
    
    역변했어

    The opposite of Covariance. Will be addressed in details when we discuss wildcards in the following article 😂


    변하지 않았어
    // ERROR
    Drawer<Object> drawer = new Drawer<Integer>(123);
    
    // SAFE
    Drawer<Integer> drawer = new Drawer<Integer>(123);
    
    범형은 변하지 않는다.따라서 등호의 왼쪽과 오른쪽에서 대체되는 유형 매개 변수는 항상 같아야 한다.따라서 우리는 오른쪽Integer을 생략할 수 있다.
    Drawer<Integer> drawer = new Drawer<>(123);
    
    자바는 정확한 유형을 추정할 수 있습니다.
    다음은 와일드카드💨

    복제약에 관한 NUS CS2030S 강좌를 참고하여 작성한 부언

    좋은 웹페이지 즐겨찾기