[Java] - 컬렉션 프레임워크, 제네릭, 어노테이션

링딩·2023년 4월 10일
0

Computer Science

목록 보기
28/49




컬렉션 프레임워크


1. 컬렉션 프레임워크란?

자바에서 컬렉션 프레임워크(collection framework)란 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미합니다

즉, 데이터를 저장하는 자료 구조와 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현해 놓은 것입니다.
=> 이러한 컬렉션 프레임워크는 자바의 인터페이스를 사용하여 구현됩니다.


2. 컬렉션 프레임워크 주요 인터페이스

List와 Set 인터페이스는 모두 Collection 인터페이스를 상속받지만, 구조상의 차이로 인해 Map 인터페이스는 별도로 정의됩니다.

따라서 List 인터페이스와 Set 인터페이스의 공통된 부분을 Collection 인터페이스에서 정의하고 있습니다.
1. List 인터페이스
2. Set 인터페이스
3. Map 인터페이스





제네릭


1. 제네릭(generic)이란?

자바에서 제네릭(generic)이란 데이터의 타입을 일반화한다는 것을 의미합니다.
제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법입니다.

2. 제네릭 선언 및 생성

class MyArray<T> {

    T element;

    void setElement(T element) { this.element = element; }

    T getElement() { return element; }

}
  • 'T' ; 타입 변수, 임의의 참조형 타입
    -> 꼭 T가 아니여도 되며, 여러 개의 타입 변수를 선언하고 싶으면 '쉼표(,)'로 구분지어 명시도 가능하다.

MyArray<Integer> myArr = new MyArray<Integer>();

📢 자바에서 타입 변수 자리에 사용할 실제 타입을 명시할 때 기본 타입을 바로 사용할 수는 없습니다.
=> 이때는 위 예제의 Integer와 같이 래퍼(wrapper) 클래스를 사용해야만 합니다.


제한된 제네릭과 와일드 카드

<K extends T> // T와 T의 자손 타입만 가능(K는 들어오는 타입으로 지정 됨)

<K super T> // T와 T의 부모(조상) 타입만 가능(K는 들어오는 타입으로 지정됨)

<? extends T> // T와 T의 자손 타입만 가능
<? super T> // T와 T의 부모 타입만 가능
<?> // 모든 타입 가능. <? extends Object>랑 같은 의미
  • 제네릭타입<? extends 상위타입> : 와일드카드의 범위를 특정 객체의 하위 클래스만 올 수 있습니다.

  • 제네릭타입<? super 하위타입> : 와일드카드의 범위를 특정 객체의 상위 클래스만 올 수 있습니다.


제네릭의 제거 시기

자바 코드에서 선언되고 사용된 제네릭 타입은 컴파일 시 컴파일러에 의해 자동으로 검사되어 타입 변환됩니다.

그 후, 코드 내의 모든 제네릭 타입은 제거되어, 컴파일된 class 파일에는 어떠한 제네릭 타입도 포함되지 않게 됩니다.

🤔 왜 제거하는거지?

이런 식으로 동작하는 이유는 제네릭을 사용하지 않는 코드와의 호환성을 유지하기 위해서입니다.






어노테이션


jkijki12 님의 글을 참고하여 작성하였습니다.

1. 어노테이션이란?

어노테이션은 작성한 코드에 대해 추가적인 정보를 제공하면서 컴파일 타임 혹은 런타임 시점에서 해당 코드에 필요한 추가적인 처리 해 주는 역할
=> 한 마디로 데이터 제공임, 도서관의 저자, 코드번호 등등과 같은 데이터의 느낌


2. 어노테이션의 종류

  • 표준(내장) 어노테이션 : 자바가 기본적으로 제공해주는 어노테이션
  • 메타 어노테이션 : 어노테이션을 위한 어노테이션
  • 사용자 정의 어노테이션 : 사용자가 직접 정의하는 어노테이션



2-1. 표준 어노테이션

  1. @Overrid : 오버라이딩을 올바르게 했는지 컴파일러가 체크하는 어노테이션

  2. @Deprecated : 앞으로 사용하지 않을 것을 권장하는 필드나 메소드 앞에 붙음

  3. @FunctionalInterface : 함수형 인터페이스를 알린다.
    -> 나아가 함수형 인터페이스의 "하나의 추상메서드만 가져야 한다는 제약"을 확인

  4. @SuppressWarnings : 컴파일러의 경고메세지가 나타나지 않게 한다.
    -> 경고가 많을 때, 새로운 경고가 가려지는 문제를 해결하고자 사용한다.



