[Java] 자바의 정석 / chap6.객체지향 프로그래밍_연습문제
6-1) + 문제에서 더 추가함
class Student {
public String name = "chanmi Kim";
public int ban = 2;
public int no = 12345;
public int kor = 100;
public int eng = 100;
public int math = 100;
public String toString() {
return "name: " + name + ", ban: " + ban + ", no: " + no + ", kor: " + kor + ", eng: " + eng + ", math: " + math
+ "\n";
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
System.out.println("** student1 => " + student1.toString());
Student student2 = new Student();
student2.name = "haze Kim";
student2.ban = 3;
student2.no = 98765;
student2.kor = 99;
student2.eng = 88;
student2.math = 77;
System.out.println("** student2 => " + student2.toString());
}
}

6-2)
class Student {
public String name;
public int ban;
public int no;
public int kor;
public int eng;
public int math;
public Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
public String info() {
return name
+", " + ban
+", " + no
+", " + kor
+", " + eng
+", " + math
+", " + (kor + eng + math)
+", " + (int)((kor + eng + math) / 3f * 10 + 0.5f) / 10f;
}
}
public class Main {
public static void main(String[] args) {
Student s = new Student ("홍길동", 1, 1, 100, 60, 76);
String str = s.info();
System.out.println(str);
}
}

6-3)
class Student {
private String name;
private int ban;
private int no;
private int kor;
private int eng;
private int math;
public Student(String name, int ban, int no, int kor, int eng, int math) {
this.name = name;
this.ban = ban;
this.no = no;
this.kor = kor;
this.eng = eng;
this.math = math;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setBan(int ban) {
this.ban = ban;
}
public int getBan() {
return ban;
}
public void setNo(int no) {
this.no = no;
}
public int getNo() {
return no;
}
public void setKor(int kor) {
this.kor = kor;
}
public int getKor() {
return kor;
}
public void setEng(int eng) {
this.eng = eng;
}
public int getEng() {
return eng;
}
public void setMath(int math) {
this.math = math;
}
public int getMath() {
return math;
}
public int getTotal(int kor, int eng, int math) {
return kor + eng + math;
}
public float getAverage(int kor, int eng, int math) {
//return (int)((kor + eng + math) / 3f * 10 + 0.5f) / 10f;
return Math.round(((kor + eng + math) / 3f) * 10) / 10.0f;
}
public String info() {
return name
+", " + ban
+", " + no
+", " + kor
+", " + eng
+", " + math;
}
}
public class Main {
public static void main(String[] args) {
Student[] students = new Student[5];
students[0] = new Student("홍길동", 5, 1, 100, 100, 100);
students[1] = new Student("김길동", 4, 2, 90, 90, 90);
students[2] = new Student("박길동", 3, 3, 80, 80, 80);
students[3] = new Student("이길동", 2, 4, 70, 70, 70);
students[4] = new Student("최길동", 1, 5, 60, 60, 60);
for (int i = 0; i < students.length; i++) {
String str = students[i].info();
System.out.println("info => " + str);
System.out.println("tot => " + students[i].getTotal(students[i].getKor(), students[i].getEng(), students[i].getMath()));
System.out.println("avg => " + students[i].getAverage(students[i].getKor(), students[i].getEng(), students[i].getMath()));
System.out.println();
}
}
}

6-4)
package example01;
public class Ex04_Chapter6 {
static double getDistance(int x, int y, int x1, int y1) {
double dis = Math.pow((x1 - x), 2) + Math.pow((y1 - y), 2);
return Math.sqrt(dis);
}
public static void main(String[] args) {
System.out.println(getDistance(1, 1, 2, 2));
}
}

