【发布时间】:2023-03-09 07:21:01
【问题描述】:
我被教导要始终使用 getter 和 setter。但是,我不知道这些方法的优缺点,因为通过实施它们,我们既暴露了数据又隐藏了它。
我对此有点困惑。任何人都可以就我们为什么使用 getter/setter 以及优势是什么提供一些适当的建议吗?
【问题讨论】:
标签: java methods getter-setter
我被教导要始终使用 getter 和 setter。但是,我不知道这些方法的优缺点,因为通过实施它们,我们既暴露了数据又隐藏了它。
我对此有点困惑。任何人都可以就我们为什么使用 getter/setter 以及优势是什么提供一些适当的建议吗?
【问题讨论】:
标签: java methods getter-setter
在封装方面,基本的“具有公共 getter 和 setter 的私有字段,除了返回或设置字段什么都不做”模式确实完全没有意义,只是它让您有机会在不更改 API 的情况下稍后更改它。
所以不要不假思索地使用这种模式。仔细考虑您实际需要哪些操作。
getter 和 setter 的真正意义在于,您应该只在适当的地方使用它们,并且它们可以做的不仅仅是获取和设置字段。
IllegalArgumentException
所有这些都是隐藏在简单的“getter and setter”接口后面的实现细节。这就是封装的意义所在。
【讨论】:
这是缺点。 Getters/Setters 倾向于将你的类的实现细节暴露给外界。这不是一件好事。想象一下,您正在编写一个汽车机械师软件包。因此,您将需要一个 Car 类,并为这些字段公开 getter 和 setter
Date lastOilChangeDate;
int lastOilChangeMileage;
在这个班级。这是因为该软件希望在客户汽车需要换油时发送电子邮件。
但是当新车问世时,您确定汽车是否需要换油,而不是“每 3000 英里或 3 个月”换油?也许这些新车的油底壳里有一个传感器来测量脏度。显然,您希望使用它来确定是否需要更换机油。
问题是您使用这些 getter/setter 解决了错误的问题。没有人真的想知道最后一次换油是什么时候,他们想知道您是否需要另一次换油。它们只是实现细节,但您使它们成为接口的一部分。你应该做的是添加一个方法
public boolean needsOilChange()
然后 Car 类可以实现它想要的任何方式。如果算法发生改变,Mechanic 类就不必改变,因为它只需要 needsOilChange 方法。
【讨论】:
这主要用于Java bean,如下所示。
public Class MyBean{
private int var1;
public void setVar1(int pVar1){
this.var1=pvar1;
}
public int getVar1(){
返回 var1;`
}
}
好处如下
1.这样我们就可以实现封装
2.它被称为DTO(数据传输对象)设计模式。 它用于在基于 MVC 的应用程序中将数据从一层传输到另一层。 就像你可以从表单中获取用户输入的数据(通过使用getter),你可以使用相同的数据插入数据库(通过使用setter),反之亦然。 最新的框架 (SPring) 将其作为内置功能提供。
【讨论】:
使用 getter 和 setter 并没有错 - 只需注意通过 使用它们并将它们全部公开,你就暴露了你的变量,并且在某种程度上,违反封装。这就是您提到的文章试图警告的内容-不要只是为所有私有实例变量自动生成getter和setter;考虑一下您想向其他类公开什么(以及在什么级别,即私有/受保护/公共),以便仅在需要时公开。
【讨论】:
getter 和 setter 的想法是控制对类中变量的访问。这样,如果需要在内部更改值以以不同的方式表示,您可以这样做而不会破坏类外的任何代码。
例如,假设您有一个带有距离变量的类,它以英寸为单位。几个月过去了,你在很多地方都在使用这个类,你突然意识到你需要用厘米来表示这个值。如果您不使用 getter 和 setter,则必须跟踪该类的每次使用并在那里转换。如果您使用了 getter 和 setter,您只需更改这些方法,使用该类的所有内容都不会中断。
public class Measurement
{
/**
* The distance in centimeters.
*/
private double distance;
/**
* Gets the distance in inches.
* @return A distance value.
*/
public double getDistance()
{
return distance / 2.54;
}
/**
* Sets the distance.
* @param distance The distance, in inches.
*/
public void setDistance(double distance)
{
this.distance = distance * 2.54;
}
}
【讨论】:
想到的一个好处是,您可以通过不为特定字段实现设置器来使字段ReadOnly。
【讨论】: