探讨java属性定义为private真的一定合理吗?

89 阅读3分钟

背景

我们在学教科书时,“老师”告诉我们,字段定义成private , 然后通过get,set访问,这样能屏蔽内部实现细节。

本文探讨的是 get , set 方法都存在的情况, 如果一个类的某个属性不允许修改,它只有get方法,那肯定要定义为private ,才能防止被篡改。

我对“屏蔽内部实现细节”这个理由到现在我都持怀疑的,原因如下

1) 我们绝大数对象都是POJO,get , set 没有任何逻辑

2) 我印象中也不鼓励在get 或者 set 中写一些特殊逻辑,很容易引发Bug, 举个的例子

public class User2 {

    private String name;

    public String getName() {
        this.name = "prefix_" + this.name;
        return name;
    }

}

上面那一代码你们看出来问题了吗?每调用一次get方法,name就会拼接一个前缀,随着次数增多,当时团队有人就在get里面做了一些逻辑, 那个字段刚好是文章的内容,结果字段越来越长,大对象直接进入老年代,应用就频繁Full GC。

所以对屏蔽内部细节而将字段定义为private 我不赞同,因为很多情况 get ,set 不应该有什么逻辑

否则lombok 框架也不会产生了。

当然说安全,我也不认同,虽然不能直接给属性赋值,但是可以通过set 进行恶意篡改,所以说什么安全我不认同。

我认为的可能的理由如下

与JSON序列化有关

因为我们与前端数据传输基本都是以JSON 形式传输的, 而不同的序列化框架处理方式不一样,有的序列化框架的JSON 字段以 定义的属性为准,而有的框架用的是get , set 方法。还有很多中间件框架通过反射来给属性赋值, 很多框架用的也是get , set 方法。

基于这种限制,既然你都有了get , set 方法, 你在将属性定义为public ,显然有些多余(尽量提供一个方式访问和修改属性)。因此我认为这是属性定义为private 的其中一个理由。

继承有关

public 属性子类能够继承过来,但是private 属性子类不会继承过来,但是get , set 方法由于是public ,因此能够被继承。

很多中间件框架,强制需要有get , set 的理由,我认为是在存在继承关系时,反射访问父类属性更加麻烦点尤其在复杂的继承关系时,如果使用get , set 方法就简单了,不需要考虑继承问题。

get , set 方法是在接口中定义的

我截取了Spring BeanDefinition 接口定义,因此它的实现类必须要实现get , set方法,

所以对应的属性,为private ,(没必要再申明public 了,已经有访问,和修改属性的方法了)

图片

AOP有关

因为AOP 只能对方法进行拦截,如果是简单的属性赋值,想扩展功能比较难,如记录属性被修改的日志,如果是对public 字段直接赋值的,记录日志将非常麻烦。但是如果是get ,set 方法,很轻松通过AOP 进行增强。

扫码_搜索联合传播样式-白色版.png

以上我个人理解的,不足之处还请斧正。