객체지향개념을 학습할 때 재사용성, 유지보수, 중복된 코드의 제거 세 가지 관점에서 보면 쉽게 이해할 수 있다.
개념에 얽매여서 고민하기보다 프로그램을 기능적으로 완성한 다음 객체지향적으로 코드를 개선할 수 있을지를 고민.
객체 === 인스턴스
객체는 인스턴스를 포함하는 일반적인 의미
인스턴스화
클래스로부터 인스턴스를 생성하는 것
클래스: 데이터와 함수의 결합
변수(하나의 데이터를 저장할 수 있는 공간)
→ 배열(같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간)
→ 구조체(서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간)
→ 클래스(데이터와 함수의 결합. 구조체+함수)
| 변수의 종류 | 선언위치 | 생성시기 |
|---|---|---|
| 클래스변수 | 클래스영역 | 클래스가 메모리에 올라갈 때 |
| 인스턴스변수 | 클래스영역 | 인스턴스가 생성되었을 때 |
| 지역변수 | 클래스 영역 이외의 영역 | 변수 선언문이 수행되었을 때 |
class Variables{
int iv; // 인스턴스 변수
static int cv; // 클래스변수(static변수, 공유변수)
void method(){
int lv = 0; // 지역변수
}
}
지역변수에는 static을 붙일 수 없다.
인스턴스변수는 인스턴스가 생성될 때마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스변수는 모든 인스턴스가 하나의 저장공간을 공유하므로 항상 공통된 값을 갖는다.

인자의 타입은 매개변수의 타입과 일치하거나 자동 형변환이 가능한 것이어야 한다.
*호출스택의 특징

모든 참조형 타입의 값은 ‘객체의 주소'이다.
반환타입이 ‘참조형'이라는 것은 메서드가 ‘객체의 주소'를 반환한다는 것을 의미한다.
매개변수의 타입이 기본형.
매개변수에 값을 복사해서 넘겨준다.

매개변수의 타입이 참조형.
인스턴스의 주소가 복사된다.

