7-1. 20장의 섯다카드를 초기화. 1~10까지 한 쌍 씩 있고 1,3,8은 한 장은 광이여야 한다.
for (int i = 0; i < CARD_NUM; i++) {
int num = i;
if(num>9){
num -= 10;
}
if((num==0||num==2||num==7)&&i<10){
// 첫 번째 턴에서 1,3,8만 광 붙임
cards[i] = new SutdaCard(num+1,true);
} else{
// 나머지는 광x
cards[i] = new SutdaCard(num+1,false);
}
}
- 답지랑 다름.
1. 정수 num에 i값을 입력한다.
2. num+1 값을 카드 번호로 입력한다. 그래서 9가 넘어가면 -10을 해준다.
3. 두 번째 조건문에서 카드 값이 1 or 3 or 8이고 i <10인 경우 (첫 번째 라운드 카드) 광을 true로 한다.
4. 나머지는 광을 false로 한다.
전체코드
class SutdaDeck {
final int CARD_NUM = 20;
SutdaCard[] cards = new SutdaCard[CARD_NUM];
SutdaDeck(){
for (int i = 0; i < CARD_NUM; i++) {
int num = i;
if(num>9){
num -= 10;
}
if((num==0||num==2||num==7)&&i<10){
// 첫 번째 턴에서 1,3,8만 광 붙임
cards[i] = new SutdaCard(num+1,true);
} else{
// 나머지는 광x
cards[i] = new SutdaCard(num+1,false);
}
}
}
}
class SutdaCard {
int num;
boolean isKwang;
SutdaCard() {
this(1, true);
}
SutdaCard(int num, boolean isKwang) {
this.num = num;
this.isKwang = isKwang;
}
// info()대신 Object클래스의 toString()을 오버라이딩했다.
public String toString() {
return num + (isKwang ? "K" : "");
}
}
public class Main {
public static void main(String[] args) {
SutdaDeck deck = new SutdaDeck();
for(int i=0; i < deck.cards.length;i++)
System.out.print(deck.cards[i]+",");
}
}
7-2. SuddaDeck 클래스에 새로운 메서드를 추가하라.
void shuffle() {
for (int i = 0; i < cards.length; i++) {
int num = (int) (Math.random() * cards.length);
SutdaCard tmp = cards[i];
cards[i] = cards[num];
cards[num] = tmp;
}
}
SutdaCard pick(){
// 인덱스가 없다. 랜덤 인덱스로 값 출력
int index = (int)(Math.random()* cards.length);
return cards[index];
}
SutdaCard pick(int index){
return cards[index];
}
1. shuffle
일반적인 배열의 변환이다. 랜덤으로 수를 뽑아주고 (범위는 배열의 길이) tmp 변수를 생성해 값을 저장해준뒤 값을 교환한다. 주의할 점은 cards 배열의 타입은 SutdaCard이므로 tmp의 타입도 SutdaCard로 해줘야한다.
2. pick
매개변수가 없으면 랜덤으로 값을 뽑고 그 값을 인덱스로 가지는 배열을 반환한다.
매개변수가 있는 메서드는 매개변수를 인덱로 하는 배열을 반환한다.
전체코드
class SutdaDeck {
final int CARD_NUM = 20;
SutdaCard[] cards = new SutdaCard[CARD_NUM];
SutdaDeck(){
for (int i = 0; i < CARD_NUM; i++) {
int num = i;
if(num>9){
num -= 10;
}
if((num==0||num==2||num==7)&&i<10){
// 첫 번째 턴에서 1,3,8만 광 붙임
cards[i] = new SutdaCard(num+1,true);
} else{
// 나머지는 광x
cards[i] = new SutdaCard(num+1,false);
}
}
}
void shuffle() {
for (int i = 0; i < cards.length; i++) {
int num = (int) (Math.random() * cards.length);
SutdaCard tmp = cards[i];
cards[i] = cards[num];
cards[num] = tmp;
}
}
SutdaCard pick(){
// 인덱스가 없다. 랜덤 인덱스로 값 출력
int index = (int)(Math.random()* cards.length);
return cards[index];
}
SutdaCard pick(int index){
return cards[index];
}
}
class SutdaCard {
int num;
boolean isKwang;
SutdaCard() {
this(1, true);
}
SutdaCard(int num, boolean isKwang) {
this.num = num;
this.isKwang = isKwang;
}
// info()대신 Object클래스의 toString()을 오버라이딩했다.
public String toString() {
return num + (isKwang ? "K" : "");
}
}
public class Main {
public static void main(String[] args) {
SutdaDeck deck = new SutdaDeck();
System.out.println(deck.pick(0));
System.out.println(deck.pick());
deck.shuffle();
for (int i = 0; i < deck.cards.length; i++) {
System.out.print(deck.cards[i]+",");
}
System.out.println();
System.out.println(deck.pick(0));
}
}
7-3. 오버라이딩이 필요한 이유?
상속받는 자손 클래스마다 필요한 기능이 다르기 때문에 오버라이딩이 필요하다.
7-4. 오버라이딩의 조건으로 옳지 않은 것은?
c. 더 넓은 범위로만 변경할 수 있다.
d. 조상 메서드보다 더 많은 수의 예외는 선언할 수 없다.
7-5. 에러를 수정하기 위해 코드를 어떻게 바꿔야 하는가?
class Tv extends Product {
Tv() {
this(10000); // 기본가격
}
Tv(int price){
super(price);
}
public String toString() {
return "Tv";
}
}
- 답지랑 다름.
product 클래스의 생성자를 입력할 tv 클래스 생성자가 없어서 매개변수가 있는 생성자를 만들어 줬다.
그리고 객체를 만들 때 매개변수를 입력하지 않았으므로 매개변수가 없는 생성자도 만들어 기본값을 입력하도록 만들었다.
전체코드
class Product{
int price;
int bonusPoint;
Product(int price) {
this.price = price;
bonusPoint = (int)(price/10.0);
}
}
class Tv extends Product {
Tv() {
this(10000) ; // 기본가격
}
Tv(int price){
super(price);
}
public String toString() {
return "Tv";
}
}
public class Main {
public static void main(String[] args) {
Tv t = new Tv();
System.out.println(t);
}
}
7-6. 자손 클래스의 생성자에서 조상 클래스의 생성자를 소환해야 하는 이유?
자손 클래스는 조상 클래스의 모든 멤버를 가져온다. 그 값들을 초기화 해야하기 때문이다.
7-7. 생성자의 순서와 실행결과를 적어라.
1. Child()
2. Child(int x)
-- 컴파일러는 생성자의 첫 줄에서 다른 생성자를 호출하지 않으면 조상의 기본 생성자를 호출한다. (super())
3. Parent()
4. Parent(int x)
-- 컴파일러는 생성자의 첫 줄에서 다른 생성자를 호출하지 않으면 조상의 기본 생성자를 호출한다. (super())
5. Object()
결과 : 200
7-8. 넓은 접근 제어자 -> 좁은
a. public -> protected -> (default) -> private
7-9. final의 의미 중 옳지 않는 것은?
c. 오버로딩x, 오버라이딩을 할 수 없다.
7-10. isPowerOn, channel, volume에 제어자를 붙이고 getter,setter 메서드를 추가하라.
- 확인 코드 안적음
외부 접근을 막기위해 멤버변수에 final 제어자를 입력하였다.
값을 반환하는 getter메서드와 값을 변경하는 setter 메서드를 추가하였다.
전체코드
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;
public int getChannel() {
return channel;
}
public int getVolume() {
return volume;
}
public void setChannel(int channel) {
this.channel = channel;
}
public void setVolume(int volume) {
this.volume = volume;
}
}
public class Main {
public static void main(String[] args) {
MyTv2 t = new MyTv2();
t.setChannel(10);
System.out.println(t.getChannel());
t.setVolume(20);
System.out.println(t.getVolume());
}
}
7-11 위의 코드에서 이전 채널로 이동하는 메서드를 추가하라.
private int prevChannel;
/*.....*/
public void setChannel(int channel) {
prevChannel = this.channel;
this.channel = channel;
}
/*.....*/
void gotoPrevChannel(){
setChannel(prevChannel);
}
1. 이전 채널의 값을 저장하는 정수 변수를 만든다.
2. setChannel에서 채널을 변경하기 전 현재 channel의 값을 1. 변수에 저장한다.
3. gotoPrevChannel 메서드에서는 1. 변수로 채널을 이동하는 메서드를 실행시킨다.
전체 코드
class MyTv2{
private boolean isPowerOn;
private int channel;
private int volume;
private int prevChannel;
final int MAX_VOLUME = 100;
final int MIN_VOLUME = 0;
final int MAX_CHANNEL = 100;
final int MIN_CHANNEL = 1;
public int getChannel() {
return channel;
}
public int getVolume() {
return volume;
}
public void setChannel(int channel) {
prevChannel = this.channel;
this.channel = channel;
}
public void setVolume(int volume) {
this.volume = volume;
}
void gotoPrevChannel(){
setChannel(prevChannel);
}
}
public class Main {
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());
}
}
7-12. 접근 제어자에 대한 설명으로 옳지 않은 것은?
c. 지역변수x. 지역변수에는 접근 제어자를 사용하지 못한다.
7-13. Math클래스의 생성자는 접근 제어자가 private이다. 그 이유는?
- 답지 봄
모든 메서드가 static이고 인스턴스 메서드가 없으므로 객체를 생성하지 않는다. 그래서 불필요한 접근을 막기위해 private로 설정하였다.
7-14. 7-1의 섯다카드의 숫자와 종류(광)가 변경이 안되도록 변경하라.
final int num;
final int isKwang;
한 번 입력된 값이 변경되면 안되므로 상수 선언을 해야한다.
전체 코드
class SutdaCard {
final int num;
final boolean isKwang;
SutdaCard() {
this(1, true);
}
SutdaCard(int num, boolean isKwang) {
this.num = num;
this.isKwang = isKwang;
}
public String toString() {
return num + (isKwang ? "K" : "");
}
}
public class Main {
public static void main(String[] args) {
SutdaCard card = new SutdaCard(1,true);
System.out.println(card);
}
}
7-15. 형변환이 옳지 않은 것은?

