제네릭
컬렉션의 요소를 특정 유형으로 제한합니다.
용어
몇 가지 메모 :
매개 변수화 유형과 원시 유형은 서로 호환됩니다.
ArrayList Collection1 = New ArrayList <integer> (); // PASS, 없음, 경고 ARRAYLIST <INTEGER> collection2 = new ArrayList (); // Pass, 경고가 있습니다.
매개 변수화 된 유형은 유형 매개 변수의 상속 관계를 고려하지 않습니다.
ArrayList <String> Collection3 = New ArrayList <Object> (); // 컴파일은 ArrayList <BEARMER4 = NEW ARRAYLIST <String> (); // 컴파일이 전달되지 않습니다.
하지만
ArrayList Collection5 = New ArrayList <integer> (); ArrayList <String> Collection6 = Collection5; // 컴파일
"?" 와일드 카드
"?" 모든 유형을 의미합니다. "?" 다양한 매개 변수화 된 유형을 참조하는 와일드 카드 문자. 매개 변수화 (예 : size) 메소드)와 관련이없는 메소드를 호출 할 수 있으며 매개 변수화와 관련된 메소드 (예 : add) 메소드)를 호출 할 수 없습니다.
와일드 카드 확장
와일드 카드 문자의 상한을 자격하십시오
ArrayList <? 숫자> collection1 = new ArrayList <integer> (); // arraylist <? 숫자> collection2 = new arraylist <string> (); // compile by not을 확장합니다
와일드 카드 문자의 하부 경계를 자격하십시오
ArrayList <? Super Integer> Collection3 = New ArrayList <번호> (); // ArrayList <? Super Integer> Collection4 = New ArrayList <string> (); // Compile By Not
맞춤형 일반 방법
C ++ 템플릿 기능
템플릿 <class t> t add (t x, t y) {return (t) (x+y);}Java Generics는 기본적으로 컴파일러에서 전적으로 구현되며, 컴파일러는 유형 검사 및 유형 판단을 수행 한 다음 일반적인 비 게릭 바이트 코드를 생성하는 데 사용됩니다. 이 구현 기술은 "삭제"입니다.
"지우기"인스턴스
컬렉션의 입력 유형을 정의하기 위해 제네릭이 Javac 컴파일러에 제공됩니다. 컴파일러가 유형 설명이있는 컬렉션을 컴파일하면 "유형"정보가 제거됩니다.
public class generictest {public static void main (String [] args) {new Genericictest (). testType (); } public void testType () {arraylist <integer> collection1 = new ArrayList <integer> (); ArrayList <String> Collection2 = New ArrayList <string> (); System.out.println (collection1.getClass () == collection2.getClass ()); //이 둘의 클래스 유형은 동일합니다. // 클래스는 java.util.arraylist이며 실제 유형 매개 변수 정보가 없습니다}}산출
진실
java.util.arraylist
반사를 사용하여 컴파일러를 건너 뛰고 다른 유형의 데이터를 일반 컬렉션에 추가하십시오.
참조 유형 만 일반 방법의 실제 매개 변수로 사용할 수 있습니다.
공개 클래스 생성 {public static void main (string [] args) {swap (new String [] { "111", "222"}, 0,1); // compile by // swap (new int [] {1,2}, 0,1); // int가 참조 유형 스왑이 아니기 때문에 컴파일하지 않음으로 컴파일합니다 (새 정수 [] {1,2}, 0,1); //}/*배열의 i-th 및 jth 요소를 교체합니다 a*/public static <t> void swap (t [] a, int i, int j) {t temp = a]; a [i] = a [j]; A [J] = 온도; }}그러나 자동 포장 및 개봉이 있기 때문에 기본 유형은 때때로 실제 매개 변수로 사용할 수 있습니다. 예제 (컴파일 및 통과) :
public class generictest {public static void main (String [] args) {new Genericictest (). testType (); int a = 더 큰 사람 (3,5); // int 및 double, 인터체인지를 숫자 번호 b = Biggerone (3,5.5)로 가져옵니다. // 문자열과 int 객체 객체 C = BiggerOne ( "1", 2)로 인터체인지를 가져옵니다. } // x에서 y, y public static <t> t biggerone (t x, t y) {return y; }}동시에,이 예제는 실제 매개 변수가 일치하지 않으면 T가 교차로, 즉 첫 번째 공통 상위 클래스를 취한다는 것을 보여줍니다. 또한 숫자 b = Biggerone (3,5.5)을 사용하는 경우; 문자열 c = Biggerone (3,5.5); 그런 다음 컴파일 오류 가보고됩니다.
오류 : (17, 29) Java : 호환되지 않는 유형 : 추론 된 유형은 상한 추론을 충족하지 않습니다 : java.lang.number & java.lang.comparable? java.lang.number & java.lang.comparable을 확장합니다
상한 : java.lang.string, java.lang.object
그러나 내가 이해하지 못한 한 가지가 있습니다. 아이디어에서 단계별 디버깅을했는데 결과는 다음과 같습니다. 일반 디버깅 스크린 샷 -1 왜 B가 Double 인 이유를 모르겠습니다 (그러나 Double B에서 반환 값을 수신 할 때 오류를 컴파일하고보고합니다). IDE와 관련이 있는지 모르겠습니다. IDE가 디버깅 할 때 가장 정확한 유형 의이 객체를 표시합니까?
유형 매개 변수의 유형 추론
컴파일러가 일반 방법의 실제 유형 매개 변수를 판단하는 프로세스를 유형 추론이라고합니다.
특정 유형 변수가 전체 매개 변수 목록에서 모든 매개 변수 중 하나와 리턴 값만 적용되면 메소드가 호출되는 시간의 실제 응용 프로그램 유형에 따라 결정됩니다. 즉, 일반 매개 변수의 유형은 메소드가 호출 될 때 전달되는 매개 변수 유형 또는 반환 값에 따라 직접 결정됩니다. 예를 들어:
스왑 (새 문자열 [3], 1,2) -> static <e> void swap (e [] a, int i, int j)
전체 매개 변수 목록의 모든 매개 변수 및 리턴 값의 여러 위치에 유형 변수가 적용될 때, 많은 실제 응용 프로그램 유형이 메소드를 호출 할 때 동일한 유형에 해당하는 경우 일반 매개 변수의 유형이 해당 유형입니다. 예를 들어:
추가 (3,5) -> static <t> t add (t a, t b)
전체 매개 변수 목록의 모든 매개 변수 및 리턴 값의 여러 위치에 특정 유형 변수가 적용되는 경우, 많은 장소의 실제 응용 프로그램 유형이 메소드를 호출 할 때 다른 유형에 해당하고 여러 매개 변수, 즉 첫 번째 공통 상위 클래스 간의 최대 교차 유형이없는 경우. 예를 들어:
채우기 (새 정수 [3], 3.5) -> static <t> void Fill (t a [], t v)
이 예제의 실제 해당 유형은 숫자, 컴파일 및 실행 문제입니다.
전체 매개 변수의 여러 위치에 유형 변수가 적용되는 전체 매개 변수 목록의 여러 위치에 적용되는 경우, 많은 장소의 실제 응용 프로그램 유형이 메소드를 호출 할 때 다른 유형에 해당하고 리턴 값이 있으면 반환 값의 유형에 우선 순위가 부여됩니다.
int x = add (3,3.5) -> static <t> t add (t a, t b)
위의 예제 컴파일 된 오류와 x 유형이 플로트로 변경되어 오류가보고되었으며 숫자 변경이 성공적입니다.
파라미터 유형의 유형 추론의 예는 전이적입니다.
복사 (새 정수 [5], 새 문자열 [5]) -> static <t> void Copy (t [] a, t [] b)
이 예제는 실제 매개 변수 유형이 객체이고 컴파일 된 것을 추론합니다.
복사 (new arraylist <string>, new Integer [5]) -> static <t> void Copy (collection <t> a, t [] b)
이 예제는 매개 변수화 된 ArrayList 클래스 인스턴스를 기반으로 유형 변수를 문자열 유형으로 직접 결정하고 컴파일에 오류를보고합니다.
맞춤형 일반 클래스
예
public class genericdao <t> {public void add (t x) {} public t findbyid (int id) {return null; } public void delete (t obj) {} public void delete (int id) {} public void update (t obj) {} public t findbyusername (String name) {return null; } public <t> set <t> findByConditions (String where) {return null; }}참고 : 변수가 일반적인 것으로 선언되면 인스턴스 변수 및 메소드 (및 임베디드 유형)에 의해서만 호출 될 수 있지만 정적 변수 및 정적 메소드는 아닙니다. 정적 멤버는 매개 변수화 된 클래스에 의해 공유되므로 정적 멤버에게는 클래스 수준 유형 매개 변수가 없어야합니다.
일반적인 방법과 일반 클래스 비교
예:
public class a <t> () {// 일반 클래스의 멤버 메소드, t는 public t memberfunc () {return null; } // 일반 방법, 여기서 t와 t는 클래스 A 공개 정적 <t> t genericfunc (t a) {return null; } public static void main (String [] args) {// 컴파일없이 컴파일 된 // 정수 i = a <string> (). findByUserName ( "s"); // set <integer> set = a <string> (). findByConditions ( "s")에 의해 컴파일되었습니다. }}여기 정수 i = a <string> (). findByUserName ( "S"); 오류를 컴파일하고보고합니다.
오류 : (35, 61) Java : 호환되지 않는 유형 : java.lang.string은 java.lang.integer로 변환 할 수 없습니다.
이 예에서, 일반 방법의 t와 클래스 A의 t는 다르다는 것을 알 수있다.
제네릭과 반사
반사를 통해 제네릭의 실제 유형 매개 변수 얻기
일반 변수를 메소드의 매개 변수로 사용하고 메소드 클래스의 getGenericParameterTypes 메소드를 사용하여 일반 유형 매개 변수 예를 얻으십시오.
public class generictest {public static void main (String [] args)은 예외 {getParamtype (); } /*반사를 사용하여 실제 매개 변수 유형의 메소드 매개 변수 유형을 얻습니다. // 메소드 유형의 일반 매개 변수 유형을 가져옵니다 [] type = method.getGenericParameterTypes (); System.out.println (유형 [0]); // 매개 변수화 된 유형 ParameterizedType ptype = (ParameterizedType) 유형 [0]; // Primitive Type System.out.println (ptype.getRawtype ()); // 실제 유형 매개 변수 System.out.println (ptype.getActualTyPearguments () [0]); System.out.println (ptype.getActualTyPearguments () [1]); } /* 매개 변수 테스트 방법* / public static void applyMap (맵 <integer, string> map) {}}출력 결과 :
java.util.map <java.lang.integer, java.lang.string> 인터페이스 java.util.mapclass java.lang.integerclass java.lang.string