본문 바로가기

자바

Day12

 

지네릭 클래스의 객체 생성과 사용 : 참조변수와 생성자에 대입된 타입(매개변수화된 타입)이 일치해야 한다. 일치하지 않으면 에러가 발생 ex) Box<Apple> appleBox = new Box<Grape>();
두 타입이 상속관계에 있어도 마찬가지 ex) Apple extends Fruit 일때 , Box<Fruit> appleBox = new Box<Apple>(); 
단, 두 지네릭 클래스의 타입이 상속관계에 있고, 대입된 타입이 같은 것은 괜찮다. ex) Fruit extends Box 일때,
Box<Apple> appleBox = new FruitBox<Apple> //ok 
생성된 Box<T>의 객체에 void add(T item)으로 객체를 추가할때, 대입된 타입과 다른 타입의 객체는 추가할 수 없다.
                                    ex) Box<Apple> appleBox = new Box<Apple>();
                                           appleBox.add(new Grape()); //에러발생
하지만 타입 T가 Fruit인 경우 Fruit의 자손들은 이 메서드의 매개변수가 될 수 있다. 
와일드 카드 : 기호'?'를 사용하며 어떠한 타입도 될 수 있다. 그러나 "?"만으로는 Object 타입과 다를게 없으므로, 
<? extends T> : 와일드 카드의 상한 제한,T와 그 자손들만 가능 (upper bound)
<? super T> : 와일드 카드의 하한 제한, T와 그 조상들만 가능 (lower bound)
<?> : 제한없음, 모든 타입이 가능하다.<? extends Object>와 동일
package com.test02;
import java.util.*;
class Fruit1 {
	String name;
	int weight;
	Fruit1(String name, int weight) {
		this.name = name;
		this.weight = weight;
	}
	public String toString() {
		return name + "("+weight+")";
	}
}
class Apple1 extends Fruit1 {
	Apple1(String name, int weight) {
		super(name, weight);
	}
}
class Grape1 extends Fruit1 {
	Grape1(String name, int weight) {
		super(name, weight);
	}
}
AppleComp와 GrapeComp는 타입만 다를뿐 완전히 같은 코드이다. 코드의 중복도 문제지만, 새로운 fruit의 자손이 생길때마다 아래와 같은 코드를 반복해서 
만들어야 한다는 것이 더 문제이다. 이 문제를 해결하기 위해서는 타입 매개변수에 하한 제한의 와일드 카드를 적용한다. 
//class AppleComp implements Comparator<Apple1> {
//	@Override
//	public int compare(Apple1 o1, Apple1 o2) {		
//		return o2.weight - o1.weight;
//	}	
//}
//class GrapeComp implements Comparator<Grape1> {
//	@Override
//	public int compare(Grape1 o1, Grape1 o2) {
//		return o2.weight - o1.weight;
//	}	
//}
따라서 Apple1과Grape1의 조상인 Fruit1을 Comparator에 타입 매개변수로 사용함으로 중복되는 코드를 줄일 수 있게 된다.
class FruitComp implements Comparator<Fruit1> {
	@Override
	public int compare(Fruit1 o1, Fruit1 o2) {
		return o1.weight - o2.weight;
	}	
}
// <T extends Fruit1>에 가능한 타입은 Fruit을 포함한 그의 자손들만 사용할 수 있게 와일드 카드로 상한 제한을 둔것이다.
class FruitBox1<T extends Fruit1> extends Box1<T> {}
class Box1<T> {
	ArrayList<T> list = new ArrayList<>();
	void add(T item) {
		list.add(item);
	}
	T get(int i) {
		return list.get(i);
	}
	ArrayList<T> getList() {
		return list;
	}
	int size() {
		return list.size();
	}
	public String toString() {
		return list.toString();
	}	
}
public class Sample14 {
	public static void main(String[] args) {
		FruitBox1<Apple1> appleBox = new FruitBox1<Apple1>();
		FruitBox1<Grape1> grapeBox = new FruitBox1<Grape1>();
		appleBox.add(new Apple1("GreenApple", 300));
		appleBox.add(new Apple1("GreenApple", 100));
		appleBox.add(new Apple1("GreenApple", 200));		
		grapeBox.add(new Grape1("Greengrape",300));
		grapeBox.add(new Grape1("Greengrape",400));
		grapeBox.add(new Grape1("Greengrape",200));		
//		Collections.sort(appleBox.getList(), new AppleComp());
//		Collections.sort(grapeBox.getList(), new GrapeComp());
		System.out.println(appleBox);
		System.out.println(grapeBox);
		System.out.println();
        오름차순 정렬
		Collections.sort(appleBox.getList(), new FruitComp());
		Collections.sort(grapeBox.getList(), new FruitComp());		
		System.out.println(appleBox);
		System.out.println(grapeBox);	
	}
}

 

