String [] Указывает на ту же ссылку в объекте VO - PullRequest
1 голос
/ 14 апреля 2011

Рассмотрим следующие два класса (один из них Main с методом main()):

Класс VO:

public class TheVO {
    private String[] theValues = null;
    /**
     * 
     */
    public TheVO(String[] theParam) {
        this.theValues = theParam;
    }

    /**
     * 
     * @return
     */
    public String[] getValues(){
        return this.theValues;
    }

    @Override
    public String toString() {
        StringBuffer buf = new StringBuffer("");
        if(this.theValues == null){
            return buf.toString();
        }
        for(String read:this.theValues){
            buf.append(read);
            buf.append(" ");
        }
        return buf.toString().trim();
    }
}

Основной класс:

public class Main {
    /**
     * 
     */
    public Main() {
        super();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        TheVO theV = new TheVO(new String[]{"Hello","World!!"});
        String[] vale = theV.getValues();
        vale[0] = "Goodbye";
        System.out.println(theV);
    }
}

Результат после выполнения:

Goodbye World !!

Вопрос:

Я знаю, что переменная массива vale ссылается на ту же самую переменную, проанализированную в конструкторе, и если я изменю одну изиндексы в массиве он меняет так же String[] в VO.

Как мне "исправить" или изменить класс TheVO так, чтобы мой результат был?:

Hello World !!

Ответы [ 6 ]

2 голосов
/ 14 апреля 2011

Вам нужно использовать защитное копирование: скопируйте String[] в своем конструкторе.Это гарантирует, что параметр не будет изменен после того, как он был передан вашему классу VO.Затем скопируйте String[] в получатель, чтобы вызывающий получатель не изменил ваш внутренний String[].Самый простой способ скопировать массив - это вызвать clone:

this.theValues = theParam.clone();

Если бы вы использовали коллекции вместо массивов, вы могли бы избавиться от защитной копии в геттере, обернув вашу коллекцию с помощью Collections.unmodifiableList() вместо этого (что является намного более дешевой операцией):

private List<String> theValues;

public List<String> getValues(){
        return Collections.unmodifiableList(this.theValues);
}

Вам все равно понадобится защитная копия в конструкторе, 'хотя.

1 голос
/ 14 апреля 2011

изменить метод getValues ​​() для клонирования массива ...

Примерно так ...

public String[] getValues(){
    return this.theValues.clone();
}
1 голос
/ 14 апреля 2011

Создайте копию массива в вашем конструкторе VO

1 голос
/ 14 апреля 2011

Я бы предложил выполнить копию внутреннего массива при возврате из TheVO.getValues().Если вы работаете на Java 1.6, вы можете использовать метод Arrays.copyOf().

public String[] getValues() {
    return Arrays.copyOf(theValues, theValues.length);
}

Обратите внимание, что нет необходимости использовать this для доступа к полю экземпляра здесь.

1 голос
/ 14 апреля 2011

Вы можете попробовать изменить getValues ​​();метод для возврата копии массива TheVO.theValues ​​вместо ссылки на исходный массив.

1 голос
/ 14 апреля 2011

Вы можете дублировать (или клонировать) вашу String [] в методе getValues ​​().

Таким образом, создав новый массив, вы потеряете связь между массивами String.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...