최종 객체를 수정할 수 있는 이유는 무엇입니까?
작업 중인 코드 베이스에서 다음 코드를 발견했습니다.
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가final
variable은 객체에 대한 참조를 보유하고 있으며 객체의 상태는 객체에 대한 조작에 의해 변경될 수 있지만 변수는 항상 동일한 객체를 참조합니다.어레이는 객체이기 때문에 어레이에도 적용됩니다.final
에 의해 될 수 는 항상 어레이를 합니다.이 경우 어레이의 컴포넌트는 어레이의 조작에 의해 변경될 수 있지만 변수는 항상 같은 어레이를 참조합니다.
여기 불변의 물체를 만드는 방법에 대한 지침이 있습니다.
최종과 불변의 것은 같은 것이 아니다.Final은 참조를 재할당할 수 없으므로 말할 수 없음을 의미합니다.
INSTANCE = ...
불변이란 객체 자체를 수정할 수 없음을 의미합니다.를 들어 " " 입니다.java.lang.String
class 할 수 . 을 사용법
자바에는 불변의 개념이 포함되어 있지 않습니다.메서드를 변환자로 표시할 방법은 없습니다.따라서 이 언어에는 객체의 불변성을 강제할 방법이 없습니다.
언급URL : https://stackoverflow.com/questions/2435163/why-can-final-object-be-modified
'programing' 카테고리의 다른 글
MySQL GUI 도구를 사용하여 필드를 NULL로 만드는 방법 (0) | 2022.09.05 |
---|---|
정적 콘텐츠 서비스용 서블릿 (0) | 2022.09.05 |
IntelliJ에서 Java 클래스의 메서드를 재정렬하는 간단한 방법? (0) | 2022.09.04 |
Joda-Time에서 두 날짜 사이의 일수 (0) | 2022.09.04 |
org.internate 를 선택합니다.hql.internal.ast 입니다.QuerySyntaxException: 테이블이 매핑되지 않았습니다. (0) | 2022.09.04 |