공부한 내용을 정리하는 글이라 틀린 내용이 있을 수 있습니다!
오늘 학습한 Generic 대한 정리.
class Apple{}
class Goods1{
private Apple apple = new Apple();
public Apple GetApple() {
return apple;
}
public void SetApple(Apple apple) {
this.apple = apple;
}
}
class Pencil{}
class Goods2{
private Pencil pencil = new Pencil();
public Pencil GetPencil() {
return pencil;
}
public void SetApple(Pencil pencil) {
this.pencil = pencil;
}
}
위 코드를 봤을때 새로운 상품이 추가 될때마다 새롭게 클래스를 만들어야 될까??
귀찮을수도 있으니 Generic을 사용해보자!!
첫번째 해결 방법은 최상위 클래스인 Object타입으로 선언하는것.
Object 객체를 저장하고 관리하는 클래스를 생성하면 과일이든, 학용품이든 저장하거나 읽어들일 수 있음
class Goods3{
private Object object = new Object();
public Object Get() {
return object;
}
public void Set(Object object) {
this.object = object;
}
}
모든타입에 데이터를 저장할 수 있고 잘못된 캐스팅을 했을때 사전에 오류를 차단할 수 있다.
접근 지정자 - class - 클래스명<T>{
}
접근 지정자 - class - 클래스명<K,T>{
}
접근 지정자 - interface - 클래스명<T>{
}
접근 지정자 - interface - 클래스명<K,T>{
}
제네릭 클래스의 객체생성
객체생성 과정은 일반 클래스의 객체 생성과 비슷
단, 클래스명 다음에<실제 제네릭 타입>을 삽입한다.
즉 객체를 생ㅅ어할때 제네릭 타입 변수에 실제 타입을 대입한다.
클래스명<실제 제네릭타입> 참조변수 명 = new 클래스명<실제 제네릭 타입>();
클래스명<실제 제네릭타입> 참조변수 명 = new 클래스명<>();
class Knight{
private String name;
public Knight(String name) {
this.name = name;
}
public void Attack() {
System.out.println(name + "칼을 휘두룸!!!");
}
}
class Wizard{
private String name;
public Wizard(String name) {
this.name = name;
}
public void Skill() {
System.out.println(name + "파이어 볼 발사");
}
}
public class Generic {
public static void main(String[] args) {
Goods3 goods3 = new Goods3();
goods3.Set(new Apple());
//타입으로 꺼내오기 위해서는 저장된 형태로 타입 캐스팅을 해야한다.
//필드 자체가 Object 타입이라 Get으로 가져오는 탑입 또한 항상 Object타입이기 때문임.
//그래서 Get을 할 때는 Set을 한 타입으로 형변환 해야한다.
// Apple apple = (Apple)goods3.Get();
//제네릭 클래스인 MyClass를 써볼꽈??
//String 타입을 저장하거나 꺼내 올 수 있는 객체지정
MyClass<String> mc1 = new MyClass<String>();
mc1.Set("안녕");
System.out.println(mc1.Get());
//Integer 타입 저장하거나 꺼내 올 수 있는 객체지정
MyClass<Integer> mc2 = new MyClass<Integer>();
mc2.Set(12345);
System.out.println(mc2.Get());
//제네릭 타입 변수가 2개인 경우
KeyValue<String, Integer> kv1 = new KeyValue<>();
kv1.SetKey("원숭이");
kv1.SetValue(12345);
String key1 = kv1.getKey();
int value1=kv1.getVlaue();
System.out.println("key : "+key1+" value : "+value1);
KeyValue<String, Void> kv2 = new KeyValue<>();
kv2.SetKey("키값만 사용하겠음");
// kv2.SetValue(12345);
/////////////////////////////////////////////////////////
CharacterFactory<Knight> knightFactory = new CharacterFactory<>(new Knight("홍길동"));
CharacterFactory<Wizard> WizardFactory = new CharacterFactory<>(new Wizard("ooo"));
knightFactory.Introduce();
Knight knight = knightFactory.getCharacter();
knight.Attack();
}
}
출력
//1. 제네릭 타입변수명이 1개일때
//접근 지정자 <T> T 메서드 이름(T t)
//2. 두개일 경우
//접근 지정자 <T, V> T 메서드 이름(T t, V v)
//3.매개변수에만 제네릭이 사용된 경우
// 접근 지정자<T> void 메서드 이름(T t){}
//4.리턴타입에만 사용된 경우!
//접근 지정자 <T> T 메서드 이름(int a){}
class GenericMethod{
public <T> T method(T t) {
return t;
}
public <T> boolean method2(T t1, T t2) {
return t1.equals(t2);
}
public <K, V> void method3(K k, V v) {
System.out.println(k+ " : "+ v);
}
}
class A{
public <T> void method(T t) {
System.out.println(t.equals("안녕"));
// System.out.println(t.length()); //불가능 . length는 String 내장메서드여서 안됌. 정의 시점에 어떤타입인지 모름
//object class가 최상위에 있음.
}
}
public class Generic01 {
public static <T> void Swap(T[] array,int index1, int index2) {
T temp = array[index1];
array[index1] = temp;
}
public static void main(String[] args) {
GenericMethod gm = new GenericMethod();
String str1 = gm.<String>method("안녕");
//제네릭 타입 자체를 유추할 수 있다면<String>을 빼도 됌
String str2 = gm.method("안녕2");
System.out.println(str1);
System.out.println(str2);
boolean b1 = gm.method2(2.5, 2.5);
System.out.println(b1);
gm.<String, Integer> method3("국어",10);
gm.method3("수학",20);
}
}
출력
출력
class Parent<T>{
T t;
public T getT(){
return t;
}
public void SetT(T t) {
this.t = t;
}
}
class Child01<T> extends Parent<T>{
}
class Child02<T1, T2> extends Parent<T1>{
}
class Shape<T>{
protected T name;
//생성자 " 도형의 이름을 받아 초기화!
public Shape(T name) {
this.name=name;
}
public double getArea() {
return 0.0;
}
public void PrintInfo() {
System.out.println("도형 : "+name);
System.out.println("Area : "+getArea());
}
}
class Circle<T> extends Shape<T>{
private double radius;
public Circle(T name, double radius) {
super(name);
this.radius=radius;
}
@Override
public double getArea() {
return Math.PI*radius*radius;
}
}
class Rectangle<T> extends Shape<T>{
private double width;
private double height;
public Rectangle(T name,double width, double height) {
super(name);
this.width = width;
this.height =height;
}
@Override
public double getArea() {
return width*height;
}
}
public class Generic03 {
public static void main(String[] args) {
Circle<String>circle = new Circle<>("원",5.0);
Rectangle<String>rectangle = new Rectangle<>("사각형",4.0,6.0);
circle.PrintInfo();
System.out.println();
rectangle.PrintInfo();
}
}
출력