자바 범 형 상세 해석(초 상세 자바 범 형 방법 해석)
초기의 Object 유형 은 임의의 대상 유형 을 받 아들 일 수 있 지만 실제 사용 에 서 는 유형 전환 문제 가 있 을 수 있 습 니 다.이 위험 이 존재 하기 때문에 자바 는 이 안전 문 제 를 해결 하기 위해 범 형 을 제공 했다.
public static void main(String[] args) {
//
ArrayList arrayList = new ArrayList();
arrayList.add("helloWorld");
arrayList.add("taiziyenezha");
arrayList.add(88);// ,
for (int i = 0; i < arrayList.size(); i++) {
// : , String
String str = (String) arrayList.get(i);
System.out.println(str.length());
}
}
이 코드 를 실행 하면 프로그램 이 실 행 될 때 이상 이 발생 합 니 다.Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
데이터 형식 변환 이상 이 발생 했 습 니 다.왜 그런 가요?
ArrayList
은 임의의 종류의 요 소 를 저장 할 수 있 기 때문이다.예 를 들 어 String 형식 을 추가 하고 Integer 형식 을 추가 한 다음 에 사용 할 때 String 방식 으로 사용 하여 꺼 낼 때 String 형식 으로 강제로 전환 한 후 ClassCastException
이 발생 하여 프로그램 이 붕괴 되 었 습 니 다.이것 은 분명히 우리 가 기대 하 는 것 이 아니다.만약 프로그램 에 잠재 적 인 오류 가 있다 면,우 리 는 타 임 스 이상 을 실행 하 는 것 이 아니 라
이다.이와 같은 문 제 를 해결 하기 위해 jdk 1.5 이후 범 형 이 생 겨 났 다.API 를 디자인 할 때 클래스 나 방법 을 지정 하여 범 형 을 지원 할 수 있 도록 합 니 다.그러면 API 를 사용 할 때 도 더욱 간결 해 지고 컴 파일 시기의 문법 검 사 를 받 을 수 있 습 니 다.첫 번 째 줄 성명 을 Array List 의 코드 를 초기 화하 여 변경 하면 컴 파일 러 는 컴 파일 단계 에서 이와 같은 문 제 를 발견 할 수 있 습 니 다.이제 효 과 를 보 자.
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("helloWorld");
arrayList.add("taiziyenezha");
arrayList.add(88);// ,
이렇게 하면 우리 유형 이 강 전 될 때 이상 이 생기 는 것 을 피 할 수 있다.2.범 형 이란 무엇 인가
범 형:명확 한 유형의 작업 을 생 성 대상 이나 호출 방법 으로 미 룰 때 만 명확 하 게 하 는 특수 한 유형 입 니 다.즉,일반적인 사용 과정 에서 작 동 하 는 데이터 유형 은 하나의 매개 변수 로 지정 되 었 고 이런 매개 변수 유형 은 유형,방법 과 인터페이스 에 사용 할 수 있 으 며 각각
,
,
이 라 고 불 린 다.메모:일반적으로 대상 을 만 들 때 알 수 없 는 유형 을 구체 적 인 유형 으로 정 합 니 다.범 형 이 지정 되 지 않 았 을 때 기본 형식 은 Object 형식 입 니 다.
3.범 형의 장점 사용
범 형 은 보통 집합 에 대량으로 사용 되 지만 우 리 는 범 형 만 완전 하 게 배 울 수 있다.범 형 은 세 가지 사용 방식 이 있 는데 그것 이 바로 범 형 류,범 형 방법,범 형 인터페이스 이다.데이터 형식 을 매개 변수 로 전달 합 니 다.
4.1 범 형 류
범 형 유형 은 클래스 의 정의 에 사용 되 며 범 형 류 라 고 불 린 다.범 형 을 통 해 한 조 의 조작 에 대해 대외 적 으로 똑 같은 인 터 페 이 스 를 개방 할 수 있다.가장 전형 적 인 것 은 List,Set,Map 등 각종 집합 프레임 용기 류 이다.
네가 어떻게 사용 하 는 지 잘 모 를 까 봐 나 는 간단 한 범 형 류 를 만 들 었 다.
/**
* @param <T> <T> T:
* T , T、E
* , 。
* 。 。
*/
public class GenericsClassDemo<T> {
//t T,T
private T t;
// t T,T
public GenericsClassDemo(T t) {
this.t = t;
}
// getT T,T
public T getT() {
return t;
}
}
범 형 은 정 의 를 내 릴 때 구체 적 이지 않 고 사용 할 때 구체 적 으로 변 한다.사용 할 때 범 형의 구체 적 인 데이터 형식 을 확인 합 니 다.즉,대상 을 만 들 때 범 형 을 확인 합 니 다.Generic<String> genericString = new Generic<String>("helloGenerics");
이때 일반적인 표지 T 의 유형 은 바로 String 유형 이다.그러면 우리 가 전에 쓴 유형 은 이렇게 생각 할 수 있다.
public class GenericsClassDemo<String> {
private String t;
public GenericsClassDemo(String t) {
this.t = t;
}
public String getT() {
return t;
}
}
일반적인 타 입 이 Integer 타 입 으로 바 뀌 고 싶 을 때 도 편리 합 니 다.직접 만 들 때 T 를 Integer 형식 으로 쓰 면 됩 니 다.Generic<Integer> genericInteger = new Generic<Integer>(666);
ArrayList
의 범 형 유형 을 쓰 지 않 아 유형 이 강하 게 바 뀌 는 문제 가 발생 하기 쉽다 는 것 이다.4.2 일반적인 방법
범 형 방법 은 방법 을 호출 할 때 범 형의 구체 적 인 유형 을 가리킨다.
예 를 들 면:
/**
*
* @param t
* @param <T>
* @return T T
* :
* 1)public <T> , 。
* 2) <T> , 。
* 3)<T> T, T。
* 4) , T , T、E 。
*/
public <T> T genercMethod(T t){
System.out.println(t.getClass());
System.out.println(t);
return t;
}
방법 을 호출 할 때 일반적인 유형 을 확정 합 니 다.
public static void main(String[] args) {
GenericsClassDemo<String> genericString = new GenericsClassDemo("helloGeneric"); // 。
String str = genericString.genercMethod("hello");// String , String
Integer i = genericString.genercMethod(123);// Integer , Integer
}
여기 서 우 리 는 결 과 를 볼 수 있다.class java.lang.String
hello
class java.lang.Integer
123
여기 서 알 수 있 듯 이 범 형 방법 은 우리 가 들 어 오 는 매개 변수 유형 에 따라 그 가 얻 은 유형 도 다르다.범 형 방법 은 방법 을 유형 에 독립 시 켜 변 화 를 일 으 킬 수 있다.
4.3 범용 인터페이스
범 형 인 터 페 이 스 는 범 형 류 의 정의 와 사용 이 기본적으로 같다.범 형 인 터 페 이 스 는 각종 종류의 생산 기 에 자주 사용 된다.
interface < > { }
아래 의 예 를 보면 범용 인 터 페 이 스 를 어떻게 정의 하 는 지 알 수 있다.
/**
*
*/
public interface GenericsInteface<T> {
public abstract void add(T t);
}
사용 형식
public class GenericsImp implements GenericsInteface<String> {
@Override
public void add(String s) {
System.out.println(" String ");
}
}
public class GenericsImp<T> implements GenericsInteface<T> {
@Override
public void add(T t) {
System.out.println(" ");
}
}
범위 확인:
public class GenericsTest {
public static void main(String[] args) {
GenericsImp<Integer> gi = new GenericsImp<>();
gi.add(66);
}
}
5.범용 어댑터범용 클래스 나 인 터 페 이 스 를 사용 할 때 전 달 된 데이터 중 범용 형식 이 확실 하지 않 으 면 어댑터를 통 해표시그러나 일반적인 마스크 를 사용 하면 Object 류 의 공통성 방법 만 사용 할 수 있 고 집합 중의 요소 자체 방법 은 사용 할 수 없습니다.
5.1 어댑터 기본 사용
일반적인 마스크:어떤 유형 으로 받 아들 일 수 있 는 지 모 르 겠 을 때 사용 할 수 있 습 니까?알 수 없 는 마스크 를 표시 합 니 다.
이 때 는 데이터 만 받 아들 일 수 있 고 이 집합 에 데 이 터 를 저장 할 수 없습니다.
예 를 들 어 여러분 이 이해 하고 사용 하면 됩 니 다.
// ?
// 、 ,
//ArrayList<Object> list = new ArrayList<String>();
// ?: <?>
ArrayList<?> list1 = new ArrayList<Object>();
ArrayList<?> list2 = new ArrayList<String>();
ArrayList<?> list3 = new ArrayList<Integer>();
주의:범 형 은 계승,다 중 관계 가 존재 하지 않 습 니 다.범 형 좌우 양쪽 은 같 아야 합 니 다.jdk 1.7 후 오른쪽 범 형 은 생략 할 수 있 습 니 다.그리고 범 형 마스크?오른쪽 에 있 는 범 형 은 임의의 유형 일 수 있다.
범용 어댑터?주로 매개 변수 전달 에 사용 되 는데 같이 보 자.
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<Integer>();
test(list1);
ArrayList<String> list2 = new ArrayList<String>();
test(list2);
}
public static void test(ArrayList<?> coll){
}
헤헤,마스크 의 대단 함 을 보 았 나?비슷 한 방법 을 전달 할 수 있 겠 군!5.2 어댑터 고급 사용
기 존 에 범 형 을 설정 할 때 실제 적 으로 임의로 설정 할 수 있 고 클래스 만 있 으 면 설정 할 수 있다.다만 JAVA 의 범 형 에 서 는 범 형의 상한 과 하한 선 을 지정 할 수 있다.
일반적인 상한 선:
<? extends >
<? super >
class Animal{}//
class Dog extends Animal{}//
class Cat extends Animal{}//
우선 범 형의 상한 선 <? extends >:
을 살 펴 보 자.
// ArrayList<? extends Animal> list = new ArrayList<Object>();//
ArrayList<? extends Animal> list2 = new ArrayList<Animal>();
ArrayList<? extends Animal> list3 = new ArrayList<Dog>();
ArrayList<? extends Animal> list4 = new ArrayList<Cat>();
범 형의 상한 선 은 이 유형의 유형 과 하위 클래스 에 불과 하 다 는 것 을 알 수 있다.<? super >:
ArrayList<? super Animal> list5 = new ArrayList<Object>();
ArrayList<? super Animal> list6 = new ArrayList<Animal>();
// ArrayList<? super Animal> list7 = new ArrayList<Dog>();//
// ArrayList<? super Animal> list8 = new ArrayList<Cat>();//
범 형의 하한 선 은 이 유형의 유형 과 부류 에 불과 하 다 는 것 을 알 수 있다.
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement(list1);
getElement(list2);//
getElement(list3);
getElement(list4);//
getElement2(list1);//
getElement2(list2);//
getElement2(list3);
getElement2(list4);
}
// : ?, Number Number
public static void getElement1(Collection<? extends Number> coll){}
// : ?, Number Number
public static void getElement2(Collection<? super Number> coll){}
118060630
여기까지 배우 면 우리 범 형 도 다 배 울 수 있어!6.총화
이 글 은 여기까지 입 니 다.만약 이 글 이 당신 에 게 도 도움 이 된다 면,당신 이 우리 의 더 많은 내용 에 관심 을 가 져 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.