Why use getters and setters/accessors?

Why use getters and setters/accessors?

技术背景

在面向对象编程中,对于类的成员变量,通常有两种访问方式:直接使用公共字段(public fields)和使用访问器方法(getters 和 setters)。公共字段允许外部代码直接访问和修改类的成员变量,而访问器方法则提供了一种间接的访问和修改方式。使用 getters 和 setters 而非直接使用公共字段的优势,是一个常见的讨论话题。

实现步骤

直接使用公共字段

1
2
3
public class Example {
public String foo;
}

使用时可以直接访问和修改:

1
2
3
Example example = new Example();
example.foo = "bar";
String value = example.foo;

使用 getters 和 setters

1
2
3
4
5
6
7
8
9
10
11
public class Example {
private String foo;

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

public String getFoo() {
return foo;
}
}

使用时通过方法来访问和修改:

1
2
3
Example example = new Example();
example.setFoo("bar");
String value = example.getFoo();

核心代码

带有验证逻辑的 setter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Example {
private int speed;

public void setSpeed(int speed) {
if (speed > 100) {
this.speed = 100;
} else {
this.speed = speed;
}
}

public int getSpeed() {
return speed;
}
}

实现接口的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public interface LiquidContainer {
public int getAmountMl();
public void setAmountMl(int amountMl);
public int getCapacityMl();
}

public class Bottle implements LiquidContainer {
private int capacityMl;
private int amountFilledMl;

public Bottle(int capacityMl, int amountFilledMl) {
this.capacityMl = capacityMl;
this.amountFilledMl = amountFilledMl;
checkNotOverFlow();
}

public int getAmountMl() {
return amountFilledMl;
}

public void setAmountMl(int amountMl) {
this.amountFilledMl = amountMl;
checkNotOverFlow();
}

public int getCapacityMl() {
return capacityMl;
}

private void checkNotOverFlow() {
if (amountFilledMl > capacityMl) {
throw new RuntimeException("Bottle overflow");
}
}
}

最佳实践

何时使用 getters 和 setters

  • 需要添加额外逻辑:如验证、计算等。例如,在设置年龄时,确保年龄在合理范围内。
  • 遵循接口规范:当实现接口时,接口通常只定义方法,需要使用 getters 和 setters 来实现对字段的访问。
  • 封装内部实现:隐藏类的内部表示,允许在不改变公共接口的情况下修改实现。

何时可以直接使用公共字段

  • 简单的数据结构:当类只是作为简单的数据容器,不包含复杂的逻辑时,可以使用公共字段。
  • 内部代码:在内部代码中,如果不需要对字段进行复杂的控制,可以暂时使用公共字段,后续根据需要再添加 getters 和 setters。

常见问题

使用 getters 和 setters 会降低性能吗?

一般情况下,使用 getters 和 setters 带来的性能开销非常小,在大多数应用中可以忽略不计。在某些性能测试中,getter 甚至可能比直接访问字段更快。

添加验证逻辑到 setter 会破坏原有的合同吗?

是的,如果在 setter 中添加验证逻辑,会改变原有的合同(即可以设置任意值的约定)。在这种情况下,可能需要修改所有使用该字段的代码。

所有字段都应该使用 getters 和 setters 吗?

不是的。如果字段不需要额外的控制或逻辑,直接使用公共字段可以使代码更简洁。过度使用 getters 和 setters 可能会导致代码变得冗长和复杂。


Why use getters and setters/accessors?
https://119291.xyz/posts/2025-04-11.why-use-getters-and-setters/
作者
ww
发布于
2025年4月24日
许可协议