오답노트/Java

자바(java)_객체배열 연습문제

개발..너... 2022. 4. 12. 22:06

▶문제 1

 

오버라이딩의 정의와 필요성에 대해서 설명하시오.

 

[답]

 

오버라이딩(overriding)이란, '조상 클래스로부터 상속받은 메서드를 자손 클래스에 맞게 재정의 하는 것'을 말한다. 

조상 클래스로부터 상속받은 메서드를 자손 클래스에서 그대로 사용할 수 없는 경우가 많기 때문에 오버라이딩이 필요하다.

 

▶문제 2

 

다음 중 오버라이딩의 조건으로 옳지 않은 것은? (모두 고르시오)

a. 조상의 메서드와 이름이 같아야 한다.
b. 매개변수의 수와 타입이 모두 같아야 한다.
c. 접근 제어자는 조상의 메서드보다 좁은 범위로만 변경할 수 있다.
d. 조상의 메서드보다 더 많은 수의 예외를 선언할 수 있다.

 

[답]

 

c, d

 

[풀이]

 

a,b ) 오버라이딩의 조건은 이름, 매개변수, 리턴타입이 같아야한다.

c ) 접근 제어자의 조상의 메서드보다 좁은 범위로 변경할 수 없다.

   ex. 조상의 메서드가 Protected라면, 범위가 같거나 넓은 Protected 또는 public 으로만 처리해야한다.

d) 예외는 조상클래스의 메서드보다 많은 수의 예외를 처리할 수 없다.

https://dlsdn73.tistory.com/306

 

 

▶문제 3

 

다음의 코드는 컴파일하면 에러가 발생한다. 그 이유를 설명하고 에러를 수정하기 위해서는 코드를 어떻게 바꾸어야 하는가?

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class Product {
 
    int price; // 제품의 가격
 
    int bonusPoint; // 제품구매 시 제공하는 보너스점수
 
 
 
    Product(int price) {
 
        this.price = price;
 
        bonusPoint = (int) (price / 10.0);
 
    }
 
}
 
 
 
class Tv extends Product {
 
    Tv() {}
 
 
 
    public String toString() {
 
        return "Tv";
 
    }
 
}
 
 
 
class Exercise7_5 {
 
    public static void main(String[] args) {
 
        Tv t = new Tv();
 
    }
 
}
cs

 

[답]

 

product 클래스에 product () {} 기본생성자를 생성해준다.

 

[풀이]

 

Tv클래스의 인스턴스를 생성할 때, 생성자  Tv( )가 호출되고 Tv( )는 조상 생성자 super( )를 호출한다. 

실제 코드에서는 super( )를 호출하는 곳이 없지만 컴파일러가 자동적으로 추가해준다. 

그래서 컴파일을 하고 나면 Tv() { } -> Tv() { super(); }와 같이 변경된다. 

추가된 super( )는 조상클래스인 Product의 기본 생성자 Product( )를 호출하는 것인데, Product클래스에는 기본 생성자 Product( )가 정의되어 있지 않다. Product클래스에는 이미 Product(int price)라는 생성자가 정의되어 있기 때문에 컴파일러가 자동적으로 추가해 주지도 않으므로 직접 Product클래스에 Product( ){ }를 넣어주면 문제가 해결된다.

 

▶문제 4

 

 자손 클래스의 생성자에서 조상 클래스의 생성자를 호출해야하는 이유는 무엇인가?

 

[답]

 

 조상에 정의된 인스턴스 변수들이 초기화되도록 하기 위해서.

 

[풀이]

 

자손클래스의 인스턴스를 생성하면 조상으로부터 상속받은 인스턴스변수들도 생성되는데, 이 상속받은 인스턴스변수들 역시 적절히 초기화되어야 한다. 상속받은 조상의 인스턴스변수들을 자손의 생성자에서 직접 초기화하기보다는 조상의 생성자를 호출함으로써 초기화되도록 하는 것이 바람직하다.

 

각 클래스의 생성자는 해당 클래스에 선언된 인스턴스변수의 초기화만을 담당하고, 조상클래스로부터 상속받은 인스턴스변수의 초기화는 조상클래스의 생성자가 처리하도록 해야하는 것이다.

 

 

▶문제 5

 

 다음 코드의 실행했을 때 호출되는 생성자의 순서와 실행결과를 적으시오.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
class Parent {
 
    int x = 100;
 
    Parent() {
 
        this(200);
 
    }
 
    Parent(int x) {
 
        this.x = x;
 
    }
 
    int getX() {
 
        return x;
 
    }
 
}
 
class Child extends Parent {
 
    int x = 3000;
 
 
 
