Java

[Java] 자바가 확장한 객체 지향

sujin7837 2021. 2. 17. 14:46
반응형

abstract 키워드-추상 메소드와 추상 클래스

추상 메소드: 선언부는 있는데 구현부가 없는 메소드

추상 메소드를 하나라도 가지고 있는 클래스는 반드시 추상 클래스로 선언해야 합니다.

 

추상 메소드와 추상 클래스의 특징

//동물.java

public abstract class 동물 {
	abstract void 울어보세요();
}

1. 추상 메소드를 포함하는 클래스는 반드시 추상 클래스여야 합니다.

 

//Driver.java

public class Driver {
	public static void main(String[] args) {
    	동물[] 동물들=new 동물[3];
        
        동물들[0]=new 쥐();
        동물들[1]=new 고양이();
        동물들[2]=new 강아지();
        
        for(int i=0;i<동물들.length;i++) {
        	동물들[i].울어보세요();
        }
        //동물 짐승=new 동물();
    }
}

2. 추상 클래스는 인스턴스, 즉 객체를 만들 수 없습니다. 그래서 Driver.java에 위의 주석과 같이 new를 사용하여 코드를 작성할 경우 오류가 발생합니다.

 

//고양이.java

public class 고양이 extends 동물 {
	void 울어보세요() {
    	System.out.println("나는 고양이! 야옹! 야옹!");
    }
}

3. 추상 메소드는 하위 클래스에게 메소드의 구현을 강제합니다. 즉 오버라이딩을 강제하므로 '울어보세요()' 메소드를 오버라이딩하지 않으면 에러가 발생합니다. 따라서 하위 클래스에 반드시 '울어보세요()' 추상 메소드를 구현해야 합니다.

 

생성자

클래스의 인스턴스, 즉 객체를 만들 때마다 new 키워드를 사용합니다.

 

동물 뽀로로=new 동물();

 

생성자의 특징

1. 개발자가 아무런 생성자를 만들지 않으면 자바는 인자가 없는 기본 생성자를 자동으로 만들어줍니다.

2. 인자가 있는 생성자를 하나라도 만든다면 자바는 기본 생성자를 만들어 주지 않습니다.

 

Static 블록

static 블록은 클래스가 스태틱 영역에 배치될 때 실행되는 코드 블록입니다. 클래스가 처음으로 로딩될 때 static 블록이 실행됩니다. 클래스 정보는 해당 클래스가 코드에서 맨 처음 사용될 때 T 메모리의 스태틱 영역에 로딩되며, 이때 단 한번 해당 클래스의 static 블록이 실행됩니다.

//동물.java

public class 동물 {
	static {
    	System.out.println("동물 클래스 레디 온!");
    }
}
//Driver01.java

public class Driver01 {
	public static void main(String[] args) {
    	동물 뽀로로=new 동물();
    }
}

코드를 실행하면 콘솔 창에서 다음과 같은 메시지를 확인할 수 있습니다.

-> 동물 클래스 레디 온!

 

클래스가 제일 처음 사용될 때

  • 클래스의 정적 속성을 사용할 때
  • 클래스의 정적 메소드를 사용할 때
  • 클래스의 인스턴스를 최초로 만들 때

 

final 키워드

final 키워드는 객체 지향 언어의 구성 요소인 세 군데에서만 나타날 수 있습니다. 바로 클래스, 변수, 메소드입니다.

 

final과 클래스

클래스에 final이 붙으면 상속을 허락하지 않겠다는 의미입니다. 따라서 해당 클래스는 하위 클래스를 만들 수 없습니다.

//고양이.java

public final class 고양이 { }

 

final과 변수

변수에 final이 붙으면 해당 변수는 변경 불가능한 상수가 됩니다.

//고양이.java

public class 고양이 {
	final static int 정적상수1=1;
    final static int 정적상수2;
    
    final int 객체상수1=1;
    final int 객체상수2;
    
    static {
    	정적상수2=2;
    }
    
    고양이() {
    	객체상수2=2;
        
        final int 지역상수1=1;
        final int 지역상수2;
        
        지역상수2=2;
    }
}

정적 상수: 선언 시, 또는 정적 생성자에 해당하는 static 블록 내부에서 초기화가 가능합니다.

객체 상수: 선언 시, 또는 객체 생성자나 인스턴스 블록에서 초기화할 수 있습니다.

지역 상수: 선언 시, 또는 최초 한 번만 초기화가 가능합니다. 

 

다른 언어에서는 읽기 전용인 상수에 대해 final 키워드 대신 const 키워드를 사용하기도 합니다. 그러나 자바에서는 이런 혼동을 피하기 위해 const를 키워드로 등록해두고 사용하지 못하게 하고 있습니다.

 

final과 메소드

메소드가 final이면 재정의, 즉 오버라이딩을 할 수 없게 됩니다.

//동물.java

public class 동물 {
	final void 숨쉬다() {
    	System.out.println("호흡 중");
    }
}

class 포유류 extends 동물 {
	//에러 발생: Cannot override the final method from 동물
	void 숨쉬다() {
    	System.out.println("호흡 중");
    }
}

 

 

instanceof 연산자

인스턴스는 클래스를 통해 만들어진 객체이며, instanceof 연산자는 만들어진 객체가 특정 클래스의 인스턴스인지 물어보는 연산자입니다. instanceof 연산자는 결과로 true 또는 false를 리턴합니다.

 

