Java/JavaCafe Study

5주차 코드 효율성

향찡 2021. 7. 11. 20:08

발표자 : 서동우

Generics - Generic programming 이란

  • 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식
  • 제네릭 프로그래밍은 여러 가지 유용한 소프트웨어 컴포넌트들을 체계적으로 융합하는 방법을 연구하는 것으로 그 목적은 알고리즘, 데이터 구조, 메모리 할당 메커니즘, 그리고 기타 여러 소프트웨어적인 장치들을 발전시켜 이들의 재사용성, 모듈화, 사용 편의성을 보다 높은 수준으로 끌어올리고자 하는 것이다.

Generics – 그럼 자바에서는?

  • JDK 1.5에서 처음 도입
  • Generics add stability to your code by making more of your bugs detectable at compile time. – Oracle Javadoc
  • 제네릭(Generic)은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법을 의미한다. – 생활코딩
  • 지네릭스는 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. – 자바의 정석

Generics - 그래서 정리하면

  • Class, interface, method 선언 시 파라미터로 type을 받는다.
  • 다른 input들에 대해서 동일한 코드를 제 사용할 수 있다.
  • Type 변수는 non-primitive(int, long 같은것들은 사용할 수 없다.) 한 type만 올 수 있다.

Generics - 왜 사용할까요?

  • 컴파일 시 타입체킹을 확실히 할 수 있다.
  • 런타임 에러보다 컴파일 에러를 수정하는 게 편하다.
  • 타입 변환(casting)을 안 해도 되니 빨라진다. (논란이 있다)
  • 하나 잘 만들어서 여러 목적으로 사용할 수 있다. (= 코드의 중복을 줄일 수 있다.?)
  • 조작해야 하는 데이터의 타입이 보장된다.

Generics 컨벤션

  • E : Element
  • K : Key
  • N : Number
  • T : Type
  • V : Value
  • S,U,V : 2nd, 3rd, 4th type

Generics 타입 파라미터 vs 타입 아규먼트

선언 부분에서 Box 에서 T는 Type Parameter

public class Box<T> // type paramter

구현 부분에서 Box 에서 String는 Type Argument

 Box<String> box2 = new Box<>(); // type argument

Generics - Raw Types

Type argument를 생략한 Generic Type

값을 할당할 경우 unchecked conversation warning 이 나옵니다.

Box<Integer> box = new Box<>();
Box<String> box2 = new Box<>();

Box box4 = new Box(); // raw types

Generics - Generic Methods

  • 타입을 파라미터로 가지고 있는 메서드
  • 타입 파라미터의 scope가 선언된 메서드 내에서만 사용
  • Static 메서드, 일반 메서드 둘 다 사용 가능
public class GenericMethod {
    public static <T> void test(T data) {

    }
    public <T> void add(T data) {

    }
}

사용하는 곳에서는 타입 추론을 한다.

GenericMethod.test(100);

Generics - Bounded Type Parameters

  • Type arguments 의 타입에 제한을 걸 때 사용
  • extends 키워드를 활용
  • T extends 클래스명으로 사용할 경우 클래스 명의 하위 클래스만 사용할 수 있도록 제한을 걸 수 있음.
  • 여러 개를 제한 조건으로 걸 수 있음
public class Box<T extends Number> { // Number클래스를 상속한 클래스만 사용할 수 있다.

}
  • & 를 이용해서 여러 개 조건을 걸 수 있음
    • T extends 클래스명 & 인터페이스명 …
    • 클래스는 한 개만 가능(다중 상속이 안되기 때문에)
    • 클래스와 인터페이스 조합의 경우는 클래스가 가장 앞에 있어야 함
public class Box<T extends Number & InterfaceBox> {

}

Generics - Wildcards

  • ? 사용
  • 제너릭 클래스나 메소드를 사용할 때 관련 type에 대한 정보를 알 수 없을 때 사용
Box<?> box;

public void setBox(Box<?> box) {
    this.box = box;
}

Generics - Upper Bounded Wildcards

  • Extends를 활용
  • A extends B라고 선언되었을 때 B 또는 B의 서브 클래스만 사용 가능하도록 제한할 수 있음

Generics - Lower Bounded Wildcards

  • super 키워드를 사용
  • A super B 라고 사용되면 A 클래스는 B클래스 또는 B클래스의 상위 클래스만 사용 가능

