Student student1; // 객체 참조를 위한 참조변수 - 객체의 주소가 여기에 담긴다.
student1 = new Student(); // 객체를 생성하면서, 참조변수에 인스턴스의 주소를 담는다.
많은 객체를 생성할 일이 있을 때 이것을 배열로 다룰 수 있다.
Student[] stuarr = new Student[5];
이 때, stuarr에는 아무것도 담기지 않았다. 클래스의 참조변수를 담을 '틀'만을 만들었을 뿐이다. 이를 해결하기 위해 아래처럼 객체를 일일이 생성해야한다. 물론 for문을 이용해도 된다.
stuarr[0] = new Student();
stuarr[1] = new Student();
...
stuarr[4] = new Student();
static을 붙여주면 된다. 클래스 변수는 모든 인스턴스가 공유하며, 클래스명.클래스변수명 형식으로 접근하여 사용 가능하다. 클래스가 메모리에 올라가는 순간 생성된다.반환타입 메서드이름 (매개변수){
//메서드 호출시 수행될 코드
}
같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만 static메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다.
매개변수의 유효성 검사
타입만 맞으면 어떤 값도 매개변수를 통해 넘어올 수 있기 떄문에, 가능한 모든 경우의 수에 대해 고민하고 이에 대비해야한다. 예를 들어 0으로 나누는 일이 발생하지 않도록 신경써주어야 한다.
프로그램 실행 중 클래스가 사용되면 클래스 데이터가 여기에 저장된다.
인스턴스가 생성되는 공간이다.
메서드가 호출되면 메서드의 작업에 필요한 메모리 공간이 이곳에 할당된다. 작업이 끝나면 할당된 메모리는 모두 반환되어 지워진다.
- 기본형 매개변수는 값을 읽기만 할 수 있다.
- 참조형 매개변수는 변수의 값을 읽고 변경할 수 있다.
하지만 메서드를 통해 매개변수의 값을 변경 할 떄 주의해야할 점이 있다. 바로 메서드를 정의할 때, 기본형 매개변수를 설정하면 변경이 불가능하다는 것이다. 따라서 참조형 매개변수 혹은 배열 자료형을 통해 변경하고자 하는 값의 주소를 넘길 수 있도록 하자.
C 언어에서도 이와 유사한 인사이트가 있다. 참고
참조형 매개변수를 이용하여 반환값, 즉 return문이 없더라도 메서드 실행결과를 받아올 수 있다.
반환타입을 참조형으로 정의함으로써, 메서드는 객체의 주소를 반환할 수 있다.
인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는 메서드다. 그리고 인스턴스 변수와 관계없는 메서드를 클래스 메서드로 정의한다.
- 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에
static을 붙여 클래스 변수로 정의한다.- 클래스 변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
- 클래스 메서드는 인스턴스 변수를 사용할 수 없다.
- 메서드 내에서 인스턴스 변수를 사용하지 않는다면,
static을 붙이는 것을 고려한다.
이 경우에도 클래스 멤버는 인스턴스 멤버를 참조하거나 호출할 수없다. 다만 클래스 멤버는 호출할 수 있다.
자바에서는 한 클래스 내에 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있더라도 매개변수의 개수 또는 타입이 다르면 같은 이름을 사용해서 메서드를 정의할 수 있다.
- 메서드 이름이 같다.
- 매개변수의 개수 또는 타입이 달라야한다.
public PrintStream printf(String format, Object... args)
여기서 주의해야하는 점은 가변인자를 사용한 메서드는 오버로딩 해선 안된다는 점이다. 왜냐하면 가변인자로 인해 매개변수의 개수를 구분할 길이 없어지기 때문이다.
생성자란 인스턴스 초기화 메서드다. 생성자의 조건은 다음과 같다.
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴 값이 없다.
단 연산자 new가 인스턴스를 생성하는 것이다. 생성자는 인스턴스 변수 초기화에 사용된다.
그런데 이상하다. 여태까지 별도로 생성자를 클래스 내에 정의한 적이 없는데 인스턴스를 생성해왔다. 왜냐하면 컴파일러가 기본 생성자를 제공하기 때문이다.
하지만 기본 생성자는 클래스에 정의된 생성자가 하나도 없을 때 뿐이므로 임의로 생성자를 정의했다면 이후 코드에서는 기본생성자를 작성하면 에러가 발생할 것이다.
본인이 직접 매개변수를 전달받는 생성자를 추가로 정의할 수 있다.
생성자 내에서 다른 생성자를 호출 할 수 있다. 하지만
- 생성자의 이름으로 this를 사용해야하며
- 한 생성자 내에서 다른 생성자를 호출할 떄, 반드시 첫 줄에서만 호출 할 수 있다.
그 밖에 Python 처럼 인스턴스 변수의 경우 this.instance_varialbe 형식으로 접근할 수 있다.
Car(Car c){
color = c.color;
gearType = c.gearType;
door = c.door;
}
Car 클래스의 생성자이나, Car c를 매개변수로 받으므로 다른 Car클래스 생성자와 구분된다. 즉 Car 클래스 인스턴스를 매개변수로 받아 새로운 Car클래스 인스턴스를 생성하는 것이다.
인스턴스를 생성할 때는 다음 2가지 사항을 결정해야한다.
- 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
- 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?
변수라는 것은 가능하면 선언과 동시에 적절한 값으로 초기화 하는 것이 바람직하다.
멤버변수는 초기화를 하지 않아도, 자료형에 맞는 기본값으로 초기화된다. 하지만, 지역변수는 사용하기 전에 반드시 초기화해야 한다.
멤버변수 초기화 방법
1. 명시적 초기화(explicit initialization)
2. 생성자(constructor)
3. 초기화 블럭
변수의 선언과 동시에 초기화하는 것을 명시적 초기화라고 한다. 간단하지만 복잡한 초기화 작업은 초기화 블럭 또는 생성자를 이용해야한다.
초기화 블럭은 두 가지로 나뉜다
- 클래스 초기화 블럭: 클래스 변수 초기화
- 인스턴스 초기화 블럭: 인스턴스 변수 초기화
{
count++;
instance_variable = count;
}
static{
count++;
class_variable = count;
}
클래스 초기화 블럭은 클래스가 메모리에 올라갈 때에 한 번 실행되고, 인스턴스 초기화 블럭은 인스턴스가 생성될 때마다 실행된다. 그리고 생성자보다 인스턴스 초기화 블럭이 먼저 수행된다.
기본값 - 명시적 초기화 - 클래스 초기화 블럭
기본값 - 명시적 초기화 - 인스턴스 초기화 블럭 - 생성자