Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我是否应该对永远不会更改的字段值使用访问器?_Java_Oop_Encapsulation - Fatal编程技术网

Java 我是否应该对永远不会更改的字段值使用访问器?

Java 我是否应该对永远不会更改的字段值使用访问器?,java,oop,encapsulation,Java,Oop,Encapsulation,我们以这门课为例: public class Student{ private String name; private String id; public Student(String name, String id){ this.name = name; this.id = id; } ... getters and setters for both fields 并将其与此进行比较: public class S

我们以这门课为例:

public class Student{
    private String name;
    private String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }

    ... getters and setters for both fields
并将其与此进行比较:

public class Student{
    public final String name;
    public final String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }
 }
我认为不需要访问器。

这会被认为是糟糕的OO设计吗?当然,如果你知道它们永远不会改变,那么你就不需要访问器了


但是如果你告诉我你确信他们永远不会改变,我不会相信你。

如果字段是
final
,那么你真的不需要使用getter/setter。一个二传者也是毫无意义的,因为他们永远不会改变。

这是一个复杂的问题

不幸的是,好的(或坏的)设计完全取决于如何使用它

根据经验,最好将成员变量保持私有,以便对象模型控制其访问。这意味着第一种方法更好

但是

如果这些值永远不变,那又有什么意义呢?如果它们永远不会被使用,为什么还要费心编写setter呢

那么,哪一个更好呢?正如我上面提到的,这取决于你这样做的目的。如果是课堂作业,我会选择第一个。你的老师会更喜欢它,因为它更像是“教科书”

因此,如果这是一个个人项目或工作,您可以利用未来的版本,我会选择两者之间的交叉:

public class Student{
    private final String name;
    private final String id;

    public Student(String name, String id){
        this.name = name;
        this.id = id;
    }

  ... getters ONLY for both fields

这种方法是安全的,因为成员字段是私有的,并且没有未使用方法的“代码味道”。这也是相当可扩展的,因为如果您的需求发生变化并且需要修改字段,您可以非常轻松地添加setter

我认为这不是个坏主意

如果它们不会改变,请确保用适当的关键字标记字段,例如
Final


让不变的值以不同的方式显示也是一个好主意。Java中的eg常量通常在所有CAP中完成。

您应该始终将可变性和范围限制在严格的最小值。在您的情况下:将字段设置为私有的、最终的、有getter的、无setter的

奖励:这样你的类就变得线程安全了


另请参见。

Getter和Setter使API更加稳定。例如,在其他类访问的类中考虑字段公共。现在,在获取和设置变量时,您需要添加任何额外的逻辑。这将影响使用API的现有客户端。因此,对这个公共字段的任何更改都需要对引用它的每个类进行更改。相反,使用访问器方法,可以很容易地添加一些逻辑,比如缓存一些数据,然后延迟地初始化它。此外,如果新值与以前的值不同,则可以触发属性更改事件。所有这些都将与使用访问器方法获取值的类无缝连接


Paragatic程序员建议也始终使用getter和setter,因为它是更通用的接口。查看这篇文章,它非常好,让我们深刻理解为什么要使用它们。

一致性规则。如果您有一些类/属性具有对变量的公共访问权限,而其他类/属性具有“getter”,那么这将不是一个好地方

假设您参加了
学生
课程,并添加了
java.util.Date
字段

public final Date dateOfBirth;
啊,现在你
学生
是可以不受控制地改变的。我们需要

private final Date dateOfBirth;
...
public Date dateOfBirth() {
     return new Date(dateOfBirth.getTime()); // Awful API.
}

通常,只需将每个(实例)字段设置为私有(数据传输对象除外)。如果您有setter,那么您可能已经放弃了封装的所有希望。getter适用于不可变值对象。(“get”前缀是Java的一种约定(主要是),但它很大程度上是噪音,特别是在支持不可变值对象和告诉不要问接口的代码中。如果删除“get”,客户端代码只有额外的“()”作为比直接字段访问更详细的内容。)

有一些很好的答案,我同意将字段设置为私有,并在需要时添加适当的构造函数/getter/setter来限制可变性

我将指出使用基于字段的作业的另一个缺点。任何基于代理的AOP在向字段分配中添加切入点时都会遇到困难,因此通过基于代理的AOP构造进行日志记录(和其他操作)将变得困难,因为它们仅限于方法拦截。你很可能被迫去编织,这会变得更复杂。从Spring自己的文档中:

SpringAOP目前只支持方法执行连接点 (建议在SpringBean上执行方法)。领域 未实施拦截,但支持现场 可以在不破坏核心Spring AOP API的情况下添加拦截。 如果需要建议字段访问和更新连接点,请考虑 语言,如AspectJ


嗯,设计不错。虽然它不符合惯例。如果在中,您需要在getter和/或setter中提供前/后处理,那么会怎样呢?如果您说setter永远不会改变,为什么会有setter?无论您如何做,都要保持一致。就使用OO设计作为衡量标准而言,POJO本身并不是OO的典范。过早的优化是万恶之源唐纳德·克努斯博士。虽然Knuth博士指的是性能优化,但同样的情况也可以说是编码实践增加了混乱而没有增加价值。@PeterGluck我认为:a)限制范围直到你需要增加它-b)不要设置设置器,直到你需要它们-c)使字段成为最终的,直到你需要更改它们?鉴于字段是最终的,字符串是不可变的,它们永远不会改变。只需按一下backspace或delete键就可以改变。最后的字段通常与常量不同——它们不是静态的。all caps命名约定通常是为编译时常量保留的。我想这是真的。我要把那部分拿出来。