본문 바로가기

신세게 - Java 공부

5주차 배운점 느낀점 - compare 예제, 제네릭, 와일드카드

728x90
반응형

5주차 마지막날

 

수업시작하시고 어제 배웠떤 compare 인터페이스 다른 분들의 코드 발표를 보는 시간을 가졌다.
제네릭에 대해서 배우며, 상한 바운드, 하한 바운드 와일드카드, 와일드카드 들의 개념과 각각 문제를 통해 실습하는 시간을 가졌다.
시간 빠르다. 벌써 5주차다 . 6개월 뚝딱일 것 같다.

 

배운점

 

Student class에서 오버라이드

 

// Integer.compare 이용
@Override
public int compareTo(Student o) {
  return Integer.compare(this.id,o.id);
}

// COMPARATOR 이용
@Override
public int compareTo(Student o) {

 return COMPARATOR.compare(this,o);
}

public static final Comparator<Student> COMPARATOR =
Comparator.comparingInt((Student stuTmp) -> stuTmp.id ); 

 

 

StrudentMain에서 오버라이드

 

// Array.sort 안에서 COMPARATOR 이용, 람다식 사용
Arrays.sort(student, new Comparator<Student>() {
      @Override
      public int compare(Student o1, Student o2) {
        return Comparator.comparingDouble((Student stuTmp) -> stuTmp.score)
                .thenComparingInt(stuTmp -> - stuTmp.id).compare(o2,o1);
 }});

//Array.sort 안에서 COMPARATOR 이용
Arrays.sort(student,new Comparator<Student>(){
  @Override
  public int compare(Student o1, Student o2) {
    if(o1.score == o2.score){
      return Integer.compare(o1.id,o2.id);
    }
    return Double.compare(o2.score,o1.score);
  }
 });

 

출력 상위2명

 

Arrays.stream(student).limit(2).forEach(studentTmp -> System.out.println(studentTmp.toString()));

 

제네릭


결정되지 않은 타입을 파라미터로 처리하고 실제 사용할 때 파라미터를 구체적인 타입으로
대체시키는 기능
<T>는 T가 타입 파라미터임을 뜻하는 기호. 타입이 필요한 자리에 T를 사용할 수 있음을 알려줌
자바프로그래밍 언어의 타입 안정성 강화를 위해 JAVA5부터 도입된 기능이다.

  • 제네릭을 사용하면 타입을 매개변수화 할 수 있다.
    동일한 코드를 다른 타입 사용할 수 있다.

제너릭은 제너릭 타입 매개변수

  • 클래스
  • 인터페이스
  • 메서드
    를 정의할 수 있는 기능 제공한다. 컴파일시 실제 타입으로 대체되어 타입 안정성을 보장한다.

    -제너릭 클래스
    하나 이상의 타입 매개변수가 있는 클래스
class MyGenericClass<T>{...} //T를 타입매개변수라고 한다.

 

제너릭 클래스의 객체 생성

 

MyGenericClass<Integer> Obj = new MyGenericClass<Integer>();

 

타입 매개변수 Integer를 사용하여
MyGenericClass 객체를 생성한다.
obj의 사용이 Integer객체만 받도록 제한된다.

 

-제너릭 메소드


자체 타입 매개변수를 갖는 메서드
클래스 수준 타입 매개변수와 다른 자체 타입 매개변수를 가질 수 있다.

 

Public <T>void MyGenericMethod(T param1, T param2..){...}

 

타입 매개변수 T 가 있는 제너릭 메서드 MyGenericMathod 를 정의한다.

 

제너릭의 와일드 카드 <?>
와일드카드 유연성을 제공하고, 알 수 없거나 여러 타입을 사용할 수 있도록 지원

 

상한 와일드 카드 <? extends T>
지정된 상한 또는 하위 타입의 모든 타입을 사용할 수 있도록 허용
특정 타입이 중요하지 않은 객체 컬렉션을 작업할 때 유용

 

하한 와일드 카드 <? super T>
지정된 하한 클래스와 동일하거나 상위 타입의 모든 타입을 사용할 수 있다.

 

- 타입 삭제
타입 지우기 기능 지원

 

자바에서 제너릭이 필요한 이유?
다양한 타입의 데이터에서 작동할 수 있는 재사용 가능한 코드를 만드는데 유용하다.

  • 코드 중복 최소화
  • 코드 베이스를 유지 관리 편해진다.
  • 컴파일 시에 타입안정성을 제공항 런타임 오류의 가능성을 줄일 수 있다.