재귀호출이란?
메서드의 작업에 인스턴스변수를 사용하면 인스턴스메서드, 사용하지 않으면 클래스메서드이다.
인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.
인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드로 정의한다.
*멤버변수: 클래스 영역에 선언된 변수를 멤버변수라 한다. 멤버변수는 인스턴스변수와 static변수를 모두 통칭하는 말로 멤버변수 중에 staic이 붙은 것은 클래스변수, 붙지 않은 것은 인스턴스변수라 한다.
같은 클래스의 멤버간에는 객체생성이나 참조변수 없이 참조할 수 있다. 그러나 static멤버들은 인스턴스 멤버들을 참조할 수 없다. 281page 참고
메서드의 호출
class TestClass{
void instanceMethod() {} // 인스턴스 메소드
static void staticMethod() {} // static(클래스) 메소드
void instanceMethod2() { // 인스턴스 메서드
instanceMethod(); // 다른 인스턴스메서드를 호출한다. ok
staticMethod(); // static메서드를 호출한다. ok
}
static void statieMethod2() { // static 메서드
instanceMethod(); // 인스턴스 메서드를 호출할 수 없다. err
staticMethod(); // static메서드는 호출할 수 있다. ok
}
}
변수의 접근
class TestClass2{
int iv; // 인스턴스 변수
static int cv; // static(클래스) 변수
void instanceMethod() { // 인스턴스 메서드
System.out.println(iv); // 인스턴스변수를 사용할 수 있다.
System.out.println(cv); // 클래스변수를 사용할 수 있다.
}
static void statieMethod() { // static 메서드
System.out.println(iv); // 인스턴스변수를 사용할 수 없다. err
System.out.println(cv); // 클래스변수를 사용할 수 있다.
}
}
*같은 클래스 내에서 클래스멤버가 인스턴스멤버를 참조 또는 호출해야 하는 경우는 드무므로 그런 경우가 발생한다면, 인스턴스메서드로 작성해랴할 메서드를 클래스메서드로 한 것은 아닌지 한 번 더 생각해봐야 한다.
⭐️알아두면 좋은것
MemberCall c = new MemberCall();
int result = c.method();
// 위 두줄을
int result = new MemberCall().method();
// 한 줄로 줄일 수 있다.
하나의 클래스에 같은 이름의 메서드를 여러 개 정의하는 것을 메서드 오버로딩, 간단히 오버로딩이라고 한다.
✅ 가능하면 가변인자를 사용한메서드는 오버로딩하지 않는것이 좋다.
메서드의 매개변수 개수가 고정적이아닌 동적으로 지정해 줄 수 있게 된 기능을 ‘가변인자’라고 한다.
‘타입… 변수명'과 같은형식으로 선언한다.
가변인자를 매개변수 중에서 제일 마지막에 선언한다. 그렇지 않으면 가변이자인지 아닌지를 구분할 방법이 없어 컴파일 에러가 발생한다.
*인스턴스 초기화 - 인스턴스 변수에 적절한 값을 저장한는 것.
Card c = new Card();
연산자 new에 의해 메모리(heap)에 Card클래스의 인스턴스가 생성된다.
참조변수 c가 선언되고 연산자 new에 의해 Card인스턴스가 생성된다
생성자 Card()가 호출되어 수행된다.
인스턴스의 생성이 생성자가 아닌 new 연산자에의해 생성된다.
연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것은 아니다.
연산자 new의 결과로, 생성된 Card인스턴스의 주소가 반환되어 참조변수 c에 저장된다.
💙 모든 클래스에는 반드시 하나 이상의 생성자가 있어야 한다.
양쪽 코드 모두 같은 내용이지만, 오른쪽의 코드가 더 간결하고 직관적이다.
클래스를 작성할 때 다양한 생성자를 제공함으로써 인스턴스 생성 후에 별도로 초기화를 하지 않아도 되도록 하는 것이 바람직하다.
class Car{
String color;
String gearType;
int door;
Car() {}
}
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;
class Car{
String color;
String gearType;
int door;
Car(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
}
Car c = new Car("white", "auto", 4);
this(): 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다. 다른 생성자 호출은 생성자의 첫 문장에서만 가능하다.
this: 인스턴스 자신을 가르키는 참조변수. 인스턴스의 주소가 저장되어있다. 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재한다.
생성자의 매개변수로 선언된 변수의 이름과 인스턴스변수 이름이 구분 되지 않을 경우 인스턴스 변수 앞에 ‘this’를 사용하면 된다.
this.color는 인스턴스변수, color는 생성자의 매개변수로 정의된 지역변수로 서로 구별이 가능하다.
Car(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
Car(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.
두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수가 동일한 값을 갖고 있다는 것을 뜻한다.
복사하여 생성된 인스턴스는 서로 같은 상태를 갖지만, 서로 독립적으로 메모리공간에 존재하는 별도의 인스턴스이므로 값들이 변경되어도 서로에게 영향을 받지 않는다.
⭐️인스턴스를 생성할 때는 다음의 2가지 사항을 결정해야한다.
| 자료형 | 기본값 |
|---|---|
| boolean | false |
| char | ‘\u0000’ |
| byte | 0 |
| short | 0 |
| int | 0 |
| long | 0L |
| float | 0.0f |
| double | 0.0d 또는 0.0 |
| 참조형 변수 | null |
명시적 초기화(explicit initialization)
class Car {
int door = 4; // 기본형 변수의 초기화
Engine e = new Engine(); // 참조형 변수의 초기화
}
생성자(constructor)
Car(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
초기화 블럭(initialization block)
클래스변수 초기화 시점: 클래스가 처음 로딩될 때 단 한번
클래스변수의 초기화 순서: 기본값 → 명시적 초기화 → 클래스 초기화블럭
인스턴스변수 초기화 시점: 인스턴스가 생성될 때 마다
인스턴스변수 초기화 순서: 기본값 → 명시적 초기화 → 인스턴스 초기화블럭 → 생성자