타입매개변수
21강
21-12 다중 매개변수 기반 제네릭 클래스의 정의
바로 int이런식으로 선언 못해서 DBox<String, Integer>(참조형 데이터 타입)선언한다. - 반드시 객체로 선언해야함.
- 객체 만들었으니 set을 통해 값을 넣는다. - set메소드에서 box.set("Apple", 25); 로 들어감.
- 들어 갈 수 있는 이유는 오토박싱이 되어있기 때문에
//21-12예제
package java_1221;
public class BoxClass {
public static void main(String[] args) {
DBox<String, Integer> box = new DBox<String, Integer>();
box.set("Apple", 25);
System.out.println(box);
}
}
class DBox<L, R> {
private L left;
private R right;
public void set(L o, R r) {
left = o;
right = r;
}
@Override
public String toString() {
return left + " & " + right;
}
}
21-13 타입 매개변수의 이름 규칙
21-14 기본 자료형에 대한 제한 그리고 래퍼 클래스
<int>x - 기본타입형x
<Integer>o - Wrapper 클래스 (객체)o
21-15 다이아몬드 기호
<>뒤에 생략하면 앞에거 <Apple> 따라옴
21-16 ‘매개변수화 타입’을 ‘타입 인자’로 전달
//21-16 예제
package java_1221;
public class BoxClass {
public static void main(String[] args) {
Box<String> sBox = new Box<>();
sBox.set("I am so happy");
Box<Box<String>> wBox = new Box<>();
wBox.set(sBox);
Box<Box<Box<String>>> zBox = new Box<>();
zBox.set(wBox);
System.out.println(zBox.get().get().get());
}
}
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
21-17 제네릭 클래스의 타입 인자 제한하기
Number는
T가 Number이거나 Number를 상속.
위의 코드에서는 T는 Integer나 Double만 올수 있음. - String 이런거 오면 오류뜸
인스턴스 생성 시 타입 인자로 Number 또는 이를 상속하는 클래스만 올 수 있음
ex) class Box<T extends Number> {...} => 와 같이 Number 클래스를 상속하면 기본형으로 타입을 제한-String, Apple과 같은 타입은 들어오지 못함
21-18 타입 인자 제한의 효과
왜 <T extends Number>이렇게 제한할까? ob.intValue();를 호출해주는 게 목적. .intValue는 Number에 있다.
근데 Number상속하지 않은 코드에서는 실수로 ob.을 붙여서 에러남.
객체 안에있는 함수를 호출하려면 반드신 extends Number처럼 함수을 제한시켜야한다.
21-19 제네릭 클래스의 타입 인자를 인터페이스로 제한하기
T (=ob)가 제한되어야함. Eatable로 제한해줌.
상위 타입은 클래스 뿐만 아니라 인터페이스도 가능하다. 인터페이스라고 해서 extends 대신 implements를 사용하지 않는다.
(출처: https://ict-nroo.tistory.com/42 [개발자의 기록습관])
//21-19 예제
package java_1221;
interface Eatable {
public String eat();
}
class Apple implements Eatable {
public String toString() {
return "I am an apple.";
}
@Override
public String eat() {
return "It tastes so good!";
}
}
class Box<T extends Eatable> {
//class Box<T extends Apple> { -상관x Apple상속받은것이기 때문
private T ob;
public void set(T o) {
ob = o;
}
//한 입 먹고 반환하는 행위의 메소드로 수정
public T get() {
System.out.println(ob.eat());
return ob;
}
}
class BoundedInterfaceBox {
public static void main(String[] args) {
Box<Apple> box = new Box<>();
box.set(new Apple());
Apple ap = box.get();
System.out.println(ap);
}
}
T는 전부 Apple 이 된다. - 형변환없이 꺼낸다는게 장점
21-20 하나의 클래스와 하나의 인터페이스에 대해 동시 제한
제네릭 타입에서만 class Name<T extends A & B>{ } 이런식으로 사용 가능
21-21 제네릭 메소드의 정의 - 여기서 어렵. 이해안되면 일단 이해하지말기
public static = 이미 배운것
<T> = 제네릭 메소드 라고 알려주는것. (함수앞에 꺽쇠오면 제네릭메소드다)
Box<T> = 리턴타입
class BoxFactory <T>{} 이렇게 T가오면 클래스전체에 T가 온다는것.
public static <T> : 이 함수에서만 써먹겠다 - 근데 써먹는거 없음. 걍 제네릭 메소드라는 걸 알려주려고 하는것.
그 다음 오는 Box<T>가 다음에 오는 Box<T>와 box에 영향을 줌.
21-22 제네릭 메소드의 제한된 타입 매개변수 선언
//21-22 예제
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
class BoxFactory{
public static <T> Box<T> makeBox(T o) {
Box<T> box = new Box<T>();
box.set(o);
return box;
}
}
class GenericMethodBoxMaker {
public static void main(String[] args) {
Box<String> sBox = BoxFactory.makeBox("Sweet");
System.out.println(sBox.get());
Box<Double> dBox = BoxFactory.makeBox(7.59);
System.out.println(dBox.get());
}
}
22강
- 현업에서도 여기까지 모르는사람들 많음. 모르겠으면 일단 패스~~
22-3 제네릭 클래스와 상속
(상속이 안되면 다형성이 안되기때문)
SteelBox<Integer>는 왜 Box<String>을 상속할 수 없을까? 문법적으로 맞지도않고 안에 내용물이 일단 다르다.
(상속관계에서도 일단 맞아야함.)
22-4 타겟 타입 - 현업에서도 잘 알지못함.
...?
22-5 와일드카드의 설명에 앞서(제네릭 메소드 vs. 일반 메소드)
상속관계가 되려면 부모에있는 데이터멤버와 함수를 그대로 올려놓고 갖다 써야하는데 String으로 체인지해서 들어가면 상속자체가 안된다.
따라서 매개변수에 Object는 들어갈 수 없다.
22-6 와일드카드 - 제네릭하고는 또 다르지만 똑같은 문법
<?> = 와일드 카드 : 마땅한 번역이 없음. 걍 와일드카드라고함.
Object랑 비슷한 기능함. <T> 붙으나 <?> 붙으나 기능은 똑같은데 <?>은 인스턴스 맘대로 넣을 수 있다.
22-7
<T>문법상으론 더 복잡해져서 <?>이걸 쓰는걸 더 권고함!
22-8 와일드 카드의 상한과 하한의 제한: Bounded Wildcards
22-9 상한 제한된 와일드카드(Upper-Bounded Wildcards)
와일드카드에다가 extends 준것.
Number를 상속한 것.
22-10 하한 제한된 와일드카드(Lower-Bounded Wildcards)
super Integer 안헷갈리는 해석 : Integer위에 있는것
22-11 와일드카드 제한의 이유 설명을 위한 도입
22-12 상한 제한의 목적
//22-12
class Box<T> {
private T ob;
public void set(T o) {
ob = o;
}
public T get() {
return ob;
}
}
class Toy {
@Override
public String toString() {
return "I am a Toy";
}
}
class BoxHandler {
public static void outBox(Box<? extends Toy> box) {
Toy t = box.get(); // 박스에서 꺼내기
// box.set(new Toy());-★오류남-why?다형성때문에.-왜 오류나는지 꼭알기
System.out.println(t);
}
public static void inBox(Box<? super Toy> box, Toy n) {
box.set(n); // 박스에 넣기
}
}
class BoundedWildcardUsage2 {
public static void main(String[] args) {
Box<Toy> box = new Box<>();
BoxHandler.inBox(box, new Toy());
BoxHandler.outBox(box);
}
}
22-13
22-14
Toy부모는 Plastic
22-15
22-16 상한 제한과 하한 제한의 좋은 예 하나!
----------------여기까지만 이해해도 괜춘
22-17
22-18 다음 형태로 메소드 오버로딩 불가능하다
제내릭 안에있는 매개변수 타입에 대해서는 오버로딩이 안된다.
, 찍고 매개변수 한개 더 적어주면 된다.
22-19 그래서 와일드 카드 선언을 갖는 메소드를 제네릭으로
와일드 카드와 제네릭을 섞음.
===============여기까지 활용도필요없음 이해까지만이라도 하면 됨.==================
22-20 제네릭 인터페이스의 정의와 구현
interface Getable<T> {
public T get();
}
//졸아서 코드 오류남
class Box<T> implements Getable<T> {
private T ob;
public void set(T o) {
}
ob=o;
}
@Override
public T et() {
return ob;
}
class Toy {
@Override
public String toString() {
return "Im a Toy";
}
}
class BoundedWildcardUsage2 {
public static void main(String[] args) {
Box<Toy> box = new Box();
box.set(new Toy());
Getable<Toy> gt = box;
System.out.println(gt.get());
}
}
23강 프레임워크
23-3 컬렉션 프레임워크 - 컴공과학생들이 차이있음
4가지-반드시 외우기
Set, List, Queue(상속받는 3개), Map 셀리큐맵
컬렉션프레임워크란?? 자료구조, 알고리즘을 구현해놓은 일종의 라이브러리.
23-5 List 인터페이스 -중요
List - 걍 1번2번3번4번 차례로 오는 개념
중복저장을 허용한다.
//23-5 그림 예제
package java_1222;
class Link {
int num; // object해서 객체로 받아도 상관x
Link link; //자기자신x
}
public class aaaa {
public static void main(String[] args) {
Link link1 = new Link();
link1.num = 3;
Link link2 = new Link();
link2.num = 5;
link1.link = link2; //그림의 예제임.
}
}
23-6 ArrayList 클래스
배열안쓰고 ArrayList같은걸로 씀
결국 ArrayList는 배열이랑 똑같은 것임. 배열로 관리한다.
List에다가 <String>(제네릭으로 선언) 넣고 new 객체 생성
list.add()하게 되면 넣는것, 이걸 꺼내는 방법은 list.get으로 꺼낸다.
그리고 그 배열을 지우고싶으면 list.remove를 쓰면된다.
그럼 다음 배열이 알아서 0번째로 옮겨간다.
.
//23-6 예제
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class BoundedWildcardUsage2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>(); // 유일한 변화!!!
// 컬렉션 인스턴스에 문자열 인스턴스 저장
list.add("Toy");
list.add("Box");
list.add("Robot");
// 저장된 문자열 인스턴스의 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
System.out.println();
list.remove(0); // 첫 번째 인스턴스 삭제
// 첫 번째 인스턴스 삭제 후 나머지 인스턴스들을 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
System.out.println();
}
}//Toy Box Robot
//Box Robot
23-7 LinkedList 클래스
배열은 연속된 공간이다. LinkedList는 연속된 공간이 아니다.
유일한 변화있음
다형성, 함수오버라이딩
//23-7 예제
import java.util.LinkedList;
import java.util.List;
public class BoundedWildcardUsage2 {
public static void main(String[] args) {
List<String> list = new LinkedList<>(); // 유일한 변화!!!
// 컬렉션 인스턴스에 문자열 인스턴스 저장
list.add("Toy");
list.add("Box");
list.add("Robot");
// 저장된 문자열 인스턴스의 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
System.out.println();
list.remove(0); // 첫 번째 인스턴스 삭제
// 첫 번째 인스턴스 삭제 후 나머지 인스턴스들을 참조
for (int i = 0; i < list.size(); i++)
System.out.print(list.get(i) + '\t');
System.out.println();
}
}//Toy Box Robot
//Box Robot
**LinkedList랑 ArrayList를 쓰는게 실력차이가 난다
23-8 ArrayList<E> vs. LinkedList<E>
ArrayList 는 배열을 한번 복사하는데도 시간걸림, 지우는것도 시간 걸림 - 배열의 단점 그대로.(단점)
검색(=참조)은 빠르다. 다이렉트로 찾아감(장점)
LinkedList 는 검색은 느리다.(단점)
저장공간은 객체를 하나씩 늘리기때문에 과정이 간단.(장점)
---장단점 잘 생각해서 둘 중 하나로 쓰면 됨!
오늘의 문제
1.제네릭 클래스의 타입 인자 제한하는 방법과 효과는?
: super 나 extends 예약어를 넣어줘서 해당클래스이거나 상속을 받는(or 하는) 애들로만 제한 할 수 있어 오류를 잡을 수 있다.
//다른분 예시
class Box <T extends Number> { // Number 혹은 Number에게 상속 받는 클래스들에게만 대상
private T ob;
public int toValue() {
return ob.intValue(); // Number에 있는 메소드를 호출하기 위함!
}
}
2.아래와 같이 출력값이 나오도록 프로그래밍 하시오.
class DDBoxDemo {
public static void main(String[] args) {
DBox<String, Integer> box1 = new DBox<>();
box1.set("Apple", 25);
DBox<String, Integer> box2 = new DBox<>();
box2.set("Orange", 33);
DDBox<DBox<String, Integer>, DBox<String, Integer>> ddbox = new DDBox<>();
ddbox.set(box1, box2);
System.out.println(ddbox);
}
}
==================
Apple & 25
Orange & 33
class DDBoxDemo {
public static void main(String[] args) {
DBox<String, Integer> box1 = new DBox<>();
box1.set("Apple", 25);
DBox<String, Integer> box2 = new DBox<>();
box2.set("Orange", 33);
DDBox<DBox<String, Integer>, DBox<String, Integer>> ddbox = new DDBox<>();
ddbox.set(box1, box2);
System.out.println(ddbox);
}
}
class DDBox<F, A> {
protected F fruit;
protected A age;
public void set(F f, A a) {
fruit = f;
age = a;
}
@Override
public String toString() {
return fruit + " & " + age + "\n";
}
}
class DBox<F, A> extends DDBox<F, A> {
public void set(F f, A a) {
fruit = f;
age = a;
}
public F getFruit() {
return fruit;
}
public void setFruit(F fruit) {
this.fruit = fruit;
}
public A getAge() {
return age;
}
public void setAge(A age) {
this.age = age;
}
}
//Apple & 25
// & Orange & 33
//오류 &이 한번 더 출력
3.아래와 같이 출력값이 나오도록 프로그래밍 하시오.
public static void main(String[] args) {
Box<Integer> box1 = new Box<>();
box1.set(99);
Box<Integer> box2 = new Box<>();
box2.set(55);
System.out.println(box1.get() + " & " + box2.get());
swapBox(box1, box2);
System.out.println(box1.get() + " & " + box2.get());
}
==========
99 & 55
55 & 99
public class NumMain {
public static void main(String[] args) {
Box<Integer> box1 = new Box<>();
box1.set(99);
Box<Integer> box2 = new Box<>();
box2.set(55);
System.out.println(box1.get() + " & " + box2.get());
swapBox(box1, box2);
System.out.println(box1.get() + " & " + box2.get());
}
private static void swapBox(Box<Integer> box1, Box<Integer> box2) {
}
}
class Box<T> {
private T inte;
public void set(T t) {
inte = t;
}
public T get() {
return inte;
}
}
//==========
//99 & 55
//55 & 99
오류
//99 & 55
99 & 55
↓문제풀이
//???
package java_1222;
class QuizMain {
private static <T extends Number> void swapBox(Box<T> box1, Box<T> box2) {
// int temp = box1.get();
// box1.set(box1.get());
// box1.set(temp);
T temp = box1.get();
box1.set(box2.get());
box2.set(temp);
}
}
public class NumMain {
public static void main(String[] args) {
Box<Integer> box1 = new Box<>();
box1.set(99);
Box<Integer> box2 = new Box<>();
box2.set(55);
System.out.println(box1.get() + " & " + box2.get());
swapBox(box1, box2);
/*
* 원래는 int a = 1; int b = 2; temp = a; a = b; b = temp; 이렇게 바꿈 - 이걸 구현
*/
System.out.println(box1.get() + " & " + box2.get());
}
private static void swapBox(Box<Integer> box1, Box<Integer> box2) {
}
}
class Box<T> {
private T obj;
public void set(T obj) {
this.obj = obj;
}
public T get() {
return obj;
}
}
4. 지네릭 메소드에 대하여 설명하시오.
: public static <T> 에서 <T>는 제네릭 메소드 라고 알려주는것이다. (함수앞에 꺽쇠오면 제네릭메소드다)
5. 와일드 카드와 상한 제한, 하한 제한에 대하여 설명하시오. *참고 vvshinevv.tistory.com/56
- 상한 제한
ex. public static void PaperBox(Paper<? extends Box> box){ }
위 코드에서 ?는 와일드카드 이므로 어떤 타입이 와도 상관 없다. 근데 extends Box로 예약어를 걸어둠으로서 Box이거나 Box를 상속하는 클래스만 와라 라고 제한을 걸어두었다. (=Box위에 Object는 올 수 없음) = 상한제한
- 하한 제한
ex. public static void PaperBox(Paper<? super Box> box){ }
위 코드에서 ?는 와일드카드이므로 box 파라미터 변수에 어떤 타입을 전달 받아도 상관없다. 근데 super Box로 예약어를 걸어두어 Box이거나 Box가 상속하는 클래스만 와라 라고 제한을 걸어두었다. (=Box아래에 있는 Double, Integer, Long 은 올 수 없음) = 하한제한
6. 아래가 에러가 나는 이유를 설명하시오.
public static void inBox(Box<? super Toy> box, Toy n) {
box.set(n); // 넣는 것! OK!
Toy myToy = box.get(); // 꺼내는 것! Error!
}
super Toy 하한제한 예약어를 줌으로서 box 인스턴스에 넣는 것은 가능하고 box 인스턴스에 꺼내는 것은 불가능
Toy 는 자식클래스인데 box.get();을 해주게 되면 자식클래스에있는 인스턴스를 꺼내게될지 부모클래스에 있는 인스턴스를 꺼내게될지 모르기때문에 에러가 난다.
7. 아래와 같이 메소드 오버로딩이 되지 않는 이유는?
// 다음 두 메소드는 오버로딩 인정 안됨.
public static void outBox(Box<? extends Toy> box) {...}
public static void outBox(Box<? extends Robot> box) {...}
제내릭 안에있는 매개변수 타입에 대해서는 오버로딩이 안된다. - 컴파일 과정에서 내용이 지워지기 때문에
오버로딩 시키려면 → , 찍고 매개변수 한개 더 적어주면 된다.
(Box<? super Toy> box, Toy t){ }
(Box<? super Robot> box, Robot r){ }
8. 아래의 결과가 나오도록 프로그래밍을 완성하시오.
public static void main(String[] args) {
Box<Integer> box1 = new Box<>();
box1.set(24);
Box<String> box2 = new Box<>();
box2.set("Poly");
if(compBox(box1, 25))
System.out.println("상자 안에 25 저장");
if(compBox(box2, "Moly"))
System.out.println("상자 안에 Moly 저장");
System.out.println(box1.get());
System.out.println(box2.get());
}
=======
24
Poly
:
public class PolyMolyMain {
public static void main(String[] args) {
Box<Integer> box1 = new Box<>();
box1.set(24);
Box<String> box2 = new Box<>();
box2.set("Poly");
if (compBox(box1, 25))
System.out.println("상자 안에 25 저장");
if (compBox(box2, "Moly"))
System.out.println("상자 안에 Moly 저장");
System.out.println(box1.get());
System.out.println(box2.get());
}
private static boolean compBox(Box<Integer> box1, int i) {
return false;
}
private static boolean compBox(Box<String> box2, String string) {
return false;
}
}//24
//Poly
9. 콜렉션 프레임워크란?
Set List Queue Map 셀리큐맵!
: 자료구조, 알고리즘을 구현해놓은 일종의 라이브러리이다.
Set< E >
(현재배운것)List< E >: 인스턴스의 저장 순서를 유지하고 동일 인스턴스의 중복 저장을 허용할 수 있다.
-ArrayList< E >: 배열 기반 자료구조로 배열을 이용하여 인스턴스에 저장한다.
-LinkedList< E >: 리스트 기반 자료구조로 리스트를 구성하여 인스턴스에 저장한다.
Queue< E >
Map<K, V>
'코딩 > 수업 정리' 카테고리의 다른 글
20.12.24 Thu [024] JSP (0) | 2020.12.24 |
---|---|
20.12.22 Tue [022] (0) | 2020.12.22 |
20.12.18 Fri [020] (0) | 2020.12.18 |
20.12.17 Thu [019] (0) | 2020.12.17 |
20.12.16 Wed [018] 예외처리, 가상머신 (0) | 2020.12.16 |
댓글