organize/자바

Java 30

001cloudid 2024. 8. 14. 00:29
728x90

※cmd에서 javac 명령어 사용

문제 : javac --version은 정상적으로 실행되나 class 파일로 컴파일이 안됨.

해결 :

  1. 설정 - 정보 - 고급 시스템 설정 - 환경 변수
  2. 시스템 변수에 변수와 값이 설정되어 있는지 확인 -> 없으면(3번 항목으로), 있으면(4번 항목으로)
  3. 시스템 변수 - 새로 만들기(W)
    변수 이름 : JAVA_HOME
    변수 값 : jdk가 설치된 경로 \bin 파일로 설정 ex)C:\Program Files\ojdkbuild\java-11-openjdk-11.0.15-1\bin
  4. 시스템 변수 - 변수 Path - 편집(I)
    환경 변수 편집 - 새로 만들기 %JAVA_HOME%

3. 시스템 변수
4. Path 편집

 

 

 

 

와일드카드 <?>

  • 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능
ArrayList<? extends Product> list = new ArrayList<Tv>(); //불일치하지만 가능
ArrayList<? extends Product> list = new ArrayList<Audio>();

 

  • <? super T> : 와일드 카드 하한 제한. T와 그 조상만 가능
  • <? extends T> : 와일드 상한 제한. T와 그 자손만 가능
  • <?> : 제한 없음. 모든 타입이 가능 == <? extends Object>와 동일
  • 메소드의  매개 변수에 와일드 카드를 사용
package chapter12;

import java.util.ArrayList;

class Fruit2			   {public String toString() {return "Fruit";}}
class Apple2 extends Fruit2{public String toString() {return "Apple";}}
class Grape2 extends Fruit2{public String toString() {return "Grape";}}

class Juice{
	String name;
	Juice(String name){this.name = name+"Juice";}
	public String toString() {return name;}
}

class Juicer{
	static Juice makeJuice(FruitBox2<? extends Fruit2> box) {
		String tmp = "";
		for(Fruit2 f : box.getList())
			tmp += f + " ";
		return new Juice(tmp);
	}
}

class FruitBox2<T extends Fruit2> extends Box2<T>{}

class Box2<T>{
	ArrayList<T> list = new ArrayList<T>();
	void add(T item) { list.add(item);}
	T get(int i) { return list.get(i);}
	ArrayList<T> getList() {return list;}
	int size() { return list.size();}
	public String toString() {return list.toString();}
}

public class Study06 {
	
	public static void main(String[] args) {
		
		FruitBox2<Fruit2> fruitBox = new FruitBox2<Fruit2>();
		FruitBox2<Apple2> appleBox = new FruitBox2<Apple2>(); //가능
//		FruitBox2<Fruit2> appleBox = new FruitBox2<Apple2>(); //에러
//		FruitBox2<? extends Fruit2> appleBox = new FruitBox2<Apple2>();
		//Fruit2와 그 자손
		
		fruitBox.add(new Apple2());
		fruitBox.add(new Grape2());
		appleBox.add(new Apple2());
		appleBox.add(new Apple2());
		
		System.out.println(Juicer.makeJuice(fruitBox));
		System.out.println(Juicer.makeJuice(appleBox));
		
	}

}

 

제네릭 메소드

  • 제네릭 타입이 선언된 메소드(타입 변수는 메소드 내에서만 유효)
static <T> void sort(List<T> list, Comparator<? super T> c)
  • 클래스의 타입 매개변수<T>와 메소드의 타입 매개변수 <T>는 별개
class FruitBox<T>{ //제네릭 클래스
	...
    //제네릭 메소드
    //제네릭 클래스 <T>와 제네릭 메소드 <T> 타입 문자 일치하지만 다른 타입 변수임
	static <T> void sort(List<T> list, Comparator<? super T> c){
    	...
    }
}
  • 메소드를 호출할 때마다 타입을 대입해야함(대부분 생략 가능)
FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
FruitBox<Apple> appleBox = new FruitBox<Apple>();
...
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Apple>makeJuice(appleBox));

static<T extends Fruit> Juice makeJuice(FruitBox<T> box){ //와일드 카드는 하나의 참조변수로 서로 다른 타입이 대인된 여러 제네릭 객체를 다루기 위한 것
	String tmp = "";
    for(Fruit f : box.getList()) tmp += f + "";
    return new Juice(tmp);
}
  • 메소드를 호출할 때 타입을 생략하지 않을 때는 클래스 이름 생략 불가
System.out.println(<Fruit>makeJuice(fruitBox)); //에러. 클래스 이름 생략 불가
System.out.println(this.<Fruit>makeJuice(fruitBox));
System.out.println(Juicer.<Fruit>makeJuice(fruitBox));

 

제네릭 타입의 형 변환

  • 제네릭 타입과 원시 타입 간의 형 변환은 바람직하지 않음.(경고 발생)
