Java学习-类的隐藏机制(封装性)
1、封装的含义
封装(encapsulation)是面向对象的三要素之一(其它两个是继承和多态),它有两成含义:
1、将数据(属性)和函数(行为)放在一个独立的类中,使类成为一个独立的单元。
2、通过访问限定符(private等)实现对信息的隐藏或公开,隐藏类的内部实现。而留下一些接口(public的成员函数)与外界进行信息交换(外界要想访问某个成员只能通过接口实现)当类的设计者改变了类的内部实现时,但只要接口不变,对于类的使用者而言,没有任何影响。这就是所谓的“接口和实现的分离”
那么什么是封装? 简单地说,封装就是将数据和函数放在一起,将不想让外界看到的内容(通常是数据)声明为private的,不允许外界存取。外界要想访问的话,就只能通过类留给外部的接口。
为了更好的理解为什么要对对象进行封装,下面举个例子进行说明
先写两个类 :
- Person类
package day01
public class Person{
public int age;
public void printAge()
{
System.out.println("年龄是:"+age);
}
}
- Test测试类
package day01
public class Test{
public static void main(String[] args)
{
Person p = new Person();
p.age = -100;
p.printAge();
}
}
运行后打印结果为:年龄是:-100
分析一下代码:
程序是没问题的也能正常运行,但是年龄为-100显然不符合正常逻辑。从代码可以看出在new完一个person对象后用户可以对它的age属性随便赋值。像这种情况是把类的属性开放出来,让调用者随意使用,这样就会出现问题,它们很容易被一些粗心的或不知情的客户端程序员所毁坏。
所以我们需要对这样不能让调用者随意使用的属性做封装和隐藏以减少程序的bug。这意味着类的创建者可以任意修改被隐藏的部分,而不用担心对其他调用者造成影响。
代码修改后如下:
package day01
public class Person{
private int age;
public void setAge(int a)
{
if(a <=150 && a>=0){
this.age = a;
}else{
System.out.println("输入的年龄:"+a+"不在0到150之间");
}
}
public int getAge()
{ return this.age;}
public void showAge()
{
System.out.println("年龄是:"+this.getAge());
}
}
package day01
public class Test{
public static void main(String[] args)
{
Person p1 = new Person();
Person p2 = new Person();
p1.setAge(55);
p1.showAge();
p2.setAge(60);
p2.showAge();
}
}
可以看到修改过后的对象不能直接通过p.age进行赋值操作,因为此时的age属性已经是被private限制,只能由类内部的成员函数调用并进行传参。
2、类的setXXX 和 getXXX
封装的一个原则是:“信息的最小化公开”,所以在理想状态下,通常将所有的数据都声明为private(因为随便对类的内部数据进行更改是很危险的),如果想改变和得到某个数据的话,那么使用相应的接口进行访问
- 通常设置数据的接口命名为setXXX(如public void setAge() )
- 将得到数据的接口命名为getXXX(如public int getAge() )
?考虑这样两个问题:
问题一: 使用Person类来定义的两个对象p1和p2,那么p1和p2两个对象在内存中的存储状态是怎么样的呢?即数据成员和成员函数是否都存放在对象中呢?
问题二: p1和p2调用相同的成员函数,为什么显示结果不一样?它们调用的是同一段代码吗?
其实对象空间中仅存储数据成员,而类的成员函数代码不会存储在对象中,用一个类的不同的对象调用成员函数时,调用的是同一段函数代码。
成员函数和普通函数的区别:
在编译器的角度来看,成员函数和普通函数是没有本质区别的,成员函数只不过是为了封装的需要,而在形式上放在类中。最主要的区别是:
成员函数暗自具备了一个从编译器传过来的指向类对象的this(当前对象的引用),通过它成员函数就可以操作当前对象的数据成员。
Person p1 = new Person();
Person p2 = new Person();
p1.setAge(55);//在这里this指向p1
p2.setAge(60);//在这里this指向p2
3、this关键字
- 在类的方法定义中使用的this关键字表示使用该方法对象的引用。
- 当必须指出当前使用方法对象是谁时要使用this
- this可以看作是一个变量,它的值是当前对象的引用
- 当处理方法中成员变量和局部变量重名时要用this
4、总结
java中类的封装和隐藏就是:
通过将类的成员数据声明为私有的(private),再提供公共的(public)方法:getXXX()和setXXX()实现对该属性的操作。以实现以下目的。
- 隐藏一个类中不需要对外提供的实现细节
- 使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;
- 便于修改,增强代码的可维护性