    Child() {
 
        this(1000);
 
    }
 
 
 
    Child(int x) {
 
        this.x = x;
 
    }
 
}
 
class Exercise7_7 {
 
    public static void main(String[] args) {
 
        Child c = new Child();
 
        System.out.println("x=" + c.getX());
 
    }
 
}
cs

 

[답]

 

순서:   Child( ) → Child(int x) → Parent( ) → Parent(int x) → Object( ) 

실행결과:  x = 200

 

[풀이]

 

컴파일러는 생성자의 첫 줄에 다른 생성자를 호출하지 않으면 조상의 기본 생성자를 호출하는 코드 'super( );' 를 넣는다. 그래서 Child(int x){ this.x = x; } 이 코드는 컴파일 후 Child(int x){ super( ); this.x =x; } 와 같은 코드로 바뀐다. 마찬가지로 Parent(int x) 역시 컴파일러가 Parent의 조상인 Object클래스의 기본 생성자를 호출하는 코드를 넣는다.

 

Child( ) → Child(int x) → Parent( ) → Parent(int x) → Object( )의 순서로 호출되니까, Child클래스의 인스턴스변수 x는 1000이 되고, Parent 클래스의 인스턴스변수 x는 200이 된다.  getX( )는 조상인 Parent의 클래스에 정의된 것이라서, getX( )에서 x는 Parent 클래스의 인스턴스변수 x를 의미한다. 그래서 x=200이 출력된다.

 

▶문제 6

 

다음 중 접근제어자를 접근범위가 넓은 것에서 좁은 것의 순으로 바르게 나열한 것은?

a. public-protected-(default)-private
b. public-(default)-protected-private
c. (default)-public-protected-private
d. private-protected-(default)-public

 

 

[답]

 

a

 

[풀이]

 

접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자

 

private - 같은 클래스 내에서만 접근이 가능하다.

default - 같은 패키지 내에서만 접근이 가능하다.

protected - 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.

public - 접근 제한이 전혀 없다.

 

▶문제 7

 

다음 중 제어자 final을 붙일 수 있는 대상과 붙였을 때 그 의미를 적은 것이다. 옳지 않은 것은? (모두 고르시오)

a. 지역변수 - 값을 변경할 수 있다.
b. 클래스 - 상속을 통해 클래스에 새로운 멤버를 추가할 수 없다.
c. 메서드 - 오버로딩을 할 수 없다.
d. 멤버변수 - 값을 변경할 수 없다.

 

[답]

 

a,c

 

[풀이]

 

final

클래스 - 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.

            그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.

메서드 - 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.

멤버변수/지역변수 - 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.

 

 

▶문제 8

 

MyTv2클래스의 멤버변수 isPowerOn, channel, volume을 클래스 외부에서 접근할 수 없도록 제어자를 붙이고 대신 이 멤버변수들의 값을 어디서나 읽고 변경할 수 있도록 getter와 setter메서드를 추가하라.

 

 

 
 
 
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
32
33
34
35
36
37
38
39
40
41
42
43
class MyTv2 {
 
    boolean isPowerOn;
 
    int channel;
 
    int volume;
 
    final int MAX_VOLUME = 100;
 
    final int MIN_VOLUME = 0;
 
    final int MAX_CHANNEL = 100;
 
    final int MIN_CHANNEL = 1;
 
    /* (1) 알맞은 코드를 넣어 완성하시오. */
 
}
 
class Exercise7_10 {
 
    public static void main(String args[]) {
 
        MyTv2 t = new MyTv2();
 
        t.setChannel(10);
 
        System.out.println("CH:" + t.getChannel());
 
        t.setVolume(20);
 
        System.out.println("VOL:" + t.getVolume());
 
    }
 
}
 
/* [실행결과]
 
CH:10
 
VOL:20 */
cs

 

[답]

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
class MyTv2 {
 
    private boolean isPowerOn;
 
    private int channel; 
    
    final int MAX_VOLUME = 100;
    
    final int MIN_VOLUME = 0;
    
    final int MAX_CHANNEL = 100;
    
    final int MIN_CHANNEL = 1;
    
    
    public boolean isIsPowerOn() {
        return this.isPowerOn;
    }
    
    public void setIsPowerOn(boolean isPowerOn) {
        this.isPowerOn = isPowerOn;
    }
    
    public int getChannel() {
        return this.channel;
    }
    
    public void setChannel(int channel) {
        this.channel = channel;
    }
    
    private int volume;
    
    public int getVolume() {
        return this.volume;
    }
    
    public void setVolume(int volume) {
        this.volume = volume;
    }
    
}
 
class Exercise7_10 {
 