6-5)
- 클래스 변수(static 변수)
: width, height
- 인스턴스 변수
: kind, num
- 지역 변수
: k, n, args, card
6-6)
package example01;
class MyPoint {
int x;
int y;
MyPoint(int x, int y) {
this.x = x;
this.y = y;
}
double getDistance(int x1, int y1) {
double dis = Math.pow((x1 - x), 2) + Math.pow((y1 - y), 2);
return Math.sqrt(dis);
}
} // MyPoint
public class Ex04_Chapter6 {
public static void main(String[] args) {
MyPoint p = new MyPoint(1, 1);
System.out.println(p.getDistance(2, 2));
}
}

6-7)
static int weapon
static int armor
static void weapoonUp()
static void armorUp()
6-8)
2 => 생성자는 객체를 생성하기 위한 것이다 → 생성자가 객체를 생성할 때 사용되기는 하지만 객체를 초기화할 목적으로 사용되는 , 것이다 객체를 생성하는 것은 연산자이다 . new .
5 => 생성자는 오버로딩 할 수 없다 → 생성자도 오버로딩이 가능해서 하나의 클래스에 여러 개의 생성자를 정의할 수 있 다.
6-9)
2 => 클래스 내에서라면 어디서든 사용할 수 있다 → 클래스 멤버 이 붙은 변수나 메서드 에는 사용할 수 없다. static
6-10)
3 => 오버로딩 성립 조건에 해당 X
4
6-11)
2
3
4
6-12)
3
5
6-13)
1
6-14)
1
5
6-15)
2
6-16)
package example01;
public class Ex04_Chapter6 {
public static void change(String str) {
str += "456";
}
public static void main(String[] args) {
String str = "ABC123";
System.out.println(str);
change(str);
System.out.println("After change: " + str);
}
}

위 문제에서 "아 ~ 당연히 "ABC123456"이 나오지. 이런걸 문제라고 내냐~" 라고 생각했다가 큰 코 다쳤당 ㅋ
파스칼로님께서 제공해주신 해설지를 참조하여 설명해보자면..

먼저 우리가 main에서 str에 값을 할당했을 때 str은 0x100이라는 주소값을 가지게 되고
change 메서드가 호출되면서 매개변수값으로 str을 넘겨받으면서
change 메서드의 str도 "ABC123"을 참조하게 된다.

main과 change는 둘 다 str이라는 참조변수를 가지고 있지만, 둘은 완전히 다른 값으로 서로 영향을 주지 않는다.
둘이 다른 영역에 존재하기 때문에 이름이 같아도 상관없는 것이다.

이제 change메서드 안에서 str += "456"이라는 연산을 수행한다.
자바에서 문자열은 불변하기 때문에 change의 참조변수 str은 0x200이라는 새로운 주소값을 가지게 된다.

반환하는 값 없이 change 메서드는 종료되고
main으로 돌아와서 문자열 str의 값 출력하면 같은 값이 출력되게 된다.
그리고 문자열 "ABC123456"을 참조하는 변수가 없으므로
적절한 시기에 가비지컬렉터에 의해 제거된다.
.
.
.
그렇다.... 그런 것이었다.
그리고 난 또 다시 궁금해졌다.
"ABC123456"을 출력하는 방법이,
그리고 각각의 참조변수의 주소값이 어떻게 변하는지.
package example01;
public class Ex04_Chapter6 {
public static String change(String str) {
System.out.println("** change: str 연산 전 => " + System.identityHashCode(str));
str += "456";
System.out.println("** change: str 연산 후 => " + System.identityHashCode(str));
return str;
}
public static void main(String[] args) {
String str = "ABC123";
System.out.println(str);
System.out.println("** main: str - change 전 => " + System.identityHashCode(str));
System.out.println("After change: " + change(str));
System.out.println("change(str) 주소값 => " + System.identityHashCode(change(str)));
System.out.println("** main: str - change 후 => " + System.identityHashCode(str));
}
}

