"스프링 입문을 위한 자바 객체 지향의 원리와 이해" 를 읽고 정리한 내용입니다.
객체 지향의 4대 특성 - 4) 캡슐화
캡슐화: 정보 은닉
자바에서 정보 은닉은 접근 제어자 (private, [default], protected, public)로 할 수 있다.
- private : 본인 클래스 내에서만 접근 가능
- default : 같은 패키지 내의 클래스에서 접근 가능
- protected : 상속 / 같은 패키지 내의 클래스에서 접근 가능
- public : 모두가 접근 가능
사실 접근 제어자는 위의 네 가지로 분류한 것만큼 단순하지 않다고 한다. 객체 멤버에 대한 접근인지, 정적 멤버에 대한 접근인지에 따라 생각할 것이 많아진다. 객체 메소드에서 정적 멤버나 정적 메소드에 접근하는 것은 가능하지만 정적 메소드에서 객체 멤버나 객체 메소드에 접근하는 것은 불가능하다. T 메모리 구조에서 봤듯이 객체 멤버와 객체 메소드는 객체가 생성되어야 만들어지기 때문이다.
저자는 아래의 두 가지를 꼭 기억하라고 강조했다.
- 상속을 받지 않았다면 객체 멤버는 객체를 생성한 후 객체 참조 변수를 이용해 접근해야 한다.
- 정적 멤버는 클래스명.정적멤버 형식으로 접근하는 것을 권장한다.
클래스명.정적멤버 형식을 권장하는 것은 메모리의 물리적 접근에 따른 이유도 있다. 아래 그림만 봐도 왜 객체참조변수명.정적멤버 형식보다 클래스명.정적멤버 형식으로 접근하는 것을 권장하는지 알 수 있다.
(사진 출처 - 티스토리)
참조 변수의 복사
기본 자료형 변수를 복사하는 경우 Call By Value (값에 의한 호출)에 의해 그 값이 복사되며 두 개의 변수는 서로에게 영향을 주지 않는다.
- CallByValue.java
public class CallByValue {
public static void main(String[] args) {
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
System.out.println(b); // 20
}
}
변수 a에 10을 대입한 후 변수 b에 a가 가진 값을 복사하고, 다시 변수 b에 20을 할당했다. a가 가진 값이 단순히 b에 복사된 것이고 a, b 변수는 서로 아무런 관계가 없다
- CallByReference.java
public class CallByReference {
public static void main(String[] args) {
Animal ref_a = new Animal();
Animal ref_b = ref_a;
ref_a.age = 10;
ref_b.age = 20;
System.out.println(ref_a.age); // 20
System.out.println(ref_b.age); // 20
}
}
class Animal {
public int age;
}
Call By Value 와 Call By Reference 사이 차이가 있는 것처럼 보이지만 둘은 본질적으로 차이가 없다. 다만 기본 자료형 변수는 저장하고 있는 값을 그 값 자체로 해석하고, 객체 참조 변수는 저장하고 있는 값을 주소로 해석한다는 것이다.
위의 예제에서 ref_a와 ref_b는 완전히 다른 변수다. 다만 같은 값을 갖고 있고 컴퓨터는 그 값을 주소로서 활용한다. 결국 두 변수가 같은 객체를 참조하고 있을 뿐이다. 그렇기 때문에 값에 의한 호출과 참조에 의한 호출은 본질적으로 차이가 없다.