페이지

2015. 1. 12.

[JAVA] Day6.제어자(modifiers)

4. 제어자(modifiers)


4.1 제어자란?


 - 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여한다.
 - 제어자는 크게 접근 제어자와 그 외의 제어자로 나뉜다.
 - 하나의 대상에 여러 개의 제어자를 조합해서 사용할 수 있으나, 접근제어자는 단 하나만 사용할 수 있다.




4.2 static  (클래스의, 공통적인)


static은 시작부터 끝까지 고정되어 있는 메모리기이기 떄문에 적당히?? 사용해야한다..

static이 사용될 수 있는 곳 : 맴버변수, 메서드, 초기화 블록

맴버변수

 - 모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다.
 - 클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다.
 - 클래스가 메모리에 로드될 때 생성된다.

메서드

 - 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
 - static메서드 내에서는 인스턴스맴버들을 직접 사용할 수 없다.





4.3 final (마지막의, 변경될 수 없는)


상수처럼 만들어 버림!!
보통 상수의 이름은 모두 대문자로 하는 것이 관례

final이 사용 될 수 있는 곳 : 클래스, 메서드 , 맴버변수, 지역변수

클래스

 - 변경될 수 없는 클래스, 확장 될 수 없는 클래스가 된다.(상속 불가능)
 - 대표적인 final클래스로는 String과 Math가 있다.

final class A
{
}

class B extends A // 상속 불가능~!
{
}

메서드

 - 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.(오버라이딩 불가능)
class A
{
    final void add()//재정의 불가능
    {}
}

맴버변수, 지역변수

 - 변수 앞에 final을 붙이면, 값을 변경할 수 없는 상수가 된다.





class Test
{
    public static void main(String[] args)
    {
        final double PI = 3.141592;    //final을 사용하여 상수로 만들어 버림!!
        PI = 99.9;    //할당 불가능!!
        System.out.println(a);
    }
}









4.4 생성자를 이용한 final 맴버변수 초기화


 - final이 붙은 변수는 상수이므로 보통은 선언과 초기화를 동시에 하지만, 인스턴스변수의 경우 생성자에서 초기화 할 수 있다.

인스턴스 변수가 초기화 되지 않았을때 명시적으로....

class A
{
    final int x = 10;    //초기화
    A(int x)
    {
        this.x = x;    //명시적으로 초기화를 1회 하였기때문에 수정 불가능
    }
}



class A
{
    final int x;    //초기화 하지 않고 선언만 한경우
    A(int x)
    {
        this.x = x;
    }
}
class Test
{
    public static void main(String[] args)
    {
        A a1 = new A(100);    //수정 가능
        System.out.println(a1.x);
    }
}






4.5 abstract (추상의, 미완성의)


미완성이란? 선언부만 존재하고 구현부가 없는것!
추상클래스는 객체를 생성할 수 없당.

abstract가 사용될 수 있는 곳 : 클래스, 메서드(주로 메서드에서 사용됨)

클래스

 - 클래스 내에 추상메서드가 선언되어 있음을 의미한다.

메서드

 - 선언부만 작성하고 구현부는 작성하지 않은 추상메서드임을 알린다.






참고
 - 추상메서드가 없는 클래스도 abstract를 붙여서 추상클래스로 선언하는 것이 가능하기는 하지만 그렇게 해야 할 이유는 없다.
 - 추상클래스를 상속을 받는다면 무조건!! 오버라이딩을 해야한다.(추상 메서드 모두를 오버라이딩)
 - 오버라이딩 하지 않으면 그 클래스 역시 추상클래스가 됨

abstract class A
{
    /*
    void add()    //선언부
    {        //구현부 : {}블록 자체가 구현부의 완성임
    }        //아무일도 하지 않는 구현부
    */
    abstract void add();    //선언부
}



