이 수업이 있다고 상상해보십시오.
public class Test
{
private String[] arr = new String[]{"1","2"};
public String[] getArr()
{
return arr;
}
}
이제 위의 클래스를 사용하는 다른 클래스가 있습니다.
Test test = new Test();
test.getArr()[0] ="some value!"; //!!!
그래서 이것은 문제입니다 : 나는 외부에서 클래스의 개인 필드에 액세스했습니다! 이 문제를 어떻게 방지 할 수 있습니까? 이 배열을 어떻게 불변으로 만들 수 있습니까? 이것은 모든 getter 메소드에서 개인 필드에 액세스하기 위해 노력할 수 있음을 의미합니까? (구아바와 같은 라이브러리는 원하지 않습니다. 올바른 방법을 알아야합니다.)
답변
배열 의 사본 을 반환해야합니다 .
public String[] getArr() {
return arr == null ? null : Arrays.copyOf(arr, arr.length);
}
답변
배열 대신 List를 사용할 수있는 경우 Collections는 수정할 수없는 목록을 제공합니다 .
public List<String> getList() {
return Collections.unmodifiableList(list);
}
답변
수정 private
자는 필드 자체 만 다른 클래스에서 액세스하지 못하도록 보호하지만이 필드의 객체 참조는 아닙니다. 참조 된 개체를 보호해야하는 경우에는 제공하지 마십시오. 변화
public String [] getArr ()
{
return arr;
}
에:
public String [] getArr ()
{
return arr.clone ();
}
또는
public int getArrLength ()
{
return arr.length;
}
public String getArrElementAt (int index)
{
return arr [index];
}
답변
은 Collections.unmodifiableList
이미 언급 된 – Arrays.asList()
이상하게 없습니다! 내 해결책은 외부에서 목록을 사용하고 다음과 같이 배열을 래핑하는 것입니다.
String[] arr = new String[]{"1", "2"};
public List<String> getList() {
return Collections.unmodifiableList(Arrays.asList(arr));
}
배열 복사의 문제점은 코드에 액세스 할 때마다 배열을 수행하고 배열이 큰 경우 가비지 수집기에 대해 많은 작업을 수행한다는 것입니다. 따라서 사본은 간단하지만 실제로 나쁜 접근 방식입니다. “저렴한”이라고 말하지만 메모리가 비쌉니다! 특히 2 개 이상의 요소가있는 경우.
당신의 소스 코드를 보면 Arrays.asList
및 Collections.unmodifiableList
이 실제로 많이 만들어지지 않습니다. 첫 번째는 복사하지 않고 배열을 래핑하고 두 번째는 목록을 래핑하여 변경 사항을 사용할 수 없게합니다.
답변
ImmutableList
표준보다 나은 것을 사용할 수도 있습니다 unmodifiableList
. 이 수업은 Google 에서 만든 구아바 라이브러리의 일부입니다 .
설명은 다음과 같습니다.
여전히 변경할 수있는 별도의 컬렉션에 대한보기 인 Collections.unmodifiableList (java.util.List)와 달리 ImmutableList의 인스턴스에는 자체 개인 데이터가 포함되어 있으며 절대 변경되지 않습니다.
사용 방법에 대한 간단한 예는 다음과 같습니다.
public class Test
{
private String[] arr = new String[]{"1","2"};
public ImmutableList<String> getArr()
{
return ImmutableList.copyOf(arr);
}
}
답변
이 관점에서 시스템 배열 사본을 사용해야합니다.
public String[] getArr() {
if (arr != null) {
String[] arrcpy = new String[arr.length];
System.arraycopy(arr, 0, arrcpy, 0, arr.length);
return arrcpy;
} else
return null;
}
}
답변
데이터 사본을 리턴 할 수 있습니다. 데이터 변경을 선택한 발신자는 사본 만 변경합니다.
public class Test {
private static String[] arr = new String[] { "1", "2" };
public String[] getArr() {
String[] b = new String[arr.length];
System.arraycopy(arr, 0, b, 0, arr.length);
return b;
}
}