백기선 자바 스터디 6주차 상속 주제에 대해 학습하면서 정리한 내용입니다.
Dynamic Method Dispatch
다이나믹 메서드 디스패치는 Overriding
된 메서드에 대한 호출이 compile-time
이 아닌 runtime
에 결정되는 메커니즘입니다.
Overriding
메서드가 조상 클래스 참조를 통해 호출될 때Java
는 호출이 발생할 때 참조되는Object
의 유형에 따라 실행할 메서드의 버전을 결정합니다.- 이 결정은
runtime
에 이루어집니다.
- 이 결정은
예시
public class Fruit {
void m1() {
System.out.println("Eat some Fruit");
}
}
class Apple extends Fruit {
void m1() {
System.out.println("Eat some Apple");
}
}
class Banana extends Fruit {
void m1() {
System.out.println("Eat some Banana");
}
}
class Dispatch {
public static void main(String args[]) {
Fruit fruit = new Fruit();
Apple apple = new Apple();
Banana banana = new Banana();
Fruit ref;
ref = fruit;
ref.m1();
ref = apple;
ref.m1();
ref = banana;
ref.m1();
}
}
- Apple, Banana 클래스는 Fruit 클래스를 상속 받고 있습니다.
- 각각의 자손 클래스에서는
m1()
를 재정의하고 있습니다. Fruit
클래스 유형의 참조 변수를 선언합니다.Apple
,Banana
인스턴스 변수를 각각ref
변수에 할당하여m1()
메서드를 호출하면 재정의한 메서드가 호출되는 걸 볼 수 있습니다.
public class A {
int x = 10;
}
class B extends A {
int x = 20;
}
class Test {
public static void main(String[] args) {
A a = new B(); // object of type B
// Data member of class A will be accessed
System.out.println(a.x);
// 10
}
}
- Java에서 메서드만 오버라이드가 가능합니다.
- 변수는 오버라이드가 불가능한데 이것에 대한 예시 코드입니다.
- B 클래스는 A 클래스를 상속 받고 있습니다.
- 두 클래스 모두 x라는 멤버 변수를 갖고 있습니다.
A
클래스 유형인 참조 변수a
로B
클래스 객체를 만듭니다.- 멤버 변수
x
는 재정의되지 않기 때문에runtime
시점에 결정되는Dynamic Method Dispatch
가 이루어지지 않고 조상 클래스A
의 멤버 변수x
의 값이 출력되게 됩니다
Dynamic Method Dispatch의 장점
- Dynamic Method Dispatch를 통해 Java는 runtime-polymorphism 핵심인 Override Method를 지원할 수 있습니다.
- 이를 통해 상속 관계를 통해 코드 중복을 줄일 수 있고, 자손 클래스에서 일부 메서드를 재정의할 수 있게 됩니다.
정적 바인딩과 동적 바인딩
- 정적 바인딩은 compile-time 동안 수행되고 동적 바인딩은 runtime 중에 수행됩니다.
private
,final
,static
method
와 변수들은정적 바인딩
을 사용하여compiler
에 의해 연결되는 반면Override method
는 runtime 객체 유형에 따라 runtime 시점에 결합하게 됩니다.
추상 클래스
추상화(abstraction) 는 특정 세부 사항을 숨기고 사용자에게 필수적인 정보만 보여줍니다. abstract class
혹은 interface
를 통해 추상화 할 수 있습니다.
abstract
키워드를 이용해 추상 클래스를 만들 수 있습니다. 메서드에도 abstract
키워드를 이용하여 추상 메서드를 만들 수 있습니다.
abstract class
: 추상 클래스는 인스턴스를 만들 수 없습니다.abstract method
: 추상 클래스에서만 사용할 수 있으며 본문은 작성하지 않습니다. 본문은 상속된 하위 클래스에서 작성되게 됩니다.
예시
abstract class Base {
public Base() {
System.out.println("Base class constructor");
}
abstract void fun();
}
class Derived extends Base {
public Derived() {
System.out.println("Derived class constructor");
}
void fun() {
System.out.println("Derived fun() called");
}
}
class Main {
public static void main(String[] args) {
Base b = new Derived();
b.fun();
// Base class constructor
// Derived class constructor
// Derived fun() called
}
}
abstract method
의 본문은 자손 클래스에서 작성되었습니다.- 추상 클래스는
기본 생성자
를 가질 수 있는데 이는상속 받은 자손 클래스
의인스턴스
가 생성될 때 호출됩니다. - 추상 클래스는 추상 메서드 없이 작성할 수 있습니다. 추상 클래스는
인스턴스화
할 수 없고,상속
만 가능하게 됩니다.
그 외
- 그 외에도 추상 클래스는
static
메서드를 정의할 수 있습니다. - 클래스에 추상 메서드가 포함되어 있으면 반드시 클래스를
abstract
로 선언해야 합니다. - 추상 클래스를 상속 받는 자손 클래스가 추상 메서드를 구현할 수 없는 경우 다음 자식 클래스가 나머지 추상 클래스를 구현할 수 있도록 해당 자식 클래스를 추상 클래스로 선언해줘야 합니다.
정리
- 추상 클래스는
기본 생성자
를 가질 수 있고, 기본 생성자는 상속 관계의 자손 클래스의인스턴스
가 생성될 때 호출됩니다. - 추상 클래스는
추상 메서드
없이 작성 가능하고, 추상 메서드를 선언할 경우 본문은 상속 관계의자손 클래스
에서 작성하게 됩니다. - 추상 클래스는
인스턴스화
할 수 없고,상속
만 가능합니다. - 추상 클래스는
static
메서드를 정의할 수 있습니다.
Java의 final keyword
final 키워드는 클래스, 메서드, 변수에서 사용 할 수 있습니다.
- final variable의 경우 변수를 상수로 만듭니다.
- final method는 메서드가 재정의되는 걸 막습니다. (Override)
- final class는 해당 클래스의 상속을 막습니다.
Final Variables
- 변수에는
final
키워드를 사용할 수 있습니다. 변수에final
을 사용하게 되면 해당 변수는 재할당 할 수 없기에 상수가 됩니다. final
키워드를 사용할 변수는 반드시 초기화해주어야 합니다.final
키워드를 사용한 참조 변수는 다른 참조 객체를 재할당 할 수 없습니다.- 하지만 참조 변수가 가리키는 객체의 내부 상태는 변경될 수 있습니다.
배열
혹은collection
에 요소를 추가하거나 제거할 수 있습니다.
final 변수의 선언과 초기화를 따로 할 수 있는 경우
일반적으로 final
키워드를 사용한 변수는 선언과 동시에 초기화를 해주어야한다. 그러지 않으면 compile-time
에러가 발생합니다.
특정한 상황에서 final
변수의 선언과 초기화를 따로 할 수 있습니다.
public class GFG {
final int THRESHOLD = 5;
final int CAPACITY;
final int MINIMUM;
static final double PI = 3.141592653589793;
static final double EULERCONSTANT;
{
CAPACITY = 25;
}
// static initializer block for
// initializing EULERCONSTANT
static {
EULERCONSTANT = 2.3;
}
public GFG() {
MINIMUM = -1;
}
public static void main(String[] args) {
final int a;
a = 10;
System.out.println(a);
int[] arr = new int[]{1, 2, 3};
for (final int i : arr) {
System.out.println(i);
}
}
}
코드 출처 : https://www.geeksforgeeks.org/final-keyword-in-java/
final
키워드를 사용한인스턴스
변수는 인스턴스 블럭에서 변수를 초기화할 수 있습니다.final
키워드를 사용한static
변수 또한static
블럭에서 변수를 초기화 할 수 있습니다.- 또한
생성자
에서final
키워드를 사용한 인스턴스 변수를 초기화 할 수 있습니다. - 지역 변수에
final
키워드를 사용하는 경우 선언과 초기화를 따로 할 수 있습니다.
Object Class
모든 Java 클래스는 직접적, 간접적으로 Object
클래스에서 파생됩니다. 클래스가 다른 클래스를 상속 받지 않으면 Object
의 직접적 자손 클래스이고 다른 클래스를 상속 받게 되면 간접적으로 파생되는 자손 클래스입니다.
Object 클래스의 메서드
1. toString()
toString() 메서드는 객체의 String 표현을 제공하며 객체를 String으로 변환하는데 사용됩니다.
- 기본적인 toString() 메서드는 객체가 인스턴스인 클래스의 이름, @, 16진수 해시코드를 String으로 반환합니다
- 일반적으로 toString() 메서드는 재정의하여 사용합니다.
2. hashCode()
- JVM은 모든 객체에 대해 해시 코드라는 고유한 번호를 생성합니다.
- hashCode() 메서드는 객체의 주소를 반환하는 것이 아닌 알고리즘을 사용하여 객체의 내부 주소를 정수로 변환합니다.
- hashCode() 메서드는 Java를 이용해 객체의 주소를 찾는 게 불가능하기 때문에, 객체의 주소를 찾기 위해 C/C++과 같은 네이티브 언어를 사용합니다.
3. equals(Object obj)
- 주어진 객체를 호출되는 객체와 비교합니다.
- equals(Object obj) 메서드를 재정의할 땐 hashCode() 메서드 또한 재정의하는 것이 좋습니다.
- 그렇지 않으면 동일한 객체가 서로 다른 해시 값을 얻을 수 있으며
Hash(HashMap, HashSet, Hashtable)
기반 컬렉션이 제대로 작동하지 않습니다.
- 그렇지 않으면 동일한 객체가 서로 다른 해시 값을 얻을 수 있으며
4. getClass()
- getClass() 메서드는
final
메서드이므로 재정의할 수 없습니다. this
객체의 클래스 객체를 반환하며 객체의 실제 런타임 클래스를 가져오는데 사용됩니다.- 클래스의
메타데이터
를 가져오는 데에도 사용할 수 있습니다. runtime
시점에JVM
이heap
영역에java.lang.Class
객체를 생성합니다. 이 클래스 객체를 사용하여getClass()
메서드는 클래스 수준 정보를 얻을 수 있습니다.
5. finalize()
finalize()
메서드는 객체가Garbage Collector
에 의해 수집되기 직전에 호출됩니다.- 시스템의 자원을 삭제하고 정리 작업을 수행하여 메모리 누수를 최소화하려면
finalize()
메서드를 재정의하여 사용해야합니다.
6. clone()
- 해당 객체와 동일한 새 객체를 반환합니다.
- 객체를 복사할 땐 얕은 복사 (Shallow Copy) 와 깊은 복사 (Deep Copy)가 있습니다. Java clone()
References
https://www.geeksforgeeks.org/dynamic-method-dispatch-runtime-polymorphism-java/
https://www.w3schools.com/java/java_abstract.asp
https://www.geeksforgeeks.org/abstract-classes-in-java/
'Java' 카테고리의 다른 글
멀티스레드 프로그래밍 (2) | 2022.09.27 |
---|---|
예외 처리 (0) | 2022.09.15 |
Java Overriding (0) | 2022.08.30 |
Java의 상속과 super 키워드 (0) | 2022.08.29 |
5주차 클래스 (0) | 2022.08.18 |