上一篇文章我们了解了三剑客之一的继承,这篇文章我们就来聊一下三剑客之二:封装
注意了,封装不像继承是一种语法,他其实更多的是体现一种编程的思想,在了解Java中的封装之前,我们可以先在生活中找一找封装的思想,毕竟知识来源于生活,Java也不例外。
生活处处是封装
在我们的生活中,到处可见封装的例子,比如电脑的主机,就被机箱给封装住了,我们看不见里面复杂的线路和硬件,我们只知道按下开机键就能开机,把U盘插在接口上电脑就能读取信息,作为普通用户,我们没有专业的硬件知识,所以我们也不需要去了解里面的结构多么复杂,相反的,将过于复杂的结构暴露给普通用户,反而不是一件好事,有可能会导致用户不小心损坏其中的部件,或者使用户发生危险等等。
再比如,我们的汽车,我们只需要知道脚下右边是油门,左边是刹车,方向盘能控制车辆行进的方向,这就可以了,我们也不需要知道发动机、变速箱、齿轮等是怎样工作的,所以他们也都被封装起来了,只有在必要的时候,才会打开,当然大部分时间这些工作都是由专业人员进行的,我们同样不需要关心车辆更换了什么部件之类的。
这就是生活中封装的思想:将内部复杂的结构封装起来,不让外部看见,而只给外部暴露简单的接口,方便用户的使用,也可以免去很多麻烦。这个思想在Java中也是如此,下面我们来看一下Java中的封装:
Java中的封装(权限修饰符)
在Java中,封装的思想也是和上面提到的思想大同小异,不过用代码方面的语言来说就是,将类中的某些信息隐藏在类的内部,不允许外部程序直接访问,而使用过该类提供的方法来访问和操作,这样就实现了对信息操作的控制。这个后面再说,我们先学习Java是如何实现封装的,答案是权限修饰符。
权限修饰符有四种,public (公开的)、protected (受保护的) 、default(默认的)、private (私密的)。他们都是写在方法名和变量名前进行修饰的,但需要注意的是,除了内部类,其他类不能用private修饰,下面用代码来理解一下:
public class AA{
private String name;
protected int age;
default void fangfa(){
}
}
在这里定义了一个公共的类,在类中定义了一个私密的String类型的name,定义了一个受保护的int类型的age,同时拥有一个默认的方法,这么修饰之后有什么用呢?,其实这是为了限制外部对于数据的调用。
他们的规则如下:
被public修饰的变量或方法在任何地方都可以被访问到
被protected修饰的变量和方法不能被不同包下的非子类访问。
被default修饰的变量和方法不能被不同包下的类访问。
被private修饰的变量和方法只能在本类中访问。
我将他们总结成表格,方便大家的记忆:
本类中 | 同一个包下的类 | 不同包下的子类 | 不同包下的非子类 | |
---|---|---|---|---|
public | yes | yes | yes | yes |
protected | yes | yes | yes | no |
default | yes | yes | no | no |
private | yes | no | no | no |
可以看出,其实还是有规律的,这也方便了大家的记忆。根据我目前的代码经验来说,应用最多的就是public 和private了,也有可能我的水平不够,不经常使用其他的哈。
使用封装实现对数据的控制
上文提到,封装可以实现对操作的控制,怎么来理解呢?下面通过一个小例子来理解一下:
假设我需要开发一个职工信息存储的系统,首先我定义一个职工类,其中包含有职工的姓名、年龄、还有工号 同时对他进行toString重写:
public class User{
String name;
int age;
int ID;
@Override
public String toString() {
return
"姓名:" + name +
",年龄:" + age +
", 工号" + ID
;
}
}
然后我用另一个类对他实现操作:
public class Test{
public static void main (String [] args){
User user1 =new user();
user.name="张三";
user.age=300;
user.ID=10001;
}
}
输出效果:
我们已经创建了一个职工,并且给他赋予了姓名、年龄、工号。但是你发现了吗。他的年龄是300,作为java语法来说,这显然是没有任何问题的,int类型别说300,就是300万也是可以的。但是从我们人的逻辑来看,根本不可能,也不应该出现这种数据,但是我们并没有对输入值进行控制,外部自然是相输入多少就输入多少,name怎么办呢,就需要用到我们的权限修饰符了。
改进上面的代码:
public class User{
String name;
private int age;
int ID;
public int getAge() {
return age;
}
public void setAge(int age) {
if(age>=0&&age<=100){
this.age = age;
}else{
System.out.println("年龄信息输入错误!");
}
}
@Override
public String toString() {
return
"姓名:" + name +
",年龄:" + age +
", 工号" + ID
;
}
}
我们将age 使用private修饰,让他只能在本类中被访问,然后我们在类中写出一个公开的get和set访问方法,这个时候,外部的类不能直接访问age,但是可以访问我们提供的方法,通过方法来访问到我们的变量,这个时候。我们就可以在方法中对他输入的数据加以控制了,比如,在setAge方法中执行判断,让输入的年龄大于0小于100,如果超出这个值,则提示错误。
这个时候,我们的测试类已经没有办法直接访问到age了,所以也要改动,使用方法来为age赋值:
public class Test{
public static void main (String [] args){
User user1 =new user();
user.name="张三";
user1.setAge(300);
user.ID=10001;
}
}
我们依旧输入300,看看会发生什么:
可以看到,出现了错误提示信息,而且300这个值并没有赋给张三。成功的对输入的值进行了控制,下面我们输入一个合理的数25,看看效果:
正确的信息被赋给了张三,我们成功的通过权限修饰符对外部的操作实现了控制!
当然,控制是多种多样的,合理运用,我们可以控制的很多:比如成绩的区间在0到150之间、比如输入的数必须是几位、必须以1001开头啊等等,合理运用,灵活控制,可以实现很多好玩的功能哦。
这篇文章跟大家分享了封装的思想和四个权限修饰符,希望对大家以后的开发和程序结构会有所帮助!