【问题标题】:Set and Get Methods in java?在java中设置和获取方法?
【发布时间】:2011-10-02 02:38:44
【问题描述】:

如何使用 set 和 get 方法,为什么要使用它们?他们真的有用吗?另外,你能给我一些 set 和 get 方法的例子吗?

【问题讨论】:

  • 你在问Java Bean。
  • 这个概念当然不限于 Java bean。
  • 您可以阅读其中一些google.com/search?q=javabeans+tutorial 717K 结果。
  • 真的吗?你们这些人太可笑了。仅仅因为这是一个非常简单的问题并不意味着您必须对每个答案都投反对票。这个问题虽然是一个非常基本的问题,但却是完全有效的,并且是在规则的范围内提出的。

标签: java methods encapsulation setter getter


【解决方案1】:

Set 和 Get 方法是一种数据封装模式。不是直接访问类成员变量,而是定义get 方法来访问这些变量,并定义set 方法来修改它们。通过以这种方式封装它们,您可以控制公共接口,如果您将来需要更改类的内部工作方式。

例如,对于成员变量:

Integer x;

你可能有方法:

Integer getX(){ return x; }
void setX(Integer x){ this.x = x; }

chiccodoro 还提到了一个重点。如果您只想允许对任何外部类的字段进行读取访问,则可以通过仅提供公共 get 方法并保持 set 私有或根本不提供 set 来实现。

【讨论】:

  • 从外观上看,如果我使用 set 和 get 方法来解决错误会更容易吗?我说的对吗?
  • 是的,例如,您可以在这些方法中设置断点,以查看其余代码何时尝试访问底层成员变量
  • 这个答案中没有提到的一个非常常见的情况:如果您只想允许对任何外部类的字段进行读取访问 - 您可以通过仅提供公共 getter 方法并保持setter 私有或根本不提供 setter。
  • 您的示例也没有显示 setter 和 getter 如何随时间演变(如您在文本中所述)。
  • 另请注意,您可以进行错误检查以及边界检查。
【解决方案2】:

我想在其他答案中添加设置器可用于防止将对象置于无效状态的其他答案。

例如,假设我必须设置一个 TaxId,建模为一个字符串。 setter 的第一个版本可以如下:

private String taxId;

public void setTaxId(String taxId) {
    this.taxId = taxId;
}

但是我们最好避免使用无效的taxId来设置对象,所以我们可以引入一个检查:

private String taxId;

public void setTaxId(String taxId) throws IllegalArgumentException {
    if (isTaxIdValid(taxId)) {
        throw new IllegalArgumentException("Tax Id '" + taxId + "' is invalid");
    }
    this.taxId = taxId;
}

下一步,为了提高程序的模块化,将 TaxId 本身作为一个 Object,能够进行自我检查。

private final TaxId taxId = new TaxId()

public void setTaxId(String taxIdString) throws IllegalArgumentException {
    taxId.set(taxIdString); //will throw exception if not valid
}

对于 getter 类似,如果我们还没有值怎么办?也许我们想有一条不同的路,我们可以说:

public String getTaxId() throws IllegalStateException {
    return taxId.get(); //will throw exception if not set
}

【讨论】:

  • -1 第一个例子很棒。删除整个“提高程序的模块化”部分,我将更改为 +1。
  • 实际上我同意 Kent Pugh 的观点,正如 Prefactoring 一书中所说:“将字符串视为原始数据类型。用抽象数据类型而不是字符串来描述属性。” -- 例如,在一个典型的客户类中,可能有几个这样的抽象类型,有些可能有复杂的验证规则,跨越几行代码(有时数百行)。这正是我所做的,我创建了其中的几个datatypes,它们足够通用,我可以通过项目重用它们。
  • 我会尝试更好地解释这一点。在面向对象的程序中,在课堂上思考的好方法可以是拟人化的方式。一个领域的领域专家,它必须把某件事做得很好,而且只做一件事。因此,客户类应该是客户方面的专家,而不是邮政编码、增值税 ID、税号、市政当局,并且不应该知道电话号码的格式。所有这些关注点都是独立的小领域,每个领域都应该有一个领域专家。我们不希望这段代码污染我们的主类。
【解决方案3】:

我想你想要这样的东西:

public class Person {

  private int age;

  //public method to get the age variable
  public int getAge(){
       return this.age
  }

  //public method to set the age variable
  public void setAge(int age){
       this.age = age;
  }
}

您只是在对象实例上调用这样的方法。这些方法很有用,尤其是在设置某些东西应该有副作用的情况下。例如。如果您想对某些事件做出反应,例如:

  public void setAge(int age){

       this.age = age;

       double averageCigarettesPerYear = this.smokedCigarettes * 1.0 / age;

       if(averageCigarettesPerYear >= 7300.0) {
           this.eventBus.fire(new PersonSmokesTooMuchEvent(this));
       }
  }

