gwooden_코린이
java_제네릭_221202(10일차) 본문
728x90
- 제네릭
1. 타입 체크 기능
2. 형변환 불필요
package 제네릭;
public class Sample01 {
public static void main(String[] args) {
//제네릭 설정할 때는 <자료형 타입> = new <> 처음에만 타입을 입력하면 된다.
/**객체 생성 **/
NoGeneric<String> nogen = new NoGeneric<>(); //String 문자열 타입 고정
String[] ss = {"홍길동", "이순신", "김유신"}; //만든 배열을 위 객체로 전달
/** 위에서 받은 배열값을 nogen으로 보낸다.**/
nogen.set(ss);
nogen.print();
for(String o : nogen.get()) {
System.out.println(o + 1);
}
Integer[] ii = {1, 2, 3};
NoGeneric<Integer> nogen1 = new NoGeneric<>();
nogen1.set(ii);
nogen1.print();
for(Integer o : nogen1.get()) {
System.out.print(o + 5);
}
}
}
package 제네릭;
public class NoGeneric<T> { //<> <-- 이 안에 T로 설정한 자료형 타입이 메인에 따라 자동으로 바뀜
//오브젝트로 처리한 이유는 어떤 자료형 타입을 사용할지 정하지 않았기 때문에
T[] v; //오브젝트 자료형 타입은 어떤한 객체든 들어갈 수 있게끔 선언해준 것
void set(T[] n) { //메인에서 호출한 무엇인가를 전달받아 클래스 변수인 v에다가 전달
v = n;
}
T[] get() { //위에서 저장된 v를 전달
return v;
}
void print() {
for(T o : v) {
System.out.print(o + " ");
}
System.out.println();
}
}
- 제네릭 작업 전
package 제네릭;
import java.util.ArrayList;
import java.util.List;
public class Sample02 {
public static void main(String[] args) {
List list = new ArrayList();
/** 객체 생성 **/
//객체 내부에는 name, id, password, age에 변수를 보관중
Member mem1 = new Member();
mem1.setName("홍길동");
mem1.setId("aaa");
mem1.setPassword("aa11");
mem1.setAge(20);
System.out.println(mem1);
Member mem2 = new Member();
mem2.setName("이순신");
mem2.setId("bbb");
mem2.setPassword("bb11");
mem2.setAge(30);
System.out.println(mem2);
Member mem3 = new Member();
mem3.setName("김유신");
mem3.setId("ccc");
mem3.setPassword("cc11");
mem3.setAge(40);
System.out.println(mem3);
list.add(mem1);
list.add(mem2);
list.add(mem3);
/** 반복문 **/
//size는 크기로 .length를 쓰면 안됨
for(int i = 0; i<list.size(); i++) {
/** 강제 형 변환 **/
//list에 들어있는 mem1-3 값들 안에 name, id, password, age를 하나씩 불러올때
//list는 순서대로 읽음
//그냥 list.get(i)로만 해서 list가 자료형 타입인지 클래스 타입인지 인식 불가
//그래서 list를 Member 클래스에 대한 객체라고 형변환
//그리고 괄호로 영역 지정
//마지막에 getName() 호출
System.out.println("이름 : " + ((Member)list.get(i)).getName());
System.out.println("아이디 : " + ((Member)list.get(i)).getId());
System.out.println("비밀번호 : " + ((Member)list.get(i)).getPassword());
System.out.println("나이 : " + ((Member)list.get(i)).getAge());
}
}
}
- 제네릭 작업 후
package 제네릭;
import java.util.ArrayList;
import java.util.List;
public class Sample02 {
public static void main(String[] args) {
//List를 제너릭으로 <> Member 클래스에 대한 객체라고 인식 시켜준다
// 이런식으로 설정하면 맨 아래에서 귀찮게 형변환 하지 않아도 되는 장점
List<Member> list = new ArrayList<>();
/** 객체 생성 **/
//객체 내부에는 name, id, password, age에 변수를 보관중
Member mem1 = new Member();
mem1.setName("홍길동");
mem1.setId("aaa");
mem1.setPassword("aa11");
mem1.setAge(20);
System.out.println(mem1);
Member mem2 = new Member();
mem2.setName("이순신");
mem2.setId("bbb");
mem2.setPassword("bb11");
mem2.setAge(30);
System.out.println(mem2);
Member mem3 = new Member();
mem3.setName("김유신");
mem3.setId("ccc");
mem3.setPassword("cc11");
mem3.setAge(40);
System.out.println(mem3);
list.add(mem1);
list.add(mem2);
list.add(mem3);
/** 반복문 **/
//size는 크기로 .length를 쓰면 안됨
for(int i = 0; i<list.size(); i++) {
/** 맨 위에서 객체 생성 할 때 제너릭으로 Member 클래스에 대해 지정해 줌 **/
System.out.println("이름 : " + list.get(i).getName());
System.out.println("아이디 : " + list.get(i).getId());
System.out.println("비밀번호 : " + list.get(i).getPassword());
System.out.println("나이 : " + list.get(i).getAge());
}
}
}
package 제네릭;
public class Member {
/**Main에서 갖다 쓰지 못함 프라이빗 접근자에서는**/
private String name;
private String id;
private String password;
private int age;
/** Member 안에 있는 값들을 리턴 **/
@Override
public String toString() {
return "Member [name=" + name + ", id=" + id + ", password=" + password + ", age=" + age + "]";
}
/** 게터 메서드로 받게 되면 Main으로 주고 받고 가능 **/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package 제네릭;
public class Sample03 {
public static void main(String[] args) {
/** Generic2에 대한 기능들을 가져다 쓰기 위해 **/
/** 객체 생성 <K에 대한 자료형 타입, V에 대한 자료형 타입> 입력**/
Generic2<String, Integer> gen = new Generic2<>();
/** set으로 입력한 K와 V에 대한 값을 gen 객체로 보낸다. **/
gen.set("문자열", 10);
// 위에서 제너릭<>에 자료형 타입을 지정하지 않으면 가능하나 지정한 상태에서는 위치 변경 불가
// gen.set(10, "an");
/** 해당 값을 불러오기 위해 해당 메서드 호출 **/
System.out.println("이름" + gen.getName());
System.out.println("나이" + gen.getId());
}
}
package 제네릭;
/** 제네릭 2개 입력 **/
/** 변수를 추가하고 싶은 만큼 추가로 넣는 것도 가능 **/
/** 그 만큼 아래 기능들도 갯수 만큼 추가 **/
public class Generic2<K, V> {
/** 아직 자료형 타입이 뭐가 될지 정해지지 않음 **/
//문자열이 될지 문자가 될지 인수가 될지 실수가 될지 아직 미정
K name; //name 변수 하나
V id; //id 변수 하나
/**Main에서 값을 받아오는 작업 set**/
void set(K name, V id) { //값을 가져온다.
this.name = name;
this.id = id;
}
/** 가져온 값을 다시 보내주는 작업 get **/
K getName() {
return name;
}
V getId() {
return id;
}
}
package 제네릭;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Sample04 {
public static void main(String[] args) {
/**제네릭<Map>**/
//list 내부에다가 Map을 넣어서 사용하는 경우
//ArrayList() 내부에는 Map을 넣어서 처리할 수 있게 된다
//Map 안에<키값과 벨류값>
//list 객체에는 Map<문자열, 오브젝트>를 담고있다.
List<Map<String, Object>> list = new ArrayList<>();
//Map을 List에 넣어서 사용하기 위해서는 아래 Map에도 위와 똑같이 <String, Object> <-- 키와 벨류 값을 넣어줘야 된다.
//HashMap에도 <> 이걸 붙여줘야 된다.
//Map에는 순서가 없음
Map<String, Object> hm = new HashMap<>();
//put을 이용해 hm 객체에 아래 키값과 벨류 값을 저장한다.
//put == 저장
hm.put("name", "홍길동");
hm.put("id", "hong");
hm.put("age", 20);
//list에 위에서 만든 Map을 추가해서 넣을 것
list.add(hm);
System.out.println(hm);
/** 두 번째 **/
// 다시 HashMap에 대한 새객체를 hm에 넣어서 현재 아무것도 없는 상태
// 기존 데이터를 없어지고 새로운 데이터 값이 넣어짐
// put을 이용하지 않아서 기존 데이터 삭제
hm = new HashMap<>();
hm.put("name", "이순신");
hm.put("id", "lee");
hm.put("age", 40);
//다시 list에 hm값을 추가
list.add(hm);
System.out.println(hm);
/** 세 번째 **/
hm = new HashMap<>();
hm.put("name", "김유신");
hm.put("id", "kim");
hm.put("age", 50);
list.add(hm);
System.out.println(hm);
for(int i = 0; i<list.size(); i++) {
// list.get(i)만 입력하면 키값과 벨류값이 전부 그대로 호출됨
//.get(name) ("키값") 괄호안에 키값을 넣어줘서 name 키값 안에 있는 name 벨류값을 불러올 수 있다.
System.out.println("이름 : " + list.get(i).get("name"));
System.out.println("아이디 : " + list.get(i).get("id"));
System.out.println("나이 : " + list.get(i).get("age"));
}
}
}
List<Map<?>> list = new ArrayList<>();
<?> : 모든 자료형 가능
<? super Object> : Object의 부모클래스 자료형을 참조 가능
<? extends Object> : Object의 자식클래스 자료형을 참조 가능
package 제네릭;
public class Sample05 {
public static void main(String[] args) {
/** 객체생성 **/
Gen3 g3 = new Gen3();
// new Gen4<Gen3> <-- 자식 클래스라 불가능
//Gen4<Gen2> <-- 자기 자신이라 가능
//Gen4<Gen1> <--부모 클래스라 가능
/** 객체생성 **/
/** 핵심. <? super Gen2> <-- 부모클래스에 대한 것만 참조가 가능 **/
Gen4<? super Gen2> g2 = new Gen4<Gen1>(g3);
// Gen4<? super Gen2> <-- 범이가 크고
// new Gen4<Gen1> <-- 범위 지정
/**
* 1. Gen4<T>는 Gen4<Gen1> 타입이 됨
* 2. obj는 g3이 보내져서 Gen4(Gen1 g3) <-- 이렇게 됨
* 3. Gen1 g3; obj라는 객체를 저장하는 변수에 g3 객체가 저장됨 (Gen1 obj = g3)
* 4. g2.obj로 호출하면 Gen4(Gen1 g3);가 호출됨
* 5. print(g2.obj) 를 하게 되면
* 6. 제네릭.Gen3@15db9742라는 Gen3 클래스 정보가 출력된다.
*/
/** 핵심. 어떤걸 받아서 사용하는지 (범위 지정) **/
/**핵심. <? extends Gen2> <-- 자식 클래스에 대한 것만 참조가 가능**/
Gen4<? extends Gen2> g4 = new Gen4<Gen3>(g3);
//자료형이 똑같아서 그냥 참조해서 사용이 가능
/**
* new 키워서를 이용해서 새로운 객체를 만들때
* Gen2에 대한 자식 개체를 사용
* Gen1는 Gen2에 자식 개체가 아니다
* T는 Gen3이 되면서 Gen3 obj;가 된다.
* <Gen3> 객체가 되면서 생성자가 실행
* 매개변수를 하나 받아가지고 실행되게 (g3)이라는 걸 전달 g3는 맨 위에서 새롭게 객체를 생성 했음
* 그래서 클래스 변수에 저장 됨
*/
// Gen4<?> g5 = new Gen4<>(123123);
// Gen2 t1 = (Gen3)g2.get(); //.get 메서드 호출
//형변환 시켜서 해줘야 가능
/**
* g2.get()
*/
}
}
package 제네릭;
/** <> 제네릭 추가 **/
public class Gen4<T> {
T obj; //T타입에 변수 선언
Gen4(T obj) {//생성자
this.obj = obj;
}
void set(T obj) {
this.obj = obj;
}
T get() {
return obj;
}
}
package 제네릭;
/** Gen2를 상속 받는다 **/
public class Gen3 extends Gen2 {
String name = "Gen3";
String getName() {
return name;
}
}
package 제네릭;
/** Gen1을 상속 받는다 **/
public class Gen2 extends Gen1 {
String name = "Gen2";
String getName() {
return name;
}
}
package 제네릭;
public class Gen1 {
String name = "Gen1";
String getName() {
return name;
}
}
package 제네릭2;
public class Main {
public static void main(String[] args) {
/**
* <T> -> <Dog> Dog 클래스만 받아서 사용한다는 의미
*/
AnimalList<Dog> dogList = new AnimalList<>(); //AnimalList에 관련된 객체 생성
dogList.add(new Dog());
AnimalList<Cat> catList = new AnimalList<>(); //AnimalList에 관련된 객체 생성
catList.add(new Cat());
/**
* <T> -> <Sparro> Sparro 클래스만 받아서 사용한다는 의미
*
*/
AnimalList<Sparrow> SparrowList = new AnimalList<>();
SparrowList.add(new Sparrow());
AnimalList.cryingAnimalList(dogList); //클래스 메소드를 호출
AnimalList.cryingAnimalList(catList);
// AnimalList.cryingAnimalList(sparrowList);
}
}
package 제네릭2;
import java.util.ArrayList;
/**
* (Dog)일 경우
* public class AnimalList<Dog>
* **/
public class AnimalList<T> { //<> 타입을 받아서 쓰게끔 지정
ArrayList<T> al = new ArrayList<T>();
public static void cryingAnimalList(AnimalList<? extends LandAnimal> al) {
// public static void cryingAnimalList(AnimalList<?> al) {
LandAnimal la = al.get(0);
// 자료형 변수 la = al.get(AnimalList<? extends LandAnimal> al)
la.crying();
}
// public static void cryingAnimalList(AnimalList<? extends LandAnimal> al) {
// LandAnimal la = al.get(0);
// la.crying();
// }
/**
* (Dog)일 경우
* void add(Dog animal)
* **/
void add(T animal) {
al.add(animal);
// Main에서 전달 받아 al 어레이리스트에 추가
}
T get(int index) {
return al.get(index);
}
}
package 제네릭2;
public class Sparrow {
void crying() {
System.out.println("짹짹");
}
}
package 제네릭2;
public class Dog extends LandAnimal{
void crying() {
System.out.println("멍멍");
}
}
package 제네릭2;
public class Cat extends Dog{
void crying() {
System.out.println("야옹");
}
}
package 제네릭2;
public class LandAnimal {
void crying() {
System.out.println("육지동물");
}
}
728x90
'java > 10일차' 카테고리의 다른 글
java_람다식_221202(10일차) (1) | 2022.12.02 |
---|
Comments