JAVA使用中未曾注意到的细节——成员变量的get方法可能破坏类的封装

        在JAVA开发中,为类中的成员变量添加get和set方法是大家习以为常的事情了。但凡有可能会在其他类中使用或修改该类的成员变量,get方法与set方法肯定是第一选择。特别是在web开发中与数据库字段相对应的实体类,get方法与set方法更是比不可少的。那么有人想过get方法有可能会破坏类的封装么?

        最近在翻看Core JAVA这本经典的JAVA书来巩固一下基础知识,突然看到了get方法可能会破坏类的封装,对此我表示十分的困惑。于是仔细研读,并经过编码试验发现确实如此。

       我先定义了两个实体类People、Employee和一个包含main函数的可执行类

public class People{
	private String name;
	private Integer sex;
	private Date birthday;
	public People(String n, Integer s, Date b){
		name = n;
		sex = s;
		birthday = b;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getSex() {
		return sex;
	}
	public void setSex(Integer sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}
public class Employee{
	private People people;
	private double salary;
	public Employee(People p, double s){
		people = p;
		salary = s;
	}
	public People getPeople(){
		return people;
	}
	public void setPeople(People p){
		people = p;
	}
	public double getSalary(){
		return salary;
	}
	public void setSalary(double s){
		salary = s;
	}
}
public class Main {
	public static void main(String[] args) {
		Employee e = new Employee(new People("hello", 0, new Date()), 2000d);
		People p = e.getPeople();
		String name = p.getName();
		Integer sex = p.getSex();
		Date birthday = p.getBirthday();
		System.out.println("------------------初始值-----------------------");
<pre name="code" class="java"><span style="white-space:pre">		</span>System.out.println(e.getPeople().getName());
		System.out.println(e.getPeople().getSex());
		System.out.println(e.getPeople().getBirthday().getTime());
name = "kitty";sex = 1;birthday.setTime(birthday.getTime() + 10000000);System.out.println("------------------第一次操作后-----------------------");
<span style="white-space:pre">		</span>System.out.println(e.getPeople().getName());
		System.out.println(e.getPeople().getSex());
		System.out.println(e.getPeople().getBirthday().getTime());
p.setName(name);p.setSex(sex);p.setBirthday(birthday);System.out.println("------------------第二次操作后-----------------------");System.out.println(e.getPeople().getName());System.out.println(e.getPeople().getSex());System.out.println(e.getPeople().getBirthday().getTime());}}

 执行main函数,控制台输出的内容 

------------------初始值-----------------------
hello
0
Wed May 20 15:23:39 CST 2015
------------------第一次操作后-----------------------
hello
0
Wed May 20 18:10:19 CST 2015
------------------第二次操作后-----------------------
kitty
1
Wed May 20 18:10:19 CST 2015

        首先创建一个Employee实例,取出其中的成员变量people的值赋值给变量p,再取出p中的三个成员变量值分别赋值给了三个变量name,sex,birthday。

        第一步打印出e中people中的成员变量值,分别为hello,0,Wed May 20 15:23:39 CST 2015。之后我对name,sex,birthday三个变量值进行了修改,再次打印e中people中的成员变量值,分别为hello,0,Wed May 20 18:10:19 CST 2015。结果e中的people中的name,sex的值并没有因为我的操作而出现改变,而birthday的值被改变了。之后我又把修改后的三个变量值赋值给了p,再一次打印e中people中的成员变量值,为kitty,1,Wed May 20 18:10:19 CST 2015,这次所有的值都与第一次的打印结果不同了而我却没执行过e的任何set方法。

       究其原因,在调用一个类的get方法时,如果get方法的返回值类型不是基本数据类型或其包装类,并不会创建一个新的实例而是返回该get方法对应的变量的内存引用,之后如果对这个引用做了任何修改都会对类本身造成影响,从而破坏了类的封装。

       建议:如果get方法的返回值类型不是基本数据类型或其包装类,应先对成员变量进行克隆,再将克隆出的副本返回。(有关克隆的知识不在本文讨论范围)

       如有错误之处还请指正,转载请注明出处。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值