Java中的访问器方法

时间:2012-07-16 04:53:09

标签: java methods accessor

所以我对“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"时,我正在更改“帐户”类中变量“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");
       }
    }

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

8 个答案:

答案 0 :(得分:7)

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

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

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

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

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

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

答案 1 :(得分:6)

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

1。创建私有实例变量。

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

3。此方法称为封装。虽然封装可用于不同的    方式,这在设计模式中很重要,就像那些不断变化的行为一样    被封装在抽象类或接口中。

4. 现在回到Getter和Setter的话题......

Getter和Setter有助于验证实例变量的输入。

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

private int age;

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

答案 2 :(得分:2)

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

Java Beans spec

答案 3 :(得分:1)

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

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

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

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

每个

下的

myAccount.nameChanged = true'

myAccount.name = whatever;

因此,您开始进行代码重复,并且错误的可能性会增加。如果我错过了名称更改,会发生什么?

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

您的setName代码如下所示:

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

你不必担心错误!

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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