1. Generic
- 데이터의 타입을 일반화한다(Generalize)
- 클래스와 메서드에서 사용할 타입을 설계도에 저장하지 않고 컴파일할 때 지정하는 기술
- 사용자가 사용할 때 타입을 결정
- JDK 1.5때 도입, 그 전에는 Object를 사용함
- Object를 사용하면 데이터 입력 시 모든 데이터 입력이 가능하므로 잘못된 데이터가 들어갈 수 있으며
데이터 사용시에도 데이터 타입을 모르니 Casting을 반드시 해야 사용 가능하다
📁 Generic1.java, Generic2.java
// Generic1.java
package day17;
import java.util.ArrayList;
public class Generic1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Food ramen = new Food("라면", "그냥 끓이거나 날로 먹으면 됨");
// OldBox
OldBox ob = new OldBox();
ob.add(ramen);
ob.add(new String("AAA")); // 아무거나 넣어도 괜찮음
// System.out.println(ob.get(0).getRecipe()); // 이렇게 사용하면 작동하지 않음 Object에는 .getRecipe()가 없기 때문에 (Food)임을 명시해주어야함
System.out.println(((Food)(ob.get(0))).getRecipe());
// NewBox를 쓸 때 얻는 장점
NewBox<Food> nb = new NewBox();
nb.add(ramen); // ramen은 Food라서 들어감
// nb.add(new String("AAA")); // Food가 아닌 것이 들어가면 에러가 남
// Generic을 사용하면 정한 타입 외에는 사용 불가함
System.out.println(nb.get(0).getRecipe()); // 16번열과 다르게 바로 사용 가능함
}
}
class Food {
String name;
String recipe;
Food(String name, String recipe){
this.name = name;
this.recipe = recipe;
}
String getRecipe() {
return recipe;
}
}
class OldBox {
ArrayList item = new ArrayList();
void add(Object o) {
item.add(o);
}
Object get(int index) {
return item.get(index);
}
}
class NewBox<T> { // [Generic] 사용자가 지정하면 (ex. <T>), ArrayList에도 <T>를 지정할 수 있다.
ArrayList<T> item = new ArrayList();
void add(T o) {
item.add(o);
}
T get(int index) {
return item.get(index);
}
}
// Generic2.java
package day17;
import java.util.ArrayList;
public class Generic2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
LuxuryBox<Instrument> box1 = new LuxuryBox();
LuxuryBox<Violin> box2 = new LuxuryBox();
LuxuryBox<Flute> box3 = new LuxuryBox();
// LuxuryBox<Bat> box4 = new LuxuryBox();
// extends Instrument 조건에 의해 <Bat>는 입구컷 당함
Bat bat1 = new Bat();
System.out.println(box3.<String>get("Cello"));
System.out.println(box3.<Bat>get(bat1));
}
}
class Instrument { }
class Violin extends Instrument { }
class Flute extends Instrument { }
class SportsTool { }
class Bat extends SportsTool { }
class LuxuryBox<T extends Instrument>{
ArrayList<T> item = new ArrayList();
public <T> T get (T data) { // 함수한테도 별도의 Generic을 줄 수 있음
return data;
}
}
2. Lambda(람다)
(1) 설명
- 1930년대, 알론조 처치라는 수학자가 제시한 함수의 수학적 표기법
➡️ Lambda Calculus(람다 대수)에 기초함
Java 8(2014)부터 지원 - 객체지향 프로그래밍에 함수형 프로그래밍의 특징이 추가됨
(2) 함수형 프로그래밍
- 일반적으로 메서드끼리 **데이터**를 주고 받는다.
- 그러나 함수형 프로그래밍은 데이터는 이미 존재하고, 함수를 넘겨주는 방식
- Java의 함수(메서드)는 기본적으로 어떤 클래스의 소속이어야 함
➡️ 나보고 정의하라는 것도 짜증나는데 클래스도 만들어야 하냐?
➡️ 심지어 만드는 것마저 일회성이냐?
- 그로 인해 "익명 객체"로 할 수 있게 변함
(3) 익명 객체(Anonymous Object)
첫 번째, 데이터 개수는 고정이니 선언은 할 수 있네?
➡️ 인터페이스
두 번째, 객체를 생성할 때(클래스를 안 만들고) 메서드를 구현
➡️ 사용자가 메서드를 만들어야 하는데, 메서드 정의가 너무 긺
=> 긴 메서드 정의를 줄이자 => 람다식 사용
(4) 정리
- 무슨 타입인지를 사용자에게 정의하도록 맡김
➡️ Generic - 무슨 함수를 사용할지를 사용자에게 맡김
➡️ 함수형 프로그래밍 - 함수를 ( )에 다 넣으려고 보니 길고 복잡함
➡️ 람다식 (의 등장)
(5) 기본 형식
Method(매개변수들.....){
실행문;
}
(매개변수들.....) -> { 실행문; }
=> Calculable.java, CalculableClass.java, CalculableReturn.java, LambdaMain.java
// Calculable.java
package day17;
public interface Calculable {
public void calculate(int x, int y);
}
// CalculableClass.java
package day17;
public class CalculableClass implements Calculable {
public void calculate(int x, int y) {
System.out.println("[일반객체] " + (x+y));
}
}
// CalculableReturn.java
package day17;
public interface CalculableReturn {
public double calculate(int r);
}
// LambdaMain.java
package day17;
import java.util.ArrayList;
public class LambdaMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 1. Standard
CalculableClass cc = new CalculableClass();
cc.calculate(100, 1000);
// 수식이 오래되었다... 바꿔 => 본체를 바꿔야 함
// 2. Anonymous Instance(익명객체) - class 없이 바로 생성해서 "익명객체"라 한다
Calculable c1 = new Calculable() {
public void calculate(int x, int y) {
System.out.println("[익명객체-일반] " + (x * y));
}
};
c1.calculate(100, 1000);
// 3. LambdaⅠ: 람다식으로 정의하면 자동으로 메서드와 매핑
// 조건: 인터페이스가 반드시 1개 (구현을 해야하는) 메서드만 있다면 가능
Calculable c2 = (x, y) -> { System.out.println("[람다정식] " + (x*y)); };
c2.calculate(100, 1000);
// 4. LambdaⅡ : return값이 있는 경우
CalculableReturn c3 = (x) -> { return 3.14 * x * 2; };
System.out.println("[람다리턴] " + c3.calculate(100));
// 5. 인풋이 1개 뿐이면 괄호도 생략
CalculableReturn c4 = x -> { return 3.14 * x * 2; };
System.out.println("[람다리턴] " + c4.calculate(100));
// 6. 리턴이 한 줄이면 중괄호도 생략
CalculableReturn c5 = x -> 3.14 * x * 2;
System.out.println("[람다리턴] " + c5.calculate(100));
// 7. 인터페이스를 내가 만들어야 하나요? 별 의미도 없는데
// UnaryOperator : 1개 입력해서 1개 출력하는 건 이걸 사용
// BinaryOperator : 2개 입력해서 1개 출력하는 건 이걸 사용
// Consumer, forEach
// 람다식은 왜이렇게 웹에서 많이 쓰일까?
// 8. 람다식의 대표적인 예제 -> forEach
ArrayList<String> ar = new ArrayList();
ar.add("Steak");
ar.add("Striper");
ar.add("Rock Group");
for(String name : ar) {
System.out.println(name );
}
ar.forEach(name -> System.out.println(name));
// 입력이 들어가서 아무 가공없이 사용될 경우
ar.forEach(System.out::println);
}
}
'📁💻 웹개발 강의 아카이빙 > (2024)☕JAVA' 카테고리의 다른 글
day18 (1) | 2024.10.03 |
---|---|
day16 (0) | 2024.09.18 |
day15 (0) | 2024.09.18 |
day14 (0) | 2024.09.18 |
day13 (0) | 2024.09.11 |