제네릭 타입
결정되지 않은 타입을 파라미터로 가지는 클래스와 인터페이스
선언부에 ‘< >’ 부호가 붙고 그 사이에 타입 파라미터들이 위치


타입 파라미터는 일반적으로 대문자 알파벳 한 글자로 표현
외부에서 제네릭 타입을 사용하려면 타입 파라미터에 구체적인 타입을 지정. 지정하지 않으면 Object 타입이 암묵적으로 사용

 

문제1) 서로 다른 두 가지 타입의 객체를 타입 매개변수로 취하는 "Pair" 제너릭 클래스를 생성하세요. 쌍의 첫번째와 두번째 객체를 나타내는 타입 T와 U의 개인 인스턴스 변수 두 개 있어야 한다.
이 인스턴스 변수를 초기화하는 생성자와 인스턴스 변수의 값을 검색하는 getter 메소드가 있어야 한다.

 

public class Pair<T, U> { // 두 가지 타입을 매개변수로 취하는..
  private T t;
  private U u;

  public Pair(T t, U u) {
    this.t = t;
    this.u = u;
  }

  public T getT() {
    return t;
  }

  public U getU() {
    return u;
  }
}

 

문제2) 'MyClass'에 모든 타입의 배열을 매개변수로 받아서 배열의 요소를 출력하는 printArray 제너릭 메서드를 작성하세요

 

public class Myclass { // <T> 안써줌 , 제너릭 메소드만들거니까!!
  public static  <T> void printArray(T[] array){
    for(T element : array){
      System.out.println(element);
    }
  }
}

 

문제3) 모든 타입의 두 객체를 매개변수로 받고 비교를 나타내는 정수 값을 반환하는 "compare" 단일 메서드를 사용하여 Comparator라는 제너릭 인터페이스를 만드세요

 

public interface Comparator<T> { // <T>적어줌
  public int compare(T a, T b);
}

 

제너릭은


다양한 타입에서 재사용할 수 있는 제너릭 코드 제공
타입 캐스팅의 필요성을 제거한다.
자바 프로그래밍하는데 필수적이다.

 

문제4)


모든 타입의 객체를 담을 수 있는 Box 라는 제너릭 클래스 생성하세요
객체는 items 라는 ArrayList에 저장됩니다.
상자에(Box) 객체를 추가(addItem())하고, 상자에서 객체를 검색(getItem() 리스트에서 첫번째 항목 검색)하고, 상자가 비어 있는지 확인하는 메서드(isEmpty)를 구현

public class Box <T>{

  private List<T> items;

  public Box() {
     items = new ArrayList<>();
  }

  public void addItem(T item){
    items.add(item);
  }
  public T getItem(){
    if(!items.isEmpty()){
      return items.get(0);
    }
    return null;
  }

  public boolean isempty(){
    return items.isEmpty();
  }
}

 

문제5) MyClass2 배열과 두 개의 인덱스를 받아 주어진 인덱스에서 요소를 교환하는 static void swap 메서드를 구현하세요.
swap 메서드는 모든 타입의 배열을 처리할 수 있어야한다.

 

static <T>void swap(T[] array, int index1, int index2){
    //static이라 메서드에도 <T>를 해줬다.
    T temp = array[index1];
    array[index1] = array[index2];
    array[index2] = temp;
  }

 

문제6) 모든 타입의 요소 두개를 저장하고 요소를 교환하는 메서드를 구현하세요. 문제 1번 "Pair" 제너릭 클래스에 추가합니다.

 

public class Pair1<T> {
  private T first;
  private T second;

  public Pair1(T first, T second) {
    this.first = first;
    this.second = second;
  }
  public void swap(){
    T temp = first;
    first = second;
    second = temp;
  }

  public T getFirst() {return first;}

  public T getSecond() {return second;}


  public static void main(String[] args) {
    Pair1<Integer> intPair = new Pair1(1,2);  // 선언하는거 보셈 !! Pair1<Integer, > ~~

    System.out.println(intPair.getFirst()+", "+intPair.getSecond());
  }

}

 

문제7) 배열과 요소를 받아 배열 내에서 해당 요소의 발생 횟수를 반환하는 countOccurrences 제너릭 메서드를 구현하세요

 

public class MyGenericClass3 {
  public static  <T>int countOccurences(T[] array, T elment){
    int count = 0;

    for(T item : array){
      if(item.equals(elment)){ // equals 사용
        count++;
      }
    }
    return count;
  }

