어느덧 두번째 평가가 돌아왔다. 1주일에 한번 꼴로 보는데 심장이 쫄깃해진다.
오늘의 평가도 역시 두 가지로, 서술형이랑 문제해결 과목을 봤다.
1. 생성자(Constructor)의 정의와 생성자 특징(3가지 이상)에 대해 서술하시오
생성자는 암묵적 문법 중에 하나로 클래스 내부에 숨겨진 특이한 메서드이다. 인스턴스 생성 시, 멤버 필드의 초기값을 입력받는 용도로 사용되고 다음의 특징이 존재한다.
첫째, 기본적으로 생성자는 호출되는 시점이 이미 정해져 있다.
즉, 우리가 new
를 통해 객체를 생성할 때 뒤에 생성자 메서드가 이미 따라온다.
두번째, 생성자 메서드는 명시하지 않으면 기본값으로 자동 생성되어 있다. 그래서 클래스에 숨겨진 생성자 메서드를 명시하여 입력받을 초기값을 설정할 수 있다.
셋째, 기본 메서드 작성 방식과 동일하다. 다만 생성자의 이름은 클래스명과 동일해야 한다.
넷째, 생성자는 개발자가 초기 설정한 기본값을 덮어씌우는 것이다.
즉, 인스턴스 생성 시 먼저 개발자의 초기값이 먼저 적용되고 생성자를 사용할 시 그 값이 변경되는 것이다.
2. 배열의 정의를 서술하고, 주로 어떤 경우에 사용하는 문법인지 설명하세요
배열은 '동일한 자료형을 가진 변수들의 집합'으로 변수선언의 한계에서 시작된다. 예를 들어 100개의 변수를 선언해야할 때, 변수만 사용하면 stack에 100번의 변수 선언해줘야 한다.
이런 비효율을 극복하기 위해 배열을 사용한다. 따라서 이는 같은 자료형의 연속된 변수 공간이 되지만 실제 데이터를 저장해두는 위치는 변수와 다르다.
배열은 stack에 해당 배열의 자료형을 알려주는 참조변수를 선언하고 데이터가 적재될 공간은 heap에 생성하여 연결한 뒤, 참조변수와 인덱스(index)를 조합해 배열 내부의 데이터에 접근한다.
그리고 연속된 공간의 특성으로 인해 반복문을 사용한다.
주로 배열의 값을 for을 이용하여 출력하거나, 객체배열을 통해 여러 개의 인스턴스를 관리하기 쉽게 묶어주기도 한다.
3. Method Overloading에 대해 서술하세요..
메서드를 선언할 때, C에서는 동일명의 메서드를 생성하면 컴파일러가 구분을 하지 못했다.
하지만 자바에서는 이를 컴파일러가 '매개변수'의 수와 타입을 기준으로 구분해 자동으로 해당 메서드를 호출한다.
이는 메서드의 반환타입이 1개로 고정된다는 이유 때문에 동일기능이어도 반환타입이 다르면 다른 메서드를 생성해야했다.
그러면 같은 기능의 이름만 다름 메서드가 늘어나게 되고, 이는 가독성과 코드 유지보수, 개발의 관점에서 효율적이지 않다.
따라서 매개변수를 통해 호출시 컴파일러가 구분함으로서 위의 문제를 개선할 수 있다.
문제해결은 오류가 난 코드를 주고 그 원인과 해결방안 두 가지를 서술해야 했다.
[ 문제 ]
public class Employee {
private String emp_id;
private String emp_name;
private int wage;
public Employee() {}
public Employee(String emp_id, String emp_name, int wage) {
this.emp_id = emp_id;
this.emp_name = emp_name;
this.wage = wage;
}
public String getEmp_id() {
return emp_id;
}
public void setEmp_id(String emp_id) {
this.emp_id = emp_id;
}
public String getEmp_name() {
return emp_name;
}
public void setEmp_name(String emp_name) {
this.emp_name = emp_name;
}
public int getWage() {
return wage;
}
public void setWage(int wage) {
wage = wage; // 원인 1
}
}
public class Main {
public static void main(String[] args) {
Employee e1 = new Employee("1001", "Jane", 11000);
Employee e2 = new Employee();
e2.setEmp_id("1002");
e2.setEmp_name("Tom");
e2.setWage(9000);
Employee[] emps = new Employee[4]; // 원인 2
emps[0] = e1;
emps[1] = e2;
emps[2] = new Employee("1003", "Mike", "13000"); // 원인 3
System.out.println("ID\tNAME\tWAGE");
System.out.println("-----------------------");
for(int i = 0; i<emps.length; i++) {
System.out.println(emps[i].getEmpId() + "\t" + emps[i].getName() + "\t" + emps[i].getWage()); // 원인 4
}
}
}
1. 자기 참조 변수의 누락
클래스 Employee
에 wage
필드가 setter
로 입력 받을 때, 외부에서 입력받는 인자값을 저장하는 공간에 문제가 있다.
즉, this
로 해당 클래스 내의 멤버필드를 지정해주지 않았기 때문에 지역변수의 특성상 자신과 가까운 매개변수 int wage
에 들어온 값을 입력한다.
결국 자신한테 값이 입력되어 출력은 int형의 기본값 0
이 나온다.
2. 배열 길이 입력 오류 : Employee[] emps = new Employee[3];
해당 객체 배열에서 사용하는 객체는 3가지이다. 그리고 각 3가지에 3개의 멤버필드가 연결된 것을 출력하고자 한다.
하지만 배열의 길이를 4가지로 해서 반복문을 돌릴 때, 빈 배열을 만나게 되면서 NullPointerException
가 발생한다.
3. 명시 생성자 인자값 입력 오류
명시 생성자의 매개변수는 (String emp_id, String emp_name, int wage)
이다.
하지만 main()
의 emps[2] = new Employee("1003", "Mike", "13000");
"13000"
은 문자열이기 때문에 오류가 난다.
4. 메서드 명 입력 오류
자바 관습 표기는 카멜 케이스를 권장한다. 문제에선 Employee
클래스의 멤버필드를 스네이크 케이스로 선언해줬고, 막상 사용할 때는 getEmpId()
라는 카멜케이스를 입력하였다.
getName()
의 경우는 아예 멤버필드에 선언된 변수명과 맞지도 않는 메서드 명을 입력했다.
1. this
자기 참조변수 설정
public void setWage(int wage) {
this.wage = wage;
}
2. 배열 길이 변경
Employee[] emps = new Employee[4];
3. 자료형 변경
emps[2] = new Employee("1003", "Mike", 13000);
로 수정.
4. 메서드 명 수정
getEmpId() - getEmp_id()
getName() - getEmp_name()
평가를 보면서 점점 이해도가 높아지고 있음을 느낀다.
물론 재밌는 건 당연하고...ㅎ
앞으로 갈 길은 멀지만 그래도 꾸준히 공부하자.