아 이게 뭐임!

Generic 두개 이상의 변수 사용

마로가마따 2021. 7. 29. 08:28

이전 포스팅에서는 Generic을 활용하여 여러가지 객체 타입을 인자로 받아낼 수 있는 것을 알게되었습니다.

 

Generic으로 내가 변수를 1개가 아닌 1개 이상 받으려면 어떻게 해야될까요.

 

 

 

 


Contents

-       Generic 

-       Generic

 

 

 

이전 포스팅 Generic이 뭐임!!에서 제네릭의 등장 배경과 제일 간단한 제네릭의 활용형태를 보셨습니다.

 

 

밑의 코드는 저번 포스팅에서 나왔던 코드입니다.

 

public class MyGeneric<T> {
	T object;

	MyGeneric(T object){ 
    	this.object= object; 
    }
    
	void showType() { 
		System.out.println(object.getClass().getName()); 
	} 
}

main

public class Main {

	public static void main(String[] args) {
		MyGeneric<Integer> obj = new MyGeneric<>(10);
		MyGeneric<Double> obj2 = new MyGeneric<>(11.29);
		
		obj.showType();
		obj2.showType();
	}
    
}

 

제네릭을 사용하여 구현했고

 

Integer 형태가 들어오든 Double 형태가 들어오든 올바르게 결과를 출력했었습니다.

 

이번엔 두개의 인자를 받아서 출력할 수 있도록 업데이트 해보겠습니다.

 

public class MyGeneric<T, V> {
	T object;
	V object2;

	MyGeneric(T object, V object2){ 
    	this.object= object; 
    	this.object2= object2; 
    }
    
	void showType() { 
		System.out.println(object.getClass().getName()); 
		System.out.println(object2.getClass().getName()); 
	} 
}

 

간단히 <> 안에 ','(콤마)와 함께 다른 변수 타입을 적어주면 됩니다.

 

 

표시된 부분에 유의하며 기존 코드를 고쳐주시면 됩니다.

 

public class Main {

	public static void main(String[] args) {
		MyGeneric<Integer, Double> obj = new MyGeneric<>(10, 11.29);
				
		obj.showType();
		
	}
}

 

메인 문을 약간 고쳐주고 출력하니 출력이 잘 되는  것을 확인할 수 있습니다.

 

 

generic 출력2

 

 

 

 

 

이런 상황에서 hashmap(해쉬맵)이 유용할 수 있습니다.

 

import java.util.HashMap;

public class MyGeneric<T, V> {
	T object;
	V object2;
	
	HashMap<T,V> map = new HashMap<>(); 

	MyGeneric(T object, V object2){ 
    	this.object= object; 
    	this.object2= object2; 
    }
    
	void showType() { 
		System.out.println(object.getClass().getName()); 
		System.out.println(object2.getClass().getName()); 
	} 
}

 

 

자바 개발자가 내부적으로 만들어둔 public 클래스인 HashMap내부를 들여다 보면 아래와 같이

 

 

해쉬맵 자체가 2개의 Generic으로 Key값과 Value값이 묶여서 동작하는 것을 알 수 있습니다.

 

 

해시맵 내부입니당~

 

 

우리보다 먼저 자바 개발자들이 재사용 가능한 클래스를 만들어 두었기 때문에

 

 

우리가 구지 매 클래스마다 우리가 필요한 변수타입에 맞는 클래스를 만들어 줄 필요가 없습니다.

 

 

이번에는 숫자에 관련된 다양한 기능을 수행하는 Number function을 만들어 보겠습니다. 

 

클래스 이름은 NumbericFns로 하겠습니다.

 

public class NumericFns<T> {
	
	T object;
	
	NumericFns(T object){
		this.object = object;
	}

	double square() {
		return object * object;
	}
}

 

숫자를 입력받으면 제곱해주는 함수를 만들었습니다.

 

하지만 이렇게 코드를 작성할 경우 return문에서 에러가 뜹니다.

 

왜냐하면 generic 으로 들어오는 변수가 문자 관련된 타입인지 숫자에 관련된 타입인지 모르기 때문입니다.

 

 

에러 메시지에도 타입이 정읟되지 않아 곱연산을 수행할 수 없다고 나옵니다.

 

String 타입이 들어올경우 String * String을 처리해야하는 상황이 생길 수 있다는 것을 미리 알고 에러를 정의해둔겁니다.

 

 

public class NumericFns<T extends Number> {
	
	T object;
	
