본문 바로가기
카테고리 없음

230208 TIL

by hbIncoding 2023. 2. 9.

 

Spring 입문 주차 4일차

1. 지네릭스(Generics)

 1)역할 

  • 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에서 컴파일 시 타입 체크를 해주는 기능
  • 타입의 안정성을 제공한다
  • 타입체크와 형변환을 생략할 수 있음으로 코드가 간결해 진다.
  • 아래 코드에서 여러 종류의 타입을 저장하고 싶으면 <Object>로 사용하면 된다. 하지만 이 경우엔 출력시 형변환 필요 ArrayList<Object> list = new ArrayList<Object>(); 
ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add("30");

Integer i =(Interger)list.get(2); //컴파일은 ok이나 실행시 ClassCastException 에러(형변환에러) 발생
//실행시 발생에러는 프로그램을 멈추게 함으로 같은 에러라면 컴파일 에러가 났다.
//즉 실행시 발생하는 에러를 컴파일에로 바꿔주기 위해(확인하기 위해) 사용되는 것이 Generics

ArrayList<Interger> list = new ArrayList();
list.add(10); // list.add(new Integer(10)); 알아서 boxing 해준 것
list.add(20);
list.add("30"); // 이 시점에서 컴파일러가 에러를 잡아준다. > list.add(30)으로 안바꾸면 실행 불가

Interger i = list.get(2); // 형변환 생략 가능
  • < > 안에 들어가는 것을 타입변수 (type variable) 이라고 한다.일반적으로 T 나 E로 사용 

  2)타입 변수

  • 형변환이 불필요한 성질과 이어진다.  보통 반환 타입이 Object이지만 지네릭스를 이용해 다양한 타입으로변환 가능
  • <E> 또는 <T>로 타입 변수를 칭한다. E나 T는 Integer와 같은 특정 타입을 지칭하는게 아닌 예시이자 대명사를 뜻함
class Tv {}
class audio{}

////
ArrayList<Tv> list = new ArrayList<Tv>(); // TV타입의 저장 객체만 가능
list.add(new Tv());
list.add(new Audio()); //불가능

Tv t = list.get(0);
// 지네릭스 안주면
Tv t = (Tv)list.get(0);

 3)지네릭스 타입과 다형성

  • 참조 변수와 생성자의 대입된 타입(매개변수화된 타입, parameterized type)은 일치해야한다.
  • 지네릭스 클리간에도 다형성은 성립, 매개변수의 다형성도 성립
ArrayList<TV> list = new ArrayList<Tv>(); // 참조변수와 생성자의 대입된 타입(=Tv) 일치

//지네릭 클래스간 다형성 성립
List<Tv> list = new ArrayList<Tv>();
List<Tv> list = new LinkedList<Tv>();

//매개변수의 다형성도 성립
ArrayList<Product> list = newArrayList<Product>();
list.add(new Product());
list.add(new Tv());		//OK
list.add(new Audio());	//OK

 4)Iterator<E>

  • 참조 변수와 생성자의 대입된 타입(매개변수화된 타입, parameterized type)은 일치해야한다.
  • 지네릭스 클리간에도 다형성은 성립, 매개변수의 다형성도 성립
public interface Iterator<E> {
    boolean hasNext();
    next();
    void remove();
}

Iterator<Student> it = list.iterator();
while(it.hasNext()){
    Student s = it.next();// 지네릭스가 없다면 (Student)it.next(); 로 받환해야함
    }

 5)HashMap<K, V>

  • 이 경우에도 예를 들면 Student라는 클래스로 V의 타입을 줬을 때 Value 반환시 형 변환 불필요
  • ex)Student s1 = (Student)map.get("1-1"); // (Student) 생략 가능

 6)제한된 지네릭 클래스

  • extends를 이용하여 해당 클래스와 클래스의 자손만 들어갈 수 있게 해준다.
  • 인터페이스를 같이 쓸때는 Fruit & Interfacename 과 같이 쓸 수 있다.
