티스토리 뷰

학습정리-11-04.txt
0.00MB

1. Generic 메소드에 대하여 설명하시오.

클래스 뿐만 아니라 메소드도 제네릭으로 선언할 수 있다.

이 경우 제네릭 클래스와 마찬가지로 함수를 만들 때는 정확한 타입을 정해주지 않고 메소드를 호출할 때 타입인자가 정해지게 된다.

(매개 타입과 리턴 타입으로 타입 파라미터를 갖는 메소드)

제네릭 메소드의 형태는 아래와 같다.

public static <T> Box<T> makeBox(T o) { 

접근제한자(public) + static + 파라미터 값으로 T o(타입)을 사용하기 위해서 <T> 제네릭 선언 + 리턴타입(Box<T>)  + 함수명(makeBox) + (T o)파라미터 값        

}

 

 

 

 


2.Generic(제네릭) 클래스의 타입 인자 제한하는 방법과 효과는?

 

제네릭 클래스의 경우 타입 인자를 특정 클래스의 자식으로 제한할 수 있다.

class Box<T extends Number> {

}
→ 인스턴스 생성 시 타입 인자로 Number 또는 이를 상속하는 클래스만 올 수 있음

위와 같이 extends를 붙여주면 해당 클래스 또는 해당 틀래스의 자식 클래스만 타입 인자로 받을 수 있다.

(implements를 써서 인터페이스 역시 동일하게 사용 가능하다.) 

또한 &을 사용하면 하나의 클래스와 인터페이스를 동시에 사용할 수 있다.

ex)   class Box<T extends Number & Toy>

 

 

 

 

 

3.와일드 카드란?

이전에 제네릭 메소드에 <T>를 통해  함수에 제네릭 선언를 해서 타입 인자를 받았던 것을 일반 메소드에서 제네릭 선언을 붙이지 않고 제네릭 인스턴스를 파라미터 값으로 받는 것을 말한다.

본래 일반 메소드는 직접 제네릭을 파라미터 값으로 받을 수 없다.

왜냐하면 제네릭 안의 인스턴스는 폴리몰티즘이 적용되지 않기 때문에  <Object>를 사용해도 다른 타입 인자를 받을 수 없다.

(Object 클래스는 모든 클래스이 부모 클래스이자만 <Object>와 <Integer>, <String>등은 서로 상속 관계가 아닌 완전히 별개이다.)

이 때 함수 앞에 <T>를 선언하지 않아도 제네릭을 파라미터로 받을 수 있게 하는 것이 와일드 카드 <?>이다.

 

와일드 카드의 형태는 아래와 같다.

public static void peekBox(Box<?> box) {

}  //  Box<Integer>의 인스턴스, Box<String>의 인스턴스를 인자로 전달 가능

제네릭 메소드와 와일드 카드는 형태만 다를 뿐 기능적으로는 완전히 동일하다. 다만 와일드 카드를 사용할 경우 코드가 좀 더 간결해 지는 장점이 있다.

 

 

 

 

 


4. 아래가 에러나는 이유를 설명하시오.
class Box<T> {
    private T ob;     
    public void set(T o) { ob = o; }
    public get() { return ob; }
}

public static void inBox(Box<? super Toy> box, Toy n) {
   box.set(n);   // 넣는 것! OK!
   Toy myToy = box.get();   // 꺼내는 것! Error!
}

super Toy는 Toy 클래스의 부모 클래스만 온다는 뜻이다.(하한 제한)

따라서  Toy myToy = box.get(); 의 경우 자식 = 부모를 해준 것과 같다.

부모에는 자식의 내용물(메소드, 인스턴스 등)이 없기 때문에 부모 것을 꺼내서 자식에게 넣을 수가 없다.

 

반대로  extends의 경우

public static void outBox(Box<? extends Toy> box) {

   box.get();   // 꺼내는 것! OK!

   box.set(new Toy());   // 넣는 것! ERROR!

}

Toy 클래스를 상속받는 자식 클래스만 온다는 뜻이다.(상한 제한)

ex)Car car = new Toy();자식 = 부모이기때문에 폴리몰티즘 적용이 되지 않아 오류.....

 

super는 set만

extends는 get만

 

 

 

 


5. 아래의 소스코드 중에 System.out.println(zBox.get().get().get()); 부분을 설명하시오.
class Box<T> {
private T ob;

public void set(T o) {
ob = o;
}

public T get() {
return ob;
}
}

public class BoxInBox {

public static void main(String[] args) {
Box<String> sBox = new Box<>();
sBox.set("I am so happy.");

Box<Box<String>> wBox = new Box<>();
wBox.set(sBox);

Box<Box<Box<String>>> zBox = new Box<>();
zBox.set(wBox);

System.out.println(zBox.get().get().get());
}
}

