제어자
제어자란?
- 클래스, 변수, 메소드의 선언부에 사용되어 부가적인 의미를 부여한다.
- 하나의 대상에 여러 개의 제어자를 조합해 사용할 수 있으나, 접근 제어자는 단 하나만 사용할 수 있다.
- 접근 제어자 : public, protected, default, private
- 그 외 제어자 : static, final, abstract, native, transient, synchronized, volatile, strictfp
static
- 멤버변수, 메소드, 초기화 블럭에 사용될 수 있다.
- 인스턴스를 생성하지 않고도 호출이 가능한 변수, 메소드로 만들어준다.
final
- 클래스, 메소드, 멤버변수, 지역변수에 사용될 수 있다.
- 변경할 수 없도록 만든다. (변수는 상수로, 클래스는 상속 불가능하도록, 메소드는 오버라이딩될 수 없도록 한다.)
* 인스턴스 변수의 경우, final이 붙어도 선언과 동시에 초기화하지 않고 생성자에서 초기화할 수 있다.
class Card {
final int NUMBER;
final String KIND; // 상수지만 멤버변수이므로 생성자에서 초기화할 수 있다.
Card(String kind, int num){
KIND = kind;
NUMBER = num;
}
}
abstract
- 클래스, 메소드에 사용될 수 있다.
- 클래스에 사용된 경우, 클래스 내에 추상 메소드가 선언되어 있는 추상 클래스임을 의미한다.
- 메소드에 사용된 경우, 구현부가 작성되지 않은 추상 메소드임을 의미한다.
접근 제어자
private | 같은 클래스 내에서만 접근이 가능하다. |
default | 같은 패키지 내에서만 접근이 가능하다. |
protected | 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근이 가능하다. |
public | 접근 제한이 전혀 없다. |
- 클래스에는 public과 default, 메소드에는 모두 사용할 수 있다.
- 외부로부터 데이터를 보호하기 위해, 그리고 외부에는 불필요한 부분을 감추기 위해 사용한다. (캡슐화)
- 캡슐화 : 클래스 내부의 멤버를 외부로부터 직접 접근하지 못하도록 감추고, 해당 클래스에 선언된 메소드를 통해서만 접근할 수 있도록 하는 것.
* 생성자의 접근 제어자
- 일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 일치하나, 생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
final class Singleton {
private static Singleton s = new Singleton();
private Singleton(){ // 생성자
//...
}
public static Singleton getInstance(){
if(s==null){
s = new Singleton();
return s;
}
// ...
}
class SingletonTest{
public static void main(String args[]){
// Singleton s = new Singleton(); -> 접근 제어자로 인해 에러 발생
Singleton s = Singleton.getInstance();
}
}
다형성 (Polymorphism)
다형성이란?
- 하나의 참조변수로 여러 타입의 객체를 참조할 수 있는 것.
- 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것. (반대는 불가능)
class Tv{
boolean power;
int channel;
}
class CaptionTv extends Tv{
String text;
}
class test{
public static void main(String argv[]){
CaptionTv c = new CaptionTv();
// CaptionTv 클래스의 모든 멤버(power, channel, text)에 접근 가능
Tv t = new CaptionTv();
// 부모 타입의 참조변수로 자손 타입의 객체를 다룰 수 있음
// Tv 클래스에 정의된 멤버(power, channel)에만 접근 가능
// CaptionTv c2 = new Tv(); 는 불가
}
}
참조변수의 형변환
- 서로 상속관계에 있는 타입 간의 형변환만 가능하다.
- 자손 타입에서 조상 타입으로 형변환 하는 경우엔 형변환을 생략할 수 있다.
class Car{
String color;
int door;
}
class FireEngine extends Car{
void water(){
// ...
}
}
class test{
public static void main(String args[]){
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
car = fe; // 자손 -> 조상으로 형변환 (Up-casting)
fe2 = (FireEngine)car; // 조상 -> 자손으로 형변환 (Down-casting)
// car.water(); -> 에러 발생. car 참조변수로는 자손 클래스의 멤버에 접근 불가.
fe2.water();
}
}
instanceof 연산자
- 참조변수가 참조하는 인스턴스의 실제 타입을 확인하는 데 사용한다.
- 결과값이 true이면 해당 타입으로 형변환이 가능하다.
class test{
public static void main(String args[]){
FireEngine fe = new FireEngine();
if(fe instanceof FireEngine){
// true.
}
if(fe instanceof Car){
// true.
}
if(fe instanceof Object){
// true.
}
}
}
참조변수와 인스턴스변수의 연결
- 멤버변수가 중복정의된 경우, 참조변수의 타입에 따라 연결되는 멤버변수가 달라진다.
- 메소드가 중복정의된 경우, 참조변수의 타입에 관계없이 항상 실제 인스턴스의 타입에 정의된 메소드가 호출된다.
class Parent{
int x = 100;
void method(){
System.out.println("Parent");
}
}
class Child extends Parent{
int x = 200;
void method(){
System.out.println("Child");
}
}
class test{
public static void main(String args[]){
Parent p = new Child();
Child c = new Child();
System.out.println(p.x); // 100
System.out.println(c.x); // 200
// 멤버변수는 참조변수의 타입에 영향을 받는다.
p.method(); // "Child"
c.method(); // "Child"
// 메소드는 참조변수의 타입에 관계없이 생성된 인스턴스에 정의된 메소드를 호출한다.
}
}
매개변수의 다형성
- 참조형 매개변수는 메소드 호출 시, 자신과 같은 타입 또는 자손 타입의 인스턴스를 넘겨줄 수 있다.
class Product {
int price;
int bonusPoint;
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}
class Buyer {
int money = 1000;
int bonusPoint = 0;
void buy(Product p){
money -= p.price;
bonusPoint +=p.bonusPoint;
}
}
class test{
public static void main(String args[]){
Buyer b = new Buyer();
Tv tv = new Tv();
Computer com = new Computer();
b.buy(tv);
b.buy(computer);
// buy 메소드의 매개변수로는 Product의 참조변수를 취하나,
// Product의 자손 클래스인 Tv나 Computer의 참조변수도 넘겨줄 수 있다.
}
}
여러 종류의 객체를 하나의 배열로 다루기
- 조상 타입의 참조변수에 자손 타입의 객체를 다룰 수 있음을 이용하여, 조상 타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
Vector 클래스
- 모든 종류의 객체들을 저장할 수 있는 클래스
Vector() | 10개의 객체를 저장할 수 있는 Vector 인스턴스를 생성한다. 10개 이상의 인스턴스가 저장되면 자동적으로 크기가 증가된다. |
boolean add(Object o) | Vector에 객체를 추가한다. 추가에 성공하면 true, 실패하면 false를 반환한다. |
boolean remove(Object o) | Vector에 저장되어 있는 객체를 제거한다. 제거에 성공하면 true, 실패하면 false를 반환한다. |
boolean isEmpty() | Vector가 비어있는지 검사한다. |
Object get(int index) | 지정된 위치의 객체를 반환한다. |
int size() | Vector에 저장된 객체의 개수를 반환한다. |
Vector cart = new Vector();
void buy(Product p){
cart.add(p);
}
'개발일기 > Java' 카테고리의 다른 글
[Java] 정규 표현식 정리 (0) | 2025.05.03 |
---|---|
[Java] Java의 정석 (7) 객체지향개념 4 (0) | 2025.03.19 |
[Java] Java의 정석 (5) 객체지향개념 2 (0) | 2025.03.04 |
[Java] Java의 정석 (4) 객체지향개념 1 (0) | 2025.03.04 |
[Java] Java의 정석 (3) 배열 (0) | 2025.03.04 |