setterFunction
과같이 final도 아닌 setter로 열려있다면public class Person {
private final String name;
private final Record record;
public Person(String name, Record record) {
this.name = name;
this.Record = record;
}
public String getName() {
return name;
}
public Record getRecord() {
return record;
}
}
public class Record {
private long score;
public Record(long score) {
this.score = score;
}
public void setterFunction(long score) { // setter
this.score = score;
}
}
Lotto lotto = new Lotto(Arrays.asList(1,2,3,4,5,6));
List<Integer> numbers =lotto.getLottoNumbers();
numbers.add(7);
가령 이러한 코드가 있다한다면 getLottoNumbers로 필드인 lottoNumbers는 final이지만 외부로 꺼낼 수 있다.
add, remove 등 list의 메서드들을 사용하여 컬렉션에 변화를 줄수 있고. lottoNumbers가 재할당이 불가능 한것이지 불변객체
가 아니기 때문에 list에 add를 객체를 변경 시킬수 있다. (새로운 List 객체를 만드는 것이아닌 요소를 추가하는 것 일뿐)
이러한 컬렉션 list를 불변으로 지키고싶다Collections.unmodifiableList
를 사용해야한다
결론 적으로는 단순히 final은 재할당을 막아줄뿐 불변성을 만들어 주지는 않는다.
public class Lotto {
private final List<Integer> lottoNumbers;
public Lotto(List<Integer> lottoNumbers) {
this.lottoNumbers = List.copyOf(lottoNumbers);
}
public List<Integer> getLottoNumbers() {
return lottoNumbers;
}
}
Unmodifiable 수정 할수 없다. 즉 'Read-Only' 용도로만 사용할 수 있다. set(), add()메서드들을 사용하면 예외가 발생한다.
하지만 Collections.unmodifiableList
사용시 주의 할점이있다. 기존 list와의 참조(연결)을 끊지 않았기 때문에 add하면 값이 추가된다.
Immutable 어떤 레퍼런스를 이용해서라도 수정할 수 없어야 한다. 기존 컬렉션의 데이터를 새로운 컬렉션으로 복사한 다음,
새로운 컬렉션으로의 수정(modify) 접근을 제한하는게 일반적이다.
따라서 컬렉션의 불변성을 유지하기 위해서는 생성자에서는 방어적 복사를 하고, 불변성을 보장하기 위해서는, getter에서는 방어적 복사 또는
unmodifiableList 반환 중 선택해서 진행하는 것을 권장한다.
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
List<String> unmodifiableList = Collections.unmodifiableList(list);
list.add("d");
System.out.println(unmodifiableList.get(3));
}
}
불필요한 연산을 하지 않을 수있다. 함수형 프로그래밍을 이해하기 위해서는 이해해야한다. 반대로는 Eager Evaluation(조급한 연산)
보통의 반복문으로 모든 조건을 다 계산하고 구한다(조급한 연산) Stream을 이용해 첫번째 조건을 구하면 다음 조건은 피한다. (느긋한 연산)
자유변수
란 람다식 내에서 정의되지 않고, 또 파라미터로도 전달되지 않은function curry(f) { // 커링 변환을 하는 curry(f) 함수
return function (a) {
return function (b) {
return f(a, b);
};
};
}