早上好,我正在学习java,我有一个问题。 我有一个带有构造函数的类“table”,它接受一个“fields”,并把它放在PRIVATE变量中。
问题是:传递对象并使用“=”放入PRIVATE变量是正确的,还是最好克隆它? 如果我使用“=”,我的类中的变量仍然可以从使用类的构造函数的方法中编辑,并最终在其中放入NULL。
例如:
class Table{
private Field field;
table (Field field)
{this.field=field;}
public String getValue()
{return field.toString(); }
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
,结果为“VALUE2”。 所以在表中传递了一个值,然后我改变了它。 但对于“良好的编程艺术”,它是可以接受的,或者是更好的
class Table{
private Field field;
table (Field field)
{this.field=field.clone();}
public String getValue()
{return field.toString();}
}
main{
Field field=new Field("VALUE1");
Table table(field);
field.value="VALUE2";
System.out.println(table.field.getValue());
}
打印VALUE1
所以如果我将值传递给Table,我不能在不使用Table方法的情况下修改它吗?
这是正确的方法吗?
答案 0 :(得分:1)
这是一个很好的问题,并指出了一个真正的问题。建议的方法是让你的类不可变。
所以问题不在Table类中,而是在Field类中 - 它应该只允许通过构造函数修改值,而不是通过直接更改或使用setter。这样你就不会遇到这个问题。
答案 1 :(得分:1)
声明变量private与其不变性无关。如果传递给你的对象不是不可变的,那么我建议制作一个(深层)副本,否则你不能依赖它不在其他地方被改变。
其他方式是使Field类不可变,然后您不必复制,只需将引用保存在私有字段中。
答案 2 :(得分:0)
在Java中没有正确或错误的方法。 Java通过引用传递对象,您需要了解通过引用传递的对象通常是可变的,这意味着它们可以更改状态。在Java中,这是预期的行为,但最初可能会令人困惑。在多线程环境中管理也很困难。
您可以选择@eis指示使用不可变对象。这有许多优点,特别是在多线程代码中,但也有一些缺点。这个讨论太长,涉及到这里。
如果您特别关注Java集合,那么集合框架允许您使集合不可变。有关如何执行此操作的详细信息,请参阅java.util.Collections.unmodifiable *方法。这些方法可以对集合进行不可修改的视图,而无需克隆数据的开销。
当您希望第二个对象在其生命周期内查看原始对象时,无论您如何更改它,请在传递它之前克隆它,或者首先使用不可变对象。如果要确保第二个对象无法更改对象,请将其设置为不可变或使用Java集合中的只读视图。
答案 3 :(得分:0)
早上好。 我猜你已经知道Java是通过引用值传递的,所以在第一种情况下,table.field和field是同一对象的“指针”。因此,修改一个将修改另一个,反之亦然。如果这是你想要的,那么你的第一个实现是正确的。
另一方面,如果您只想传递一个对象并且您不会使用您创建的对象字段,那么以下更适合:
Table table(new Field("Value 1"));
最后,如果您只想传递值,则field和table.field引用碰巧具有相同值的不同对象。修改一个不会修改另一个。 clone()方法是一种有效的解决方案,但并非所有类都实现此方法。如果类Field不支持方法clone(),那么最好的办法是在Field类中实现类似的方法:
class Field {
//...Your code...
//First possibility
public void copyField(Field originalField) {
this.atribute1 = originalField.attribute1;
this.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
//Second possibility (a static method)
public static void copyField(Field newField, Field originalField) {
newField.atribute1 = originalField.attribute1;
newField.atribute2 = originalField.attribute2;
//This way you copy all the attributes manually
}
}
//**Using each method to make a copy of field1 in field2**
Field field1 = new Field(...);
Field field2 = new Field();
field2.copyField(field1); //Non-static method
Field.copyField(field1, field2); //Static method
另一个解决方案是制作一个与非静态方法几乎完全相同的复制构造函数:
public Field(Field fieldToCopy) {
this.atribute1 = fieldToCopy.attribute1;
this.atribute2 = fieldToCopy.attribute2;
//...
}
正如您所看到的,有几种正确的方法可以做到这一点。您需要能够根据您正在解决的特定问题选择并实施其中任何一个。