Java中getter / setter的用途是什么?

我已经看到成员变量给出了私有修饰符,然后使用getter / setter方法来设置和获取变量的值(在标准化的名称中)。

那么为什么不将变量公开给自己(除了像弹簧框架这样依赖于IOC的getter / setter等的情况)。 它有助于达到目的。

在C#中,我看到了getter / setter和成员变量的大写。 为什么不将变量公开?

为了从第一次拍摄中获得稳定的API 。 Java专家认为,如果以后,您可能希望在设置/获取实例成员时有一些额外的逻辑,您不希望通过使用公共方法替换公共字段来破坏现有API 。 这是Java的主要原因。

在C#的情况下,由于二进制接口兼容性 ,使用公共属性而不是公共字段。 在SO上,有人在这里问了一个类似的问题 。

所以,这一切都是关于封装一些逻辑,同时仍然保留接口以进行未来validation。

即使在2003年,人们也知道, 吸气剂和二传手法是邪恶的 。

因为接口只允许指定方法,而不是变量。 接口是API的基石。

因此,要通过接口访问字段,您需要具有getter和setter。

这样做是为了您可以在发布之后更改公共API中的getter或setter实现。 使用公共字段,您将无法检查有效性的值。

封装

您还提到了C#属性。 这些实际上只是吸气剂/定位器,但具有更简洁的语法。

它是封装的一部分:从其实现 (使用实例变量)抽象类的接口 (“getters”和“setter”)。 虽然您可能决定今天通过直接访问实例变量来实现该行为,但您可能希望明天以不同方式实现。 假设你需要通过网络检索值而不是在本地存储它 – 如果你已经封装了行为,这是一个微不足道的变化。 但是,如果其他对象依赖于对实例变量的直接访问,则会遇到困难。

Java中getter和setter的最重要用途是惹恼开发人员。 第二个最重要的用途是用无用的噪声使代码混乱。 此外,它会强制您为同一事物使用不同的名称,具体取决于您所在的位置(在课堂内部或外部)。 不要忘记添加的歧义(你在课堂上调用getter还是直接使用该字段?)接下来,它们用于允许访问私有数据,但这只是一个小的副作用;)

在其他编程语言中,编译器将为您生成它们(当然,除非您提供自己的实现)。 例如,在Delphi中,您具有字段的write修饰符(就像Java中的privatestaticfinal )。 定义是否为您生成了getter或setter。

与delphi人不同,Java人员希望一切都是明确的。 “如果它不在源头,那就不存在了”。 所以唯一的解决方案就是强迫人们手动编写所有的getter和setter。 更糟糕的是,人们不得不为同一件事使用不同的名称。

吸血鬼和二传手可能是有史以来最大的骗局。 它们被认为是良好设计的标志,而事实恰恰相反。 应该教新程序员适当的封装,而不是编写除了getter和setter之外什么都不包含的哑数据载体类。

(如果你想在以后更改实现,你需要getter和setter来代替你的代码的想法是YAGNI的一个明显的例子。但这确实是不重要的。)

最常见的原因是对封装的理解不足。 当开发人员认为封装内容实际上只意味着获取者和设置者,而不是封装行为。

拥有getter / setter的正当理由是:

1)您正在创建一个通用的对象,例如JComponent。 通过使用getter / setter而不是直接访问变量意味着您可以首先对所述变量进行一些预处理(例如validation它是否具有设置范围)或更改底层实现(从int切换到BigInteger)不改变公共API)。

2)您的DI框架不支持ctor注入。 只需设置一个setter就可以确保变量只设置一次。

3)(与#1联系)允许工具与您的对象进行交互。 通过使用这样一个简单的约定,GUI工具可以轻松获得给定组件的所有设置。 这方面的一个例子是NetBeans中的UI构建器。

¹非通用类型。 使用不好的词我知道,请提出替代方案。

有一个setter允许你

  • 执行validation
  • 如果新值与先前值不同,则触发属性更改事件

在有问题的情况下,如果只是读取或写入值,则不需要getter和setter。

好,

OOP 。 ;)

或者更准确一点:

Getters和Setter用于为类属性提供已定义的接口。 检查OOP链接,它更详细地描述了概念……

ķ

如果存在约束,则需要封装这些属性,或者进行一般有效性检查或在更改或事后发布事件。 基本用法是将属性隐藏在“外部世界”中。

一些Java框架需要它们(我认为是JavaBeans)。

– 编辑

一些海报试图说这是关于封装。 事实并非如此。

封装是关于隐藏对象的实现细节,并仅暴露相关的函数。

提供一个除了设置值之外什么都不做的get / set根本不会完成这个,它们的唯一原因是:

  • 在设置/获取之前执行一些额外的validation
  • 从其他地方获取变量
  • 与框架集成(EJB)

有几个原因:

  • 一些Java API依赖于它们(例如Servlet API);
  • 使非最终变量公开被认为是一种不好的风格;
  • 进一步的代码支持:如果将来某个时候你需要在变量的每次访问/变异(获取/设置)之前执行一些操作,那么你将遇到更少的问题。 在像C#这样的结构中

    public int Age {get {return(int)(today() – m_BirthDate); }}

只是语法糖。

属性理念是OOP(面向对象编程)的核心。 但问题是Java不是在语言的核心(语法/ JVM)中引入它们,而是(可能几年之后…… Java的历史更好)作为惯例:一对getter / setter是bean中的属性,属性的概念是在图书馆,而不是核心。

这在少数库,框架中产生问题。 单个getter是否为只读属性? 就是那个问题。 Iein JPA实体如果你想实现经典方法(算法),像getCurrentTine()这样的“get”开始是@Transient禁用具有值的属性的解释的最佳标记。

换句话说,我非常喜欢C#设计的10年后更好的财产概念。 BTW C#属性也有getter / setter,但有时/部分隐藏,在低级调试时可见。 免于提问“为什么得到”等…

在Java世界中有趣的是阅读Groovy属性概念(隐藏的getter / setter以不同于C#的方式) http://www.groovy-lang.org/objectorientation.html#_fields_and_properties

编辑:从现实生活中,每个java对象都有getClass()方法, java.beans.BeanInfo包中的工具报告这个属性为"class" ,但这不是真的。 完全意义上它不是财产(只读属性)。 我想像C#(他的内部隐藏名称get_Something1)这样的属性与“functional”GetSomething2()没有冲突