class 的 getters() 和 setters() 简化

getters() and setters() simplification for a class

这是我们使用 set 和 get 方法时的源代码示例:

public class Dog {

    private String dogName;
    private int dogAge;

    public Dog(String dogName, int dogAge) {
        this.dogName = dogName;
        this.dogAge = dogAge;
    }

    public String getDogName() {
        return dogName;
    }

    public void setDogName(String dogName) {
        this.dogName = dogName;
    }

    public int getDogAge() {
        return dogAge;
    }

    public void setDogAge(int dogAge) {
        this.dogAge = dogAge;
    }

    @Override
    public String toString() {
        return "Dog{" + "dogName=" + dogName + ", dogAge=" + dogAge + '}';
    }

}

setters和getters用于实现Encapsulation.

是的,我们可以让它在没有 setter 和 getter 的情况下工作。

Why do we exactly need to use the set and get methods in our class that use private attributes?

如果你想隐藏实现的细节(encapsulation - a fundamental principle of object-oriented programming),你不想让外面的人访问它们,你只提供一个方法 returns 一些价值,但你不'想揭示实现。

另外有时当你设置一个值时,你需要改变其他可能相关的变量,或者改变一些逻辑,它并不总是一个简单的赋值语句。

When it is really used during our program process?

这个问题很难回答,这真的取决于程序。您可以使用 settersgetters 来获取或设置值。

Can we still make it work without it?

当然,当你有 public 个字段而不是 private 时,它 有效 ,在设计意义上,建议从 [=11] 开始=] 变量,并且只有在 必须 时才更改它们。

我个人不喜欢 setter 和 getter,如果可以的话,我会用 public 字段替换它们。但是,保留它们有技术原因:

  • 模拟:Mockito 或 Easymock 等模拟框架无法模拟或覆盖直接字段访问
  • 代理:出于各种原因,使用了代理(DI 框架中的 Scopin、日志记录等)。同样,不适用于字段
  • 基于 JavaBeans 的框架:某些 XML 序列化框架不支持字段访问。

因此,在许多情况下,使用 getters/setters 只会让您的生活更轻松。但是,如果您根据 类 负责所有代码,只需在 运行 遇到问题时在 eclipse 中使用 Refactor->Encapsulate Field(非常确定所有主要 IDE 中都存在类似的功能) .

  • 为什么我们确实需要在使用私有属性的 class 中使用 set 和 get 方法?

使用也称为 Accessors and MutatorsGetters()Setters() 方法,因此我们可以从外部访问 class 中的私有字段。

public class myClass(){
  public void newDog(){
    Dog d=new Dog("Foxy", 2);
    d.setDogAge(d.getDogAge()+1);//get the age of the dog and increment it
  }
}
  • 真正在我们的程序过程中什么时候用到?

它们在我们需要实现read(with getters)/write(with setters)时使用使用我们的私有字段进行操作(如上一个示例)。

  • 没有它我们还能让它工作吗?

是的,如果我们将这些字段声明为 public(默认大小写),当然可以:

String dogName;
int dogAge;

前面的例子是:

public class myClass(){
  public void newDog(){
    Dog d=new Dog("Foxy", 2);
    d.dogAge=d.dogAge+1;//get the age of the dog and increment it without getters and setters
  }
}

查看 TutorialsPoint's Encapsulation Tutorial 了解更多信息。

为什么我们确实需要在使用私有属性的 class 中使用 set 和 get 方法?

这个术语 "Encapsulation" 属于面向对象编程。封装是您隐藏实现但提供访问权限。

真正在我们程序过程中什么时候用到?

getter 是为了获取一些值,setter 是为了设置一个值。在您的代码中,您将 Dogs name 设置为 String,将 age 设置为 int。最后你有吸气剂来获得设定值。

没有它我们还能用吗?

是的。您可以通过将 private 声明的变量更改为 public 来使其工作。实际上 private 关键字将使该变量仅对声明它的 class 可见。

这为您提供了有关对象的详细说明。 http://docs.oracle.com/javase/tutorial/java/concepts/object.html

如果您看不出封装的意义,请允许我用一个 "real life" 示例进行演示(其中 .

private boolean amIDrunk = true;

public boolean getAmIDrunk(Object asker){
    if (asker instanceof PoliceOfficer){
        return false;
    } else if (asker instanceof DrinkingBuddy ){
        return true;
    }
    return amIDrunk;
}

public void setAmIDrunk(boolean setter){
    if (hadLessThen10Beers()) {
        this.amIDrunk = false;
        return;
    }
    this.amIDrunk = setter;
}

当然,这是一个 'nitwit' 示例,但它只是为了表明有时,仅仅因为您调用 setter,可能有理由不设置该值,有时,当调用 getter 时,可能有一个原因,您不想 return 实际值。

无论如何,继续这个例子:将 amIDrunk 作为私有变量,通过将 amIDrunk 设置为 true,确保其他人不会将您声明为 'drunk',而无需执行您自己的 set 方法同意。

我建议阅读 Kotlin kotlinlang.org

您可以在 1 行中为 POJO 编写 getters/setters: 例如

data class Customer(val name: String, val email: String, val company: String)

getters和setters确实是为了封装的原理,答案中有很好的解释here。根据约定 getter,setter 除了存储和检索 属性 之外不能添加任何功能。由于这是这些方法唯一要做的事情,因此越来越多的人支持将这些变量设置为 public 并直接访问它们,而无需这些方法。由于这些方法只是将它们公开,因此没有功能差异。对于约定和某些框架,需要 getters 和 setter。

您可以随时让您的 IDE (Eclipse, IntelliJ, Netbeans) write the getters and setters for you. But if you want your code to be DRY and easy to read you can also consider using Lombok,它会自动为您生成 getters 和 setter。

使用 'access methods'(setters 和 getter)的另一个原因是它是 IoC(控制反转)中使用的约定。所以像 Spring 等框架。 创建它们似乎很乏味,但是如果您将 eclipse 用作 IDE,例如,您可以自动生成 setters 和 getter(来源|生成 getter 和 setters)。

此外,您的私有成员变量很重要。 假设您有:

public String telephoneNumber;

如何阻止某人这样做:

object.telephoneNumber = "not a telephone number".

如果您使用 setter,您可以这样做:

public void setTelephoneNumber(final String telephoneNumber) {
   if (telephoneNumber==null||telephoneNumber.length()==0) {
      throw new IllegalArgumentException("you cannot supply null telephone numbers");
   }
   ... etc.
   this.telephoneNumber = telephoneNumber;
}

以这种方式,您的 telephoneNumber 成员变量将永远只保存一个有效的 telephoneNumber。您的 class 现在完全独立(封装),因为您不依赖外部 classes 来尊重您的成员变量。