programing

수업에서 개인 필드의 수정을 방지하려면 어떻게 해야 하는가?

prostudy 2022. 5. 20. 21:36
반응형

수업에서 개인 필드의 수정을 방지하려면 어떻게 해야 하는가?

내가 이런 수업을 한다고 생각해봐:

public class Test
{
  private String[] arr = new String[]{"1","2"};    

  public String[] getArr() 
  {
    return arr;
  }
}

이제, 나는 위의 수업을 사용하는 다른 수업이 있다.

Test test = new Test();
test.getArr()[0] ="some value!"; //!!!

그래서 이것이 문제다.나는 밖에서 수업의 사적인 영역에 접속했다!어떻게 하면 이것을 막을 수 있을까?어떻게 하면 이 배열을 불변하게 할 수 있을까?이것은 모든 게터 방법을 동원해서 민간 분야에 접근하기 위해 노력해도 된다는 뜻인가? (과바 같은 도서관은 원하지 않는다.올바른 방법만 알면 된다.)

배열 대신 목록을 사용할 수 있는 경우 컬렉션은 수정할 수 없는 목록을 제공한다.

public List<String> getList() {
    return Collections.unmodifiableList(list);
}

어레이의 복사본을 반환하십시오.

public String[] getArr() {
  return arr == null ? null : Arrays.copyOf(arr, arr.length);
}

수식어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));
}

배열을 복사할 때의 문제는 코드에 액세스할 때마다 배열이 크면 쓰레기 수거업자에게 확실히 많은 작업을 생성한다는 점이다.그래서 그 복사본은 간단하지만 정말 나쁜 접근법이다. "싸다"라고 말하고 싶지만, 기억력은 비싸다!특히 두 가지 이상의 요소가 있을 때는 더욱 그렇다.

의 소스 코드를 보면Arrays.asList그리고Collections.unmodifiableList사실 별로 만들어지지 않았다.첫 번째는 어레이를 복사하지 않고 랩으로 감싸기만 하고, 두 번째는 목록을 랩으로 감싸서 변경 사항을 사용할 수 없게 한다.

당신은 또한 표준보다 더 나은 것을 사용할 수 있다.unmodifiableList이 수업은 구글에 의해 만들어진 Guava 라이브러리의 일부분이다.

다음 설명은 다음과 같다.

Collections.unmodifiedList(java.util)와 달리.목록)은 여전히 변경할 수 있는 별도의 컬렉션의 보기입니다. ImableList의 인스턴스는 자체적인 개인 데이터를 포함하며 절대 변경되지 않음

사용 방법의 간단한 예는 다음과 같다.

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;
    }
}

문제의 핵심은 당신이 돌연변이 물체에 포인터를 돌려준다는 것이다.웁스. 객체를 불변하게 렌더링하거나(수정 불가능한 목록 솔루션) 객체의 복사본을 반환하십시오.

일반적으로 물체의 미세성은 물체가 변이될 경우 물체가 변경되는 것을 보호하지 않는다.이 두 가지 문제는 "키스 사촌"이다.

수정할 수 없는 목록을 반환하는 것은 좋은 생각이다.그러나 getter 메서드에 대한 호출 중 수정할 수 없는 목록은 여전히 클래스 또는 클래스에서 파생된 클래스에 의해 변경될 수 있다.

대신, 당신은 그 목록을 수정해서는 안 된다는 것을 클래스를 확장하는 누구에게도 분명히 해야 한다.

예를 들어 다음과 같은 코드로 이어질 수 있다.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Test {
    public static final List<String> STRINGS =
        Collections.unmodifiableList(
            Arrays.asList("1", "2"));

    public final List<String> getStrings() {
        return STRINGS;
    }
}

위의 예에서 나는 다음과 같이 말했다.STRINGS현장 공개, 원칙적으로 당신은 메서드 콜을 제거할 수 있다, 그 값은 이미 알려져 있다.

또한 문자열을 에 할당할 수도 있다.private final List<String>클래스 인스턴스(instance)를 구성하는 동안 수정할 수 없는 필드.(시뮬레이터의) 상수 또는 인스턴스화 인수를 사용하는 것은 클래스 설계에 따라 달라진다.

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Test {
    private final List<String> strings;

    public Test(final String ... strings) {
        this.strings = Collections.unmodifiableList(Arrays
                .asList(strings));
    }

    public final List<String> getStrings() {
        return strings;
    }
}

예, 어레이 복사본을 반환하십시오.

 public String[] getArr()
 {
    return Arrays.copyOf(arr);
 }

Java 9 이후, 고정적인 공장 방식에서 불변 리스트를 구성할 수도 있으며, 이 방법에서는 수입과 코드가 약간 줄어들게 된다.

을 별이에서 은 경우이다.getUsers()대로가 .users필드를 수정할 수 있음:

class Computer {
    private String[] users = new String[] {"user1", "user2", "user3"};
    public String[] getUsers;

    String[] getUsers() {
        return this.users;
    }
}

Computer c = new Computer();
c.getUsers()[0] = "me";
for (String user: c.getUsers()) {
    System.out.println(user);
}

출력:

me
user2
user3

불변 목록 사용:

import java.util.List;

class Computer {
    private String[] users = new String[] {"user1", "user2", "user3"};
    public List<String> getUsers;

    List<String> getUsers() {
        return List.of(this.users);
    }
}

Computer c = new Computer();
c.getUsers().set(0, "me");
for (String user: c.getUsers()) {
    System.out.println(user);
}

출력:

user1
user2
user3

참조URL: https://stackoverflow.com/questions/14809293/how-do-i-prevent-the-modification-of-a-private-field-in-a-class

반응형