Program Club

최종 ArrayList의 의미는 무엇입니까?

proclub 2020. 11. 29. 12:32
반응형

최종 ArrayList의 의미는 무엇입니까?


ArrayList (또는 다른 Collection)를 최종화하여 얻을 수있는 장점 / 단점은 무엇입니까? 여전히 ArrayList에 새 요소를 추가하고 요소를 제거하고 업데이트 할 수 있습니다. 하지만 이펙트가 최종적으로 만드는 것은 무엇입니까?


하지만 이펙트가 최종적으로 만드는 것은 무엇입니까?

즉, 다른 컬렉션 인스턴스 를 가리 키도록 변수를 리 바인드 할 수 없습니다 .

final List<Integer> list = new ArrayList<Integer>();
list = new ArrayList<Integer>(); // Since `list' is final, this won't compile

스타일 문제로 변경하지 않으려는 대부분의 참조를 final.

여전히 ArrayList에 새 요소를 추가하고 요소를 제거하고 업데이트 할 수 있습니다.

원하는 경우 다음을 사용하여 삽입, 제거 등을 방지 할 수 있습니다 Collections.unmodifiableList().

final List<Integer> list = Collections.unmodifiableList(new ArrayList<Integer>(...));

이는 참조를 다시 할당 할 수 없음을 의미합니다. 아래와 같은 작업을 시도하면 컴파일러 오류가 발생합니다.

final List<String> list = new ArrayList<String>();

list = new LinkedList<String>();
     ^
     Compiler error here

정말 불변 목록을 원한다면 Collections.unmodifiableList()메서드를 사용해야합니다 .


new ArrayList예를 들어 참조를 수정할 수 없습니다 .


변수를 final만들면 할당 된 후에 해당 objest 참조를 다시 할당 할 수 없습니다. 언급했듯이 목록을 변경하는 방법을 계속 사용할 수 있습니다.

final키워드와 Collections.unmodifiableList 사용 을 결합하면 다음과 같이 달성하려는 동작을 얻을 수 있습니다.

final List fixedList = Collections.unmodifiableList(someList);

이로 인해가 가리키는 목록을 fixedList변경할 수 없습니다. 그러나 someList참조를 통해 여전히 변경 될 수 있다는 점에 유의하십시오 (따라서이 계약 이후 범위를 벗어난 지 확인하십시오.)


final 다중 스레딩에서 많은 결과가 있습니다.

  1. JMM은 final필드의 초기화 완료를 확실하게 정의합니다 .

명확하게 정의되지 않은 것은 다음과 같습니다.

  1. 컴파일러는 메모리 장벽을 넘어서 재 배열 할 수 있습니다.
  2. 컴파일러는 항상 캐시 된 사본을 읽을 수 있습니다.

정당하게 관찰 한대로 ArrayList로 할 수있는 작업에는 영향을주지 않습니다. ArrayList 자체는 여전히 변경 가능합니다. 참조를 변경 불가능하게 만들었습니다.

그러나 변수를 최종화하면 다른 이점이 있습니다.

  • 일정하게 유지 될 것으로 예상되는 경우 변수가 변경되는 것을 방지합니다. 이는 향후 버그를 방지하는 데 도움이 될 수 있습니다.
  • 변수 final만드는 것은 컴파일러가 특정 성능을 최적화하는 데 도움이 될 수 있습니다.

일반적으로 불변으로 만드는 것이 많을수록 좋습니다. 따라서 참조를 최종적으로 만드는 것은 (변경 가능한 객체에 대한 참조 인 경우에도) 일반적으로 좋은 생각입니다.


Final은 Java의 키워드 또는 예약어이며 Java의 멤버 변수, 메서드, 클래스 및 로컬 변수에 적용 할 수 있습니다. 참조를 최종적으로 만들면 해당 참조를 변경할 수 없으며 Java에서 최종 변수를 다시 초기화하려고하면 컴파일러가이를 확인하고 컴파일 오류를 발생시킵니다.


