프로그래밍

자바와 닷넷 비교 - final과 sealed, final과 readonly and const

Jinwookoh 2025. 3. 2. 20:15

C#과 Java에서 각각의 키워드인 final, sealed, readonly, const의 차이점을 비교해 보겠습니다.


1. final (Java) vs sealed (C#)

Java의 final과 C#의 sealed는 클래스 상속 및 메서드 재정의 방지와 관련이 있습니다.

기능 Java (final) C# (sealed)
클래스 제한 final class는 상속 불가능 sealed class는 상속 불가능
메서드 제한 final 메서드는 오버라이드 불가능 sealed는 override된 메서드만 사용 가능 (sealed override)
변수 제한 final 필드는 한 번 할당 후 변경 불가 sealed는 변수에 사용 불가

예제

Java (final)

final class FinalClass {} // 이 클래스는 상속 불가능

class Parent {
    final void finalMethod() {
        System.out.println("Cannot be overridden");
    }
}

class Child extends Parent {
    // 컴파일 에러 발생 (final 메서드는 오버라이드 불가)
    // void finalMethod() {}
}

C# (sealed)

sealed class SealedClass {} // 이 클래스는 상속 불가능

class Parent {
    public virtual void Method() { }
}

class Child : Parent {
    public sealed override void Method() { } // 더 이상 override 불가능
}

2. final (Java) vs readonly & const (C#)

Java의 final 필드와 C#의 readonly, const는 변수의 변경 가능성과 관련이 있습니다.

기능   Java (final) C# (readonly)  C# (const)
변경 가능 여부 한 번 초기화 후 변경 불가 생성자에서만 변경 가능 컴파일 타임 상수, 변경 불가
할당 시점 선언과 동시에 or 생성자에서 가능 선언과 동시에 or 생성자에서 가능 선언과 동시에만 가능
인스턴스/정적 필드 인스턴스 필드, 정적 필드 모두 가능 인스턴스 필드, 정적 필드 모두 가능 반드시 정적(static)이며, 리터럴 값만 가능
사용 가능한 값 모든 값 가능 (객체, 기본형) 모든 값 가능 (객체, 기본형) 리터럴 값만 가능 (숫자, 문자열 등)

예제

Java (final)

class Example {
    final int instanceValue; // 생성자에서 초기화 가능
    final static int STATIC_VALUE = 100; // 선언과 동시에 초기화 가능

    Example(int value) {
        this.instanceValue = value; // 생성자에서만 초기화 가능
    }
}

C# (readonly vs const)

class Example {
    public readonly int instanceValue; // 생성자에서 초기화 가능
    public const int CONSTANT_VALUE = 100; // 상수 값, 변경 불가

    public Example(int value) {
        this.instanceValue = value; // 생성자에서 초기화 가능
        // this.CONSTANT_VALUE = 200; // 오류 발생 (const는 변경 불가)
    }
}

3. final 변수 vs readonly 필드 vs const 차이 정리

  • final(Java) ≈ readonly(C#) → 생성자에서 값을 변경할 수 있음.
  • const(C#) → 반드시 컴파일 타임 상수여야 하며, 선언과 동시에 초기화해야 함.

사용 예시

예제  Java (final)  C# (readonly)  C# (const)
인스턴스 필드 ✅ (생성자에서 초기화 가능) ✅ (생성자에서 초기화 가능) ❌ (불가능)
정적 필드 ✅ (final static 사용) ✅ (static readonly 사용) ✅ (const 사용)
런타임 값 할당 가능 여부 ✅ (가능) ✅ (가능) ❌ (컴파일 타임에 결정된 값만 가능)

결론

  • 클래스 상속 제한
    • Java는 final을 사용.
    • C#은 sealed을 사용.
  • 메서드 재정의 제한
    • Java는 final을 사용.
    • C#은 sealed override를 사용.
  • 변수 변경 제한
    • Java는 final을 사용.
    • C#은 readonly 또는 const를 사용 (readonly는 생성자에서 초기화 가능, const는 변경 불가).

 

Java와 C#에서 abstract와 final(Java) 또는 sealed(C#)을 함께 사용하는 경우를 살펴보겠습니다.


1. abstract와 final (Java)

Java에서 abstract와 final은 동시에 사용할 수 없습니다.
이유는 abstract는 상속을 통해 구현해야 하는 미완성 클래스를 의미하지만,
final은 상속을 금지하기 때문입니다.

Java에서 불가능한 코드

abstract final class Example { // 오류 발생
}

컴파일 오류: The class Example can not be declared both abstract and final

해결 방법:

  • abstract를 유지하고 final을 제거 (abstract class Example {})
  • final을 유지하고 abstract를 제거 (final class Example {})

단, abstract 클래스 내의 메서드에서 final을 사용하는 것은 가능합니다.

abstract class Parent {
    final void nonOverridableMethod() {
        System.out.println("This method cannot be overridden");
    }
    
    abstract void mustBeImplemented();
}

class Child extends Parent {
    // final 메서드는 오버라이드 불가
    // void nonOverridableMethod() {} // 오류 발생

    @Override
    void mustBeImplemented() {
        System.out.println("Implemented in Child");
    }
}

2. abstract와 sealed (C#)

C#에서도 abstract와 sealed는 동시에 사용할 수 없습니다.
이유는 Java와 동일하게 abstract는 상속을 요구하는 반면,
sealed는 상속을 금지하기 때문입니다.

C#에서 불가능한 코드

public abstract sealed class Example {} // 오류 발생

컴파일 오류: 'Example' cannot be both abstract and sealed

해결 방법:

  • abstract를 유지하고 sealed를 제거 (abstract class Example {})
  • sealed를 유지하고 abstract를 제거 (sealed class Example {})

하지만, C#에서는 sealed override를 사용하여 메서드의 재정의를 막을 수 있습니다.

abstract class Parent {
    public abstract void MustBeImplemented();

    public virtual void NormalMethod() {
        Console.WriteLine("Can be overridden");
    }
}

class Child : Parent {
    public override void MustBeImplemented() {
        Console.WriteLine("Implemented in Child");
    }

    public sealed override void NormalMethod() {
        Console.WriteLine("Cannot be overridden anymore");
    }
}

class GrandChild : Child {
    // public override void NormalMethod() {} // 오류 발생 (sealed로 인해 재정의 불가)
}

결론

특징  Java (final)  C# (sealed)
abstract class와 함께 사용 가능? ❌ 불가능 ❌ 불가능
메서드에서 사용 가능? ✅ 가능 (final 메서드는 오버라이드 금지) ✅ 가능 (sealed override로 재정의 금지)
  • 클래스에서는 abstract와 final/sealed를 함께 사용할 수 없다.
  • 메서드에서는 final(Java) 또는 sealed override(C#)를 사용하여 오버라이드를 막을 수 있다.

 

'프로그래밍' 카테고리의 다른 글

자바와 닷넷 비교 - 생성자  (0) 2025.03.02
자바와 닷넷 비교 - static  (0) 2025.03.02
자바와 닷넷 문자열 비교  (2) 2025.03.02
자바와 닷넷 리플렉션 비교  (0) 2025.03.02
자바와 닷넷 비교 - ENUM  (0) 2025.03.02