java set get访问器理解

简述

java中习惯将类的成员变量属性设置为私有(private),并通过设置setXXX和getXXX方法来完成对成员变量的赋值和取值操作。在刚开始学习java时一直很疑惑为什么不将成员变量设为公有(public),直接操作成员变量不是更方便吗?其实这样设计是源于java的三大特性(封装,继承,多态)中封装的概念。

封装

封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口(该接口并非指java中interface,而是泛指只关心方法而不关心具体实现的方法,在此处可理解为set,get访问器)。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装是一种信息隐藏技术,在java中通过关键字private实现封装。什么是封装?封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。

上述解释来自百度百科,红字部分为自己理解

public VS private

我们来看下为什么不采用public标记实例域的理由:

我们可以用public 标记实例域,但是这是一种极为不提倡的做法。public数据域允许程序中的任何方法对其进行读取和修改。这就完全破坏了封装。任何类的任何方法都可以修改public域,从我们经验来看,某些代码将使用这种存取权限。而这并不是我们所希望的,因此,这里强烈建议将实例域标记为private。

上述解释摘自 《java核心技术 卷一 (第九版)》 p109

作者只从破坏封装的角度谈了一下public标记实例域的缺点,其实我们可以从另一方面考虑。我们发现set get访问器和成员方法本质是一样(逻辑上不同),那么我们可以考虑下调用方法和直接访问属性的不同。

只有修改权限

这绝对是用public标记实例域无法办到的(反射除外),而访问器可以通过暴露set方法来实现。

成员变量类型改变

public class Person {private String age;public String getAge() {return age;}public void setAge(String age) {this.age = age;}}

这是我们需要将age类型改为int

public class Person {private int age;public String getAge() {return ""+age;}public void setAge(String age) {this.age = Integer.parseInt(age);}}

所有依赖person的类都无需修改代码,如果是public标记实例域就必须将所有对依赖person对象age属性的代码进行修改。假如依赖100个。这还不是做可怕的,如果依赖类下面还要用到这个属性那该行代码同样可能需要修改。

返回引用可变对象

这里我们创建一个Person类,该类有一个birthday(生日)属性,正常情况下,人的生日在出生(初始化)的时候就已经固定,并且不会放生改变。

public class Person {    private Date birthday;    public Person(Date birthday){        this.birthday=birthday;    }    public Date getBirthday() {        return birthday;    }    public static void main(String[] args) {        Person john=new Person(new GregorianCalendar(1991,6,5).getTime());        Date d=john.getBirthday();        System.out.println(john.getBirthday()); //=>Fri Jul 05 00:00:00 CDT 1991        d.setMonth(0);        System.out.println(john.getBirthday()); //=>Sat Jan 05 00:00:00 CST 1991    }}

出错的原因很微妙。d和john.getBirthday引用同一对象.对d调用更改器方法就可以自动修改生日这个私有状态。这是我们其实是要将get方法中return birthday修改为return (Date) birthday.clone();即可。

当然public标记实例域也可以实现,只不过每次获取成员变量是都需要手动复制一遍。显示增加代码的复杂度,而且增加了代码的重复率。

而从关注点分离的角度来看,复制这个行为和调用者的业务无关,身为调用者我只是想拿到john的生日,并将这个日期进行一些处理,而不应该去关心你传递的是一个引用所以我需要复制一下。这本身就是技术对于业务逻辑的污染,应该是我们尽量去避免的。

看自家总在期待,不知将来好歹,新乐吧总在不断等待,

java set get访问器理解

相关文章:

你感兴趣的文章:

标签云: