java - String[] 指向 VO 对象中的同一个引用

标签 java reference arrays

考虑以下两个类(一个是带有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);
    }
}

执行后结果:

再见世界!!

问题:

我知道 vale 数组变量指的是在构造函数中解析的同一个变量,如果我更改数组中的索引之一,它也会更改相同的 String[]。

如何“修复”或更改 TheVO 类以便我的结果是?:

Hello World !!

最佳答案

您需要使用防御性复制:在您的构造函数中复制 String[]。这确保参数在传递给您的 VO 类后不会被修改。然后复制getter中的String[],避免getter的调用者修改你内部的String[]。复制数组的最简单方法是调用 clone:

this.theValues = theParam.clone();

如果你使用集合而不是数组,你可以通过使用 Collections.unmodifiableList() 包装你的集合来摆脱 getter 中的防御性副本。相反(这是一个更便宜的操作):

private List<String> theValues;

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

不过,您仍然需要构造函数中的防御副本。

关于java - String[] 指向 VO 对象中的同一个引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5661078/

相关文章:

java - 在Java中如何从匿名类外部访问变量

java - 静态代码块有什么用?

PHP 通过引用传递数组

java - 我必须创建一个 deepArray2String 方法,该方法需要一个 2D int 数组 'x' 并返回其字符串表示形式

java - 在 Java 中交换字符串值

java - 如何为导入语句创建自定义 IntelliJ 警告/错误?

c++ - 将局部变量分配给引用参数

c++ - 为什么 C++ 中的 "this"指针是指针而不是引用?

php - 通过对象属性运行循环并赋值

javascript - 如何在 javascript 中打印具有固定列宽的二维数组?