	NumericFns(T object){
		this.object = object;
	}

	double square() {
		return object.intValue() * object.doubleValue();
	}
}

 

 

간단히 제네릭을 선언해준 <> 에 자바 개발자들이 미리 정의한 Number를 상속시켜주고 object를 각각 int와 double로 확정지어주면 위의  에러가 사라지는 것을 볼 수 있다.

 

 

 

이제 메인문으로 돌아와서

 

메인문을 다음과 같이 수정했습니다

public class Main {

	public static void main(String[] args) {

		NumericFns<Integer> iOb = new NumericFns<>(4);
		System.out.println(iOb.square());
				
	}
}

 

실행시켜주면 다음과 같은 결과를 얻을 수 있습니다.

 

결과

잘  작동하는군요...!

 

부연설명을 좀 하자면

 

 

상속받은 Number 객체는 Integer, Double, Float을 자식 객체로 가지고 있습니다.

 

그렇기 때문에 Main에서 

 

 

Integer로 선언해도 에러가 생기지 않습니다...!

 

하지만 해당하는  빨간부분을 String으로 바꿔줄 경우 

 

 

 

Number와 결속된 파라미터가 아니라고 에러가 표시되는 것을 확인할 수 있습니다.

 


이번엔 새로 어떤 값하고 절댓값을 비교했을때 큰지 작은지 판단하는 함수를 만들어 봤습니다.

 

 

이름은 absEqual입니다.

 

public class NumericFns<T extends Number> {
	
	T num;
	
	NumericFns(T object){
		this.num = object;
	}

	double square() {
		return num.intValue() * num.doubleValue();
	}
	
	boolean absEqual(NumericFns<T> object) {
		if (Math.abs(num.doubleValue()) == Math.abs(object.num.doubleValue()))
			return true;
		return false;
	}
}

 

그 다음 메인문을 수정해 주었습니다.

 

public class Main {

	public static void main(String[] args) {
		NumericFns<Integer> iOb = new NumericFns<Integer>(6);
		NumericFns<Double> dOb = new NumericFns<Double>(-6.0);
				
		iOb.absEqual(dOb);
		
	}
}

 

이렇게 절댓값을 비교하려고 해봤으나 에러가 뜹니다.

 

 

 

 

일단 에러 메세지는 함수에서 <Integer>를 요구하는데 제가 집어 넣은 값이 <Double>이라고 합니다..

 

하지만 저희는 Generic으로 분명 어떤 입력이 들어와도 처리 할 수 있도록 했습니다.

 

 

 

 

원인이 무엇일까요..?

 

 

 

iOb 객체 속에서 absEqual이 호출됩니다.

 

iOb는 생성될때 Integer 객체로 생성됐습니다.

 

원인은..

 

생성자에서 Integer로 받아서 함수를 호출할때 인자로 Integer를 요구하는 것이었습니다.

 

그러면 어떻게 해결해야할까요

 

저는 객체가 가진 숫자 값을 다른 객체가 가진 숫자와 비교하고 싶습니다.

 

숫자이지만 비교되는 숫자의 타입이 지정되지 않을때 비교연산을 수행하고 싶다면

 

public class NumericFns<T extends Number> {
	
	T num;
	
	NumericFns(T object){
		this.num = object;
	}

	double square() {
		return num.intValue() * num.doubleValue();
	}
	
	boolean absEqual(NumericFns<?> object) {
		if (Math.abs(num.doubleValue()) == Math.abs(object.num.doubleValue()))
			return true;
		return false;
	}
}

 

<?>를 사용하면 간단히 해결이 됩니다.

 

메인문을 약간 고쳐서 비교연산을 수행해 보겠습니다.

 

public class Main {

	public static void main(String[] args) {
		NumericFns<Integer> iOb = new NumericFns<Integer>(6);
		NumericFns<Double> dOb = new NumericFns<Double>(-6.0);
				
		System.out.println(iOb.absEqual(dOb));		
	}
}

 

 

 

출력이 잘되는것까지 확인!!!

 

 

고생하셨습니다~

 

 

반응형

'아 이게 뭐임!' 카테고리의 다른 글

Telnet이 뭐임?  (0) 2022.04.19
JSON이 뭐임...!! (HTT...P..?)  (0) 2021.07.30
Generic이 뭐임!! [JAVA]  (0) 2021.07.28
NULL은 특별하다...!  (0) 2021.07.27
제어의 역전이 뭐임!! [Inversion of Control]  (0) 2021.07.26