    public static void main(String args[]) {
 
        MyTv2 t = new MyTv2();
 
        t.setChannel(10);
 
        System.out.println("CH:" + t.getChannel());
 
        t.setVolume(20);
 
        System.out.println("VOL:" + t.getVolume());
 
    }
 
}
cs

 

 

[풀이]

 

MyTv2() -> setChannel(int channel) -> int channel -> getChannel()

MyTv2() -> setVolume(int volume) -> int volume -> getVolume()

 

순서로 값이 이동된다. 

Mytv2를 메인에서 객체를 생성할 때 자바에서 Mytv2에 기본생성자를 자동으로 만들어준 상황이다.

 

 

▶문제 9

 

문제 8에서 작성한 MyTv2클래스에 이전 채널(previous channel)로 이동하는 기능의 메서드를 추가해서 실행결과와 같은 결과를 얻도록 하시오. ([Hint]이전 채널의 값을 저장할 멤버변수를 정의하라.)

메서드명 : gotoPrevChannel
기능 : 현재 채널을 이전 채널로 변경한다.
반환타입 : 없음
매개변수 : 없음

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class MyTv2 { 
 
    /*  (1)문제 7-10의 MyTv2클래스에 gotoPrevChannel 메서드를 추가하여 완성하시오. */
 
}
 
class Exercise7_11 {
 
    public static void main(String args[]) {
 
        MyTv2 t = new MyTv2();
 
        t.setChannel(10);
 
        System.out.println("CH:" + t.getChannel());
 
        t.setChannel(20);
 
        System.out.println("CH:" + t.getChannel());
 
        t.gotoPrevChannel();
 
        System.out.println("CH:" + t.getChannel());
 
        t.gotoPrevChannel();
 
        System.out.println("CH:" + t.getChannel());
 
    }
 
}
 
[실행결과]
 
CH:10
 
CH:20
 
CH:10
 
CH:20
}
cs

 

 

[답]

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class MyTv2 {
 
    private boolean isPowerOn;
    private int channel; 
    private int volume;
    
    final int MAX_VOLUME = 100;
    
    final int MIN_VOLUME = 0;
    
    final int MAX_CHANNEL = 100;
    
    final int MIN_CHANNEL = 1;
    
    private int prevCh;
    
    
    public boolean isIsPowerOn() {
        return this.isPowerOn;
    }
    
    public void setIsPowerOn(boolean isPowerOn) {
        this.isPowerOn = isPowerOn;
    }
    
    public int getChannel() {
        return this.channel;
    }
    
    public void setChannel(int channel) {
       if(channel > MAX_CHANNEL || channel < MIN_CHANNEL) return ;
 
       prevCh = this.channel;
       this.channel = channel;
 
    }
    
    
    public int getVolume() {
        return this.volume;
    }
    
    public void setVolume(int volume) {
        this.volume = volume;
    }
 
    public void gotoPrevChannel(){
        setChannel(prevCh);
    }
    
}
cs

 

[풀이]

 

이전 채널이든 현재 채널이든 Main에서 채널을 받아와야하는 것은 똑같기에 setChannel에 코드를 작성해주어야한다.

그리고 setChannel안에서 channel이 this를 통해 private channel로 올라가기 전에 prevCh라는 변수에 담아두면 채널이 바뀌어도 그 전 채널은 prevCh에 담겨서 "이전"채널의 정보를 유지할 수 있게 된다.

 

▶문제 10

 

다음 중 접근 제어자에 대한 설명으로 옳지 않은 것은? (모두 고르시오)

a. public은 접근제한이 전혀 없는 접근 제어자이다.
b. (default)가 붙으면, 같은 패키지 내에서만 접근이 가능하다.
c. 지역변수에도 접근 제어자를 사용할 수 있다.
d. protected가 붙으면, 같은 패키지 내에서도 접근이 가능하다.
e. protected가 붙으면, 다른 패키지의 자손 클래스에서 접근이 가능하다.

 

[답]

 

C

 

▶문제 11

 

섯다카드의 숫자와 종류(isKwang)는 사실 한번 값이 지정되면 변경되어서는 안 되는 값이다. 카드의 숫자가 한번 잘못 바뀌면 똑같은 카드가 두 장이 될 수도 있기 때문이다. 이러한 문제점이 발새하지 않도록 아래의 SutdaCard를 수정하시오.

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class SutdaCard {
 
    int num;
 
    boolean isKwang;
 
 
 
    SutdaCard() {
 
        this(1true);
 
    }
 
 
 
    SutdaCard(int num, boolean isKwang) {
 
        this.num = num;
 
        this.isKwang = isKwang;
 
    }
 
 
 
    public String toString() {
 
        return num + (isKwang ? "K" : "");
 
    }
 
}
 
 
 