aix가 말했듯이 다른 컬렉션으로 다시 바인딩 할 수 없습니다.

예 : 불변 목록 구현과 함께 사용하면 공개 할 수있는 안전한 멤버를 얻을 수 있습니다.

예 : 참조가 변경되지 않으면 최종적으로 필요합니다. 예를 들어 동기화 시나리오에서 마찬가지입니다.

훨씬 더 많은 예가있을 수 있습니다. 참조를 전혀 변경하지 않으려면 멤버를 최종적으로 선언하는 것이 좋습니다.


정말 불변의 목록을 얻으려면 목록 내용의 깊은 복사본을 만들어야합니다. UnmodifiableList는 참조 목록을 다소 불변으로 만 렌더링합니다. 이제 목록 또는 배열의 깊은 복사본을 만드는 것은 크기가 커짐에 따라 메모리에서 힘들 것입니다. 직렬화 / 역 직렬화를 사용하고 배열 / 목록의 전체 복사본을 임시 파일에 저장할 수 있습니다. 멤버 varaible이 변경 불가능해야하므로 setter를 사용할 수 없습니다. getter는 멤버 변수를 파일로 직렬화 한 다음 깊은 복사본을 가져 오도록 지정합니다. Seraialization은 객체 트리의 깊이로 들어가는 본질적인 특성을 가지고 있습니다. 그래도 일부 성능 비용으로 완전한 불변성을 보장합니다.

 package com.home.immutable.serial;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

public final class ImmutableBySerial {

    private final int num;
    private final String str;
    private final ArrayList<TestObjSerial> immutableList;

    ImmutableBySerial(int num, String str, ArrayList<TestObjSerial> list){
        this.num = num;
        this.str = str;
        this.immutableList = getDeepCloned(list);
    }

    public int getNum(){
        return num;
    }

    public String getStr(){
        return str;
    }

    public ArrayList<TestObjSerial> getImmutableList(){
        return getDeepCloned(immutableList);
    }

    private ArrayList<TestObjSerial> getDeepCloned(ArrayList<TestObjSerial> list){
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        ArrayList<TestObjSerial> clonedObj = null;
        try {
             fos = new FileOutputStream(new File("temp"));
             oos = new ObjectOutputStream(fos);
             oos.writeObject(list);
             fis = new FileInputStream(new File("temp"));
             ois = new ObjectInputStream(fis);
             clonedObj = (ArrayList<TestObjSerial>)ois.readObject();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                oos.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return clonedObj;
    }
}

I personally mark the collections field of my classes as final to save the users of my class from checking whether it is null or not. This works because, once the value is already assigned to a final variable, it can never be reassigned to another value, including null.


Essentially what you are trying to achieve here is making the list immutable I guess. However when you mark the list reference final it implies that the reference cant be pointed to any other list object other than this.

If you want a final (immutable) ArrayList go for Collections class's utility method Collections.unmodifaibleList( list ) instead.


I came to think of this same question and coded and example to add to the explanation from yet another angle.

The final arrayList can still be modified, refer to the example below and run it to see for your self.

Here is the immutable class with immutable List declaration:

public final class ImmutableClassWithArrayList {
 final List<String> theFinalListVar = new ArrayList<String>();
}

And here is the driver:

public class ImmutableClassWithArrayListTester {
public static void main(String[] args) {
    ImmutableClassWithArrayList immClass = new ImmutableClassWithArrayList();
    immClass.theFinalListVar.add("name");
    immClass.theFinalListVar.forEach(str -> System.out.println(str));
 }
}

As you can see, the main method is adding (modifying) the list. So the only thing to note is that the "reference" to the object of the collection type can't be re-assigned to another such object. As in the answer by adarshr above, you can't do immClass.theFinalListVar = new ArrayList(); in the main method here.

The modification part really helped me understand this and hope it helps in same way.

참고URL : https://stackoverflow.com/questions/10750791/what-is-the-sense-of-final-arraylist

반응형