class FruitBox<T extends Fruit>{}

 7)지네릭스의 제약

  • static에 타입 변수 사용 불가 : static은 모든 인스턴스에 공통인데 타입 변수에 대입은 인스턴스 별로 다르게 가능하기 때문이다.
  • 배열 생성할 때 타입 변수 사용 불가, 타입 변수로 배열 선언은 가능 => T나 E사용 불가 ex) new T 는 사용 불가

 8)와일드 카드

  • 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능
    • <? extends T> 와일드 카드의 상한 제한으로 T와 자손들만 가능
    • <? super T> 와일드 카드의 하한제한, T와 그 조상들만 가능
    • <?> 제한 없음, <? extends Object>와 동일

 9)지네릭 메서드

  • 지네릭 타입이 선언된 메서드(타입 변수는 메서드 내에서만 유호), 대부분 생략 가능
static <T extends Fruit> Juice makeJucie(FruitBox<T> box)
//여기서 T에는 Fruit의 자손만 대입가능

 10)지네릭 타입의 형 변환

  • 지네릭 타입과 원시 타입간의 형변환은 바람직 하지 않다. 하지만 항상 가능
Box		box = null;
Box<Object> objBox = null;

box = (Box)objBOx;			//Ok. 지네릭타입> 원시타입, 경고발생
objbox = (Box<Object>)box;	//Ok. 원시타입> 지네릭타입, 경고발생
  • 대입된 타입이 다른 지네릭 타입 간에는 형변환이 불가능하다.
Box<Object> objBox = null;
Box<String> strBox = null;

objbox = (Box<Object>)strBox;	//에러 Box<Stirng> -> Box<Object>
strbox = (Box<String>)objBox;	//에러 Box<Object> -> Box<String>
  • 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능 
Box<Object> objBox = (Box<Object>) new Box<String>(); // 에러 발생, 형변환 불가능
Box<? extends Object> wBox = (Box<? extends Object>) new Box<String>(); // OK
Box<? extends Object> wBox =  new Box<String>();//Ok, 위 문장과 동일 생략 가능

 11)지네릭 타입의 제거

  • 컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다.
  • 지네릭 타입의 경계(bound)를 제거, 하위호환성// 지네릭은 컴파일 수준에서만 존재하여 하위 버전에서 구동 가능     (자바의 특징이다)
  • 지네릭 타입을 제거한 후에 타입이 일치하지 않으면 형변환을 추가한다.

2. 열거형(enum)

 1) 기초

  • 여러 상수를 선얼 할 때 편리하게 사용하는 방법, 아래 방법이 아니라면 하나한 0,1,2,3... 값을 지정해 주어야 함
class Card{
    enum Kind {CLOVER,HEART,DIAMOND,SPADE} // 순서대로 0,1,2,3 부여
    enum Value {TWO,THREE,FOUR} // 마찬가지로 0,1,2 부여
    final Kind kind;
    final Value value;
}
  • 타입은 int 가 아닌 Kind와 Value 처럼 선언 할 때와 같은 형태로 주어야 한다.
  • 조건식에서 type을 먼저 비교하게 함으로써 컴파일 단계에서 에러를 도출하여 미리 예방한다.
if(Card.CLOVER == Card.TOW) /// true이지만 false이어야 의미가 맞음
if(Card.Kind.CLOVER == Card.Value.TOW) /// type부터 비교하여 컴파일에러 발생

2)열거형의 정의와 사용

  • 정의하는 방법 : enum 열거형이름 {상수명1,상수명2, .....}
  • 열거형 타입의 변수를 선언하고 사용하는 방법
enum Direction {EAST, SOUTH, WEST, NORTH}

class Unit{
	int x, y;
    Driction dir;
    