꽤나 복잡했다.
첫번째로, change메서드 연산 실행 후에 str의 주소값이 바뀐 걸 확인할 수 있었다.
두번째로, 같은 결과값을 출력해도 다른 주소값을 가질 경우를 고려해야 한다는 점을 깨달았다.
str = change(str);
System.out.println("After change: " + str);
System.out.println("After change: " + change(str));
위 코드는 모두 같은 결과값을 출력한다.
나 역시도 change메서드가 어차피 str을 반환하기 때문에 2번째 코드처럼 바로 str을 출력했다.
하지만 모든 변수들의 주소값을 확인해보면서 2번째 코드처럼 출력을 하면,
main메서드에 처음 할당된 str의 주소값이 아닌 change메서드의 연산 수행 후
새로운 주소값을 가진 str을 반환한다는 것을 알게되었다.
따라서 str에 change메서드가 반환한 str을 다시 넣어주는 작업이 필요하다는 생각이 들었다.
6-17)
package example01;
import java.util.Arrays;
public class Ex04_Chapter6 {
public static int[] shuffle(int[] original) {
for (int i = 0; i < original.length; i++) {
int randomNum = (int)(Math.random() * original.length);
int temp = original[i];
original[i] = original[randomNum];
original[randomNum] = temp;
}
return original;
} // shuffle
public static void main(String[] args) {
int[] original = {1, 2, 3, 4, 5, 6, 7, 8, 9};
System.out.println(java.util.Arrays.toString(original));
int[] result = shuffle(original);
System.out.println(Arrays.toString(result));
}
}

자바의 정석 연습문제 해설지를 보니까 original배열의 값이 비워져있을 경우를 shuffle 코드에 작성해주었다. (유효성 체크)
코드를 직접 실행시키기 전까지는 배열이 null이거나 배열의 길이가 0일 경우, 유효성 체크를 하지 않고 실행을 하면 오류가 뜬다고 생각했다. 하지만 정상 출력되었고, 그 이유가 궁금했다.
아직 명확한 답이다!!!!! 라는 답을 얻진 못했는데 아래와 같은 이유가 맞는 거 같긴 하다.

그렇구만......
월요일에 선생님께 다시 한 번 여쭤봐야겠다.
6-18)
package example01;
public class Ex04_Chapter6 {
public static boolean isNumber(String str) {
for (int i = 0; i < str.length(); i++) {
char currentChar = str.charAt(i);
if (currentChar < '0' || currentChar > '9') {
return false;
}
}
return true;
}
public static void main(String[] args) {
String str = "123";
System.out.println(str + "는 숫자입니까? " + isNumber(str));
str = "123o";
System.out.println(str + "는 숫자입니까? " + isNumber(str));
}
}

사실 위 문제에서 생각하지 못했던 문제가 있었다.
package example01;
public class Ex04_Chapter6 {
public static boolean isNumber(String str) {
if (str == null || str.equals("")) {
return false;
} //str 유효성 검사
for (int i = 0; i < str.length(); i++) {
char currentChar = str.charAt(i); //123
if (currentChar < '0' || currentChar > '9') {
return false;
} else {
return true;
}
}
}
public static void main(String[] args) {
String str = "123";
System.out.println(str + "는 숫자입니까? " + isNumber(str));
str = "1234o";
System.out.println(str + "는 숫자입니까? " + isNumber(str));
}
}

