programing

최종 객체를 수정할 수 있는 이유는 무엇입니까?

prostudy 2022. 9. 5. 21:46
반응형

최종 객체를 수정할 수 있는 이유는 무엇입니까?

작업 중인 코드 베이스에서 다음 코드를 발견했습니다.

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }

    public static void addProvider(ConfigurationProvider provider) {
        INSTANCE.providers.add(provider);
    }

    ...

INSTANCE로서 선언되다final. 오브젝트를 추가할 수 있는 이유INSTANCE최종판 사용을 무효화해야 하지 않을까요?(그렇지 않다).

나는 그 답이 포인터와 기억과 관련이 있다고 추측하지만 확실히 알고 싶다.

final오브젝트 참조를 변경할 수 없게 할 뿐입니다.이렇게 함으로써 그것이 가리키는 물체는 불변의 것이 아니다. INSTANCE는 다른 개체를 참조할 수 없지만 참조하는 개체의 상태가 변경될 수 있습니다.

최종적인 것은 불변의 것과 같지 않다.

final != immutable

final키워드는 참조가 변경되지 않았는지 확인하기 위해 사용합니다(즉, 가지고 있는 참조를 새 참조로 대체할 수 없습니다).

단, Atribute가 self로 변경 가능한 경우 방금 설명한 작업을 수행해도 됩니다.

예를 들어.

class SomeHighLevelClass {
    public final MutableObject someFinalObject = new MutableObject();
}

이 클래스를 인스턴스화하면 속성에 다른 값을 할당할 수 없습니다.someFinalObject마지막이니까.

따라서 이것은 불가능합니다.

....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor  = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final

그러나 객체 자체가 다음과 같이 변이 가능한 경우:

class MutableObject {
     private int n = 0;

     public void incrementNumber() {
         n++;
     }
     public String toString(){
         return ""+n;
     }
}  

그러면 해당 가변 객체에 포함된 값이 변경될 수 있습니다.

SomeHighLevelClass someObject = new SomeHighLevelClass();

someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();

System.out.println( someObject.someFinal ); // prints 3

이것은, 투고 내용과 같은 효과를 가져옵니다.

public static void addProvider(ConfigurationProvider provider) {
    INSTANCE.providers.add(provider);
}

여기서는 인스턴스 값을 변경하지 않고 내부 상태(via, providers.add 메서드)를 변경합니다.

클래스 정의가 다음과 같이 변경되지 않도록 하려면 다음과 같이 하십시오.

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }
    // Avoid modifications      
    //public static void addProvider(ConfigurationProvider provider) {
    //    INSTANCE.providers.add(provider);
    //}
    // No mutators allowed anymore :) 
....

단, 별로 의미가 없을 수 있습니다.

덧붙여서, 기본적으로 같은 이유로 액세스도 동기화해야 합니다.

오해의 열쇠는 질문의 제목에 있습니다.최종적인 것이 아니라 변수입니다.변수의 값은 변경할 수 없지만 변수 내의 데이터는 변경할 수 있습니다.

참조 유형 변수를 선언할 때 해당 변수의 값은 객체가 아니라 참조입니다.

final은 참조를 변경할 수 없음을 의미합니다.인스턴스가 최종 참조로 선언된 경우 다른 참조에 다시 할당할 수 없습니다.객체의 내부 상태는 여전히 변동 가능합니다.

final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;

컴파일 오류가 발생합니다.

한 번final변수가 할당되어 있으며 항상 같은 값이 포함되어 있습니다.만약 a가finalvariable은 객체에 대한 참조를 보유하고 있으며 객체의 상태는 객체에 대한 조작에 의해 변경될 수 있지만 변수는 항상 동일한 객체를 참조합니다.어레이는 객체이기 때문에 어레이에도 적용됩니다.final에 의해 될 수 는 항상 어레이를 합니다.이 경우 어레이의 컴포넌트는 어레이의 조작에 의해 변경될 수 있지만 변수는 항상 같은 어레이를 참조합니다.

원천

여기 불변의 물체를 만드는 방법에 대한 지침이 있습니다.

최종과 불변의 것은 같은 것이 아니다.Final은 참조를 재할당할 수 없으므로 말할 수 없음을 의미합니다.

INSTANCE = ...

불변이란 객체 자체를 수정할 수 없음을 의미합니다.를 들어 " " 입니다.java.lang.Stringclass 할 수 . 을 사용법

자바에는 불변의 개념이 포함되어 있지 않습니다.메서드를 변환자로 표시할 방법은 없습니다.따라서 이 언어에는 객체의 불변성을 강제할 방법이 없습니다.

언급URL : https://stackoverflow.com/questions/2435163/why-can-final-object-be-modified

반응형