为什么要提供getter 和setter方法?

一个类提供这两个方法,通常都是public的,意味着任何地方都可以new一个对象然后通过setter修改他们的成员变量,那这个成员变量修饰为private有用什么作用?何不直接就实例.属性修改?

阅读 7.8k
6 个回答

Java封装是否多余?

我们在学习Java的时候,书上告诉我们面向对象都是具有封装性的。那怎么体现封装性呢?就是将我们的成员变量用private进行修饰。

给出这个成员变量的set、get方法。这样就体现了封装性了。

那我们有没有想过,这是为什么呢??我们每次都要写一大堆的set、get方法,干嘛呢??就为了体现它这么一个封装性??封装性又体现在哪呢??

我们日常中给这些变量赋值的时候都是setXXX()这样子。

那如果我们不设置成private,直接设置成public的话。赋值起来不是更加简单??例如:


    Person p = new Person();

    //age定义成public的,我们就直接赋值了
    p.age = "22";


    //name定义成private,我们要通过方法来进行赋值。
    p.setName("zhongfucheng");

看完上边的代码,我们会发现:封装性究竟体现在哪??这不是搞我吗?他俩实现的效果不是一样的吗?都是赋值而已啊。

对啊,对于上面的代码,确实是这样的。如果自己用的话,那他俩实际的效果是一样的,没啥多大的区别。

那我们为什么要封装?

我觉得java中需要封装,有下面几个原因:

  • 我们可以在set方法中做其他的事,比如用户传递进来一个名字”傻逼“,我们判断这个名字是否合法,如果不合法就不给他取了。也就是说:我们可以在set方法中做逻辑判断,可以干该属性相关的事
  • JavaBean规范就是对成员变量对其修饰为私有,给出对应的set、get方法。这是一种规范。那我们打破这个规范会怎么样??可以说:绝大部分的Java框架、类库在使用的时候都是调用set、get方法来设置数据、获取数据。如果我们不遵守这个规范,那么我们的类库都用不了啦。
  • 假设我们使用的是public来修饰成员变量,我们这个成员变量已经被多个类使用了。可是有一天,我们发现这个成员变量要做的事情不仅仅是赋值,还有别的事要干(这个变量的值需要加上一些数据)。那就惨了,需要我们找到每个用这个变量的地方。如果我们使用了set、get的话,那么我们只要该了set、get方法的内部,其他的数据都全变了。

我觉得第二点和第三点是我们需要使用Java中set、get方法的主要原因。

由于stackoverflow上已有人提出过这个问题,并且解答也很好,我就直接搬运最高票过来,并稍作翻译。

  • Encapsulation of behavior associated with getting or setting the
    property - this allows additional functionality (like validation) to
    be added more easily later.
  • 对与get&set类属性有关的类的行为进行封装可以方便以后增加其他功能(比如验证)
  • Hiding the internal representation of the property while exposing a
    property using an alternative representation.
  • 用不同于内部的展现方式对外公布属性
  • Insulating your public interface from change - allowing the public
    interface to remain constant while the implementation changes without
    affecting existing consumers.
  • 避免对外接口发生变化 —— 当实现发生变化时,对外接口不变,不会影响到现有的调用方
  • Controlling the lifetime and memory management (disposal) semantics
    of the property - particularly important in non-managed memory
    environments (like C++ or Objective-C).
  • 控制属性的生命周期和内存管理 —— 在无内存管理的环境中尤其重要(比如C++和Objective-C)
  • Providing a debugging interception point for when a property changes
    at runtime - debugging when and where a property changed to a
    particular value can be quite difficult without this in some
    languages.
  • 当属性的值在运行时发生变化的时候,提供一个调试入口 —— 在某些语言中调试属性值的变化是很困难的
  • Improved interoperability with libraries that are designed to operate
    against property getter/setters - Mocking, Serialization, and WPF
    come to mind.
  • 提高与那些操作属性的getter/setter的库的互通性 —— 比如Mocking(单测常用的东西,我平时也直接说Mock,不知道怎么翻译), 序列化, WPF等等
  • Allowing inheritors to change the semantics of how the property
    behaves and is exposed by overriding the getter/setter methods.
  • 允许子类继承并覆写修改属性的行为的语义
  • Allowing the getter/setter to be passed around as lambda expressions
    rather than values.
  • 允许getter/setter作为lambda表达式而不是值进行传递
  • Getters and setters can allow different access levels - for example
    the get may be public, but the set could be protected.
  • getter/setter可以有不同的可访问性,比如get可以public而set则是protected

这属于封装,直接暴露属性就意味着你没有办法在不修改API的情况下改变数据的表示方法。
采用getter setter 你就可以扩展你自己的类,但是调用者不需要改变

新手上路,请多包涵

第一个是数据安全性
第二个大部分的框架需要要到反射机制 ,比如struts mybtais和hibernate等等 都是需要get和set方法的

他们都说了很高级的原因了。我说个简单的。
我希望写代码的时候,提示器不要把那写变量展示出来。
image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题