  public static void main(String[] args) {
    String[] strArray = {"apple","banana","apple","orange","apple"};
    String target = "apple";

    int occurrences = countOccurences(strArray,target);
    // static이라 바로 사용
    System.out.println(target + "문자열 객체가 "+ occurrences);
  }
}

 

제한된 타입 파라미터
모든 타입으로 대체할 수 없고, 특정 타입과 자식 또는 구현 관계에 있는 타입만 대체할 수 있는 타입 파라미터

 

public <T extends 상위타입> 리턴타입 메소드(매개변수, ...){...}

 

상위 타입은 클래스뿐만 아니라 인터페이스도 가능

 

 

와일드카드 타입 파라미터


자바 제너릭에서 와일드카드 알 수 없는 타입을 나타내는데 사용된다.
와일드 카드를 사용하면 제너릭 타입 매개변수를 다른 타입으로 대체할 수 있도록 지정이 가능하다.

 

필요성: 매개변수의 정확한 타입을 알 수 없거나, 관련이 없는 상황에서 타입 안정성을 희생하지 않고 알 수 없는 타입을 처리할 수 있는 방법 제공

 

자바 제너릭 와일드 카드는 물음표 기호로 표시된다<?>
1. 바인딩되지 않은 와일드 카드(?): 알 수 없는 타입을 나타낸다. 실제 타입 인수에 관심이 없는 상황에서 사용
상황1) 알 수 없는 요소의 리스트를 받아 문자열 표현을 출력해야하는 메서드 구현

public static void printList(List<?> list){
    //모든 타입의 리스트를 받는다. 알수없는 요소가 넘어올 때
    for(Object element: list){
      System.out.println(element.toString());
    }
  }
  1. 상한 바운드 와일드카드 (? extends Type)
    지정된 타입의 하위 타입인 알 수 없는 타입을 나타낸다. 특정 클래스나 인터페이스에서 파생된 모든 타입 허용

상황2) 숫자 리스트의 합계를 계산하는 listTotal()

public static Double listTotal(List<? extends Number> numbers){
    double total = 0;
    for(Number number: numbers){ // extends안할땐 Object였음
      total += number.doubleValue();
    }
    return total;
  }
  1. 하한 와일드 카드 (? super Type)
    지정된 타입의 상위 타입인 알 수 없는 타입을 나타낸다. 특정 클래스 또는 인터페이스의 상위 타입인 모든 타입을 허용하려는데 유용
public static void addElements(List<? super Integer>list){
    list.add(10);
  }

 

? super Integer 사용하면 addElements() 메서드가 Object 또는 Number 와 같은 Integer의 모든 상위 타입인 List 허용할 수있다.
정수와 Integer의 상위타입인 다른 모든 객체를 추가할 수 있다.

 

문제8) 모든 타입의 ArrayList를 출력할 수 있는 printList 라는 메서드를 작성하세요.(단 와일드 카드를 사용하세요)

 

public static void printList(List<?> list){
    list.forEach(System.out::println);
  }

 

printList(BoardList) 할때 Board에 toString 오버라이딩 해놓으면 이렇게 해도 출력됨

 

문제9)객체 리스트를 받아들이고 리스트의 각 요소를 출력하는 printList 메서드를 만들었어요 ~ . 이 메서드는 Comparable 인터페이스를 구현하는 객체 리스트만 받아서 printList 할 수 있도록 수정해 주세요

 

  public static <T extends Comparable<T> & Cloneable>void printList(List<T> list){
    list.forEach(System.out::println);
  }

 

제네릭 타입을 매개값이나 리턴 타입으로 사용할 때 범위에 있는 모든 타입으로 대체할 수 있는
타입 파라미터. ?로 표시

 

회고

 

수업시작하실때 어제 배웠던 compare 인터페이스 구현 한 것에 대해서, 각자 짠 코드를 발표 시키셨다. 다양한 코드들을 보고 이렇게도 쓸 수 있구나 하고 배웠다. 잘하는 분들은 람다를 잘쓰시는것같다.
람다 사용할 것 !! 이라고 강조하셨다. 지금 안해놓으면 현업가서 고생할수도있다고하셨다. 난 아직 안익숙하다. 웬만하면 람다로 짜보려고 노력해야겠다.
제네릭에 대해서 배웠다. 이타입 저 타입 넣을 수있어서 사용하면 코드재사용성이 엄청 높아 보인다. 잘쓰면 간지날것같다

반응형