본문 바로가기

자바스프링웹공부(2024)/자바

2024.09.20. 추상클래스, 추상메서드, final, block

반응형

* 추상메서드 (Abstract Method)

- 메서드 구현부 (=바디{})가 없는 메서드 (미완성 메서드)
- 메서드의 동작을 기술하는 구현부가 없는 추상메서드는 실행할 수 있는 코드가 없으므로 외부로부터 호출되면 안됨
  => 따라서, 추상메서드를 갖는 클래스는 반드시 추상클래스로 선언되어야 한다!
- 메서드 정의 시 선언부의 접근제한자 뒤에 abstract 키워드를 붙여서 정의
  => abstract 키워드가 붙은 메서드는 추상메서드 이므로 바디를 가질 수 없다!
  (따라서, 메서드 선언부 마지막에 바디{} 대신 세미콜론(;)으로 끝냄)
- 서브클래스에서 반드시 오버라이딩 하도록 강제성을 부여해야하는 메서드는 슈퍼클래스에서 추상메서드로 선언하면
  서브클래스에가 무조건 오버라이딩 필수!
  => 강제성을 통해 업캐스팅 시 코드의 통일성을 더욱 향상 시킬 수 있다. 
 
  < 추상메서드 정의 기본 문법 >
  [접근제한자 ] abstract 리턴타입 메서드명 ([매개변수...]);

 

* 추상클래스 (Abstract Class)

- 객체(인스턴스)를 생성할 수 없는 클래스 (미완성 클래스) - new XXX()... 안됨.
  => 따라서 new 연산자를 통해 생성자 호출 불가능 
- 추상메서드를 가질 수 있는 클래스 
  => 상속받는 서브클래스에서 반드시 오버라이딩 해야한다!
      추상클래스라고 반드시 추상 메서드를 가져야되는 것은 아니다.
- 추상클래스는 추상메서드, 일반메서드, 생성자, 멤버변수를 가질 수 있음.
- 상속을 통해 서브클래스에서 사용 가능하며, 업캐스팅을 통한 다형성 활용 가능

  즉, 변수의 클래스 타입으로 사용 가능.

 
< 추상클래스 정의 기본 문법 >
  abstract class 클래스명 {
    // 멤버변수(인스턴스 멤버, 클래스(static) 멤버 - 어차피 객체생성 안할거니까 사용해도된다고????)
    // 생성자
    // 메서드 (abstract 추상메서드 포함! - 동적바인딩 용도)
   }

 


*  초기화 블록 (Initialization block) 

1. 클래스 초기화 블록 (static {})

  - 클래스 변수 (static 으로 선언된 변수)의 복잡한 초기화에 사용된다.
  - 클래스가 처음 로딩될 때 한번만 수행된다.
2. 인스턴스 초기화 블록 ({})
  - 인스턴스 변수의 복잡한 초기화에 사용된다.
  - 인스턴스가  생성될 때 마다 (new 될때마다) 수행된다.
  - 생성자보다 먼저 수행된다.

public class Ex1_1 {
	{
		System.out.println("인스턴스 초기화 블록 호출됨."); // 생성자보다 먼저 실행됨.
	}
	public Ex1_1() {
		System.out.println("기본생성자 호출됨");
	}
	public static void main(String[] args) {
		// 메서드 내에서의 중괄호 블록
		// => 로컬 변수의 범위를 제한하기 위해 사용된다.
		int num1 = 10;
		{
			int num2 = 20;
		}
//		System.out.println(num2); // 안됨. 선언이 중괄호 안에 있으므로
		// => 마치 for문에서 선언되고 반복이 종료되면 사라지는 i와 마찬가지로 중괄호 블록 외부에서 접근할 수 없다.
		new Ex1_1();
	}
}

 

public class Ex1 {
	static int a;
	int b;
	static {
		// static 붙으 애들(static int a)을 초기화하려고 사용??
		//객체와 관계없이 시작되자마자 로딩됨.
//		b = 20; // 인스턴스 변수는 접근 불가!
		a = 10;
		System.out.println(a); // 제일먼저 실행됨. 한번만 실행됨.
	}
	{
		System.out.println("인스턴스 초기화 블록 호출됨.");  // 여러번 실행됨
	}
	public Ex1() {
		System.out.println("기본생성자 호출됨"); // 여러번 실행됨
	}
	public static void main(String[] args) {
		new Ex1();
		new Ex1();
	}
}


*  final 키워드 

- 클래스, 메서드 , 변수에 지정가능
- 정말 마지막이라는 뜻

 

1) 변수에 final이 붙은 경우
  - 변수값 변경 불가 = 상수로 취급
  => 즉, 기존에 저장된 값ㅇ르 사용하는 것만 가능하고, 값을 변경할 수는 없다.
2) 메서드에 final이 붙은 경우
  - 메서드 변경 불가 = 오버라이딩 금지
  => 즉, 슈퍼클래스의 메서드를 상속받아 사용하는 것은 가능하나
       오버라이딩을 통해 슈퍼클래스의 메서드를 변경할 수는 없다.
3) 클래스에 final이 붙은 경우
 - 클래스 변경 불가 = 상속 금지
  => 즉, 특정 클래스 자체를 그대로 사용하는 것은 가능하나
       다른 클래스에서 해당 클래스를 상속 받을 수는 없다.
  => 어떤 클래스 자체롤 이미 완전한 클래스 기능을 수행하는 경우 상속을 금지시킴.
 - final 메서드보다 더 광범위한 제한을 두도록 할 때 사용함.

public class Ex1 {
	public static void main(String[] args) {
		final int a; // 로컬변수라서 진짜 값이 안들어간다. 
		a = 20; // 값 고정
//		a = 30; // X 변경불가
		
		FinalMemberVar fmv = new FinalMemberVar();
		fmv.normalVar = 90;
		System.out.println(fmv.normalVar);
//		fmv.finalVar = 999; // final로 선언된 멤버변수는 값 변경 불가!
		System.out.println(fmv.finalVar); // 출력은 가능함.
	}
}

// ---------------- final 멤버변수 -----------------------
class FinalMemberVar {
	int normalVar = 10;
	final int finalVar = 20; // 만들자마자 오류가 남.main에서는 되는데 왜 여기서는 안되는가? 이거는 메인에서 객체생성하면 값이 0이 이미 들어가 버리기 때문이다. new 할때마다 0으로 값을 초기화해버리기 때문에 안된다.
}

// --------------- final 메서드 ------------------------
class FinalMethod {
	public void normalMethod () {
		System.out.println("normalMethod");
	}
	public final void finalMethod () {
		System.out.println("finalMethod");
	}
}
class SubClassFinalMethod extends FinalMethod {
	public void normalMethod() {
		System.out.println("서브클래스에서 오버라이딩 된 normalMethod()");
	}
//	public void finalMethod () {
//		// 오류발생. final 메서드는 서브클래스에서 오버라이딩 불가
//	}
}

//--------------- final 클래스 ------------------------
class SuperClass {}
final class FinalClass extends SuperClass{}
//class SubClass extends FinalClass {} // 오류발생. final 클래스는 상속불가

// final 클래스의 대표적인 예 : String 클래스
//class OtherClass extends String{} // 오류 발생. F3눌러서 드가면 public final class String 나옴.

반응형