4

所以我有一个关于“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”类中的变量设为私有,然后使用“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");
       }
    }

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

4

8 回答 8

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 的原因——所以如果需要,可以执行类似的代码。

于 2012-07-16T04:59:25.550 回答
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");
    }
}
于 2012-07-16T06:09:40.700 回答
2

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

Java Bean 规范

于 2012-07-16T05:02:10.860 回答
1

如果您的代码从不更改,那么您是对的 - 没有区别。

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

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

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

myAccount.nameChanged = true'每个下

myAccount.name = whatever;

因此,您开始有代码重复,并且出现错误的可能性增加了。如果我错过了改名怎么办?

解决此问题的最佳方法是将成员变量归类为private.

您的 setName 代码如下所示:

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

而且您不必担心错误!

于 2012-07-16T05:02:40.330 回答
1

Encapsulation当您声明一些私有实例变量并声明public gettersetter method访问和更改实例变量值时,将调用此方法。

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

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

于 2012-07-16T05:05:40.563 回答
0

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

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

于 2012-07-16T05:02:04.260 回答
0

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

于 2012-07-16T05:02:48.223 回答
0

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

于 2014-05-22T21:46:04.877 回答