【问题标题】:Accessor Methods in JavaJava 中的访问器方法
【发布时间】:2012-07-16 04:53:09
【问题描述】:

所以我有一个关于“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");
       }
    }

我不明白使用此方法有何不同或应该防止人们更改私有字段的值。有什么帮助吗?

【问题讨论】:

  • 通过使用“getter”和“setter”方法,您可以确保您的变量仅以决定的方式设置。在小型的“玩具”程序中,这似乎很愚蠢和不必要:但在大型、复杂的程序中,它可以成为救命稻草。另外:使用“getting”和“setter”方法恰好是 Java bean 的工作方式。

标签: java methods accessor


【解决方案1】:

使用普通的访问器方法,除了样式没有区别,但你也可以用它们执行代码,例如:

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

【讨论】:

  • 谢谢。我对Java有点陌生,但我真的很喜欢它。当我在研究生院攻读气象学学位时,唯一教给我的就是 FORTRAN,而且并不太喜欢这种语言,哈哈。
【解决方案2】:

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

1.创建私有实例变量。

2. 创建 public 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");
    }
}

【讨论】:

  • 啊哈!早些时候有人评论说,当 setter 和 getter 方法中有某种逻辑时,它们会更有效,我现在明白你的意思了。只是为了确保我掌握了这个概念:如果我正在编写一个视频游戏并且其中一个变量是“健康”,我可以使用private int health = 500 对其进行初始化。然后,如果有人试图通过将他们的生命值设置为 1000 或其他值来作弊,那么 setter 方法可能会有类似的内容:if health &gt; 500 then blah blah blah don't allow them to do that。
  • 要完整,您可以编辑具有波西米亚风格的保护示例
  • 我假设健康可以从 1 到 500 对....所以如果是这种情况,请使用 Setter 方法来设置它.. dont set it directly as private int health = 500; 只需将其声明为 private int health;。是的,您可以在 setter 方法 health>500 中检查它
  • 封装绝对与访问器方法有关。与此答案相反,访问器方法往往会破坏封装。
  • 我想指出,所有的约束,比如上面的年龄约束,都需要记录在案。另外,我建议使用更有意义的反馈信息。您应该始终清楚地记录和说明您的方法的合同。
【解决方案3】:

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

Java Beans spec

【讨论】:

    【解决方案4】:

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

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

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

    所以现在你必须遍历每个源文件并放一个

    myAccount.nameChanged = true' 下每个

    myAccount.name = whatever;

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

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

    您的 setName 代码如下所示:

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

    而且您不必担心错误!

    【讨论】:

      【解决方案5】:

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

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-10-01
              • 1970-01-01
              • 2012-06-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-10-14
              • 2016-09-14
              相关资源
              最近更新 更多