Box<Object> objBox = null;
Box box = (Box)objBox; //제네릭 타입 → 원시 타입. 가능은 하지만, 경고(노란색 전구) 발생
objBox = (Box<Object>)box; //원시 타입 → 제네릭 타입. 가능은 하지만, 경고(노란색 전구) 발생

//=======================================

Box<Object> objBox = null;
Box<String> strBox = null;

objBox = (Box<Object>)strBox; // 에러. Box<String> → Box<Object>
strBox = (Box<String>)objBox; // 에러. Box<Object> → Box<String>
  • 와일드 카드가 사용된 제네릭 타입으로는 형 변환 가능
Box<Object> objBox = (Box<Object>)new Box<String>(); //에러. 형 변환 불가능
Box<? extends Object> wBox = (Box<? extends Object>)new Box<String>(); //가능
// == Box<? extends Object> wBox = new Box<String>();

//매개변수 FruitBox<Fruit>, FruitBox<Apple>, FruitBox<Grape> 등이 가능
static Juice makeJuice(FruitBox<? extends Fruit> box){...}

FruitBox<? extends Fruit> box = new Fruit<Fruit>(); //가능
FruitBox<? extends Fruit> box = new Fruit<Apple>(); //가능

 

 

package chapter12;

import java.util.ArrayList;

interface Eatable{}

class Fruit implements Eatable{
	public String toString() {return "Fruit";}
}

class Apple extends Fruit{public String toString() {return"Apple";}}
class Grape extends Fruit{public String toString() {return"Grape";}}
class Toy				 {public String toString() {return"Toy";}}

public class Study07 {

	public static void main(String[] args) {
		
//		Box b = null; //Box b = new Box<String>();
//		Box<String> bStr = null;
//		b = (Box)bStr;			//Box<String> → Box 가능. 경고
//		bStr = (Box<String>)b;	//Box → Box<String> 가능. 경고
		
//		FruitBox<Fruit> fruitbox = new FruitBox<Fruit>();
		FruitBox<? extends Fruit> fruitbox = (FruitBox<? extends Fruit>)new FruitBox<Fruit>(); //타입 불일치로 (FruitBox<? extends Fruit>)들어가야하지만 생략
		FruitBox<Apple> applebox = new FruitBox<Apple>(); //가능
//		FruitBox<? extends Fruit> applebox = new FruitBox<Apple>(); //가능
		FruitBox<Apple> appleBox1 = (FruitBox<Apple>)applebox; //가능. 경고발생
		

		FruitBox<Fruit> fruitBox = new FruitBox<Fruit>();
		FruitBox<Apple> appleBox = new FruitBox<Apple>();
		FruitBox<Grape> grapeBox = new FruitBox<Grape>();
//		FruitBox<Grape> grapeBox = new FruitBox<Apple>(); // 에러. 타입 불일치
//		FruitBox<Toy>   toyBox    = new FruitBox<Toy>();   // 에러.

		fruitBox.add(new Fruit());
		fruitBox.add(new Apple());
		fruitBox.add(new Grape());
		appleBox.add(new Apple());
//		appleBox.add(new Grape());  // 에러. Grape는 Apple의 자손이 아님
		grapeBox.add(new Grape());

		System.out.println("fruitBox-"+fruitBox);
		System.out.println("appleBox-"+appleBox);
		System.out.println("grapeBox-"+grapeBox);		
	}
}

class FruitBox<T extends Fruit & Eatable> extends Box<T> {}

class Box<T> {
	ArrayList<T> list = new ArrayList<T>();
	void add(T item)  { list.add(item);      }
	T get(int i)      { return list.get(i); }
	int size()        { return list.size();  }
	public String toString() { return list.toString();}
}

 

제네릭 타입의 제거

컴파일러는 제네릭 타입을 제거하고, 필요한 곳에 형 변환 함

//1. 제네릭 타입의 경계(bound)를 제거
class Box<T extends Fruit>{
	void add(T t){
    	...
    }
}
// 컴파일 후 코드
class Box{
	void add(Fruit t){
    	...
    }    
}

//2. 제네릭 타입 제거 후 타입이 불일치하면, 형 변환을 추가
T get(int i){
	return list.get(i);
}
// →
Fruit get(int i){
	return (Fruit)list.get(i);
}

//3. 와일드 카드가 포함된 경우, 적절한 타입으로 형 변환 추가
static Juice makeJuice(FruitBox<? extends Fruit>box){
	String tmp = "";
    tmp += f + " ";
    return new Juice(tmp);
}
// →
static Juice makeJuice(FruitBox box){
	String tmp = "";
    Iterator it = box.getList().iterator();
    while(it.hasNext()){
    	tmp += (Fruit)it.next() + " ";
    }
    return new Juice(tmp);
}

 

728x90

'organize > 자바' 카테고리의 다른 글

Java 32  (0) 2024.08.20
Java 31  (0) 2024.08.15
Java 29  (0) 2024.08.13
Java 28  (0) 2024.05.16
Java 27  (0) 2024.05.14