객체_참조_변수 instanceof 클래스명

 

//Driver.java

class 동물 {

}

class 조류 extends 동물 {

}

class 펭귄 extends 조류 {

}

public class Driver {
	public static void main(String[] args) {
    	동물 동물객체=new 동물();
        조류 조류객체=new 조류();
        펭귄 펭귄객체=new 펭귄();
        
        System.out.println(동물객체 instanceof 동물);
        
        System.out.println(조류객체 instanceof 동물);
        System.out.println(조류객체 instanceof 조류);
        
        System.out.println(펭귄객체 instanceof 동물);
        System.out.println(펭귄객체 instanceof 조류);
        System.out.println(펭귄객체 instanceof 펭귄);
        
        System.out.println(동물객체 instanceof Object);
    }
}

실행 결과 모든 경우에 true가 출력되는 것을 확인할 수 있습니다.

 

//Driver.java

class 동물 {

}

class 조류 extends 동물 {

}

class 펭귄 extends 조류 {

}

public class Driver {
	public static void main(String[] args) {
    	동물 동물객체=new 동물();
        동물 조류객체=new 조류();
        동물 펭귄객체=new 펭귄();
        
        System.out.println(동물객체 instanceof 동물);
        
        System.out.println(조류객체 instanceof 동물);
        System.out.println(조류객체 instanceof 조류);
        
        System.out.println(펭귄객체 instanceof 동물);
        System.out.println(펭귄객체 instanceof 조류);
        System.out.println(펭귄객체 instanceof 펭귄);
        
        System.out.println(동물객체 instanceof Object);
    }
}

객체 참좆 변수의 타입이 아닌 실제 객체의 타입에 의해 처리하기 때문에 위 코드의 실행 결과도 모두 true 입니다.

 

//Driver.java

interface 날수있는 {

}

class 박쥐 implements 날수있는 {

}

class 참새 implements 날수있는 {

}

public class Driver {
	public static void main(String[] args) {
    	날수있는 박쥐객체=new 박쥐();
        날수있는 참새객체=new 참새();
        
        System.out.println(박쥐객체 instanceof 날수있는);
        System.out.println(박쥐객체 instanceof 박쥐);
        
        System.out.println(참새객체 instanceof 날수있는);
        System.out.println(참새객체 instanceof 참새);
    }
}

instanceof 연산자는 클래스들의 상속 관계뿐만 아니라 인터페이스의 구현 관계에서도 동일하게 적용됩니다. 따라서 위의 코드의 실행 결과도 모두 true를 리턴합니다.

 

 

package 키워드

package 키워드는 네임스페이스(이름공간)를 만들어주는 역할을 합니다. 서로 다른 두 부서에서 Customer라는 같은 이름의 클래스를 사용하고자 한다면, 두 클래스는 이름 충돌이 발생하게 됩니다. 이럴 때 이름 공간을 나누어 첫번째 부서에서는 '첫번째부.Customer', 두번째 부서에서는 '두번째부.Customer'라고 이름을 지정하면 이름 충돌을 피할 수 있습니다. 여기서 Customer앞에 붙은 소유자 역할을 하는 것이 패키지라고 할 수 있습니다.

 

 

interface 키워드와 implements 키워드

인터페이스는 추상 메소드와 정적 상수만 가질 수 있기에 따로 메소드에 public과 abstract, 속성에 public과 static, final을 붙이지 않아도 자동으로 자바가 알아서 붙여줍니다.

//public, static, final, abstract 키워드가 생략된 경우

interface Speakable {
	double PI=3.14159;
    final double absoluteZeroPoint=-275.15;
    
    void SayYes();
}
//public, static, final, abstract 키워드가 표시된 경우

interface Speakable {
	public static final double PI=3.14159;
    public static final double absoluteZeroPoint=-275.15;
    
    public abstract void SayYes();
}

위의 두 코드는 결과적으로 같은 코드입니다.

 

 

this 키워드

this는 객체가 자기 자신을 지칭할 때 쓰는 키워드입니다.

  • 지역 변수와 속성(객체 변수, 정적 변수)의 이름이 같은 경우 지역 변수가 우선합니다.
  • 객체 변수와 이름이 같은 지역 변수가 있는 경우 객체 변수를 사용하려면 this를 접두사로 사용합니다.
  • 정적 변수와 이름이 같은 지역 변수가 있는 경우 정적 변수를 사용하려면 클래스명을 접두사로 사용합니다.

 

super 키워드

단일 상속만을 지원하는 자바에서 super는 바로 위 상위 클래스의 인스턴스를 지칭하는 키워드입니다. 그러나 super.super 형태로 상위의 상위 클래스의 인스턴스에는 접근이 불가능합니다.

//Driver.java

class Animal {
    void method() {
        System.out.println("동물");
    }
}

class Bird extends Animal {
    void method() {
        super.method();
        System.out.println("조류");
    }
}

class Penguin extends Bird {
    void method() {
        super.method();
        System.out.println("펭귄");
    }
}

public class Main {
    public static void main(String[] args) {
        Penguin pororo=new Penguin();

        pororo.method();
    }
}

실행 결과

->동물

    조류

    펭귄

반응형