💡 해당 글은 『자바의 신 3판』을 복습하며 도서의 내용과 본인의 주관적인 생각을 정리한 글입니다.
☁️ 내용정리
interface
interface
는 구현할 기능의 명세를 추상화 시켜놓은 타입? 이라고 생각한다.
클래스의 다중 상속이 불가능한 한계를 해결하여 다중 상속이 가능하다.
개발의 일반적인 프로세스는 다음과 같다. 분석 → 설계 → 개발 및 테스트 → 시스템 릴리즈
요구사항을 분석한다. → 분석 단계에서 도출된 문서를 통해 프로그램을 설계한다.
해당 단계에서 interface 혹은 abstract class를 정의하면 개발 및 테스트 단계에서 개발 속도를 향상시킬 수 잇다고 한다. 나는 아직 사용해보질 않아서 잘 모르겠다.
interface나 abstaract class를 사용하면 메서드 시그니처를 미리 정해두고 협업 시 코드 컨벤션을 지킬 수 있게 되어 코드 품질이 좋아진다는 것은 경험해봤다.
인터페이스는 아래와 같이 선언할 수 있다.
public interface MyInterface {
void myMethod();
}
public class MyInterfaceImple implements MyInterface {
@Override
public void myMethod() {
// ...
}
}
// 혹은 아래처럼 익명 클래스도 가능
public static void main(String[] args) {
MyInterface my = new MyInterface() {
@Override
public void myMethod() {
//...
}
}
}
인터페이스에 선언된 메서드에 접근 제어자를 선언하지 않으면 자동으로 public 접근 권한을 부여한다.
protected 접근 권한은 지원하지 않는다.
java8 부터는 interface에 staic과 default 메서드를 지원한다. 인터페이스에서 메서드를 구현할 수 있다.
java9 부터는 interface에 private 접근 권한이 지원된다. private 접근 권한을 가지는 메서드는 반드시 interface 내부에서 메서드 로직이 구혀되어 있어야 한다.
default 메서드에서 로직을 분리하고 외부로 해당 로직을 감추기 위함인 것 같다. 어찌 점점 abstract 클래스의 완벽한 상위호환이 되는 것 같다.
abstract
abstract
클래스는 일부 메서드만 구현해놓은 클래스이다.
public abstract class MyabstractClass {
public abstract void method();
public void method(String str) {
// ...
}
}
abstract class를 extends하는 클래스가 반드시 모든 abstract 메서드를 구현해야 하는 것은 아니다. 하지만 하나라도 구현하지 않을 시 해당 클래스 또한 abstract 클래스로 선언해야 한다.
abstract와 final은 함께 쓰일 수 없다. 상속 받은 클래스가 구현해야 하는 메서드인데 상속이 불가능하다는 것은 어불성실이기 때문에 당연하다.
abstract 클래스에서 구현해놓은 메서드에 final 키워드를 통해 상속이 불가능하게 하는 것은 가능하다.
final
메서드나 클래스에 final
을 붙이는 것은 상속
이 불가능하다는 의미이다.
변수에 final을 붙이는 것은 조금 다르게 사용된다. final이 붙은 변수는 더 이상 변경이 불가능하다는 것을 의미한다.
public static void main(String[] args) {
final B a;
a = new B();
a = new B(); // 컴파일 오류
}
이렇게 지역변수는 선언할 땐 초기화를 해주지 않아도 된다. 하지만 한 번 값이 할당되고 난 후에는 변경할 수 없다.
인스턴스 변수가 final로 선언된 경우 필드 혹은 생성자에서 초기화를 해주어야만 한다.
reference type을 final로 선언한 경우 유의해야할 점이 있다. 만약 final은 변수 공간에 저장된 값이 변경되지 않도록 하는 것이다. 즉 final reference type은 다른 인스턴스로 변경될 수 없다. 하지만 해당 인스턴스가 자신의 프로퍼티의 변경을 허용한다면, 이에 접근하여 프로퍼티를 변경할 수 있다는 점을 유의해야 한다.
아래와 같은 코드가 가능하다는 것이다.
private final Map<String, String> map = new HashMap();
public void put(String key, String value) {
map.put(key, value);
}
enum
enum은 static final 상수의 집합이다.
public abstract class Enum<E extends Enum<E>>
implements Constable, Comparable<E>, Serializable {
java.lang.Enum
은 모든 열거체의 조상이다.
public enum MyEnum {
VAR1, VAR2, VAR3;
}
이런식으로 사용할 수 있다. enum의 상수들은 모두 객체이다.
public enum MyEnum {
A(1),
B(2),
C(3);
private final int value;
private MyEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
이런식으로 값을 할당하고 프로퍼티에 접근도 가능하다.
☁️ 내 생각
default 메서드를 사용하는 경우 문제는?
Java8부터 interface는 default 메서드를 지원한다. default 메서드는 인터페이스에서 메서드를 구현할 수 있는 기술이다. 여기서 의문이 생겼다. 자바에서 다중 상속을 지원하지 않는 이유 중 하나는 다이아몬드 상속 문제이다.
그럼 아래와 같은 코드는 어떻게 실행되어야 할까?
interface A {
default void method() {
System.out.println("A");
}
}
interface B {
default void method() {
System.out.println("B");
}
}
class C implements A, B {
// C inherits unrelated defaults for method() from types A and B
}
직접 코드를 작성해보니 컴파일 오류가 발생한다. method를 override하여 사용하라는 의미이다.
근데 이럴거면 그냥 interface는 높은 추상화의 개념으로 놔두고, 클래스간 다중상속이 가능하게 해주면 안되는거냐?
고 잠깐 생각이 들긴 했는데 사이드 이펙트를 생각하면 불가능할 거 같긴 하다.
class C implements A, B {
@Override
public void method() {
A.super.method(); // 이렇게 A 인터페이스의 method를 호출할 수 있다. 신기하다
}
}
어우 default 메서드는 오히려 추상화의 개념이 깨지는 것 같아 잘 사용하지 않을 것 같다.
'JAVA > 자바의 신' 카테고리의 다른 글
16장. 클래스 안에 클래스가 들어갈 수도 있구나 (0) | 2024.01.07 |
---|---|
15장. String (1) | 2024.01.07 |
12장. 모든 클래스의 부모 클래스는 Object에요 (0) | 2024.01.05 |
11장. 매번 만들기 귀찮은데 누가 만들어 놓은 거 쓸 수 없나요? (0) | 2024.01.05 |
10장. 자바는 상속이라는 것이 있어요 (0) | 2024.01.05 |