열거형[enum]  서로 관련된 상수를 편리하게 선언하기 위한 것으로 여러 상수를 정의 할때 사용하면 유용하다. 
상수의 값이 바뀌면, 해당 상수를 참조하는 모든 소스를 다시 컴파일 해야하는데, 열거형 상수를 사용하면, 기존의 소스를 다시 컴파일 하지 않아도되는 장점이 있다.
열거형의 메서드
Class<E> getDeclaringClass() 열거형의 Class 객체를 반환한다.
String name() 열겨형 상수의 이름을 문자열로 반환한다.
int ordinal() 열거형 상수가 정의된 순서를 반환한다.(0 부터 시작)
T valueOf(Class<T>enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다.

 

package com.test03;
enum Transportation {
	Bus(100) {
		int fare(int distance) {
			return distance*Basic_Fare;
		}
	},
	Train(150) {
		int fare(int distance) {
			return distance*Basic_Fare;
		}
	},
	Ship(100) {
		int fare(int distance) {
			return distance*Basic_Fare;
		}
	},
	Airplane(300) {
		int fare(int distance) {
			return distance*Basic_Fare;
		}
	};
	protected final int Basic_Fare;	//protected로 해야 각 상수에서 접근가능
	Transportation(int basicFare) {
		Basic_Fare = basicFare;
	}
	public int getBasicFare() { 제어자로 운송 요금을 반환
		return Basic_Fare;
	}
	abstract int fare(int distance); // 거리에 따른 요금을 계산하는 추상 메서드
}
public class Sample25 {
	public static void main(String[] args) {
		System.out.println("bus fare ="+Transportation.Bus.fare(100));
		System.out.println("train fare ="+Transportation.Train.fare(100));
		System.out.println("ship fare="+ Transportation.Ship.fare(100));
		System.out.println("airplane fare="+Transportation.Airplane.fare(100));
	}
}

 

 

애너테이션(annotation) : 자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기 보다 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다. 그래서 소스코드의 주석'/** ~ */'에 소스코드에 대한 정보를 저장하고, 소스코드의 주석으로부터 HTML문서를 생성해내는 프로그램을 만들어서 사용했다. 
ex) @Override : 컴파일러에게 오버라이딩 하는 메서드라는 것을 알린다.
람다식(Lambda expression) : 메서드를 하나의 '식(expression)'으로 표현한 것이다. 함수를 간략하면서도 명확한 식으로 표현할 수 있게 해준다. 
메서드를 람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로, 람다식을 '익명함수(anonymous function)'이라고 한다.
메서드와 함수의 차이 : 메서드는 함수와 같은 의미이지만, 특정 클래스에 반드시 속해야 한다는 제약이 있기 때문에 기존의 함수와 같은 의미의 다른 용어를 선택해서 사용한 것이다. 그러나 이제 람다식을 통해 메서드가 하나의 독립적인 기능을 하기 때문에 함수라는 용어를 사용하게 되었다.
람다식의 작성 : '익명 함수' 답게 매서드에서 이름과 반환타입을 제거하고 매겨변수 선언부와 몸통{}사이에 ->를 추가한다.
ex) int max(int a, int b) { return a > b ? a : b ;} -------->  (int a, int b) -> { return a > b ? a : b;}  ----------->
[만약 반환값이 있는 메서드의 경우] : (int a , int b) -> a > b ? a: b -------> (a , b) -> a > b ? a : b
package com.test03;
interface MyFunction {void run();}
public class Sample21 {
	static void execute(MyFunction f) { // 매개변수타입이 MyFunction인 메서드
		f.run();
	}
	static MyFunction getMyFunction() { // 반환 타입이 MyFunction인 메서드 
		MyFunction f = () -> System.out.println("f3.run()");
		return f;
	}
	public static void main(String[] args) {
		MyFunction f1 = () -> System.out.println("f1.run()");
		MyFunction f2 = new MyFunction() { //익명클래스로 run()을 구현 
			public void run() { //public을 반드시 붙여야함 
				System.out.println("f2.run()");
			}
		};
		MyFunction f3 = getMyFunction();
		f1.run(); // f1.run()
		f2.run(); // f2.run()
		f3.run(); // f3.run()
		execute(f1); // f1.run()
		execute( () -> System.out.println("run()")); // run()
	}
}

'자바' 카테고리의 다른 글

Day14  (0) 2021.05.24
Day13  (0) 2021.05.21
Day11  (0) 2021.05.18
Day10-1  (0) 2021.05.17
2주차 은행 계좌 예제 수정  (0) 2021.05.16