위의 코드의 경우 출력 값이 I am so happy.이다.

zBox.get().get().get()

→  wBox.get().get()

→  sBox.get()

와 같기 때문에 결국 sBox.get()으로 호출된 값이 출력되게 된다.

 

 

 

 


6. 아래를 컴파일 에러가 나지 않게끔 프로그래밍 하시오.
    public static void main(String[] args) {
        Box7<Integer> box1 = new Box7<>();
        box1.set(99);

        Box7<Integer> box2 = new Box7<>();
        box2.set(55);

        System.out.println(box1.get() + " & " + box2.get());
        swapBox(box1, box2); 
        System.out.println(box1.get() + " & " + box2.get());
    }

출력 =========================================

99 & 55
55 & 99

class Box7<T>{
	private T ob;
	
	public void set(T ob) {
		this.ob = ob;
	}
	
	public T get() {
		return ob;
	}
}

class GenericPrac2 {
	
	public static <T> void swapBox(Box7<T> box1, Box7<T> box2) {		
		/*		
 		T ob1 = box1.get(); // 오토 박싱?
		T ob2 = box2.get();
		
		box1.set(ob2);
		box2.set(ob1);	
		*/		
		
		T ob = box1.get();
		box1.set(box2.get());
		box2.set(ob);
		// 정석 스왑 방식
		 
	}
	

	public static void main(String[] args) {
		Box7<Integer> box1 = new Box7<>();
		box1.set(99);

		Box7<Integer> box2 = new Box7<>();
		box2.set(55);

		System.out.println(box1.get() + " & " + box2.get());
		swapBox(box1, box2);
		System.out.println(box1.get() + " & " + box2.get());

	}
}
//99 & 55
//55 & 99

스왑 방식은 먼저 빈 공간을 만들어서 그곳에 하나를 담고 시작! 

제네릭으로 바로 만들기 힘들면 일단 지정된 객체를 넣고 만든 다음 순차적으로 수정해가기.

 

 

 

 


7.Scanner를 이용하여 한 라인을 읽고, 공백으로 분리된 어절이 몇 개 들어 있는지 "그만"을 입력할 때까지 반복하는 프로그램을 작성하라.
>>I love Java.
어절 개수는 3
>>자바는 객체 지향 언어로서 매우 좋은 언어이다.
어절 개수는 7
>>그만
종료합니다...
[Hint] Scanner.nextLine()을 이용하면 빈칸을 포함하여 한 번에 한 줄을 읽을 수 있다.

(1) StringTokenizer 클래스를 이용하여 작성하라.

import java.util.Scanner;
import java.util.StringTokenizer;

class WordTest {

	public static void main(String[] args) {

		while (true) {
			Scanner sc = new Scanner(System.in);

			System.out.println("글을 입력하세요. 종료를 원하시면 " + "\"" + "그만" + "\"" + "을 입력하세요.");
			System.out.print(">>");
			String str = sc.nextLine();

			if (str.equals("그만")) {
				System.out.println("종료합니다.");
				break;
			}

			StringTokenizer st = new StringTokenizer(str, " ");

			int sum = 0;
			while (st.hasMoreTokens()) {

				String[] nt = { st.nextToken() };
				sum += nt.length; // foreach써도 되네...?

			} // while(st.hasMoreTokens())

			System.out.println("어절 개수는 " + sum);

		} // while(true)
	}
}

이번에도.....클래스로 빼주는 건 실패......

앗...countTokens()함수가 있었다니..

try catch 써주기(사실 netLine은 대부분의 것을 다 받기 때문에 오류가 날 확률이 거의 없지만 써주는 습관 들이기)

버퍼 비우기!(sc.nextLine();)

먼저 클래스 만들고 하나의 함수에 전체를 다 넣어주기!

import java.util.Scanner;
import java.util.StringTokenizer;

class TokensCount {

	private String words;

	public void run() {
		Scanner sc = new Scanner(System.in);

		while (true) {

			try {
				words = sc.nextLine();

				if (words.equals("그만")) {
					System.out.println("종료합니다.");
					break;
				}

				StringTokenizer tokens = new StringTokenizer(words, " ");

				System.out.println("어절 갯수는 " + tokens.countTokens());
			} catch (Exception e) {
				System.out.println("잘못된 입력입니다. 다시 입력하세요.");
				sc.nextLine();
			}

		} // while(true)
	}

}

class WordTest {

	public static void main(String[] args) {

		TokensCount count = new TokensCount();

		count.run();

	}
}

 

 

제네릭 복습..........필수..........정리해도 무슨 소린지 모르겠다..........

 


input 태그

See the Pen formtag by SE (@whaletree) on CodePen.

 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함