gwooden_코린이

java_제네릭_221202(10일차) 본문

java/10일차

java_제네릭_221202(10일차)

gwooden22 2022. 12. 2. 11:07
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