16일차 09/13/2022

SangYu Lee·2022년 9월 13일
0

codestates backend

목록 보기
16/30

keyword - enum, generic, exception, collection

1. enum

상수형을 열거해놓아 사용하기 쉽게 선언해놓은것. 보통 대문자로 표현한다.

enum Grade {FRESHMAN, SOPHOMORE, JUNIOR, SENIOR}

//사용할때는
Grade.FRESHMAN
Grade.SOPHOMORE
  • 보기 편하다
  • 상수명의 중복을 피할 수 있다
  • 타입 안정성(switch문 등에 사용가능)을 보장한다.


2. Generic

클래스나 메서드를 작성할 때, 타입을 확정적으로 명시하지 않고 사용자가 원하는 대로 대입해서 사용할 수 있게 만들어 놓은 것.

Generic Class


class Person<t> {
	private T race;
    
    Person(T race) {
    	this.race = race;
    }
}

Person이라는 클래스의 race라는 변수는 타입이 T라고 적혀있다. 이것을 타입 매개변수라고 하는데, 아직 뭐가 될지 안정했고, 클래스를 생성할 때 정해주겠다는 의미이다. 위에 작성한 클래스는 Person의 race(인종)이 뭐가 될지 모르기 때문에 제네릭으로 선언한 상태이다.

Person<Asian> Syu = new Person<Asian>(new Asian("상유"));

위 코드의 의미는, Perosn의 제네릭 타입을 Asian으로 설정하여 생성한다는 의미이다.

주의할점

  1. 타입 매개변수는 하나가 아닐 수도 있다.
class Person<T, K, V, E> { };
  1. static 변수에는 타입 매개변수를 지정할 수 없다.
    => static 변수는 공통 인스턴스인데, 타입이 각 개체마다 다르면 무슨 의미가 있나?

  2. 제네릭 클래스를 인스턴스화 할때, primitive형을 사용할 수 없다.
    => wrapper class 사용

    Person<Integer> Syu = new Person<Integer>(89);

타입 매개변수에 조건을 걸 수도 있다. 제한된 제네릭이라고 한다.

class Asian {}
class Korean extends Asian {}
class Japanese extends Asian {};
class Chinese extends Asian {};

class Person<T extends Asian> { }

Person의 타입 매개변수로 Asian을 상속받은 클래스만 들어올 수 있다. Asian클래스를 상속받은 Korean이나 Janpanese, Chinese등이 들어올 수 있겠다. 또한 특정 클래스를 상속받은 클래스 뿐만 아니라, 특정 인터페이스를 구현한 클래스로 한정할 때에도 똑같이 extends 키워드를 사용한다.

특정 클래스도 상속받고, 특정 인터페이스도 구현한 클래스만 한정해서 타입 매개변수로 받고 싶다면, &연산자로 클래스 먼저 적고, 인터페이스를 나중에 적는다.

interface hotTemper {}
class Asian {}
class Korean extends Asian implements hotTemper {}
class Japanese extends Asian {};
class Chinese extends Asian {};

class Person<T extends Asian & hotTemper> { }

Generic Method

클래스 전체보다는 클래스 내부의 일부 메서드에만 제네릭을 설정하는 것이다.

class Person<T> {
	...
    public <T> void printName(T person) {
    	...
    }
}

반환 타입 앞에 타입 매개변수를 작성한다.

  1. 메서드 타입 매개변수는 메서드 안에서만 사용할 수 있다.
  2. 클래스 타입 매개변수 T와 메서드 타입 매개변수 T는 다른 타입 매개변수이다.
  3. static method에도 타입 매개변수를 사용할 수 있다.
    => 변수와 다르게 method는 호출 될 떄 타입 지정이 이루어지기 떄문에
  4. 특정 타입(String같은)의 메서드를 사용할 수 없다. 아직 타입 지정이 안됐기 떄문에, 그러나 Object 클래스의 메서드는 사용할 수 있다.

와일드카드
제네릭의 문제점은 불공변이라는 것이었다. 예를 들어 collection에서는 printCollection처럼 모든 타입 변수에서 공통적으로 사용할 수 있는 메서드를 만들 수가 없었으며, 그러한 문제점을 해결하기 위해서 와일드카드가 도입되었다.

제네릭 : 지금은 이 타입을 모르지만, 이 타입이 정해지면 그 타입 특성에 맞게 사용하겠다!
와일드 카드 : 지금도 이 타입을 모르고, 앞으로도 모를 것이다!

List<?> list; 
// 1. 원소를 꺼내 와서는 Object에 정의되어 있는 기능만 사용하겠다. 
// equals(), toString(), hashCode()…
// 2. List에 타입이 뭐가 오든 상관 없다. 
// 나는 List 인터페이스에 정의되어 있는 기능만 사용하겠다. 
// size(), clear().. 단, 타입 파라미터와 결부된 기능은 사용하지 않겠다! add(), addAll()


List<T> list;
// 1. 원소를 꺼내 와서는 Object에 정의되어 있는 기능만 사용하겠다. 
// equals(), toString(), hashCode()…
// 2. List에 타입이 뭐가 오든 상관 없다. 
// 나는 List 인터페이스에 정의되어 있는 기능만 사용을 하고, 
// 타입 파라미터와 결부된 기능도 사용하겠다.
@Test
public void sampleCode2() {
	List<Integer> integerList = Arrays.asList(1, 2, 3);
	printList1(integerList);
	printList2(integerList);
}
static void printList1(List<?> list) {
	## 1. 와일드 카드는 list에 담긴 원소에는 전혀 관심이 없기 때문에 
    원소와 관련된 add 메소드를 사용할 수 없다.
	## 2., null은 들어갈 수 있다.
	list.add(list.get(1)); // 컴파일 실패
}
static <T> void printList2(List<T> list) {
	## 1. 제네릭은 list에 담긴 원소에 관심을 갖기 때문에 
    원소와 관련된 add 메소드를 사용할 수 있다.
	## 2. 당연히 null도 들어갈 수 있다.
	list.add(list.get(1)); // 컴파일 성공
}

출처: https://vvshinevv.tistory.com/55?category=692309

예외 처리

에러는 심각한 수준, 예외(exception)는 경미한 수준의 타입 에러 같은 부분.

  1. 컴파일 예외 : syntax 예외라고 부르기도 하며, 컴파일러가 잘못된 문법 등을 잡아내는 예외이다.
  2. 런타임 에러 : JVM이 잡아내는 컴퓨터가 수행할 수 없는 명령 예외. 0으로 나누는 예외 등

예외 클래스

컴파일러는 RuntimeException은 경미한 예외라고 생각하며, 이 외에 Exception클래스의 하위 예외들은 try/catch 문으로 예외 처리를 강제하고 있다.

byte[] list = {'a', 'b', 'c'};
try {
    System.out.write(list);
} catch (IOException e) {
    e.printStackTrace();
} finally {
	System.out.println("finally");
}

finally{} 는 예외가 나든 안나든 무조건 실행되는데, 필수는 아니다.

profile
아이스커피

0개의 댓글