【问题标题】:Accessing private variable of Model class without getters在没有 getter 的情况下访问 Model 类的私有变量
【发布时间】:2015-11-27 09:51:54
【问题描述】:

我的项目中定义了一个模型类。和往常一样,它有一些私有变量和公共 getter 和 setter

public class Person{

 private ArrayList<String> mark;

 public void setMark(ArrayList<String> mark){
  this.mark = mark;
 }

 public void getMark(){
  return this.mark;
 }
}

假设在其他课程中我正在使用这个模型,例如

Person person = new Person();
ArrayList<String> mark = new ArrayList();
mark.add("10");
mark.add("15");
mark.add("18");
person.setMark();

然后person的私有变量保存值“我的名字”,我正在使用类的公共getter访问变量

ArrayList<String> localMark = person.getMark()

据我所知 person.getMark() 返回私有变量名的引用,所以如果我修改局部变量'localMark',那么它将影响 Person 类的私有变量,因此它破坏了私有属性变量

例如:

 ArrayList<String> localMark = person.getMark();
 System.out.println(localMark.get(0)); // will be "10"
 localMark.set(0,"25") // person.mark will be changed
 System.out.println(person.getMark().get(0)); //will be printing "25"

我猜大多数开发人员都遵循相同的设计模式,但是创建Models的正确方法是什么

编辑

根据我检查过的 vinod 的评论,字符串它传递值但不传递引用,但对于 ArrayList...它返回引用。

【问题讨论】:

  • System.out.println(person.getName()); //将打印“新名称” ==> 你检查了吗?我认为您应该检查打印的内容:)
  • 如何修改localName?不变性呢?
  • 我没有,但如果它返回引用,它应该是值不是吗?
  • 我对你的问题投了反对票,因为你发布了一些不会发生在字符串上的东西。 重新分配引用不会改变任何事情,因为 java 是 pass-by-value。接下来,如果您的 getter 返回了 mutable 实例,您对不同类中的实例所做的更改将影响实际实例(您不应该这样做,您应该返回可变实例的防御性副本)
  • @sᴜʀᴇsʜᴀᴛᴛᴀ - 但他应该在发布之前尝试他的代码。 :)。你不认为我的评论给了他足够的信息/提示吗? :)

标签: java model private getter-setter


【解决方案1】:

您有一个对象实例(名称的值)的引用(名称)。由于引用是私有的,因此您可以完全控制它。

当您返回引用时,实际上是return'按值',这意味着返回了引用的副本。两个引用都指向同一个值(String 实例)。

获取引用的外部调用者可以分配一个新值,但您的模型自己的引用不受此影响,仍然指向该值。

就像一条狗(物体)被拴在皮带上(参考)。

  • 当您返回参考时,您将一条新皮带返回给同一只狗。
  • 当狗是可变的(字符串不可变,因此不能修改)时,新引用的所有者可以修改您的狗(抚摸它、刮胡子等等)
  • ...或者他可以将一条新狗系在皮带上
  • ...但他永远不能(抛开思考)将您的浸出液粘在另一只狗身上。

【讨论】:

  • 喜欢狗和皮带的类比。 +1
【解决方案2】:

如果通过调用get() 公开的实例是可变的,那么您在其他地方所做的任何更改都将反映在使用它的实例中。

例子:

methodX classA - 
 List<String> locaNamesList = person.getNamesList();
 locaNamesList.clear();

Somewhere else
methodY classB -
List<String> locaNamesList = person.getNamesList(); // note the same person instance should be used.
//locaNamesList will be empty here

只是重新分配引用不会改变任何事情。

List<String> locaNamesList = person.getNamesList();
locaNamesList = null; // won't change the actual list. You are setting local field locaNamesList to null and not the actual instance.

如果您不希望外部玩家更改原始实例,您必须使用可变实例的防御副本并将它们传递(前提是您不能制作实例本身不可变)

【讨论】:

  • 那么我该如何重新设计我的模型类?你说的防御性副本是什么意思?
  • @VividVervet - 防御性复制意味着 - 创建一个与原始对象完全相同的新对象。这通常通过复制构造函数完成。您可以使用工厂或其他方法。因此,您将返回实例的副本,而不是实际实例本身
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-07
  • 1970-01-01
  • 2015-03-20
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多