본문 바로가기
CS/JAVA

[JAVA] Anonymous class, Lambda Expression, Generics

by 두둠칫 2021. 1. 14.

 

1. Anonymous class(익명 클래스)

- 말 그대로 이름 없는 class

- Interface 사용 시 주로 익명 클래스가 사용됨 : 가독성 증가

Interface_name variable_name = new Interface_name(params...) {
	@Override
    // abstract method
}

 

 

2. Lambda Expression(람다식)

1) 목적

- Method는 Class 안에 존재할 수 있고 JAVA의 최소 단위는 Class이다.

- 따라서 Method를 만들기 위해 불필요한 Class 생성이 유발될 수 있다.

- 하지만 람다식을 이용하면 Class를 표현하지 않고 Method만 만들 수 있다.(Method 즉, 기능에 더 집중할 수 있다.)
- 이러한 형태의 프로그래밍을 함수형(함수기반) 프로그래밍이라 한다.

cf) 실제로 런타임 때는 Class기반(익명 클래스)로 수행됨

 

 

2) 특징

- 간결한 표현식

- 하나의 Abstract Method를 가진 Interface 생성 시 람다식이 이용 가능

- 하나의 Abstract Method만을 강제하기 위해 @FunctionalInterface 어노테이션 사용

 

 

3) 문법

// params X, return X
() -> { ... };

// params O, return X 
(data_type var, ...) -> { ... };

// params X, return O
() -> { return value; };

// params O, return O
(data_type var, ...) -> { return value; };

// 생략
(var, ...) -> value; // 실행문이 return문 한 줄일 때

 이 때 params의 data type을 생략할 수 있고 실행문이 return 문 한 줄이면 {, return, } 을 같이 생략할 수 있다.

 

 

4) 활용 예시

- 정렬

// 익명 클래스
Arrays.sort(list, new Compartor<String>(){
	@Override
    public int compare(string s1, string s2){
    	return s1.compareTo(s2); // 오름차순
    }
});


// 람다식
Arrays.sort(list, (s1, s2) -> s1.compareTo(s2));

효율도랏;

 

 

3. Generics(제너릭스)

1) 목적

- 무엇이든 담을 수 있는 Box class를 만들고 싶다고 가정하자

- 그런데 data를 받기 위해선 JAVA가 다루는 type 개수만큼 method를 overloading해야한다.

 

- Object를 사용해서 다형성을 이용한다면?

  원하지 않는 data type이 저장되어도 compile error가 나지 않는다. 즉, 런타임 때서야 알 수 있다.

  또한 저장된 data 사용 시 형변환도 일일히 해야한다.

 

- 이때 제너릭스를 사용한다.

// Object
Class Box{
	Object obj;
    // setter & getter
}

// Generics
class Box<T>{
	T obj;
    // setter & getter
}

public class Testgenerics{
	public static void main(...){
    	Box<String> b = new Box<String>();
    }
}

T는 인스턴스를 생성할 때 정해주는 것으로 위의 예시에서는 String으로 정해주었다.

이를 통해 원하지 않는 data type 할당 시 compile error로 확인할 수 있고 데이터 활용 시 형 변환이 필요 없어진다.

평소 자주 사용하던 List<T>도 제너릭스를 활용한 자료구조였다.

 

 

2) Generics Interface

generics <T>에 T는 참조형만 가능하다. 따라서 기본형은 wrapper class를 사용한다.

기본형 Wrapper class
int Integer
char Character
나머지 첫문자를 대문자로
(기본형에서 Class가 되니까
라고 외우면 좋음)

 

 

3) 와일드카드 : <?>

제너릭스를 활용한 데이터를 params로 받는 함수에 대해 overload의 번거로움을 해결할 수 있다.

List<String> list1 = ...;
List<Integer> list2 = ...;

printData(list1);
printData(list2);

public static void printData(List<?> obj){ // <?>을 안쓰면 <String>, <Integer> 2가지를 overload해야함
	sysout(obj);
}

 

4) <? extends class_name>

특정 클래스와 해당 특정 클래스를 상속받은 클래스만 generics로 받을 수 있도록 제약하는 표현

public static void printData(List<? extends Pet> list){ // Pet과 Pet을 상속받은 클래스만 generics로 받을 수 있다
	...
}

 

5) <? super class_name>

특정 클래스와 해당 특정 클래스의 부모 클래스만 generics로 받을 수 있도록 제약하는 표현

'CS > JAVA' 카테고리의 다른 글

[JAVA] Functional Interface, Stream, String, StringBuffer  (0) 2021.01.14
[JAVA] Collection API  (0) 2021.01.14
[JAVA] Abstract, Interface  (0) 2021.01.12
[JAVA] 상속, 다형성, 캡슐화  (0) 2021.01.12
[JAVA] 데이터의 메모리 할당 순서  (0) 2021.01.12