class Exercise7_14 {
 
    public static void main(String args[]) {
 
        SutdaCard card = new SutdaCard(1true);
 
    }
 
}
cs

 

[답]

 

final int NUM;

final boolean ISKWNAG;

 

▶문제 12

 

클래스가 다음과 같이 정의되어 있을 때, 형변환을 올바르게 하지 않은 것은? (모두 고르시오)

class Unit {} 
class AirUnit extends Unit {} 
class GroundUnit extends Unit {} 
class Tank extends GroundUnit {} 
class AirCraft extends AirUnit {} 

Unit u = new GroundUnit(); 
Tank t = new Tank(); 

AirCraft ac = new AirCraft();

a. u = (Unit)ac; 
b. u = ac;
c. GroundUnit gu = (GroundUnit) u; 
d. AirUnit au = ac;
e. t = (Tank)u; 
f. GroundUnit gu = t;

 

[답]

 

e

 

[풀이]

 

a,b)자식 클래스를 부모클래스에 넣어주는 것으로 u = ac; (=b)로 암묵적 형변환이 가능해 (Unit)은 생략이 가능하다.

c) u가 참조하는 객체가 GroundUnit이므로 가능하다.

d) AirUnit은 AirCraft의 조상임으로 ac(AirCraft)는 au(AirUnit)에 암묵적으로 담겨질 수 있다.

e) Unit은 Tank의 조상클래스이다. 조상타입의 인스턴스를 자손타입이 형변환 할 수 없다.

 

 

▶문제 13

 

다음 중 연산결과가 true가 아닌 것은? (모두 고르시오)

class Car {} 
class FireEngine extends Car implements Movable {} 
class Ambulance extends Car {} 

FireEngine fe = new FireEngine();

a. fe instanceof FireEngine
b. fe instanceof Movable
c. fe instanceof Object
d. fe instanceof Car
e. fe instanceof Ambulance

 

[답]

 

e

 

[풀이]

 

instanceof 연산자는 실제 인스턴스의 모든 조상이나 구현한 인터페이스에 대해 true를 반환한다. 그래서, FireEngine 인스턴스는 Object, Car, Movable, FireEngine타입에 대해 instanceof 연산을 하면 결과로 true를 얻는다. 어떤 타입에 대해 instanceof 연산결과가 true라는 것은 그 타입으로 형변환이 가능하다는 것을 뜻한다. 

 

▶문제 14

 

아래 세 개의 클래스로부터 공통부분을 뽑아서 Unit이라는 클래스를 만들고, 이 클래스를 상속받도록 코드를 변경하시오.

 

 

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
32
33
34
35
36
37
38
39
class Marine { // 현재 위치
 
    int x, y; // 
 
    void move(int x, int y)  { /* 지정된 위치로 이동 */ } 
 
    void stop()  { /*현재 위치에 정지 */ } 
 
   void stimPack()  { /* 스팀팩을 사용한다.*/} 
 
}
 
class Tank { //탱크 
 
    int x, y; //현재 위치 
 
    void move(int x, int y)  { /*지정된 위치로 이동 */ } 
 
    void stop()  { /*현재 위치에 정지 */ } 
 
    void changeMode()  { /* 공격모드를 변환한다. */} } 
 
        
 
class Dropship { //수송선 
 
    int x, y; // 현재 위치
 
    void move(int x, int y)  { /*지정된 위치로 이동 */ } 
 
    void stop()  { /*현재 위치에 정지 */ } 
 
    void load()  { /* 선택된 대상을 태운다.*/ } 
 
    void unload()  { /* 선택된 대상을 내린다.*/ } }
 
    }
 
}
cs

 

[답]

 

 

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
32
33
34
35
36
37
38
39
40
41
abstract class Unit{
 
    int x,y;
 
    abstract void move(int x, int y); //추상클래스
 
    void stop(){/*현재 위치에 정지*/}
 
}
 
 
 
class Marine extends Unit{ // 현재 위치
 
  void move(int x, int y){/* 지정된 위치로 이동*/}; 
 
    void stimPack()  { /* 스팀팩을 사용한다.*/
 
 
 
 
class Tank extends Unit{ //탱크 
 
    void move(int x, int y){/* 지정된 위치로 이동*/}; 
 
    void changeMode()  { /* 공격모드를 변환한다. */
 
 
        
 
class Dropship extends Unit{ //수송선 
 
    void move(int x, int y){/* 지정된 위치로 이동*/};
 
    void load()  { /* 선택된 대상을 태운다.*/ } 
 
    void unload()  { /* 선택된 대상을 내린다.*/ } 
 
}
cs