Generics - 제너릭의 제한사항

  • Primitive type을 사용할 수 없다.
  • Type parameter의 인스턴스를 생성할 수 없다.
  • Static field에서는 사용할 수 없다. (C#에서는 가능)
  • Casting 하거나 instanceof 를 활용할 수 없다.
  • 파라미터 타입의 배열을 생성할 수 없다.
  • 오버로딩 할 수 없다.
  • Parameter Type 객체를 Catch, Throw 할 수 없다.

Enum Type

  • Enumerate
  • 영어의 의미는 열거하다.
  • 무엇인가를 열거하는 용도로 사용
  • 상수의 그룹을 사용할 수 있는데 특수한 데이터 타입
  • 상수이기 때문에 대문자로 표시(권장)
  • enum 키워드를 사용하여 정의
  • 특수한 클래스이다.
  • 불변의 객체
// 보통 아래와 같은 형태이다.
public enum Example1 {
    AAAAAA,
    BBBBBB,
    CCCCCC;
}

Enum - 자바와 다른 언어의 차이점

  • 메소드와 필드 정보를 가질 수 있다.
  • 컴파일러에서 자동으로 유용한 메서드를 추가

Annotation

  • 과거에는 특별한 처리를 위해 정보가 필요할 경우 메소드 명이나 클래스 명의 Full-Name이나 Prefix 등의 문자열을 약속하여 사용
  • Junit의 경우 메소드 명에 test를 붙임
    • testUserSerivce, testLoginService

문제점

  • 코딩 시 오타가 날 수 있음
  • 특별한 상황에는 해당 Naming 사용 불가
  • 컴파일 레벨에서 해당 오류를 찾을 수 없음

Annotation

  • 주석
  • 메타데이터
  • 비즈니스 로직에는 영향을 주지 않지만 해당 타켓의 연결 방법이나 소스코드의 구조를 변경할 수 있음
  • 사용
    • 컴파일러에게 정보를 제공
    • 컴파일 단계와 배포 단계 처리
    • 런타임 처리

Annotation은 어디에서 호출 가능할까요?

  • 클래스, 인터페이스, 메소드의 선언 부
  • 인스턴스 생성 시
  • 타입 캐스팅
  • Implements 구문
  • Throw 선언 구문

META Annotation - @Retention

자바 컴파일러가 Annotation Annotation을 다루는 방법을 기술하며, 특정 시점까지 영향을 미치는지를 결정합니다.

보통 리플렉션을 활용할 때 많이 사용하므로 RUNTIME을 많이 사용한다.

종류

  1. RetentionPolicy.SOURCE : 컴파일 전까지만 유효. (컴파일 이후에는 사라짐, 소스 로직 내에서 영향을 미칠 때)
  2. RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때까지 유효.
  3. RetentionPolicy.RUNTIME : 컴파일 이후에도 JVM에 의해 계속 참조가 가능. (리플렉션 사용)

META Annotation – @Target

어노테이션이 적용할 위치를 선택합니다.

배열 형태로 지정하면 여러 개 지정할 수 있다.

종류

  • ElementType.PACKAGE : 패키지 선언
  • ElementType.TYPE : 타입 선언
  • ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
  • ElementType.CONSTRUCTOR : 생성자 선언
  • ElementType.FIELD : 멤버 변수 선언
  • ElementType.LOCAL_VARIABLE : 지역 변수 선언
  • ElementType.METHOD : 메서드 선언
  • ElementType.PARAMETER : 전달 인자 선언
  • ElementType.TYPE_PARAMETER : 전달인자 타입 선언
  • ElementType.TYPE_USE : 타입 선언

META Annotation – 그외

  • @Documented
    • 해당 어노테이션을 Javadoc에 포함시킵니다.
  • @Inherited
    • 어노테이션의 상속을 가능하게 합니다.
  • @Repeatable
    • Java8 부터 지원하며, 연속적으로 어노테이션을 선언할 수 있게 해줍니다.

사전에 정의된 Annotation

  • @Deprecated
    • 없어질 인터페이스, 클래스, 메서드 등을 표시할 때 사용(사용을 권장하지 않을 때)
  • @Override
    • 오버라이드 된 메소드를 나타낼 때 사용
  • @SuppressWarnings
    • 컴파일러가 특정한 경고를 나타내지 않을 때 사용
  • @SafeVarargs
    • 제너릭 같은 가변 인자 매개변수를 사용할 때 경고를 무시합니다
  • @FunctionalInterface
    • 람다 함수 등을 위한 인터페이스를 지정합니다. 메소드가 없거나 두 개 이상 되면 컴파일 오류가 납니다.

Reflection이란?

  • 구체적인 클래스 타입을 알지 못해도, 그 클래스의 메소드, 타입, 변수 등에 접근할 수 있는 자바 API
  • 런타임 시에 해당 클래스의 정보를 가져올 수 있는 상황에서 사용