JAVA
chapter22 : Generic
GAWON
2023. 5. 16. 18:38
1.1 제네릭(Generic)
- Java5부터 새로 추가된 타입으로 제네릭을 이용함으로써
잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다.
- 컬렉션 등에서 널리 사용되므로 확실히 이해해 두어야 한다.
- 클래스나 메소드에서 컴파일 할 때 타입체크(Type check)를 하는 기능이다.
1.2 제네릭의 이점
- 컴파일 시 강한 타입 체크를 할 수 있다.
클래스나 메소드에서 컴파일 할 때 타입체크(Type check)를 하여
★실행 에러가 나기 전 컴파일 단계에서 에러를 사전에 방지한다.
- 미리 객체(인스턴스)의 공통적인 타입을 명시해서 처리하기 때문에 안정성이 높고,
★타입 변환(casting)을 제거한다.
ex)
<비제네릭 코드>
List list = new ArrayList();(동적코드인 인스턴스 객체)//업 캐스팅
list.add("hello"); //add-값을 넣는다
String str = (String)list.get(0); // 타입 변환을 해야 한다.
↓
<제네릭 코드>
List<String> list = new ArrayList<String>();//문자열타입 <String>
list.add("hello");//값을 넣는다
String str = list.get(0); // 타입 변환을 하지 않는다.
- 제네릭 클래스와 제네릭 메소드의 구현이 가능하다.
- 2개 이상의 제네릭 타입 선언이 가능하다.
- 주의사항
1) T obj = new T(); 불가능! (T의 크기를 알 수 없기 때문에) T는 제네릭
2) T[] arr = new T[3]; 불가능! (T의 크기를 알 수 없기 때문에)
3) T[] arr; 가능!
class Box <T> {
private T obj;
public void setObj(T obj) {
this.obj = obj;
}
public T getObj() {
return obj;
}
}
// main
Box<String> box = new Box<>(); // 구체화 : T가 무엇인지 알려주는 것
Box<String> box = new Box<String>(); (위와 동일한내용) // 구체화는 referenceType
참조타입 만 가능 하다. (PrimitiveType은 불가!!)
// 컴파일 시점
T <- String
class Box { // 컴파일 시점에 구체화 된 클래스
private String obj;
public void setObj(String obj) {
this.obj = obj;
}
public String getObj() {
return obj;
}
} //데이터 타입 명시한다( private/public)
Q1. Test01.java
문자/정수/실수 타입의 배열을 전달하고 데이터 타입을 체크하여
해당 데이터 타입과 해당 배열의 데이터들을 출력
class TypeCheckClass - 필드 : T[] arr
메소드 : String checkType(T[] arr),
-> 타입에 따라서 "문자형 입니다.","정수형 입니다" 등등 리턴,
toString()->배열 데이터, 데이터 형태 출력
package org.joonzis.test;
import java.util.Arrays;
class TypeCheckClass<T>{
private T[] arr;
public String checkType(T[] arr) {
this.arr = arr;
if(arr instanceof String[]) {
return "문자형 입니다";
}else if(arr instanceof Integer[]) {
return "정수형 입니다";
}else {
return "실수형 입니다";
}
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("배열 데이터 : ").append(Arrays.toString(arr)).append("\n");
sb.append("배열 형태 : ").append(checkType(arr));
return sb.toString();
}
}
public class Test01 {
public static void main(String[] args) {
String[] arr1= {"a", "b", "c"};
Integer[] arr2 = {123, 456, 789};
Double[] arr3 = {1.5, 2.43, 3.14};
TypeCheckClass<String> ck1 = new TypeCheckClass<>();
TypeCheckClass<Integer> ck2 = new TypeCheckClass<>();
TypeCheckClass<Double> ck3 = new TypeCheckClass<>();
ck1.checkType(arr1);
ck2.checkType(arr2);
ck3.checkType(arr3);
System.out.println(ck1);
System.out.println(ck2);
System.out.println(ck3);
}
}
Q2. Test02.java
정수/실수 타입의 배열을 전달하면 해당 배열에 저장된 모든 요소의 합을 리턴하는 sum() 메소드를 구현하시오.
예) int 5개 전달하면 5개의 합 출력
★
- static <T extends Number> double sum(T[] arr) 형식 작성
-> Number 형태의 데이터만 가능하다는 의미(int, long, float, double, byte, short)
- 배열의 값을 가져올때 배열.doubleValue()사용
-> 배열인덱스.doubleValue()
package org.joonzis.test;
public class Test02 {
static <T extends Number> double sum(T[] arr) {
double total = 0;
for(int i=0; i<arr.length; i++) {
total += arr[i].doubleValue();
}
return total;
}
public static void main(String[] args) {
Integer[] arr1 = {123, 456, 789};
Double[] arr2 = {1.5, 2.43, 3.14};
String[] arr3 = {"hello", "java"};
System.out.println(sum(arr1));
System.out.println(sum(arr2));
//System.out.println(sum(arr3));
}
}
Q3. Test03.java
1. 메인클래스를 보고 알맞은 클래스들을 구현하시오.
2. Product 클래스를 구현하시오.
필드 : T1 category, T2 model
적절한 메소드 구현하기
public static void main(String[] args) {
Product<Elec, Tv> product1 = new Product<>();
Product<Life, Cup> product2 = new Product<>();
product1.setCategory(new Elec());
product1.setModel(new Tv("LG"));
System.out.println(product1); // 출력 예시) 전자제품, LG TV
}
package org.joonzis.test;
class Product<T1, T2>{
private T1 category;
private T2 model;
public void setCategory(T1 category) {
this.category = category;
}
public void setModel(T2 model) {
this.model = model;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(category).append(", ").append(model);
return sb.toString();
}
}
class Elec{
@Override
public String toString() {
return "전자제품";
}
}
class Tv{
private String model;
public Tv(String model) {
this.model = model;
}
@Override
public String toString() {
return model + " TV";
}
}
class Life{
@Override
public String toString() {
return "생활용품";
}
}
class Cup{
private String model;
public Cup(String model) {
this.model = model;
}
@Override
public String toString() {
return model;
}
}
public class Test03 {
public static void main(String[] args) {
Product<Elec, Tv> product1 = new Product<>();
Product<Life, Cup> product2 = new Product<>();
product1.setCategory(new Elec());
product1.setModel(new Tv("LG"));
System.out.println(product1); // 출력 예시) 전자제품, LG TV
product2.setCategory(new Life());
product2.setModel(new Cup("머그컵"));
System.out.println(product2);
}
}
Q4. Test04.java
interface Car 메소드 : info();
class Bus implements Car
class CityTourBus extends Bus
class SeoulBus extends Bus
class Taxi implements Car
Class Bicycle
Class Test04 메소드 : static <T extends Car> void onlyCar(T car)
- CityTourBus, SeoulBus, Taxi 정보 출력
package org.joonzis.test;
interface Car{
public void info();
}
class Bus implements Car{
@Override
public void info() {}
}
class CityTourBus extends Bus{
@Override
public void info() {
System.out.println("시티 투어 버스");
}
}
class SeoulBus extends Bus{
@Override
public void info() {
System.out.println("서울 버스");
}
}
class Taxi implements Car{
@Override
public void info() {
System.out.println("택시");
}
}
class Bicycle{
}
public class Test04 {
static <T extends Car> void onlyCar(T car) {
car.info();
}
public static void main(String[] args) {
Car bus1 = new CityTourBus();
Car bus2 = new SeoulBus();
Car taxi = new Taxi();
onlyCar(bus1);
onlyCar(bus2);
onlyCar(taxi);
}
}