제한자(modifier)
클래스,변수,메서드 선언부에 함께 사용되어 부가적인 의미 부여
접근 제한자: public, protected,(default = package),private
그 외 제한자: static, final, abstract, synchronized
→ final : 마지막, 더 이상 바뀔 수 없음
용도
- **final class - 상속 금지 → 오버라이드 방지**
- **final method - 더 이상 재정의 할 수 없음: overriding 금지**
- **final variable - 더 이상 값을 바꿀 수 없음: 상수화**
멤버 등에 사용되며 해당 요소를 외부에서 사용할 수 있는지 설정
예제 코드
접근 제한자는 부모의 제한자 범위와 같거나 넓은 범위로만 사용 가능하다
class Parent{
protected void method() {}
}
public class OverrideRule extends Parent{
@Override
void method() {} //접근 제한자 설정 안 해주면 default -> 에러 (default < protected)
protected void method() {}
public void method() {}
}
package accessex1;
import accessex2.AccessEx3;
import accessex2.AccessEx4;
public class AccessEx1 extends AccessEx4{
private int x=10;
private int y=20;
public static void main(String[] args) {
AccessEx1 ob1=new AccessEx1();
System.out.println(ob1.x+" "+ob1.y);
System.out.println(ob1.xx+" "+ob1.yy);
AccessEx2 ob2=new AccessEx2();
System.out.println(ob2.x+" "+ob2.y);
AccessEx3 ob3=new AccessEx3();
System.out.println(ob3.x+" "+ob3.y);
}
}
//test1
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The field AccessEx2.x is not visible
The field AccessEx2.y is not visible
//test2
10 20
10000 20000
100 200
1000 2000
AccessEx2.java
//test1
package accessex1;
public class AccessEx2 {
private int x=100;
private int y=200;
}
AccessEx2.java
//test2
package accessex1;
public class AccessEx2 {
int x=100;
int y=200;
(default)
}
default가 되므로 protectd, public은 자동
보통 private과 public을 사용하자 protected 는 상속관계만 생각하자
외부에서 변수에 직접 접근하기 때문에 정보를 보호하기 위한 대책이 필요
여러 개의 객체가 필요 없는 경우
Singleton 디자인 패턴
Singleton의 목표: 각각의 객체들이 하나의 메모리 공간에 모아서 관리하자!
예제 코드 1
public class Speaker1 extends Object{
private int volume;
public Speaker1() {
this.volume = 5;
}
public int getVolume() {
return volume;
}
public void setVolume(int volume) {
this.volume = volume;
}
// @Override
// public String toString() {
// return "볼륨: " + volume;
// }
}
//일반 객체
public class Main1 {
public static void main(String[] args) {
Speaker1 s1=new Speaker1();
Speaker1 s2=new Speaker1();
Speaker1 s3=new Speaker1();
System.out.println(s1); //or s1.toString()
System.out.println(s2);
System.out.println(s3);
s1.setVolume(10);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
s2.setVolume(20);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
}
}
1번 케이스에서 s1과 s2와 s3는 각각 다른 객체이므로 다른 주소값을 가지고 있다 → Singleton x
예제 코드 2
public class Speaker2 {
//자기 자신의 클래스 객체 private static 선언
//클래스 객체 하나가지고 다 돌려막기 할 거니까
private static Speaker2 speaker;
private int volume;
//생성자를 private걸어서 외부에서 바로 생성 못하도록
private Speaker2() {
volume=5;
}
//Singleton 방식에서 객체 초기화 하는 방법
public static Speaker2 getInstance() {
//자기 자신의 객체가 없으면 새로 생성
if(speaker==null) {
speaker=new Speaker2();//여기서 객체 생성
}
//자신의 객체가 있다면 자신의 객체 반환
return speaker;
}
public int getVolume() {
return volume;
}
public void setVolume(int volume) {
this.volume = volume;
}
}
public class Main2 {
public static void main(String[] args) {
Speaker2 s1 = Speaker2.getInstance();
Speaker2 s2 = Speaker2.getInstance();
Speaker2 s3 = Speaker2.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s2.getVolume());
s1.setVolume(10);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
s2.setVolume(20);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
}
}
2번 case 에서 s1,s2,s3 는 모두 하나의 객체 주소를 가지고 있다. static으로 main 실행전에 메서드 영역에 올라와 있음
예제 코드 3번
public class Speaker3 {
private static Speaker3 speaker=new Speaker3();
private int volume;
private Speaker3() {
volume=5;
}
public static Speaker3 getInstance() {
return speaker;
}
public int getVolume() {
return volume;
}
public void setVolume(int volume) {
this.volume = volume;
}
}
public class Main3 {
public static void main(String[] args) {
Speaker3 s1 = Speaker3.getInstance();
Speaker3 s2 = Speaker3.getInstance();
Speaker3 s3 = Speaker3.getInstance();
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s2.getVolume());
s1.setVolume(10);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
s2.setVolume(20);
System.out.println(s1.getVolume());
System.out.println(s2.getVolume());
System.out.println(s3.getVolume());
}
2번과 내용은 동일하다