program story

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

inputbox 2020. 10. 4. 11:00
반응형

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


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

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키워드는 반드시 참조가 변경되지 않습니다를 만드는 데 사용됩니다 (즉,이 새 것으로 대체 할 수있다 참조)

그러나 속성 자체가 수정 가능한 경우 방금 설명한대로 수행해도됩니다.

예를 들어

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

이 클래스를 인스턴스화하면 finalsomeFinalObject 이기 때문에 속성에 다른 값을 할당 할 수 없습니다 .

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

....
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);
}

여기에서 INSTANCE의 값을 변경하지 않고 내부 상태를 수정하고 있습니다 (via, provider.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 :) 
....

그러나 그것은별로 의미가 없을 수도 있습니다. :)

그건 그렇고, 기본적으로 같은 이유로 액세스를 동기화 해야합니다 .


The key to the misunderstanding is in your question's title. It's not the object which is final, it's the variable. The variable's value can't change, but the data within it can.

Always remember that when you declare a reference type variable, the value of that variable is a reference, not an object.


final just means the reference can't be changed. You can't reassign INSTANCE to another reference if it's declared as final. The internal state of the object is still mutable.

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

would throw a compilation error


Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if a final variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.

Source

Here's a guide on making an object immutable.


Final and immutable are not the same thing. Final means the reference cannot be reassigned so you can't say

INSTANCE = ...

Immutable means that the object itself cannot be modified. An example of this is the java.lang.String class. You cannot modify the value of a string.


Java doesn't have the concept of immutability built into the language. There is no way to mark methods as a mutator. Therefore the language has no way to enforce object immutability.

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

반응형