main 메서드를 가지지 않는 대부분의 클래스들은 외부 클래스에서 이용할 목적으로 설계된 라이브러리 클래스이다.
라이브러리 클래스를 설계할 때는 외부 클래스에 접근할 수 있는 멤버와 접근할 수 없는 멤버로 구분해서, 필드, 생성자, 메서드를 설계한다.
멤버들은 객체 자신들만의 속성이자 특징이므로 대외적으로 공개되는 것이 결코 좋은 것은 아니다.그런 이유로 프로그래머가 객체의 멤버들에게 접근 제한을 걸 수가 있는데 자바에서는 이를 접근 제한자라 한다.
항상 은닉화를 전제로 한다. 관련이 있는 데이터 그리고 동작들을 하나로 묶어 요약하고 사용자에게는 내부적인 접근을 허용하지 않는 대신에 사용의 편의성을 제공해 주는 것이다.
interface는 다중 상속을 위해 만드는데, 보통 2가지 방식으로 설계한다. 하나는 여러 class에서 공통적으로 사용하기 위한 상수 위주로 만들거나, 메서드 위주로 만든다. 인터페이스는 접근 제한자 없이 만들어지는데, 기본적으로 public 이다. 여러 클래스에서 사용하기 위해서 인터페이스를 만들어도 되고, 상수(Constant) 클래스를 만들어도 된다. 본인의 선택.
추상화 클래스를 만드는 이유는 추상화 메서드를 만들기 위해서이다. 추상화 클래스를 상속하는 자식 클래스는 추상화 메서드를 자신의 입맛대로 수정할 수 있다.
public, protected, default, private 순서로 접근 제한이 강화.
| 접근 제한자 | 적용 대상 | 접근 가능 대상 | 접근 불가 대상 |
|---|---|---|---|
| public | 클래스, 필드, 생성자, 메서드 | 모든 대상 | 없음 |
| protected | 필드, 생성자, 메서드 | 같은 패키지 또는 자식 클래스 | 자식 클래스가 아닌 다른 패키지에 소속된 클래스 |
| default | 클래스, 필드, 생성자, 메서드 | 같은 패키지에 소속된 클래스 | 다른 패키지에 소속된 클래스 |
| private | 필드, 생성자, 메서드 | 클래스 내부 | 클래스 외부 |
클래스를 선언 시 같은 패키지 내에서만 사용할 것인지, 다른 패키지에서도 사용할 수 있도록 할 것인지 결정한다.
클래스에 적용할 수 있는 접근 제한: public, default
// default 접근 제한
class 클래스 { . . . }
// public 접근 제한
public class 클래스 { . . . }
클래스 선언 시 public 을 생략한다면 default 접근 제한을 가진다.
같은 패키지에서는 아무런 제한 없이 사용, 다른 패키지에서는 사용 불가.
클래스 선언 시 public 접근 제한자를 붙이면 public 접근 제한을 가진다.
같은 패키지 뿐만 아니라 다른 패키지에서도 아무런 제한 없이 사용 가능.
다른 개발자가 클래스를 사용하도록 라이브러리 클래스로 개발 시, public 접근 제한을 갖도록 한다.
A.java
package com.example.package1;
Class A { } // default 접근 제한
B.java
package com.example.package1;
publcic Class B { // public 접근 제한
A a; // A 클래스 접근 가능(같은 패키지), 필드로 선언할 수 있다.
}
C.java
package com.example.package2; // 다른 패키지
import com.example.package1.*; // package1 import
public class C {
A a; // A 클래스 접근 불가 (컴파일 에러)
B b; // B 클래스 접근 가능
}
C클래스는 A클래스와 다른 패키지 이므로
default 접근 제한 A클래스에 접근 불가, public 접근 제한 B클래스 접근 가능
C클래스에서 B클래스를 이용한 필드 선언 및 생성자 / 메서드 내부에서 변수 선언 가능
public class ClassName {
// public 접근 제한 생성자
public ClassName( . . . ) { . . . }
// protected 접근 제한 생성자
protected ClassName( . . . ) { . . . }
// default 접근 재한 생성자
ClassName( . . . ) { . . . }
// private 접근 제한 생성자
private ClassName( . . . ) { . . . }
}
객체를 생성하기 위해 new 연산자로 생성자를 호출해야 한다.
생성자가 어떤 접근 제한을 갖느냐에 따라 호출 가능 여부가 달라진다.
생성자에 적용할 수 있는 접근 제한: public, protected, default, private
클래스에 생성자를 선언하지 않으면, 컴파일러에 의해 기본 생성자가 추가된다.
자동으로 생성되는 기본 생성자의 접근 제한은 클래스의 접근 제한과 동일하다.(public, default)
public class ClassName이라면 public ClassName() {} 기본 생성자가 자동 생성되고,
class ClassName이라면 ClassName() {} 기본 생성자(default 접근 제한자)가 자동 생성된다.
| 접근 제한자 | 생성자 | 설명 |
|---|---|---|
| public | 클래스( . . . ) | 모든 패키지에서 제한 없이 생성자 호출 가능. 생성자가 public 접근 제한이면, 클래스도 public 접근 제한을 가지는 것이 정상적. 클래스가 default 접근 제한 가질 때, 클래스 사용 패키지로 한정되므로 생성자가 public 접근 제한을 가지더라도 같은 패키지 내에서만 호출 가능. |
| protected | 클래스( . . . ) | default 접근 제한과 마찬가지로, 같은 패키지에 속하는 클래스에서 생성자 호출 가능. 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 생성자를 호출할 수 있다. |
| default | 클래스( . . . ) | 생성자를 선언할 때 public/private 생략 시 default 접근 제한을 가진다. 같은 패키지 내에서 아무런 제한 없이 생성자 호출 가능. 다른 패키지에서는 생성자를 호출할 수 없다. |
| private | 클래스( . . . ) | 동일 패키지, 다른 패키지 상관 없이 생성자를 호출 할 수 없다. 클래스 외부에서 new 연산자로 객체 생성 불가. 오로지 클래스 내부에서만 생성자 호출할 수 있고, 객체를 만들 수 있다. |
A.java(클래스 내부)
package com.example.xmlparsingtest.package1;
public class A {
A a1 = new A(true); // 가능(클래스 내부)
A a2 = new A(1); // 가능(클래스 내부)
A a3 = new A("문자열"); // 가능(클래스 내부)
public A(boolean b) {} // public 접근 제한
A(int b) {} // default // default 접근 제한
private A(String S) {} // private 접근 제한
}
클래스 내부에서는 A의 모든 생성자 호출 가능.
B.java(같은 패키지, 다른 클래스)
package com.example.xmlparsingtest.package1; // A와 동일 패키지
public class B {
// 필드
A a1 = new A(true); // 가능(A 클래스의 public 생성자)
A a2 = new A(1); // 가능 (A 클래스의 default 생성자, 같은 패키지)
A a3 = new A("문자열"); // 불가능: private 생성자 이기 때문에 컴파일 에러
}
C.java(다른 패키지, 다른 클래스)
package com.example.xmlparsingtest.package2; // 다른 패키지
import com.example.xmlparsingtest.package1.A; // package1 import
public class C {
// 필드
A a1 = new A(true); // 가능(A의 default 생성자 접근 가능)
A a2 = new A(1); // 다른 패키지라서 컴파일 에러(dafualt 생성자)
A a3 = new A("문자열"); // 다른 패키지라서 컴파일 에러(private 생성자)
}
클래스 내부에서만 사용할 것인지, 패키지 내에서만 사용할 것인지, 다른 패키지에서도 사용할 것인지 결정.
필드와 메서드가 어떤 접근 제한을 갖느냐에 따라 결정된다.
필드, 메서드에 적용할 수 있는 접근 제한: public, protected, default, private
// 필드 선언
[ public | protected | private ] [static] 타입 필드;
// 메서드 선언
[ public | protected | private ] [static] 리턴타입 메서드( . . . ) { . . . }
| 접근 제한자 | 필드/매서드 | 설명 |
|---|---|---|
| public | 필드 메서드(...) | 모든 패키지에서 아무 제한 없이 필드, 메서드 사용 가능.필드, 메서드가 public 접근 제한이면, 클래스도 public 접근 제한을 가져야 한다. 클래스가 default 접근 제한이라면, 같은 패키지 안에서만 클래스가 사용되기 때문이다. |
| protected | 필드 메서드(...) | default 접근 제한과 마찬가지로, 같은 패키지에 속하는 클래스에서 필드, 메서드 사용 가능. 다른 패키지에 속한 클래스가 해당 클래스의 자식 클래스라면 필드와 메서드를 사용할 수 있다. |
| default | 필드 메서드(...) | public/private 생략 시 default 접근 제한을 가진다. 같은 패키지에서만 필드, 메서드 사용 가능. 다른 패키지에서는 필드, 메서드 사용 불가. |
| private | 필드 메서드(...) | 동일 패키지, 다른 패키지 간에 필드와 메서드 사용 불가. 클래스 내부에서만 사용 가능. |
A.java
package com.example.xmlparsingtest.package1;
public class A {
// 필드
public int field1; // public 접근 제한 필드
int field2; // default 접근 제한 필드
private int field3; // private 접근 제한 필드
// 생성자
public A() {
field1 = 1; // 가능(클래스 내부 필드)
field2 = 2; // 가능(클래스 내부 필드)
field3 = 3; // 가능(클래스 내부 필드)
method1(); // 가능(클래스 내부 메서드)
method2(); // 가능(클래스 내부 메서드)
method3(); // 가능(클래스 내부 메서드)
}
// 메서드
public void method1() {} // public 접근 제한 메서드
void method2() {} // default 접근 제한 메서드
private void method3() {} // private 접근 제한 메서드
}
B.java
package com.example.xmlparsingtest.package1;
public class B { // public
// 생성자
public B() {
A a = new A(); // A 클래스 접근 가능(public)
a.field1 = 1; // 가능: A 클래스의 public 필드 접근 가능
a.field2 = 2; // 가능: A 클래스의 default 필드 접근 가능(같은 패키지)
a.field3 = 3; // 불가능(컴파일 에러): A 클래스의 private 필드 접근 불가
a.method1(); // 가능: A 클래스의 public 메서드 접근 가능
a.method2(); // 가능: A 클래스의 default 메서드 접근 가능(같은 패키지)
a.method3(); // 불가능(컴파일 에러): A 클래스의 private 메서드 접근 불가
}
}
C.java
package com.example.xmlparsingtest.package2; // A, B 클래스와 다른 패키지
import com.example.xmlparsingtest.package1.A; // import A 클래스
public class C {
// 생성자
public C() {
A a = new A(); // a 객체 생성, A 클래스 접근 가능
a.field1 = 1; // 가능: public 필드 접근 가능
a.field2 = 2; // 불가능: default 필드 접근 불가(컴파일 에러)
a.field3 = 3; // 불가능: private 필드 접근 불가(컴파일 에러)
a.method1(); // 가능: public 메서드 접근 가능
a.method2(); // 불가능: default 메서드 접근 불가(컴파일 에러)
a.method3(); // 불가능: private 메서드 접근 불가(컴파일 에러)
}
}
일단 static 객체에서 static 이 아닌 객체를 호출 하는것은 불가능 하다.
static 이 먼저 정의가 되기 때문에 아직 정의되지 않은 객체는 호출할 수 없기 때문이다.