2-2. 메타 어노테이션

메타 어노테이션은 어노테이션을 위한 어노테이션이다.


1. @Target :

어노테이션을 정의할 때, 적용대상을 지정하는데 사용한다.

@Target({TYPE, FIELD, TYPE_USE})
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnnotation{}

@MyAnnotation // 적용 대상이 Type(클래스, 인터페이스)
class MyClass{
	@MyAnnotation //적용 대상이 FIELD인 경우
    int i;
    
    @MyAnnotation //적용 대상이 TYPE_USE인 경우
    MyClass mc;
}

2. @Retention :

어노테이션이 유지되는 기간을 지정하는데 사용

  • SOURCE : 소스 파일에만 존재.
  • RUNTIME : 클래스 파일에 존재. 실행시에 사용가능
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{}

3. @Documented

javadoc으로 작성한 문서에 포함시키려면 해당 어노테이션을 붙인다.

4. @Inherited

어노테이션도 상속이 가능하다. 어노테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.
좀 더 이해해보자

@Inherited
@interface SuperAnno{}

@SuperAnno
class Parent{}

// <- 여기에 @SuperAnno 가 붙은 것으로 인식
class Child extends Parent{}

어노테이션도 상속이 안돼요.

@Inherited 어노테이션은 클래스에 선언된 어노테이션을 자식 클래스가 쓸수 있다는 말.

어노테이션이 상속을 지원하지 않는 다는 것은 즉, 어노테이션을 선언할 때 미리 만들어 놓은 어노테이션을 확장해서 사용할 수 없다는 것.


5. @Repeatable

반복해서 붙일 수 있는 어노테이션을 정의할 때 사용

@Repeatable(ToDos.class)
@interface ToDo{
	String value();
}

@ToDo("delete test codes.")
@ToDo("override inherited methods")
class MyClass{
	~~
}

@interface ToDos{
	ToDo[] value();
}

MyClass에 보면 @ToDo 어노테이션이 여러개가 정의된 것을 볼 수 있는데
=> @Repeatable 어노테이션 위의 "ToDos"처럼 "컨테이너 어노테이션"도 정의해야 한다.



2-3. 사용자 정의 어노테이션

◽ 만드는 방법

@interface 이름{
	타입 요소 이름(); // 어노테이션의 요소를 선언
	    ...
}

◽ 예시

@interface DateTime{
	String yymmdd();
    String hhmmss();
}

@interface TestInfo{
	int count() default 1;
    String testedBy();
    TestType testType();
    DateTime testDate();
}


@TestInfo{
	testedBy="Kim",
    testTools={"JUnit", "AutoTester"},
    testType=TestType.FIRST,
    testDate=@DateTime(yymmdd="210922", hhmmss="211311")
)// count를 생략했으므로 default인 "count=1"이 적용된다.
public class NewClass{...}

📕어노테이션 요소 특징

  • 적용시 값을 지정하지 않으면, 사용될 수 있는 기본값을 지정할 수 있다.(위의 default)

  • 요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능하다.

@interface TestInfo{
	String value();
}
@TestInfo("passed") // value="passed"와 동일
class NewClass{...}
  • 요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다.
@interface TestInfo{
	String[] testTools();
}

@TestInfo(testTools={"JUnit", "AutoTester"})
@TestInfo(testTools="JUnit") // 요소가 1개일 때는 {}를 사용하지 않아도 된다.
@TestInfo(testTool={}) // 요소가 없으면 {}를 써넣어야 한다.


📢어노테이션 규칙

어노테이션에도 반드시 지켜주어야 하는 규칙이 있다. 다음 4가지를 살펴보자.

  • 요소의 타입은 기본형, String, enum, 어노테이션, Class만 허용된다.
  • 괄호()안에 매개변수를 선언할 수 없다.
  • 예외를 선언할 수 없다.
  • 요소의 타입을 매개변수로 정의할 수 없다.(<T>)

잘못된 예시를 통해서 이해해보자!

@interface AnnoConfigTest{
    int id = 100; // 상수 ok
    String major(int i, int j) //매개변수 x
    String minor() throws Exception; // 예외 x
    ArrayList<T> list(); // 요소의 타입을 매개변수 x


참고

steady-coding님의 글을 참고하였습니다.
heetaeheo님의 글을 참고하였습니다.

profile
초짜 백엔드 개린이

0개의 댓글