일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 불친절한 SQL 프로그래밍
- 스프링
- Numpy
- 자바연습문제
- docker
- 계층 쿼리
- 시큐어코딩
- JPA
- Secure Coding
- Spring
- 자바의정석
- 제네릭
- 이것이자바다
- 스프링입문
- 스프링MVC
- 김영한
- DispatcherServlet
- 인프런
- 자바공부
- 스프링 핵심원리
- inflearn
- 불친절한SQL프로그래밍
- java
- 분석함수
- 서블릿
- Python
- 스프링 부트와 JPA
- REGEXP_SUBSTR
- Java의정석
- 자바의정석 연습문제
- Today
- Total
Continuous Challenge
[Java의 정석_연습문제 풀이] Chapter12 Generics, Enumeration, Annotation(지네릭스, 열거형, 애너테이션) 본문
[Java의 정석_연습문제 풀이] Chapter12 Generics, Enumeration, Annotation(지네릭스, 열거형, 애너테이션)
응굥 2019. 11. 5. 15:13[12-1] 클래스 Box가 다음과 같이 정의되어 있을 때, 다음 중 오류가 발생하는 문장은? 경고가 발생하는 문장은?
class Box<T> { //지네릭 타입 T를 선언
T item;
void setItem(T item) { this.item = item; }
T getItem() { return item; } }
}
a. Box<Object> b = new Box<String>( ); //에러. 대입된 타입이 반드시 같아야 한다.
b. Box<Object> b = (Object)new Box<String>( ); //에러. Object타입을 Box<Object>타입의 참조변수에 저장불가. (타입 불일치)
c. new Box<String>( ).setItem(new Object( )); //에러. 대입된 타입이 String이므로, setItem(T item)의 매개변수 역시, String타입만 허용된다.
d. new Box<String>( ).setItem("ABC"); //OK. 대입된 타입인 String과 일치하는 타입을 매개변수로 지정했기 때문에 OK.
답 : a, b, c
[12-2] 지네릭 메서드 makeJuice( )가 아래와 같이 정의되어 있을 때, 이 메서드를 올바르게 호출한 문장을 모두 고르시오. (Apple과 Grape는 Fruit의 자손이라고 가정하자.)
class Juicer {
static <T extends Fruit> String makeJuice(FruitBox<T> box) {
String tmp = "";
for (Fruit f : box.getList())
tmp += f + " ";
return tmp;
}
}
a. Juicer.<Apple>makeJuice(new FruitBox<Fruit>( ));
//에러. 지네릭 메서드에 대입된 타입이 Apple이므로, 이 메서드의 매개변수는 'FruitBox<Apple>'타입이 된다. new FruitBox<Fruit>( )는 매개변수의 타입과 일치하지 않으며, 자동형변환도 불가능한 타입이므로 에러이다.
b. Juicer.<Fruit>makeJuice(new FruitBox<Grape>( ));
//에러. Grape가 Fruit의 자손이라고 해도, 타입이 다르기 때문에 같은 이유로 에러.
c. Juicer.<Fruit>makeJuice(new FruitBox<Fruit>( ));
d. Juicer.makeJuice(new FruitBox<Apple>( ));
//OK. 지네릭 메서드의 타입 호출이 생략된 형태. 생략하지 않았다면, 'Juicer.<Apple>makeJuice(new FruitBox<Apple>( ));'과 같다. 대부분의 경우 이처럼 생략한다.
e. Juicer.makeJuice(new FruitBox<Object>( ));
//에러. 지네릭 메서드의 타입 호출이 생략되지 않았다면, 'Juicer.<Object>makeJuice(new FruitBox<Object>( ));' 과 같다. d번의 경우와 같이 타입이 일치하긴 하지만, <T extends Fruit>로 제한이 걸려있으므로, 타입 T는 Fruit의 자손이어야 한다. Object는 Fruit의 자손이 아니므로 에러.
답 : a, d c, d
[12-3] 다음 중 올바르지 않은 문장을 모두 고르시오.
class Box<T extends Fruit> { // 지네릭 타입 T를 선언
T item;
void setItem(T item) {this.item = item;}
T getItem() {return item;}
}
a. Box<?> b = new Box( );
//OK. Box<?>는 Box<? extends Object>를 줄여쓴 것이다. 객체 생성에 지네릭 타입을 지정해 주지 않았지만 문제가 되지는 않는다. 그래도, new Box<>( ) 대신 new Box( )를 사용하는 것이 좋다.
b. Box<?> b = new Box<>( );
//OK. new Box<>( );는 타입을 생략한 것으로, 일반적으로는 참조변수의 타입과 같은 타입으로 간주된다. 참조변수의 타입이 <?>, 즉 <? extends Object>이므로 생략된 타입은 Object이라고 생각하기 쉬운데, 여기서는 지네릭 클래스 Box에 정의된 타입이 T extends Fruit>와 같이 제한되어 있기 때문에, 'Obect'가 아니라 'Fruit'이 생략된 것으로 봐야 한다. 그래서 Box<?> b = new Box<Object>( );와 같이 하면 에러가 발생한다. Object는 Fruit의 자손이 아니기 때문이다.
Box<?> b = new Box<>( ); //OK. Box<?> b = new Box<Fruit>( ); 와 동일
Box<?> b = new Box<Object>( ); //에러
Box<?> b = new Box<Fruit>( ); //OK.
'Box<? extends Object>'는 Box<Object>와 같지 않음에 주의하자. 지네릭 클래스 Box는 타입 T가 Fruit의 자손으로 제한되어 있기 때문에, Box<Object>와 같이 Fruit의 자손이 아닌 클래스를 대입할 수 없다. 그러나, 'Box<? extends Object>'와 같이 와일드 카드를 사용하는 것은 가능하다.
c. Box<?> b = new Box<Object>( );
d. Box<Object> b = new Box<Fruit>( ); //에러. 타입 불일치
e. Box b = new Box<Fruit>( ); //OK. 바람직하지 않음. 'Box<?> b'가 더 나음.
f. Box<? extends Fruit> b = new Box<Apple>( ); //OK.
g. Box<? extends Object> b = new Box<? extends Fruit>( ); //에러. new연산자는 타입이 명확해야하므로 와일드카드와 같이 사용불가.
답 : c, d, g
[12-4] 아래의 메서드는 두 개의 ArrayList를 매개변수로 받아서, 하나의 새로운 ArrayList로 병합하는 메서드이다. 이를 지네릭 메서드로 변경하시오.
public static ArrayList<? extends Product> merge(
ArrayList<? extends Product> list, ArrayList<? extends Product> list2){
ArrayList<? extends Product> newList = new ArrayList<>(list);
newList.addAll(list2);
return newList;
}
답 :
public static <T extends Product> ArrayList<T> merge (
ArrayList<T> list, ArrayList<T> list2) {
ArrayList<T> newList = new ArrayList<>(list);
newList.addAll(list2);
return newList;
}
[12-5] 아래는 예제 7-3에 열거형 Kind와 Number를 새로 정의하여 적용한 것이다. (1)에 알맞은 코드를 넣어 예제를 완성하시오. (Math.random( )을 사용했으므로 실행결과가 달라질 수 있다.)
class DeckTest {
public static void main(String args[]) {
Deck d = new Deck(); // 카드 한 벌(Deck)을 만든다.
Card c = d.pick(0); // 섞기 전에 제일 위의 카드를 뽑는다.
System.out.println(c); // System.out.println(c.toString());과 같다.
d.shuffle(); // 카드를 섞는다.
c = d.pick(0); // 섞은 후에 제일 위의 카드를 뽑는다 .
System.out.println(c);
}
}
class Deck {
final int CARD_NUM = Card.Kind.values().length * Card.Number.values().length;// 카드의 개수
Card cardArr[] = new Card[CARD_NUM]; // Card객체 배열을 포함
Deck() {
/*
* (1) 알맞은 코드를 넣어서 완성하시오.
* Deck의 카드를 초기화한다 .
*/
}
Card pick(int index){ 지정된 위치 에 있는 카드 하나를
꺼내서 반환
(index) return cardArr[index]; }
Card pick() { // Deck에서 카드 하나를 선택한다.
int index = (int) (Math.random() * CARD_NUM);
return pick(index);
}
void shuffle() { // 카드의 순서를 섞는다.
for (int i = 0; i < cardArr.length; i++) {
int r = (int) (Math.random() * CARD_NUM);
}
Card temp = cardArr[i];
cardArr[i] = cardArr[r];
cardArr[r] = temp;
}
}
//Card 클래스
class Card {
enum Kind {CLOVER, HEART, DIAMOND, SPADE}
enum Number {ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING}
Kind kind;
Number num;
Card() {
this(Kind.SPADE, Number.ACE);
}
Card(Kind kind, Number num) {
this.kind = kind;
this.num = num;
}
public String toString() {
return "[" + kind.name() + "," + num.name() + "]";
}
}
[실행결과]
[CLOVER,ACE]
[HEART,TEN]
답 :
(1)
int i = 0;
for(Card.Kind kind : Card.Kind.values()){
for(Card.Number num : Card.Number.values()) {
cardArr[i++] = new Card(kind,num);
}
}
[12-6] 다음 중 메타 에너테이션이 아닌 것을 모두 고르시오.
a. Documented
b. Target
c. Native
d. Inherited
답 : c
애너테이션 |
설명 |
@Override |
컴파일러에게 오버라이딩하는 메서드라는 것을 알린다. |
@Deprecated |
앞으로 사용하지 않을 것을 권장하는 대상에 붙인다. |
@SuppressWarnings |
컴파일러의 특정 경고메시지가 나타나지 않게 해준다. |
@SafeVarargs |
지네릭스 타입의 가변인자에 사용한다. (JDK1.7) |
@FunctionalInterface |
함수형 인터페이스라는 것을 알린다. (JDK1.8) |
@Native |
native메서드에서 참조되는 상수 앞에 붙인다. (JDK1.8) |
@Target * |
애너테이션이 적용가능한 대상을 지정하는데 사용한다. |
@Documented * |
애너테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다. |
@Inherited * |
애너테이션이 자손 클래스에 |
@Retention * |
애너테이션이 유지되는 범위를 지정하는 데 사용한다. |
@Repeatable * |
애너테이션을 반복해서 적용할 수 있게 한다. (JDK1.8) |
[자바에서 기본적으로 제공하는 표준 애너테이션 (*가 붙은 것은 메타 애너테이션)]
[12-7] 애너테이션 TestInfo가 다음과 같이 정의되어 있을 때, 이 애너테이션이 올바르게 적용되지 않은 것은?
@interface TestInfo {
int count() default 1;
String[] value() default "aaa";
}
a. @TestInfo class Exercise12_7 { }
//default값이 지정되어 있는 요소는 애너테이션을 적용할 때값을 생략할 수 있다.
b. @TestInfo(1) class Exercise12_7 { }
//요소의 이름이 value가 아닌 경우에는 요소의 이름을 생략할 수 없다.
'@TestInfo(count=1)'이라고 써야 맞음.
c. @TestInfo("bbb") class Exercise12_7 { }
//@TestInfo(count =1, value = {"bbb"})의 생략된 형태
d. @TestInfo("bbb", "ccc") class Exercise12_7 { }
//요소의 타입이 배열이고, 지정하려는 값이 여러 개인 경우 괄호{ }가 필요함.
@TestInfo({"bbb","ccc"}) 또는 @TestInfo(value={"bbb","ccc"})와 같이 써야함.
답 : b, d
'Study > Java의 정석' 카테고리의 다른 글
[Java의 정석_연습문제 풀이] Chapter14. 람다와 스트림 (0) | 2019.11.06 |
---|---|
[Java의 정석_연습문제 풀이] Chapter13 쓰레드 (0) | 2019.11.06 |
[Java의 정석_연습문제 풀이] Chapter11 컬렉션 프레임워크 (0) | 2019.11.05 |
[Java의 정석_연습문제 풀이] Chapter10 날짜와 시간 & 형식화 (0) | 2019.10.30 |
[Java의 정석_연습문제 풀이] Chapter9 java.lang패키지와 유용한 클래스 (0) | 2019.10.28 |