추상클래스를 상속을 받는다면 무조건!! 오버라이딩을 해야한다.(추상 메서드 모두를 오버라이딩)
오버라이딩 하지 않으면 그 클래스 역시 추상클래스가 됨

abstract class A
{
    abstract void add();    //선언부
}
class B extends A
{
    void add()    //오버라이딩
    {
    }
}








4.6 접근 제어자(access modifier)

거의 private, public만 사용됨

 - 맴버 또는 클래스에 사용되어, 외부로 부터의 접근을 제한한다.
 - private : 같은 클래스 내에서만 접근 가능.
 - default : 같은 패키지 내에서만 접근 가능.
 - protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근 가능
 - public : 접근 제한이 전혀 없다.



4.7 접근 제어자를 이용한 캡슐화


접근 제어자를 사용하는 이유
 - 외부로부터 데이터를 보호하기 위해
 - 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해


private는 "선언된 클래스에서만 사용하겠다"는 의미
변수를 감추는것 : 캡슐화(변수에 private를 주는것)

보통 대부분의 변수는 private를 두어서 접근을 할 수 없도록 만든다.
접근이 필요할 시에는 우회적으로 접근한다.


class A
{
    private int x = 10;
    public void setX(int x)//우회하는 메서드
    {
        if(x <= 100 && x > 0)
            //유효성 검사와 같은 것도 사용할 수 있다.
            this.x = x;
    }
    public int getX()//우회하는 메서드
    {
        return x;
    }
}
class Test
{
    public static void main(String[] args)
    {
        A a = new A();
        a.setX(500);
        System.out.println(a.getX());
    }
}

>>이런 방식을 DTO(Data Transfer Object) 방식이라고 한다..
>>변수는 private, 메소드는 public







4.8 생성자의 접근 제어자


 - 일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 일치한다.
 - 생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.

객체를 만든다는것은 개별적인 인스턴스 변수가 필요할 때인것
그렇지 않다면 객체를 만들 필요가 없다....
따라서 이럴때 일부러 생성자를 사용하지 못하도록 함
대표적으로 System class

class A
{
    private A()    //생성자에 private
    {    }
}
class Test
{
    public static void main(String[] args)
    {
        A a = new A();    //객체 생성 불가능
        System.out.println(a);
    }
}

=====================================

final class Singleton
{
    private static Singleton s = new Singleton();
    private Singleton()    //생성자에 접근을 제어함
    {
    }
    public static Singleton getInstance()    //참조형(Singleton)리턴
    {   
        if(s==null)
        {
            s = new Singleton();
        }
        return s;
    }
}
class SingletonTest
{
    public static void main(String[] args)
    {
        //Singleton s = Singleton();    //에러! Singleton() has private...
        Singleton s1 = Singleton.getInstance();
        //변수가 없고 메서드만 있는경우
        //변수가 모두 상수있때
        //즉, 개별적 저장공간이 없을때(인스턴스변수가 없을때)
        //Singleton 방식을 사용한다.
    }
}



4.9 제어자의 조합


클래스 : public, (default), final, abstract


메서드 : 모든 접근 제어자, final, abstract, static


맴버변수 : 모든 접근 제어자, final, static


지역변수 : final


 - 메서드에 static과 abstract를 함께 사용할 수 없다.(static메서드는 구현부가 있는 메서드에만 사용할수 있기 때문)
 - 클래스에 abstract와 final을 동시에 사용할 수 없다.(클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미고, abstract는 상속을 통해서 완선되어야 한다는 의미이므로 서로 모순되기 때문.)
 - abstract메서드의 접근제어자가 private일 수 없다.(abstract메서드는 자손클래스에서 구현해주어야 하는데 접근제어자가 private이면, 자손클래스에서 접근할 수 없기 때문이다.)
 - 메서드에 private과 final을 같이 사용할 필요는 없다.(접근 제어자가 private인 메서드는 오버라이딩될 수 없기 때문, 이 둘 중 하나만 사용해도 의미가 충분하다.)