자바 어댑터
1. 마스크 의 상계
List < Cat > 가 List < Anilmal > 의 하위 유형 이 아니 라 는 것 을 알 았 으 니 그 를 대신 해서 해결 할 방법 을 찾 아야 한다. AnimalTrianer. act () 방법 이 더욱 통용 되 는 것 이다 (List < Animal > 유형 도 받 아들 일 수 있 고 List < Cat > 등 매개 변수 도 받 아들 일 수 있다).자바 에서 해결 방법 은 바로 마스크 를 사용 하 는 것 입 니 다. "?" 구체 적 으로 AnimalTrianer 는 방법 을 act (List list) 로 바 꾸 는 것 입 니 다. 그 중에서 "?" 는 마스크 이 고, "extends Animal" 은 마스크 "?" 의 상 계 는 Animal 입 니 다. 다시 말 하면 "? extends Animal" 은 Animal 또는 그 하위 클래스 를 대표 할 수 있 습 니 다.애니메이션 의 부모 클래스 (예 를 들 어 Object) 를 대표 할 수 없습니다. 어댑터 의 상 계 는 Animal 이기 때 문 입 니 다.다음 과 같이 개 선 된 AnimalTrianer 를 위해
public class AnimalTrainer {
public void act(List<? extends Animal> list) {
for (Animal animal : list) {
animal.eat();
}
}
}
다시 한 번 테스트 해 보 겠 습 니 다. 다음 과 같 습 니 다. Test 2 는 컴 파일 을 통과 할 수 있 습 니 다.
public class TestAnimal {
public static void main(String[] args) {
AnimalTrainer animalTrainer = new AnimalTrainer();
//Test 1
List<Animal> animalList = new ArrayList<>();
animalList.add(new Cat("cat1"));
animalList.add(new Bird("bird1"));
animalTrainer.act(animalList); //
//Test 2
List<Cat> catList = new ArrayList<>();
catList.add(new Cat("cat2"));
catList.add(new Cat("cat3"));
animalTrainer.act(catList); //
}
}
상기 분석 을 통 해 알 수 있 듯 이 List < Animal > 과 List < Cat > 는 모두 List 의 하위 형식 으로 List < Bird > 와 유사 하 며, List < Magpie > 도 List 의 하위 형식 입 니 다.
현재 요약 하면 다음 과 같다. 마스크 의 상계 에 대해 다음 과 같은 몇 가지 기본 적 인 규칙 이 있다. (주어진 범 형 유형 이 G 라 고 가정 하면 (예 를 들 어 List < E > 중의 List), 두 개의 구체 적 인 범 형 매개 변수 X, Y, 그 중에서 Y 는 X 의 하위 클래스 (예 를 들 어 위의 Animal 과 Cat)) 이다.
여기까지 배우 면 의 심 스 러 운 부분 이나 이해 가 안 되 는 부분 을 만 날 수 있 습 니 다. 먼저 다음 과 같은 두 단락 의 코드 부분 을 관찰 하여 가능 한 지 판단 하 시 겠 습 니까?
public void testAdd(List<? extends Animal> list){
//....
list.add(new Animal("animal"));
list.add(new Bird("bird"));
list.add(new Cat("cat"));
}
List<? extends Animal> list = new ArrayList<>();
list.add(new Animal("animal"));
list.add(new Bird("bird"));
list.add(new Cat("cat"));
먼저 다음 과 같이 분석 합 니 다. "extends Animal" 은 Animal 또는 그 하위 클래스 (Bird, Cat) 를 대표 할 수 있 기 때문에 위의 조작 은 가능 할 것 입 니 다.사실은 '안 돼', 즉 컴 파일 을 통과 할 수 없어 요. 왜 죠?
설명 하기 전에 이미 알 고 있 는 규칙 을 다시 한 번 강조 합 니 다. List < Aimal > list 에 Animal 류 대상 과 그 하위 대상 (예 를 들 어 Cat 과 Bird 대상) 만 추가 할 수 있 고, List < Bird > 에 Bird 류 와 그 하위 대상 (예 를 들 어 Magpie) 만 추가 할 수 있 으 며, Animal 대상 (Bird 의 하위 클래스 가 아 님) 을 추가 할 수 없습니다.비슷 한 것 은 List < Cat > 과 List < Magpie > 에 Cat 와 Bird 대상 만 추가 할 수 있 습 니 다 (또는 하위 클래스 대상 은 표시 되 지 않 았 습 니 다). 이제 testAdd () 방법 을 돌 이 켜 보면 List < Animal >, List < Cat 등 이 모두 List 의 하위 형식 이라는 것 을 알 수 있 습 니 다. 먼저 들 어 오 는 매개 변 수 를 List < Animal > 이 라 고 가정 하면 첫 번 째 코드 의 세 개의 "add" 입 니 다.작업 은 모두 가능 합 니 다. 그러나 List < Bird > 라면? 두 번 째 "add" 만 실행 할 수 있 습 니 다. 다시 List < Tiger > (Tiger 는 상상 한 것 이 고 Cat 의 하위 클래스 라 고 생각 할 수 있 습 니 다) 가 들 어 왔 다 고 가정 하면 세 개의 "add" 작업 은 실행 할 수 없습니다.
지금 은 반대로 testAdd 에 서로 다른 파 라 메 터 를 전달 합 니 다. 세 개의 "add" 작업 은 모두 유형 불 균형 문 제 를 일 으 킬 수 있 습 니 다. 들 어 오 는 파 라 메 터 는 알 수 없 기 때문에 자바 는 그 유형 이 일치 하 는 것 을 보호 하기 위해 List 에 임의의 대상 을 추가 하 는 것 을 금지 합 니 다. 그러나 null, 즉 list. add (null) 를 추가 할 수 있 습 니 다.가능 합 니 다. 위 에서 언급 한 기초 가 있 으 면 두 번 째 코드 를 이해 하 는 것 은 어렵 지 않 습 니 다. List 의 유형 "? extends Animal" 은 확실 하지 않 습 니 다. Animal, Bird 또는 Cat 등 일 수 있 기 때문에 그 유형의 일치 성 을 보호 하기 위해 list 에 임의의 대상 을 추가 할 수 없 지만 null 을 추가 할 수 있 습 니 다.
먼저 다음 과 같이 요약 합 니 다. list 에 임의의 대상 을 추가 할 수 없습니다. null 을 제외 하고.
또한 주의해 야 할 점 은 List 에서 Animal 대상 이나 Bird 대상 등 (특정한 대상 일 뿐) 일 수 있다 는 점 이다. 반대로 List list 에 서 는 모두 Animal 대상 이다. 즉, Bird 도 Animal 대상 이 고 Cat 도 Animal 대상 이다.그러면 Animal 에서 의 모든 방법 은 호출 할 수 있 습 니 다. 다음 과 같 습 니 다.
for (Animal animal : list) { animal.eat(); }
2. 어댑터 의 하계
어댑터 의 상계 가 있 으 니 당연히 어댑터 의 하계 가 있 습 니 다. 어댑터 의 하계 List 를 이렇게 정의 할 수 있 습 니 다. 그 중에서 "Bird" 는 어댑터 의 하계 입 니 다. 주의: 범용 어댑터 가 상계 와 하 계 를 동시에 설명 할 수 없습니다.
세부 사항 에 주의 하기 전에 우 리 는 먼저 마스크 의 사용 규칙 을 살 펴 보 자. 마스크 의 상계 에 대해 다음 과 같은 몇 가지 기본 적 인 규칙 이 있다. (주어진 범 형 유형 이 G 라 고 가정 하고 (예 를 들 어 List < E > 중의 List), 두 개의 구체 적 인 범 형 매개 변수 X, Y, 그 중에서 Y 는 X 의 하위 클래스 (예 를 들 어 위의 Animal 과 Cat)))
public void testAdd(List<? super Bird> list){
list.add(new Bird("bird"));
list.add(new Magpie("magpie"));
}
List<? super Bird> list = new ArrayList<>();
list.add(new Bird("bird"));
list.add(new Magpie("magpie"));
list.add(new Animal("animal"));
첫 번 째 코드 를 보면 그 분석 은 다음 과 같다. 왜냐하면?슈퍼 버드 는 버드 나 그 부 류 를 대표 하고, 매 그 피 는 버드 의 하위 클래스 이기 때문에 상소 코드 는 컴 파일 을 통 해 컴 파일 할 수 없다.그런데 사실은 '행', 왜 일 까?
의문 을 풀기 전에 하위 클래스 는 부모 클래스, 즉 Bird 도 Animal 대상 을 가리 킬 수 있 는 지식 을 강조 합 니 다. 이 제 는 test Add () 에 들 어 가 는 것 을 고려 합 니 다.가능 한 모든 매개 변 수 는 List < Bird >, List < Animal > 또는 List < Objext > 등 이 있 습 니 다. 이러한 매개 변 수 는 Bird 또는 아버지 류 라 는 것 을 발견 할 수 있 습 니 다. 그러면 우 리 는 이렇게 볼 수 있 습 니 다. bird, magpie 를 Bird 대상 으로 볼 수도 있 고 bird, magpie 를 Animal 대상 으로 볼 수도 있 습 니 다. 유사 한 것 은 Object 대상 으로 볼 수 있 습 니 다. 마지막 으로 이러한 것들 이 List list 에 추 가 된 대상 은 모두 같 습 니 다.하나의 대상 (예 를 들 어 본 고 에서 방금 언급 한 Test 1) 이기 때문에 testAdd 방법 은 논리 에 부합 되 고 컴 파일 을 통 해 할 수 있 습 니 다.
이제 두 번 째 코드 를 살 펴 보 겠 습 니 다. 두 번 째, 세 번 째 줄 코드 에 대한 설명 은 위의 글 과 마찬가지 로 마지막 줄 인 "list. add (new" Animal ("animal") "은 컴 파일 할 수 없습니다. 왜 입 니까?? 유형의 일치 성 을 보호 하기 위해"? 슈퍼 Bird "는 Animal 일 수도 있 고 Object 또는 다른 Bird 의 부류 일 수도 있 습 니 다. 그 유형 을 확인 할 수 없 기 때문에 List 에 Bird 의 임의의 부류 대상 을 추가 할 수 없습니다.
부모 클래스 의 대상 을 확인 할 수 없 는 이상 List 를 어떻게 옮 겨 다 녀 야 합 니까? Object 는 모든 클래스 의 루트 이기 때문에 Object 로 옮 겨 다 닐 수 있 습 니 다. 아래 와 같 지만 그 의 미 는 크 지 않 은 것 같 습 니 다.
for (Object object : list) {//...}
그럼 "? super Bounding Type" 은 어디 에 사용 할 수 있 습 니까?? "? super Bounding Type" 은 상대 적 으로 광범 위 하 게 사용 되 고 있 습 니 다. 혼합 용 에 불과 합 니 다. 다음은 간단 한 예 를 들 어 다음 과 같은 두 개의 Student 와 College Student 가 있 습 니 다. 그 중에서 College Student 는 학생 을 계승 합 니 다. 다음 과 같 습 니 다.
public class Student implements Comparable<Student>{
private int id;
public Student(int id) {
this.id = id;
}
@Override
public int compareTo(Student o) {
return (id > o.id) ? 1 : ((id < o.id) ? -1 : 0);
}
}
public class CollegeStudent extends Student{
public CollegeStudent(int id) {
super(id);
}
}
먼저 그들의 id 에 따라 그들 을 정렬 해 야 합 니 다 (여 기 는 배열 대상 을 정렬 하 는 것 입 니 다). 디자인 방법 은 다음 과 같 습 니 다. (n 은 배열 요소 의 개 수 를 말 합 니 다)
public static <T extends Comparable<? super T>>
void selectionSort(T[] a,int n)
먼저 이 방법의 의 미 를 이해 합 니 다. 먼저 < T extends Comparable < T > > 는 배열 의 대상 이 Comparable 인 터 페 이 스 를 실현 해 야 한다 고 규정 하고 있 습 니 다. Comparable 는 부모 클래스 가 Comparable 인 터 페 이 스 를 실현 하면 그 자체 가 실현 되 지 않 을 수 있다 고 합 니 다. 예 를 들 어 CollegeStudent 와 같은 배열 이 있다 고 가정 합 니 다. 다음 과 같 습 니 다.
CollegeStudent[] stu = new CollegeStudent[]{
new CollegeStudent(3),new CollegeStudent(2),
new CollegeStudent(5),new CollegeStudent(4)};
실행 방법 selection Sort (stu, 4) 는 충분히 통과 할 수 있 습 니 다. 그러나 정 의 된 selection Sort 방법 은 다음 과 같 습 니 다.
public static <T extends Comparable<T>>
void selectionSort(T[] a,int n)
방법 selectionSort (stu, 4) 는 실행 할 수 없습니다. CollegeStudent 는 Comparable < CollegeStudent > 인 터 페 이 스 를 실현 하지 못 했 기 때 문 입 니 다. 다시 말 하면 "슈퍼 T" 는 selectionSort 방법 을 더욱 통용 시 켰 습 니 다. selectionSort 전체 코드 의 실현 은 본문의 끝 을 참고 할 수 있 습 니 다.
3. 무한 어댑터
어댑터 의 상계 와 하 계 를 알 게 된 것 은 사실 무 계 어댑터 를 알 게 된 것 과 같 습 니 다. 아무런 수식 도 넣 지 않 으 면 됩 니 다. 단독 "?". 예 를 들 어 List , "?" 는 임의의 유형 을 대표 할 수 있 습 니 다. "임 의" 는 알 수 없 는 유형 입 니 다. 무 계 어댑터 는 보통 아래 두 가지 상황 에 사 용 됩 니 다.
1. 방법 이 원래 의 Object 형식 을 매개 변수 로 사용 할 때 다음 과 같 습 니 다.
public static void printList(List<Object> list) {
for (Object elem : list)
System.out.println(elem + "");
System.out.println();
}
다음 과 같이 선택 할 수 있 습 니 다.
public static void printList(List<?> list) {
for (Object elem: list)
System.out.print(elem + "");
System.out.println();
}
이렇게 하면 리스트 < Object > 가 아니 라 더 많은 출력 을 호 환 할 수 있 습 니 다. 다음 과 같 습 니 다.
List<Integer> li = Arrays.asList(1, 2, 3);
List<String> ls = Arrays.asList("one", "two", "three");
printList(li);
printList(ls);
2. 정 의 된 방법 체 의 업무 논 리 는 일반적인 유형 과 무관 합 니 다. 예 를 들 어 List. size, List. cliat. 실제로 가장 많이 사용 되 는 것 은 Class 입 니 다. Class < T > 는 T 에 의존 하지 않 기 때 문 입 니 다.
마지막 으로, List < Object > 는 List 와 같 지 않 습 니 다. List < Object > 는 List 의 하위 클래스 입 니 다. 그리고 List list 에 임의의 대상 을 추가 할 수 없습니다. null 을 제외 하고.
부록: selection Sort 의 코드 구현: (좋 은 출력 이 필요 하 다 면 Student 의 toString 방법 을 다시 쓰 는 것 이 좋 습 니 다)
public class SortArray {
// ,n
public static <T extends Comparable<? super T>>
void selectionSort(T[] a,int n) {
for (int index = 0; index < n-1; index++) {
int indexOfSmallest = getIndexOfSmallest(a,index,n-1);
swap(a,index,indexOfSmallest);
}
}
public static <T extends Comparable<? super T>> int getIndexOfSmallest(T[] a, int first, int last) {
T minValue = a[first]; // minValue
int indexOfMin = first; // minValue
for (int index = first + 1; index <= last; index++) {
if (a[index].compareTo(minValue) < 0) {
minValue = a[index];
indexOfMin = index;
}
}
return indexOfMin;
}
public static void swap(Object[] a,int first,int second) {
Object temp = a[first];
a[first] = a[second];
a[second] = temp;
}
public static void main(String[] args) {
CollegeStudent[] stu = new CollegeStudent[]{
new CollegeStudent(3),
new CollegeStudent(2),
new CollegeStudent(5),
new CollegeStudent(4)};
selectionSort(stu, 4);
for (Student student : stu) {
System.out.println(student);
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.