자바 어댑터

17400 단어 자바범 형어댑터
다음으로 이동:http://www.linuxidc.com/Linux/2013-10/90928.htm
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)) 이다.
  • G 는 G 의 하위 형식 (예 를 들 어 List 은 List 의 하위 형식) 입 니 다.
  • G < X > 는 G 의 하위 형식 (예 를 들 어 List < Animal > 은 List 의 하위 형식)
  • G G 는 List 와 같 습 니 다.List 동일 합 니 다.

  •  
    여기까지 배우 면 의 심 스 러 운 부분 이나 이해 가 안 되 는 부분 을 만 날 수 있 습 니 다. 먼저 다음 과 같은 두 단락 의 코드 부분 을 관찰 하여 가능 한 지 판단 하 시 겠 습 니까?
    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)))
  • G 는 G 의 하위 유형 (예 를 들 어 List 은 List 의 하위 유형) 입 니 다.
  • G < X > 는 G 의 하위 유형 (예 를 들 어 List < Animal > 은 List 의 하위 유형)
  • 이제 다음 코드 를 살 펴 보고 논리 에 맞 는 지 판단 합 니 다.
    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);
    		}
    	}
    }

    좋은 웹페이지 즐겨찾기