Java中的访问器方法

所以我对“setter”和“getter”方法有疑问,以及它们是否有用。

假设我只是写了一个非常基本的程序,如下所示:

public class Account { String name; String address; double balance; } 

然后,假设我编写另一个使用此“帐户”类的类,如下所示:

  class UseAccount { public static void main(String[] args) { Account myAccount = new Account(); Account yourAccount = new Account(); myAccount.name = "Blah blah" } } 

等等

当我写myAccount.name = "Blah blah" ,我正在更改“Account”类中变量“name”的值。 我可以自由地按照我喜欢的方式执行此操作。 但是,我注意到,最好将“帐户”类中的变量设为私有,然后使用“setter”和“getter”方法。 所以,如果我写下面的内容:

  public class Account { private String name; private String address; private String balance; public void setName(String n) { name = n; } public String getName() { return name; } } 

我仍然可以通过创建另一个具有以下内容的类来更改变量“name”的值:

  class UseAccount { public static void main(String[] args) { Account myAccount = new Account(); myAccount.setName("Blah blah"); } } 

我不明白使用这种方法有什么不同或者应该阻止人们改变私有字段的价值。 有帮助吗?

试试这个面向对象编程的黄金法则。

1.创建私有实例变量。

2.创建公共 getter和setter以访问这些Instance变量。

这种方法称为封装 。 虽然Encapsulation可以以不同的方式使用 ,但这在设计模式中很重要,就像那些不断变化的行为必须封装在抽象类或接口中。

好吧现在回到Getter和Setter的主题….

Getter和Setter帮助validation实例变量的输入。

例如:假设我有一个方法来分配狗的年龄,现在年龄不能为负,如果我没有setter方法,那么我将无法validation年龄的输入。

 private int age; public void setDogAge(int age){ if (age>0){ this.age = age; } else{ System.out.println("Please Enter a Valid Age"); } } 

使用简单的访问器方法,除了样式之外没有区别,但您也可以使用它们执行代码,例如:

 public void setName(String name) { if (name == null) { throw new IllegalArgumentException("Name may not be null"); } this.name = name; } 

您还可以从getter返回副本 ,从而保护您的数据:

 private List middleNames; public List getMiddleNames() { return new ArrayList(middleNames); // return a copy // The caller can modify the returned list without affecting your data } 

这只是两个简单的例子,但是有关如何使用访问器方法的无限例子。

最好遵循一致的样式,这就是为什么我们总是使用getter / setter – 所以如果需要的话可以执行这样的代码。

使用setter和getter的优点是你可以包含延迟初始化,validation等规则。另外,如果你需要实现Java Beans投诉代码,你需要遵循这些规则。

Java Beans规范

如果你的代码永远不会改变那么你是对的 – 没有区别。

但是,代码变化很大。 如果您需要跟踪谁修改了他们的名字,会发生什么?

您需要在Account类中有一个布尔值,只要名称字段发生更改,该布尔值就会变为true。

所以现在你必须浏览每个源文件并放一个

每个下面都有myAccount.nameChanged = true'

myAccount.name = whatever;

因此,您开始使用代码重复,并且可能会增加错误。 如果我错过了名字变更怎么办?

抵消这种情况的最佳方法是将成员变量归类为private

你的setName代码看起来像这样:

 public void setName(String newName) { name = newName; nameChanged = true; } 

而且你不必担心错误!

当您声明一些私有实例变量并声明public gettersetter method来访问和更改实例变量值时,这称为Encapsulation

如果您正在使用这些getter和setter方法来访问/设置实例变量,那么如果开发人员更改了实例变量名,那么它会使您的程序不会失败。

例如,在当前版本中,您使用名称,地址,平衡实例变量,并且在没有getter和setter方法的情况下访问它们,例如myAccount.setName("Blah blah"); 但是如果下一个版本开发人员将实例变量名称从name更改为userName ,那么用户程序将会中断,但如果你使用getter和setter,它不会破坏,因为开发人员不会更改getter和setter方法名称(根据OOPS基础知识)。

您总是可以在不使用getter和setter方法的情况下开发应用程序。正如您所解释的那样。但是使用getter和setter是更好的做法,因为访问修饰符private / public为您提供了OOPSfunction的封装。 你总是可以在不使用封装,抽象,inheritance等OOPSfunction的情况下编写你的程序……但是如果你不使用大型应用程序而你将无法维护,很快就会意识到这些function的重要性。

事实上,它不会阻止,并且在您更改getter / setter方法的访问修饰符或向其中添加其他逻辑之前没有区别。 后者并不总是一个好主意,但有时会有所帮助,例如更新名称应强制更新某些缓存值或执行某些检查。 使用getter / setter是一种很好的做法,并且在POJO和JavaBeans等几种方法中使用,但是如果你不打算在getter / setter中添加自定义逻辑并且不打算使用这些方法,那么你将对使用直接访问字段感到满意。

有一件事我想提一下。 使用getter / setter可以提供在对象中不存在的运行时字段中计算的数据。 例如,您的Account类的对象包含出生日期,您需要获得它的年龄。

每个Account类的字段声明前面的java关键字“private”阻止直接引用该字段。 如果您在UseAccount类中输入myAccount.name =“whatever”,则会收到错误消息:“name在Account中具有私有权限”。 UseAccount程序员不需要引用myAccount.name,而是需要调用方法myAccount.setName或方法myAccount.getName。 这些方法称为访问器方法,因为它们提供对Account类字段的访问。