Collections.unmodifiableset ()는 Java에서 무엇을합니까?
-
19-09-2019 - |
문제
나는 그것을 볼 수있다 Collections.unmodifiableSet
주어진 세트의 수정할 수없는보기를 반환하지만 왜 우리가 사용할 수 없는지 이해할 수 없습니다. final
이것을 달성하기위한 수정 자.
내 이해로 final
상수를 선언합니다 : 수정할 수없는 것. 따라서 세트가 상수로 선언되면 수정할 수 없습니다. 세트에서 아무것도 제거 할 수없고 아무것도 추가 할 수 없습니다.
왜 우리에게 필요한가? Collections.unmodifiableSet
?
해결책
final
수정할 수없는 객체 참조를 선언합니다.
private final Foo something = new Foo();
새로운 것을 만듭니다 Foo
그리고 참조를 배치합니다 something
. 그 후, 변경할 수 없습니다 something
다른 사례를 가리 킵니다 Foo
.
이것은 그렇습니다 ~ 아니다 객체의 내부 상태의 수정을 방지합니다. 나는 여전히 모든 방법을 부를 수 있습니다 Foo
관련 범위에 액세스 할 수 있습니다. 해당 메소드 중 하나 이상이 해당 객체의 내부 상태를 수정하면 final
그것을 막지 않습니다.
따라서 다음은 다음과 같습니다.
private final Set<String> fixed = new HashSet<String>();
하다 ~ 아니다 a Set
추가 할 수 없거나 다른 방식으로 변경할 수 없습니다. 그것은 단지 그것을 의미합니다 fixed
해당 인스턴스 만 참조 할 것입니다.
대조적으로 : 수행 :
private Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
a의 인스턴스를 만듭니다 Set
던질 것입니다 UnsupportedOperationException
전화를 시도하는 경우 fixed.add()
또는 fixed.remove()
, 예를 들어 - 객체 자체는 내부 상태를 보호하고 수정되지 않도록합니다.
완전성을 위해 :
private final Set<String> fixed = Collections.unmodifiableSet( new HashSet<String>() );
a의 인스턴스를 만듭니다 Set
내부 상태가 변경 될 수 없으며 fixed
해당 세트의 인스턴스 만 지적합니다.
그 이유 final
프리미티브의 상수를 생성하는 데 사용될 수 있습니다. 값을 변경할 수 없다는 사실에 기초합니다. 기억 fixed
위는 단지 참조 일뿐입니다 - 변경할 수없는 주소가 포함 된 변수입니다. 글쎄, 프리미티브의 경우, 예를 들어
private final int ANSWER = 42;
의 가치 ANSWER
그게 42입니다 ANSWER
변경할 수 없습니다. 값 42 만 있으면됩니다.
모든 줄을 흐리게하는 예는 다음과 같습니다.
private final String QUESTION = "The ultimate question";
위의 규칙에 따라 QUESTION
인스턴스의 주소를 포함합니다 String
"궁극적 인 질문"을 나타내며 그 주소는 변경할 수 없습니다. 여기서 기억해야 할 것은 그 것입니다 String
그 자체는 불변입니다 - 당신은 String
그것을 변경하고 그렇지 않으면 그렇게 할 작업 (예 : replace
, substring
, 등) 완전히 다른 인스턴스에 대한 참조를 반환합니다. String
.
다른 팁
final
이를 보장합니다 참조 변수를 나타내는 객체에 따라 변경할 수 없습니다. 객체의 인스턴스와 그 돌연변이에 대해서는 아무것도하지 않습니다.
final Set s = new Set();
할 수없는 것을 보장합니다 s = new Set();
다시. 설정을 수정할 수 없게 만들지는 않습니다. 처음에는 아무것도 추가 할 수 없었습니다. 그래서 그것을 명확하게하기 위해 final
변수에만 영향을줍니다 참조 참조가 가리키는 객체가 아닙니다.
다음을 수행 할 수 있습니다.
final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);
그러나 나는 이것을 할 수 없다.
l = new ArrayList<String>();
다시 final
변수 L이 무엇을 가리키는 지 수정할 수 없습니다.
컬렉션 컨테이너 스레드를 안전하게 만들려면 다음 세 가지 중 하나를 수행해야합니다.
java.util.Collections.syncronizedXXX();
또는
java.util.Collections.unmodifiableXXX();
또는 적절한 용기 중 하나를 사용하십시오 java.util.concurrency.* package
.
내가 가지고 있다면 Person
대상과 그랬습니다 final Person p = new Person("me");
재 할당 할 수 없다는 것을 의미합니다 p
다른 사람을 가리키는 것 Person
물체. 나는 여전히 할 수 있습니다 p.setFirstName("you");
상황을 혼란스럽게하는 것은 바로 그 것입니다
final int PI = 3.14;
final String greeting = "Hello World!";
보입니다 const
C ++에서, 실제로 그들이 가리키는 물체가 본질적으로 불변/지정할 수없는 경우. 객체의 내부 상태를 변경할 수있는 뮤지토 방법이있는 컨테이너 또는 물체는 const
그냥 그 참조 그 대상들에게 final
그리고 재 할당 할 수 없습니다 참조 다른 대상.
final
그렇지 않음 (C ++ -Style) const
. C ++와 달리 Java는 가지고 있지 않습니다 const
-메트로 드 또는 그와 비슷한 것, 그리고 객체를 변경할 수있는 메소드는 final
참조.
Collections.unmodifiable*
해당 컬렉션의 읽기 전용을 시행하는 래퍼입니다.
그만큼 Collections.unmodifiableSet(Set<? extends T>)
원본 세트에서 래퍼를 만듭니다. 이 래퍼 세트는 수정할 수 없습니다. 그러나 여전히 원래 세트를 수정할 수 있습니다.
예시:
Set<String> actualSet=new HashSet<String>(); //Creating set
일부 요소 추가
actualSet.add("aaa");
actualSet.add("bbb");
추가 요소 인쇄
System.out.println(actualSet); //[aaa, bbb]
꼭 actualSet
수정할 수없는 세트로 및 새로운 참조에 할당됩니다 (wrapperSet
).
Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);
Wrapperset을 인쇄하십시오. 그래서 그것은 가질 것입니다 actualSet
가치
System.out.println(wrapperSet); //[aaa, bbb]
하나의 요소를 제거/추가하려고합니다 wrapperSet
.
wrapperSet.remove("aaa"); //UnSupportedOperationException
하나 더 요소를 추가하십시오 actualSet
actualSet .add("ccc");
인쇄 actualSet
그리고 wrapperSet
. 두 세트 값은 모두 동일합니다. 따라서 실제 설정에 요소를 추가/제거하면 변경 사항이 래퍼 세트에도 반영됩니다.
System.out.println(actualSet); //[aaa, ccc, bbb]
System.out.println(wrapperSet); // [aaa, ccc, bbb]
용법:
이것 Collections.unmodifiableSet(Set<? extends T>)
모든 객체의 세트 getter 메소드 수정을 방지하는 데 사용됩니다. 말하자
public class Department{
private Set<User> users=new HashSet<User>();
public Set<User> getUsers(){
return Collections.unmodifiableSet(users);
}
}
우리가 할 수 있고 할 수 없다고 요약하십시오.
준비:
private Set<String> words = new HashSet<>(Arrays.asList("existing word"));
참조로 최종
private final Set<String> words = new HashSet<>();
~할 수 있다:
words.add("new word");
캔트:
words = new HashSet<>(); //compilation error
참조로 최종 및 컬렉션별로 수정할 수 없습니다.
개인 최종 세트 단어 = collections.unmodifiableSet (단어);
~할 수 있다:
String word = words.iterator().next();
캔트:
words = new HashSet<>(); // compilation error
words.add("new word"); // runtime error UnsupportedOperationException
참조로 최종 및 컬렉션으로 수집 할 수 없지만 컬렉션의 객체로 상호 상호.
하지만 컬렉션이있는 경우 상호간의 개체 해당 객체의 내부 상태를 변경할 수 있습니다.
class A {
public int a; //mutable field. I can change it after initialization
public A(int a) {this.a = a;}
}
private final Set<A> set = Collections.unmodifiableSet(Arrays.asList(new A(25)));
아직도 할 수 없습니다
set = new HashSet<>(); // compilation error
set.add(new A(777)); // runtime error UnsupportedOperationException
하지만 할수있다
A custom = words.iterator().next(); //here custom.a = 25;
custom.a = 777; //here first element of **final, unmodifible** collection
//was changed from 25 to 777