    void init() {
    	dir = Direction.EAST;
    }
}
  • 열거형 상수의 비교에는 == 와 compartTo() 사용 가능,    [<,>] 같은 비교 연산자 사용 불가
  • compareTo(), 왼쪽이 크면 양수, 같으면 0, 오른쪽이 크면 음수를 반환

 3)열거형의 조상- java.lang.Enum 

  • 모든 열거형은 Enum의 자손이며, 아래의 메서드를 상속받는다.
    • Class<E> getDeclaringClass() : 열거형의 Class 객체를 반환
    • String name() : 열거형 상수의 이름을 문자열로 반환
    • int ordinal() : 열거형 상수가 정의된 순서를 반환(0부터 시작)
    • T valueOf(Class<T> enumType, String name) : 지정된 열거형에서 name과 일치하는 열거형 상수를 반환
  • 조상엔 없지만 자동으로 추가해 주는 메서드
    • values() : 열거형에 정의된 모든 상수를 출력하는데 사용 ex) Direction darr = Direction.values();
    • valuseOf(String name) : 열거형 상수의 이름을 문자열 상수에 대한 차조를 얻을 수 있게 해준다.

 4)열거형에 멤버 추가하기

  • 불연속적인 열거형 상수의 경우 원하는 값을 괄호안에 적는다. 여러개도 가능 ex) EAST(1, ">")
  • 값을 호출하려면 생성자가 필요하기 때문에 아래와 같이 사용하게 된다.
enum Direction {
	EAST(1), SOUTH(5),WEST(-1),NORTH(10);
    
    private final int value;
    Dirention(int value) {this.value = value;}
    
    public int getValue() { return value;}
}

3. 에너테이션(annotation)

 1) 에너테이션이란?

  • 과거 소스코드와 문서를 하나의 파일로저장하려고 하였으며, @붙은 태그를 이용하여 주석안에 정보를 저장 하고 , javadoc.exe라는 프로그램이 이 정보를 읽어서 문서 작성하는데 사용한다. 이 기능을 응용하여, 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 바로 애너테이션
  • 애너테이션은 주석처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유요한 정보를 제공한다.
  • JDK에서 제공하는 표준 애너테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공한다.
    • @Override
    • @Deprecated
    • @SuppressWarnings
    • @SafeVarargs
    • @FunctionalInterface
    • @Native

 2)애너테이션 타입 정의하기

@interface 애너테이션이름 {
	타입 요소이름(); //애너테이션의 요소를 선언한다.
    ........
}
  • 애너테이션 요소는 반환값이 있고 매개변수는 없는 추상 매서드의 형태를 가지며, 상속을 통해 구현하지 않아도 된다.
  • 요소형의 타입은 기본형, String, enum, 애너테이션, Class 만 허용
  • ()안에 매개변수를 선언 할 수 없다.
  • 예외를 선언할 수 없다.
  • 요소를 타입 매개변수로 정의할 수 없다.

4. 참고 자료

 1)API 공통 응답 포맨 개발

https://velog.io/@qotndus43/%EC%8A%A4%ED%94%84%EB%A7%81-API-%EA%B3%B5%ED%86%B5-%EC%9D%91%EB%8B%B5-%ED%8F%AC%EB%A7%B7-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0

 

스프링 API 공통 응답 포맷 개발하기

클라이언트 ↔︎ 서버 구조에서클라이언트는 서버에 요청을 보내고 서버는 요청에 대한 결과를 응답합니다.예를 들어 클라이언트가 1번 상품을 요청하는 경우 서버는 1번 상품을 조회해 응답하

velog.io

https://velog.io/@wwe221/ApiReponse

 

Api 공통 응답 포맷 만들기

Api 공통 Response 만들기

velog.io

https://hyuckang.tistory.com/68

 

[JAVA/SPRING] API 응답 공통 포맷 만들기

개발을 하다 보면 수많은 오류가 발생하게 되고 발생하는 오류에 대해 적절한 HTTP Status Code로 핸들링하기는 어려움이 있습니다. 그렇기 때문에 공통적인 포맷을 만들고 Response status와 message로 Req

hyuckang.tistory.com

2)예외 처리 https://velog.io/@dbsrud11/Spring-MVC-2-9.-API-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC

 

[Spring MVC] [2] 9. API 예외 처리

📌 API 예외처리 - ExceptionResolver, @ExceptionalHandler, @ControllerAdvice

velog.io