这一节我们学习面向对象中的第一个特性,封装(encapsulation)
封装:是指隐藏对象的发生和实现细节,仅对外提供公共访问方式.
那么什么是隐藏对象的实现细节?我们来举例学习.
比如我们来定义一个人的类,简单点说,人的属性有年龄,行为有说话.
我们看下面的代码:
~~~
class Person//定义一个人的类
{
int age;
void speak()
{
System.out.println("age = "+age);
}
}
class PersonDemo//定义测试类
{
public static void main(String[] args)
{
Person p = new Person();
p.age = -20;//这时代码仍然正常运行了,这就造成了安全隐患
p.speak();
}
}
~~~
结果:
![](https://box.kancloud.cn/2016-05-18_573c41af62be0.jpg)
我们看到存在安全隐患,当我们为人的年龄属性赋值为负数时,程序是正常运行的.
那么现在把Person类修改一下
~~~
<pre name="code" class="java">class Person
{
private int age;
void speak()
{
System.out.println("age = "+age);
}
}
~~~
~~~
~~~
结果:
![](https://box.kancloud.cn/2016-05-18_573c41af73230.jpg)
我们看到报错了,因为我们对age进行了私有,在PersonDemo类中无法访问.
为了进一步解决问题,我们再对两个类进行修改:
~~~
class Person
{
private int age;//把该成员属性设置为私有
public void setAge(int a)
{
if(a>0 && a<130)
{
age = a;
speak();
}
else
System.out.println("错误的数据");
}
void speak()
{
System.out.println("age = "+age);
}
}
class PersonDemo
{
public static void main(String[] args)
{
Person p = new Person();
p.setAge(-20);//调用方法设置年龄,但是我们不知道该方法的内部实现
}
}
~~~
结果:
![](https://box.kancloud.cn/2016-05-18_573c41af86870.jpg)
我们看到当age>0 && age<130时,才合法.
从这个过程我们看到,当我们要操作Person中的age属性时,是通过setAge方法来实现的,但是setAge方法是怎么实现的,外部类是无法知道的,这就是我们所要说的隐藏对象的属性和实现细节,也就是封装.
其实对于属性的封装,为了外部访问,我们一般有规范的get和set方法,我们来看一下两个规范且常用的方法:
~~~
class Person
{
private int age;//把该成员属性设置为私有
public void setAge(int a)//设置年龄
{
age = a;
}
public int getAge()//获取年龄
{
return age;
}
}
~~~
下面我们再来说说封装的优点和原则:
优点:
1.提高代码安全性;
2.实现对内部属性的可控性;
3.提高代码的复用性;
4.隔离变化;
原则:
1.将不需要对外提供的内容都隐藏起来;
2.把属性都隐藏起来,提供公共方法供外部访问(当然不是所有方法都必须是公共方法).
最后我们再看一下刚才我们用到的一个关键字:private.
**private关键字**:指私有,是一个权限修饰符,用于修饰成员.私有的内容只在本类中有效.
它的常见用法:就是将成员变量私有化,对外提供对应的set,get方法对其进行访问.提高对数据访问的安全性.
注意:私有仅仅是封装的一种体现而已.
对于java语言来讲,最小的封装体就是函数.类也是封装体.框架本身也是封装体.这些都一个共性,就是我们可以不知道实现细节,直接拿来用就可以了.
- 前言
- 1.1 基本常识
- 1.2 Java语言概述
- 1.3 Java语言的环境搭建
- 1.4 Java程序开发之初体验--Hello World
- 2.1 关键字
- 2.2 标识符
- 2.3 注释
- 2.4 常量
- 2.5 进制扫盲
- 2.6 变量和数据类型(1)
- 2.7 变量和数据类型(2)
- 2.8 运算符
- 3.1 if语句
- 3.2 switch语句
- 3.3 while和do-while语句
- 3.4 for语句
- 3.5 for循环的嵌套
- 3.6 break语句与continue语句
- 4.1 函数的定义
- 4.2 定义函数的两个明确
- 4.3 函数的内存加载过程
- 4.4 函数的重载
- 5.1 数组的定义
- 5.2 数组的内存分配及特点
- 5.3 数组操作中常见问题
- 5.4 数组常用操作(1)
- 5.5 数组常用操作(2)
- 5.6 二维数组
- 6.1 面向对象的概述
- 6.2 类与对象的关系
- 6.3 对象的内存体现
- 6.4 成员变量与局部变量
- 6.5 类类型参数与匿名对象
- 6.6 基本数据类型参数与引用数据类型参数的传递过程
- 6.7 封装
- 7.1 构造函数概述与默认构造函数
- 7.2 构造函数与一般函数的区别
- 7.3 构造函数的重载
- 7.4 构造函数的内存加载
- 7.5 构造函数需要注意的几个细节
- 7.6 this关键字的原理
- 7.7 this关键字的细节与应用
- 8.1 static关键字之特点
- 8.2 成员变量与静态变量的区别
- 8.3 static关键字使用的注意细节
- 8.4 main函数的解析与细节
- 8.5 static关键字的使用场景
- 8.6 静态的内存加载
- 8.7 静态代码块
- 8.8 构造代码块
- 9.1 继承
- 9.2 单继承与多重继承
- 9.3 子父类中成员变量特征体现