当然,如果有人忘记调用setAge(int) 并直接使用this.age 设置age,这可能会很危险。

【讨论】:

  • 这是我见过的最好的说“不”的方式。
【解决方案4】:

拥有访问器方法优于直接访问字段,因为它控制如何访问字段(可能会强制进行数据检查等)并适合接口(接口不能要求字段存在,只有方法)。

【讨论】:

    【解决方案5】:

    Setter 和 getter 用于替换从外部类直接访问成员变量。如果您在访问属性时使用 setter 和 getter,则可以包括初始化、错误检查、复杂转换等。一些示例:

    private String x;
    
    public void setX(String newX) {
        if (newX == null) {
            x = "";
        } else {
            x = newX;
        }
    }
    
    public String getX() {
        if (x == null) {
            return "";
        } else {
           return x;
        }
    }
    

    【讨论】:

    • 有趣,因为x 不能为空,因为setX,所以getX 不需要检查它。但是有道理,任何理解这个评论的人都会明白关于 getter 和 setter 的全部意义。 +1
    • 如果在调用 setX 之前调用 getX,X 将为 null。
    • 为什么x 不只是初始化为""?然后你把支票存入getX
    • 当然可以,而且几乎可以肯定应该是,但不一定是。
    【解决方案6】:

    使用 getter 和 setter(称为 encapsulationdata-hiding)的一些好处:

    (原回答here

    1.类的字段可以设为只读(仅提供 getter)或只写(仅提供 setter)。这使该类可以完全控制谁可以访问/修改其字段。

    例子:

    class EncapsulationExample {
        private int readOnly = -1;  // this value can only be read, not altered
        private int writeOnly = 0;    // this value can only be changed, not viewed
        public int getReadOnly() {
            return readOnly;
        }
        public int setWriteOnly(int w) {
            writeOnly = w;
        }
    }
    

    2。类的用户不需要知道类实际如何存储数据。这意味着数据是独立于用户而存在的,因此可以更轻松地修改和维护代码。这允许维护人员进行频繁的更改,例如错误修复、设计和性能增强,同时不会影响用户。

    此外,封装的资源可供每个用户统一访问,并且具有独立于用户的相同行为,因为该行为是在类内部定义的。

    示例(获取值):

    class EncapsulationExample {
        private int value;
        public int getValue() {     
            return value; // return the value
        }
    }
    

    现在,如果我想返回两倍的值怎么办?我可以更改我的 getter,所有使用我的示例的代码都不需要更改,并且将获得两倍的值:

    class EncapsulationExample {
        private int value;
        public int getValue() {
            return value*2; // return twice the value
        }
    }
    

    3.使代码更简洁、更易读、更易于理解。

    这是一个例子:

    无封装:

    class Box {
        int widthS; // width of the side
        int widthT; // width of the top
        // other stuff
    }
    
    // ...
    Box b = new Box();
    int w1 = b.widthS;  // Hm... what is widthS again? 
    int w2 = b.widthT;  // Don't mistake the names. I should make sure I use the proper variable here!
    

    带封装:

    class Box {
        private int widthS; // width of the side
        private int widthT; // width of the top
        public int getSideWidth() {
            return widthS;
        }
        public int getTopWIdth() {
            return widthT;
        }
        // other stuff
    }
    
    // ...
    Box b = new Box();
    int w1 = b.getSideWidth(); // Ok, this one gives me the width of the side
    int w2 = b.getTopWidth(); // and this one gives me the width of the top. No confusion, whew!
    

    看看在第二个示例中,您对获取的信息有多少控制权,以及这是否更清晰。请注意,这个示例是微不足道的,在现实生活中,您将处理许多不同组件访问的大量资源的类。因此,封装资源可以更清楚地了解我们正在访问哪些资源以及以何种方式(获取或设置)。

    这里是 good SO thread 关于这个主题的。

    这里是good read 数据封装。

    【讨论】:

    • 为什么不使用更好的变量名称“sideWidth”,你必须迟钝不明白什么是“w1 = sideWidth;”意思。
    • @DuckSoy 这个例子是微不足道的,不应该从表面上看。重点是将您自己的命名约定和规则与 API 的用户分开的总体思路
    【解决方案7】:

    上面的答案比我更好地总结了 getter 和 setter 的作用,但是我确实想补充一点,您的代码应该在理想的结构上减少对纯 getter 和 setter 的使用,即那些没有复杂构造、验证和等等,因为它们打破了封装。这并不意味着你永远不能使用它们(stivlo 的回答展示了一个很好地使用 getter 和 setter 的例子),只是尽量减少你使用它们的频率。

    问题在于 getter 和 setter 可以作为直接访问私有数据的解决方法。私有数据之所以称为私有数据,是因为它不打算与其他对象共享;它表示对象的状态。允许其他对象访问一个对象的私有字段会破坏首先将其设置为私有的整个目的。此外,您为您编写的每个 getter 或 setter 引入耦合。例如,考虑一下:

    private String foo;
    
    public void setFoo(String bar) {
        this.foo = bar;
    }
    

    如果在路上的某个地方,您决定不再需要 foo,或者您想让它成为一个整数,会发生什么?现在,每个使用 setFoo 方法的对象都需要与 foo 一起更改。

    【讨论】:

      【解决方案8】:

      只是因为 OOP 规则:数据隐藏和封装。在大多数情况下,将对象声明为公共并即时更改它是一种非常糟糕的做法。还有很多其他原因,但根源在于OOP中的封装。和“买一本书或读一读面向对象编程”,读完任何一本面向对象编程的书后,你就会明白这一切。

      【讨论】:

        【解决方案9】:

        get() set() 方法的好处如下..

        1. 您可以轻松地序列化您的对象。
        2. 您可以从包含类创建一个持久对象。
        3. 您可以轻松地将属性转换为 JSON。
        4. 在 DAO 层(Hibernate 等框架)中,您可以直接将对象保存到 DB。
        5. 轻松理解面向对象的概念。
        6. 需要所有设计模式,但可能是单色调模式。
        7. 保护直接访问的属性的安全性。
        8. 多态性、封装性可以通过这类类轻松理解和实现。

        示例:

        private String personName;
        private int personId;
        
            public void setPersonName(String name) throws Exception{
            if(!(name.equals("")||name=="")){
              this.personName = name;
            }
          }
          public String getPersonName(){
            return this.personName;
          }
          public void setPersonId(int id) throws Exception{
            this.personId = id;
          }
          public int getPersonId(){
            return this.personId;
          }
        

        【讨论】:

        • 这个操作是做什么的?第一次遇到这样的语句 name.equals("")"
        【解决方案10】:

        以上答案都假设所讨论的对象是具有行为的对象。 OOP 中的一个高级策略是将数据对象(压缩,只有字段)和行为对象分开。

        对于数据对象,省略 getter 并使用公共字段是完全可以的。它们通常没有设置器,因为它们通常是不可变的——它们的字段是通过构造函数设置的,并且永远不会再设置。 详情请查看 Bob Martin 的 Clean Code 或 Pryce 和 Freeman 的 Growing OO Software...

        【讨论】:

          【解决方案11】:
          public class Person{
          
          private int age;
          
          public int getAge(){
               return age;
          }
          
          public void setAge(int age){
               this.age = age;
          }
          }
          

          我想这就是你想要的.. 这也叫pojo

          【讨论】:

            【解决方案12】:

            这是set方法的代码

            public void setAge(int age){
              this.age = age;
            }
            

            【讨论】:

              【解决方案13】:

              如果您想要 setAge 创建方法,看起来您正在尝试执行类似于 C# 的操作
              setAge(int age){ this.age = age;}

              【讨论】:

                【解决方案14】:

                我在这里没有看到第二个问题(为什么)的简单答案。就这样吧。

                假设您有一个在您的代码中经常使用的公共字段。每当您决定在提供或设置此字段之前需要做一些额外的事情时,您就会遇到问题。您必须为此字段创建一个特殊的 getter 和 setter,并将您的完整代码从直接使用该字段更改为使用 getter 和 setter。

                现在假设您正在开发一个被许多人广泛使用的库。当您需要进行上述更改并将该字段的直接访问权限设置为私有时,所有使用该字段的人的代码都会中断。

                使用 getter 和 setter 是关于代码的未来规划,它使代码更加灵活。当然,您可以使用公共字段,尤其是对于仅包含一些数据的简单类。但最好只将字段设为私有并为其编写 get 和 set 方法。

                【讨论】:

                  【解决方案15】:

                  这个答案是从另一个问题合并而来的。

                  您的getAge() 方法在Java 中称为实例方法。

                  要调用实例方法,您应该有一个定义该方法的类的对象。

                  例如,如果这个方法在一个名为Person的类中,那么

                  1. 使用 new 运算符创建一个 Person 对象

                     Person p = new Person();
                    
                  2. 要获取Person 对象的年龄,请使用此方法

                    p.getAge()
                    

                  【讨论】:

                  • 在一秒钟内被否决。不知道他们如何评价。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多