불변 클래스?
Java 클래스를 불변으로 만들 수있는 방법은 무엇이며 불변성의 필요성은 무엇이며 이것을 사용하면 어떤 이점이 있습니까?
불변 객체 란 무엇입니까?
불변 객체는 인스턴스화 된 후에 상태를 변경하지 않는 객체입니다.
객체를 불변으로 만드는 방법?
일반적으로 불변 객체는 노출 된 멤버가없고 setter가없는 클래스를 정의하여 만들 수 있습니다.
다음 클래스는 불변 객체를 만듭니다.
class ImmutableInt {
private final int value;
public ImmutableInt(int i) {
value = i;
}
public int getValue() {
return value;
}
}
위의 예에서 볼 수 있듯이의 값은 ImmutableInt
객체가 인스턴스화 될 때만 설정 될 수 있으며 getter ( getValue
) 만 있으면 인스턴스화 후에 객체의 상태를 변경할 수 없습니다.
그러나 개체가 참조하는 모든 개체도 변경 불가능해야하며 그렇지 않으면 개체의 상태를 변경할 수 있다는 점에주의해야합니다.
예를 들어 배열에 대한 참조를 허용하거나 ArrayList
getter를 통해 가져 오도록 허용하면 배열 또는 컬렉션을 변경하여 내부 상태를 변경할 수 있습니다.
class NotQuiteImmutableList<T> {
private final List<T> list;
public NotQuiteImmutableList(List<T> list) {
// creates a new ArrayList and keeps a reference to it.
this.list = new ArrayList(list);
}
public List<T> getList() {
return list;
}
}
위 코드의 문제점 ArrayList
은를 통해 획득 getList
하고 조작 할 수있어 객체 자체의 상태가 변경되어 불변이 아니라는 것입니다.
// notQuiteImmutableList contains "a", "b", "c"
List<String> notQuiteImmutableList= new NotQuiteImmutableList(Arrays.asList("a", "b", "c"));
// now the list contains "a", "b", "c", "d" -- this list is mutable.
notQuiteImmutableList.getList().add("d");
이 문제를 해결하는 한 가지 방법은 getter에서 호출 될 때 배열 또는 컬렉션의 복사본을 반환하는 것입니다.
public List<T> getList() {
// return a copy of the list so the internal state cannot be altered
return new ArrayList(list);
}
불변성의 장점은 무엇입니까?
불변성의 장점은 동시성입니다. 여러 스레드가 동일한 객체의 상태를 변경하려고 할 수 있기 때문에 변경 가능한 객체의 정확성을 유지하는 것은 어렵습니다. 목적.
불변 객체를 가짐으로써 불변 객체의 상태가 변경되지 않기 때문에 객체를보고있는 모든 스레드가 동일한 상태를 보게 될 것입니다.
이미 주어진 답변 외에도, 놓치기 쉬운 세부 사항 (예 : 방어 적 사본)이 있으므로 Effective Java, 2nd Ed.의 불변성에 대해 읽는 것이 좋습니다. 또한, Effective Java 2nd Ed. 모든 Java 개발자가 반드시 읽어야 할 문서입니다.
다음과 같이 클래스를 불변으로 만듭니다.
public final class Immutable
{
private final String name;
public Immutable(String name)
{
this.name = name;
}
public String getName() { return this.name; }
// No setter;
}
다음은 Java 클래스를 변경 불가능하게 만들기위한 요구 사항입니다.
- 클래스 를 다음과 같이 선언해야합니다
final
(하위 클래스를 만들 수 없음). - 클래스의 멤버 는 다음과 같이 선언되어야합니다
final
(객체 생성 후 값을 변경할 수 없도록) - 멤버 값 을 가져 오기 위해 모든 변수에 대해 Getter 메서드 를 작성 합니다.
- Setters 메서드 없음
불변 클래스는
스레드로부터 안전 하기 때문에 유용 합니다.
-그들은 또한 당신의 디자인에 대해 깊은 것을 표현합니다 : "이것을 바꿀 수 없습니다.", 그것이 적용되면 정확히 당신이 필요로하는 것입니다.
불변성은 주로 두 가지 방법으로 달성 할 수 있습니다.
final
재 할당을 피하기 위해 인스턴스 속성 사용- 클래스 내부의 내용을 수정할 수있는 작업을 허용하지 않는 클래스 인터페이스를 사용합니다 ( 게터 만 사용 하고 세터 없음
불변성의 장점은 다음 객체에 대해 할 수있는 가정입니다.
- 부작용이없는 규칙 (함수 프로그래밍 언어에서 매우 인기가 있음)을 얻고 동시 환경에서 객체를 더 쉽게 사용할 수 있습니다. 객체가있을 때 원자 적 또는 비원 자적 방식으로 변경할 수 없다는 것을 알고 있기 때문입니다. 많은 스레드에서 사용
- 언어 구현은 이러한 객체를 다른 방식으로 처리하여 정적 데이터에 사용되는 메모리 영역에 배치하여 이러한 객체를 더 빠르고 안전하게 사용할 수 있도록합니다 (이는 문자열의 JVM 내부에서 발생합니다).
불변 클래스는 인스턴스화 된 후에 값을 재 할당 할 수 없습니다. 생성자는 개인 변수에 값을 할당합니다. 개체가 null이 될 때까지 setter 메서드를 사용할 수 없기 때문에 값을 변경할 수 없습니다.
불변하기 위해서는 다음을 만족해야합니다.
- Al 변수는 private 이어야합니다 .
- mutator 메서드 (세터)가 제공 되지 않습니다 .
- class final (Strong Immutability) 또는 메서드를 final (Week immutability)로 만들어 메서드 재정의를 피하십시오.
- 기본이 아니거나 변경 가능한 클래스가 포함 된 경우 깊게 복제하십시오.
/**
* Strong immutability - by making class final
*/
public final class TestImmutablity {
// make the variables private
private String Name;
//assign value when the object created
public TestImmutablity(String name) {
this.Name = name;
}
//provide getters to access values
public String getName() {
return this.Name;
}
}
장점 : 불변 객체는 죽을 때까지 초기화 된 값을 포함합니다.
java-immutable-classes-short-note
불변 클래스 는 생성 후 객체를 변경할 수없는 클래스 입니다.
변경 불가능한 클래스는 다음과 같은 경우에 유용합니다.
- 캐싱 목적
- 동시 환경 (ThreadSafe)
- Hard for inheritance
- Value cannot be changed in any environment
Example
String Class
Code Example
public final class Student {
private final String name;
private final String rollNumber;
public Student(String name, String rollNumber) {
this.name = name;
this.rollNumber = rollNumber;
}
public String getName() {
return this.name;
}
public String getRollNumber() {
return this.rollNumber;
}
}
Another way to make immutable object is using Immutables.org library:
Assuming that required dependencies were added, create an abstract class with abstract accessor methods. You can do the same by annotating with interfaces or even annotations (@interface):
package info.sample;
import java.util.List;
import java.util.Set;
import org.immutables.value.Value;
@Value.Immutable
public abstract class FoobarValue {
public abstract int foo();
public abstract String bar();
public abstract List<Integer> buz();
public abstract Set<Long> crux();
}
It is now possible to generate and then use the generated immutable implementation:
package info.sample;
import java.util.List;
public class FoobarValueMain {
public static void main(String... args) {
FoobarValue value = ImmutableFoobarValue.builder()
.foo(2)
.bar("Bar")
.addBuz(1, 3, 4)
.build(); // FoobarValue{foo=2, bar=Bar, buz=[1, 3, 4], crux={}}
int foo = value.foo(); // 2
List<Integer> buz = value.buz(); // ImmutableList.of(1, 3, 4)
}
}
As a non-native English speaker, I dislike the common interpretation of "immutable class" being "constructed class objects are immutable"; rather, I myself lean to interpret that as "the class object itself is immutable".
That said, "immutable class" is a kind of immutable object. The difference is when answering what the benefit is. To my knowledge/interpretation, immutable class prevents its objects from runtime behavior modifications.
참고URL : https://stackoverflow.com/questions/3162665/immutable-class
'IT박스' 카테고리의 다른 글
npm을 이전 버전으로 다운 그레이드 (0) | 2020.10.05 |
---|---|
자바 : Thread.currentThread (). sleep (x) 대 Thread.sleep (x) (0) | 2020.10.05 |
JFrame의 닫기 버튼 클릭 이벤트를 캡처하는 방법은 무엇입니까? (0) | 2020.10.05 |
Android Studio에서 기본 활동을 찾을 수 없습니다. (0) | 2020.10.05 |
null이 매개 변수를 캐스팅하는 이유는 무엇입니까? (0) | 2020.10.05 |