Java约定:在类中使用getter / setter吗?

时间:2011-12-11 19:29:56

标签: java coding-style

我的教授真的强调通过始终使用访问器和更改器访问私有实例变量来防止隐私泄露;但是,我是否必须在类中使用类的getter / setter?

例如,如果我有以下类:

public class Person 
{
    private String name;
    private int age;
}

我想为它编写一个toString()方法。我可以写一下:

public String toString()
{
    return name + " " + age;
}

或者我需要做这样的事情:

public String toString()
{
    return this.getName() + " " + this.getAge();
}

12 个答案:

答案 0 :(得分:35)

你可以做任何一个。但是,您的教授可能会喜欢使用这些方法而不是直接访问。这就是原因。

假设你有一个这样的课程:

class SomeClass {
    private int someValue;
    private String someString;

    public SomeClass(int someValue, String someString) {
        this.someValue = someValue;
        this.someString = someString;
    }

    public int someValue() {
        return someValue;
    }

    public int someString() {
        return someString;
    }

    public String toString() {
        return someValue + ": " + someString;
    }

}

这很简单,对吧?那么,如果我们突然想要改变计算someValue的方式的实现,并将其基于someString,那该怎么办?

public int someValue() {
    int value = 0;
    for(int i = 0; i < someString.length; i++) {
         if(someString.charAt(i) == ' ') value++;
    }
    return value;
}

现在您还必须更改使用变量someValue的每个地方。

因此,如果您希望从长远来看使代码更易于维护,请使用方法调用。这样当您对自己进行代码更改(并相信我,它会一直更改)时,您只需要在一个位置而不是两个位置进行更改。

是的,您希望在获取someString时使用方法调用,而不是在最后一个方法中使用直接访问: - )

答案 1 :(得分:16)

当我设计一个类时,我试图明确区分内部(实现细节)和外部(暴露给世界的接口)。 getter和setter提供了一个方便的位置,可以在存储在对象实例成员中的表单与外部世界看到它们的表单之间转换值。内部使用getter和setter会破坏它,因为它们会被内部和外部使用。

如果您发现自己想要从同一个班级的其他部分隐藏一部分课程,请考虑将您要隐藏的部分分解为自己的班级。

答案 2 :(得分:13)

由于多种原因,这通常不是一个好主意:

  • 您甚至可能不想要所有字段的访问者
  • 有些访问者可能会制作一个防御性副本,以免暴露内部状态,这通常是在你知道你不会修改它的类中是不必要的 - 或者如果你知道你要修改它就是明白错误
  • 它使调试更加烦人,因为你必须遵循getters / setters
  • 这使得在大多数IDE中更难以阅读代码,因为它们中的大多数颜色字段与局部变量不同

...但与往常一样,也有例外。有些setter可能有你想要执行的副作用(例如设置第二个值),那么使用setter可能会更好。此外,如果您为继承设计类,如果您希望子类能够改变行为,那么通过访问器可能会更好。

答案 3 :(得分:7)

一般来说,没有。如果你的getter返回的字段不是字段的值,那么你应该使用该方法,但在极少数情况下,你的方法应该有一个更具描述性的名称。举个不好的例子,如果你有:

public void setName(String name)
{
  _name = name;
}

并且你的getter返回了其他内容,比如

public String getName()
{
  return _name.toUpperCase();
}

然后是的,你应该使用getter。不过,最好有一个更具描述性的吸气剂名称:

public String getNameAsUppercase()
{
  return _name.toUpperCase();
}

答案 4 :(得分:5)

可以使用访问者和变种者,但它是一个混乱的标准。

它会使你的代码变得混乱,并且会让任何试图阅读它的人感到困惑,因为它可能不属于你的课程。

基本上,只需直接从类内部访问变量,间接访问其他任何变量。

答案 5 :(得分:5)

不,你没有。您可以从班级中访问任何变量,private,public或protected。

以下是一些可以帮助您的表:

enter image description here

Source: Java Tutorials

答案 6 :(得分:3)

另一方面,从设计的角度考虑它。 getter / setter的一个动机是底层数据存储可以改变,实现该类的东西不需要更改,因为它是封装的。

因此,记住这一点,在课堂上使用getter / setter可以使未来的更改更容易。您必须更改getter / setter,而不必直接找到更改成员的所有位置。根据类的复杂性,这可能会显着减少更改存储成员所需的工作量。

例如,假设您从年龄开始使用年龄变量。然后由于某种原因,您稍后决定将其存储为秒。但是你想要总是多年打印它。所以在你的例子中,你可以在你的toString()函数中(以及任何需要多年作为单位的地方)进行数学运算,或者你可以在getAge()例程中改变数学,从秒开始返回几年,没有别的东西。改变。

显然这个例子有点微不足道。类越复杂,在其中使用getter / setter就越有用。

答案 7 :(得分:3)

如果您的课程(或相关的访问者方法)不是final,那么您一定要使用访问者方法。

如果另一个类扩展了您的类并覆盖了这些访问器,那么您的类应该使用重写的访问器。如果这会破坏你的超类,那么你的超类设计不正确;阻止这些访问者被final覆盖,或者改变你的类的设计。

答案 8 :(得分:1)

不,你可以在课堂内直接使用你的实例变量,你没有违反任何“规则”。其他类必须使用getter和setter来访问类的实例变量,以免违反封装原则(这在OO编程中非常重要)。

最后这是一个选择问题,但是您使用第一个示例保存了一个方法调用。

答案 9 :(得分:1)

如果存在getter和setter,那么应该总是在class中使用。当然,如果getter和setter在方法上做了更多的事情,那么必须考虑它是否满足了需求。

应该使用不是必须使用的手段。属性可以直接使用(如果属性是私有的,则只在内部类中 - 应该是)但在实践中是使用getter和setter。

因此可以直接使用属性,但我建议使用getset,因为它提供了更多的灵活性,可以做更多的事情而不是典型的分配或获取。

例如,如果在第一位置setter只设置一些东西,但在一段时间之后setter被更改为做更多的事情。

 setName(name){

     this.name=name;
 }

因此,代码setName("John");中的name="John"相等。但想象一下,我们想在设置name时设置另一个属性:

 setName(name){

     this.name=name;
     this.nameIsSet=true;
 }

另一个例子(听众模式)

setName(name){

     this.name=name;
     this.listener.nameChanged(this.name); //we call listener that variable changed
 }

然后程序员需要在课堂上找到像name="John"这样的每个分配,并将其重构为新的行为。如果仅使用setName,则不必更改代码。

当然,一切都取决于需要,并且设置,从外部获取财产可以做更多和更多的事情,而不是满足我们在课堂上的需要。

答案 10 :(得分:0)

我认为我们应该使用getters()和setters()而不是直接访问。它也使调试变得非常容易。例如,如果您需要在类中分配一个变量多个位置,之后您想要查找变量分配的位置,那么您需要找到所有赋值并设置断点。

但是如果你使用setter,你可以简单地在setter方法中放置一个断点,并且可以看到变量分配了多少时间。

答案 11 :(得分:0)

我将两者混合使用。访问器方法增加了更多的混乱,因此我仅在多次使用变量时才使用它们。如果该变量仅使用一次或两次,则不使用它们。