- 자손 -> 조상의 변환일 때 타입을 생략할 수 있다.
- 참조변수가 가리키는 인스턴스의 자손으로는 형변환이 불가하다.
e. u의 인스턴스 타입은 GroundUnit이다. Tank t 는 GroundUnit의 자손이므로 형변환이 불가능하다.
7-16. 다음 중 결과가 true가 아닌것은?

e. Ambulance는 FireEngine의 조상도 인터페이스도 아니기때문에 false가 나온다.
7-17. 공통부분을 뽑아서 클래스를 만들고 상속해라.
abstract class Unit{
int x,y;
abstract void move(int x,int y);
void stop(){/* stop */}
}
class Marine extends Unit{
void move(int x, int y){
super.x = x;
super.y = y;
}
void stimPack(){/*stimPack*/}
}
class Tank extends Unit{
void move(int x, int y){
super.x = x;
super.y = y;
}
void changeMode(){/*mode changek*/}
}
class Dropship extends Unit{
void move(int x, int y){
super.x = x;
super.y = y;
}
void load(){/*load*/}
void unload(){/*unload*/}
}
이동 메서드와 정지 메서드가 중복되므로 조상 클래스(Unit)으로 옮겨준다.
이동 메서드는 유닛별로 차이가 있으므로 추상 메서드로 정의해주고 클래스도 추상 클래스로 변경한다.
각 유닛별로 이동 메서드를 정의해준다.
7-18. 코드를 완성하라.
static void action(Robot r){
if(r instanceof DanceRobot){
((DanceRobot) r).dance();
}
else if(r instanceof SingRobot){
((SingRobot) r).sing();
}
else if(r instanceof DrawRobot){
((DrawRobot) r).draw();
}
else{
System.out.println("");
}
}
매개변수가 참조하는 인스턴스를 조건문으로 구별하여 필요한 형변환 후 필요한 메서드를 실행시킨다.
전체 코드
class Robot{}
class DanceRobot extends Robot {
void dance(){
System.out.println("춤을 춥니다.");
}
}
class SingRobot extends Robot {
void sing(){
System.out.println("노래를 합니다.");
}
}
class DrawRobot extends Robot {
void draw(){
System.out.println("그림을 그립니다.");
}
}
public class Main {
static void action(Robot r){
if(r instanceof DanceRobot){
((DanceRobot) r).dance();
}
else if(r instanceof SingRobot){
((SingRobot) r).sing();
}
else if(r instanceof DrawRobot){
((DrawRobot) r).draw();
}
else{
System.out.println("");
}
}
public static void main(String[] args) {
Robot[] arr = {new DanceRobot(), new SingRobot(),new DrawRobot()};
for (int i = 0; i < arr.length; i++) {
action(arr[i]);
}
}
}
7-19. buy 메서드, add 메서드, summary 메서드를 구현하라.
void buy (Product p){
if(p.price > money){
System.out.println("잔액이 부족합니다. 가진 돈 : "+money+" 가격 : "+p.price);
}
else{
money -= p.price;
add(p);
}
}
void add (Product p){
if(i >= cart.length){
Product[] tmpCart = new Product[cart.length*2];
System.arraycopy(cart,0,tmpCart,0,cart.length);
this.cart = tmpCart;
}
cart[i++] = p;
}
void summary(){
int sum=0;
for (int j = 0; j < cart.length; j++) {
if(cart[j]!=null){
sum += cart[j].price;
System.out.print(cart[j].toString()+",");
}
}
System.out.println();
System.out.printf("사용한 금액 : %d\n", sum);
System.out.printf("남은 금액 : %d\n", 1000-sum);
}
1. buy 메서드
가진 돈보다 가격이 높으면 구입이 불가하다는 문구를 출력하고 그렇지 않으면 돈에서 가격을 빼고 add 메서드를 실행시킨다.
2. add 메서드
i 값이 cart 배열의 길이와 같거나 크면 장바구니가 모자르므로 장바구니의 크기를 늘려줘야한다.
임시의 장바구니 tmpCart를 원래 장바구니 크기의 2배 크기로 생성 후 값을 복사해준다.
그리고 원래 카트랑 tmpCart를 바꿔준다.
그 후 카드에 인스턴스를 저장하고 i 값을 증가시킨다.
3. summary 메서드
For문을 실행하여 cart[i] 값이 null이 아니면 cart[i]를 출력하고 가격을 더한다.
for문이 끝나면 전체 가격과 구매 후 남은 돈을 출력해준다.
전체 코드
class Product{
int price;
public Product(int price) {
this.price = price;
}
}
class Tv extends Product{
Tv() {super(100);}
public String toString() {return "Tv";}
}
class Computer extends Product{
Computer() {super(200);}
public String toString() {return "Computer";}
}
class Audio extends Product{
Audio() {super(50);}
public String toString() {return "Audio";}
}
class Buyer {
int money = 1000;
Product[] cart = new Product[3];
int i = 0;
void buy (Product p){
if(p.price > money){
System.out.println("잔액이 부족합니다. 가진 돈 : "+money+" 가격 : "+p.price);
}
else{
money -= p.price;
add(p);
}
}
void add (Product p){
if(i >= cart.length){
Product[] tmpCart = new Product[cart.length*2];
System.arraycopy(cart,0,tmpCart,0,cart.length);
this.cart = tmpCart;
}
cart[i++] = p;
}
void summary(){
int sum=0;
for (int j = 0; j < cart.length; j++) {
if(cart[j]!=null){
sum += cart[j].price;
System.out.print(cart[j].toString()+",");
}
}
System.out.println();
System.out.printf("사용한 금액 : %d\n", sum);
System.out.printf("남은 금액 : %d\n", 1000-sum);
}
}
public class Main {
public static void main(String[] args) {
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Tv());
b.buy(new Audio());
b.buy(new Computer());
b.buy(new Computer());
b.buy(new Computer());
b.summary();
}
}
7-20 다음 코드를 실행한 결과를 쓰시오.
-틀림
100
Child method
200
Child method
메서드는 오버라이딩된 메서드로 결과가 같다.
하지만 조상 클래스와 자손 클래스의 인스턴스 이름이 같은 경우 참조변수 타입에 따라 값이 달라진다. 조상 클래스로 참조했으면 조상 클래스의 변수 값, 자손 클래스로 참조했으면 자손 클래스의 변수 값이 나온다.
7-21. 다음 메서드의 매개변수로 가능한 것 두 가지
인터페이스를 구현하는 클래스 생성, null?
7-22. Circle 클래스와 Rectangle 클래스를 작성하라.
class Circle extends Shape{
double r;
Circle(double r){
this(new Point(0,0),r);
}
Circle (Point p, double r){
super(p);
this.r = r;
}
@Override
double calcArea() {
return r*r*Math.PI;
}
}
class Rectangle extends Shape {
double width;
double height;
public Rectangle(double width, double height) {
this(new Point(0,0),width,height);
}
public Rectangle(Point p, double width, double height) {
super(p);
this.width = width;
this.height = height;
}
@Override
double calcArea() {
return width*height;
}
boolean isSquare(){
if (width==height)
return true;
else
return false;
}
}
1. circle
반지름 r을 double로 선언한다.
Point p와 반지름을 매개변수로 받는 생성자에서 조상의 생성자는 super로 값을 입력하고 반지름은 this.r로 입력한다.
반지름만 매개변수로 받는 경우는 조상의 생성자는 기본값을 (0,0) 입력한다.
2. rectagle
생성자 부분과 넓이는 원과 같고 정사각형을 판단하는 메서드는 가로와 세로의 길이가 같은지 확인 후 boolean으로 반환한다.
7-23. 면적을 구하는 메서드를 작성하라.
static double sumArea(Shape[] arr){
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i].calcArea();
}
return sum;
}
arr의 길이만큼 for문을 돌리고 각 배열의 넓이 값을 sum에 더한다.
for문이 종료되면 넓이의 합을 리턴한다.
전체 코드
abstract class Shape{
Point p;
public Shape() {
this(new Point(0,0));
}
public Shape(Point p) {
this.p = p;
}
abstract double calcArea();
Point getPosition(){
return p;
}
void setPosition(Point p){
this.p = p;
}
}
class Point{
int x;
int y;
public Point() {
this(0,0);
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public String toString(){
return "["+x+","+y+"]";
}
}
class Circle extends Shape{
double r;
Circle(double r){
this(new Point(0,0),r);
}
Circle (Point p, double r){
super(p);
this.r = r;
}
@Override
double calcArea() {
return r*r*Math.PI;
}
}
class Rectangle extends Shape {
double width;
double height;
public Rectangle(double width, double height) {
this(new Point(0,0),width,height);
}
public Rectangle(Point p, double width, double height) {
super(p);
this.width = width;
this.height = height;
}
@Override
double calcArea() {
return width*height;
}
boolean isSquare(){
if (width==height)
return true;
else
return false;
}
}
public class Main {
static double sumArea(Shape[] arr){
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i].calcArea();
}
return sum;
}
public static void main(String[] args) {
Shape[] arr = {new Circle (5.0), new Rectangle(3,4), new Circle(1)};
System.out.println(sumArea(arr));
}
}
7-24. 인터페이스의 장점이 아닌 것은?
e. 패키지간의 연결을 도와준다는 설명은 없다.
7-25. Outer 클래스 내부 클래스 Inner 멤버변수 iv 값을 출력하시오.
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
System.out.println(inner.iv);
외부 클래스의 인스턴스를 생성하고 내부 클래스에 접근하여 iv의 값을 불러온다.
전체 코드
class Outer{
class Inner{
int iv = 200;
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
System.out.println(inner.iv);
}
}
7-26. Outer 클래스 내부 클래스 Inner 멤버변수 iv 값을 출력하시오.
Outer.Inner inner = new Outer.Inner();
System.out.println(inner.iv);
static 클래스는 인스턴스 형성없이 바로 접근이 가능하다.
전체 코드
class Outer{
static class Inner{
int iv = 200;
}
}
public class Main {
public static void main(String[] args) {
Outer.Inner inner = new Outer.Inner();
System.out.println(inner.iv);
}
}
7-27. 코드를 완성하시오
System.out.println(value);
System.out.println(this.value);
System.out.println(Outer.this.value);
/* ..... */
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
30은 지역변수니까 value, 20은 클래스 내의 인스턴스 변수니까 this.value, 10은 외부 클래스의 변수이므로 Outer.this.value.
전체 코드
class Outer{
int value = 10;
class Inner{
int value = 20;
void method1() {
int value = 30;
System.out.println(value);
System.out.println(this.value);
System.out.println(Outer.this.value);
}
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.method1();
}
}
7-28. 익명 클래스로 변경하시오.
import java.awt.*;
import java.awt.event.*;
public class Main {
public static void main(String[] args) {
Frame f = new Frame();
WindowAdapter eventHandler = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
e.getWindow().setVisible(false);
e.getWindow().dispose();;
System.exit(0);
}
};
f.addWindowFocusListener(eventHandler);
}
}
EventHandler 클래스를 익명 클래스로 변경하기 위해 조상 클래스인 WindowAdapter 클래스로 익명 클래스를 생성하였다.
7-29. 지역 클래스에서 지역변수는 final이 붙은 상수만 접근 할 수 있는 이유는 무엇인가?
지역변수가 소멸되어도 지역 클래스의 인스턴스가 그 지역변수를 참조할 수 있기 때문이다.
'Java > 개념' 카테고리의 다른 글
| (java.lang) Object 클래스 (0) | 2023.01.13 |
|---|---|
| 11장 문제풀이 (0) | 2023.01.02 |
| Ch5. 배열 (0) | 2022.12.06 |
| Ch.4 조건문과 반복문 (0) | 2022.12.06 |
| 자바가 구동되는 방식 (0) | 2022.12.06 |