for문을 다 돌리기도 전에 return값을 정해주어 오류가 떴었다.
문제를 풀 때 예외사항을 먼저 생각하고, 예외사항을 먼저 걸러내는 코드를 작성할 생각을 해야겠다.
++ 추가)
또 잊어버린게 있다... str의 유효성 검사를 안했다.
기존 코드에 추가하겠다.
6-19)
package example01;
class MyTv {
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;
void turnOnOff() {
if (isPowerOn) {
isPowerOn = false;
} else {
isPowerOn = true;
}
// 이렇게 쉬운 방법이....!
//isPowerOn = !isPowerOn;
} // turnOnOff
void volumeUp() {
if (volume < MAX_VOLUME) {
volume++;
}
} // volumeUp
void volumeDown() {
if (volume > MIN_VOLUME) {
volume--;
}
} // volumeDown
void channelUp() {
if (channel < MAX_CHANNEL) {
channel++;
} else if (channel == MAX_CHANNEL) {
channel = MIN_CHANNEL;
}
// 관계성을 생각한다면 이 코드가 올바른 방법 같다.
//if(channel == MAX_CHANNEL) {
// channel = MIN_CHANNEL;
//} else {
// channel++;
//}
} // channelUp
void channelDown() {
if (channel > MIN_CHANNEL) {
channel--;
} else if (channel == MIN_CHANNEL) {
channel = MAX_CHANNEL;
}
// 관계성을 생각한다면 이 코드가 올바른 방법 같다.
//if(channel == MIN_CHANNEL) {
// channel = MAX_CHANNEL;
//} else {
// channel--;
//}
} // channelDown
} // class MyTv
public class Ex04_Chapter6 {
public static void main(String[] args) {
MyTv t = new MyTv();
t.channel = 100;
t.volume = 0;
System.out.println("CH: " + t.channel + ", VOL: " + t.volume);
t.channelDown();
t.volumeDown();
System.out.println("CH: " + t.channel + ", VOL: " + t.volume);
t.volume = 100;
t.channelUp();
t.volumeUp();
System.out.println("CH: " + t.channel + ", VOL: " + t.volume);
t.channelUp();
System.out.println("CH: " + t.channel + ", VOL: " + t.volume);
t.channelDown();
System.out.println("CH: " + t.channel + ", VOL: " + t.volume);
}
}

6-20)
package example01;
import java.util.Arrays;
public class Ex04_Chapter6 {
public static int max(int[] data) {
if (data == null || data.length == 0) {
return -999999;
}
int max = data[0];
for (int i = 0; i < data.length; i++) {
if (max < data[i]) {
max = data[i];
}
}
return max;
}// max
public static void main(String[] args) {
int[] data = { 3, 2, 9, 4, 7 };
System.out.println(Arrays.toString(data));
System.out.println("최댓값: " + max(data));
System.out.println("최댓값: " + max(null));
System.out.println("최댓값: " + max(new int[] {}));
}
}

6-21)
package example01;
public class Ex04_Chapter6 {
public static int abs(int value) {
return Math.abs(value);
}
public static void main(String[] args) {
int value = 5;
System.out.println(value + "의 절대값 : " + abs(value));
value = -10;
System.out.println(value + "의 절대값 : " + abs(value));
}
}

나는 Math 클래스에 존재하는 abs메서드를 사용했는데 자바 해설지에서는 코드가 달라 공유한다.
package example01;
public class Ex04_Chapter6 {
public static int abs(int value) {
if (value >= 0) {
return value;
} else {
return -value;
}
}
public static void main(String[] args) {
int value = 5;
System.out.println(value + "의 절대값 : " + abs(value));
value = -10;
System.out.println(value + "의 절대값 : " + abs(value));
}
}
메서드를 사용하는 것이 아닌 value의 값이 0이상일 경우에는 그대로 value값을 반환하도록 하고
0보다 미만일 경우에는 -부호를 붙여 부호를 반대로(+) 바꿔주었다.
당연히 출력값은 동일하다.
.
.
.
+ 느낀점)
화요일(9/5)에 간단한 문제만 풀어보고
나머지 문제들은(코드를 작성해보는 문제) 오늘 (토요일, 9/9) 풀어봤는데
확실히 메서드를 직접 만들어보니까 개념이 조금씩 잡히는 것 같다.
꽤나 힘겨웠다.....
그리고 내가 하는 생각들보다 더 깊고 논리적인 사고력을 필요하다는 것을 느꼈다.
이렇게 해야지, 이렇게 작성하면 될 거 같은데? 라는 생각을 하면서 코드짜기에 급급한 것이 아닌
한번 더 생각해보고, 더 깊게, 더 논리적으로 접근하는 것을 습관화 해야겠다.