面向对象的三大特征:封装、继承、多态。今天我们来浅谈一下封装。
什么是封装
我们不用那么专业那么难懂的语言讲解,我们就走一波野路子:封装就是指用private 这个访问权限修饰符 修饰类中的成员或者方法,使被修饰的信息只能在其所在的类中看到具体的实现。
就相当于,你不需要知道为什么一加一等于二,你只要会计算就可以了。
class Person{
private int age;
private String name;
private String sex;
我们在这里抽象出来人这个类,不妨想成一下这是一个女人,随意询问一位女士的年龄之类的信息是非常失礼的,因此我们把这个类中的三个属性用private 修饰一下。
现在我们再来试一下礼貌性地搭讪:
看来我们被很明确地拒绝了……
虽然我们没有搭讪成功,但是至少我们见识到了封装的力量!那请问:如果我们的封装就只是为了不让我们使用数据,那为什么不直接不写这个数据呢?
首先,我们封装的意义只是为了不让类中的信息被外人所窥探,比如这个类中有哪些属性,比如这个类中实现了哪些方法……但是出于人道主义,我们一般会在使用private的同时,给程序的使用着提供一个get/set接口 这样子使用者就可以在不清楚程序的具体实现的情况下获得/设置被封装的内容了!
public Person(int age, String name, String sex) {
this.age = age;
this.name = name;
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
兄弟们可千万不要以为以后我们每使用一次类都要写上这么多的代码啊,写代码又不是八股文。没有那么多凡尘俗套:
鼠标右键,然后慢慢点就行了,我们的Ideal会帮助我们实现构造方法以及接口的!赞美伟大的Ideal开发者!!
Person person=new Person(20,"cyt","man");
// System.out.println(person.name);
System.out.println(person.getName());
person.setName("qxy");
System.out.println(person.getName());
再来看一下接口的使用:
这样子我们就做到了封装的属性与用户之间的交互!
对于现实生活中,授人以渔不如授人以鱼,我要是把王者荣耀的代码给你了,我还怎么挣钱啊!!
访问权限修饰符
四种修饰符权限从小到大依次是:
private<default(默认的包访问权限)<protected<public
public很开放,只要是一个Java文件里面的都是可以是使用的。
protect只能是在一个包中或者不同包但是存在继承关系的情况下访问。
default不是一个修饰符名称,而是指在我们不加以修饰符的时候,默认的修饰权限就是在一个包里面。
private比较腼腆,只能在它所在的类中访问,出了这个类一概不熟!!
现在我们还没有接触到继承的知识,所以先不加以讨论,在这里我本可以随便敲几行代码,随便截几张图,这样可以水不少字数,但是谁让阿涛我人心善呢,我直接教兄弟们如何在Ideal上面分辨:
一个包就相当于是一个文件夹,里面可以放好多的类,我们可以通过New Package来创建一个又一个包,我们说的包访问权限就是指着在这一个文件夹下面的那么多类中,被包访问权限修饰符修饰的都是可以畅通无阻地使用的,而我们说的类就是指的前面有c 标识的。
导入import一个包package?
就在刚刚我们似乎说到了一关于包的知识,其实对于包我们并不是那么陌生,我们一直都是在潜移默化地使用着:
注意看现在上面什么都没有:
之前我们讲过Java中地输入,其中就提到了这个,通常来说我们的Sca还没数完Ideal就会智能提示我们,我们只需要按下回车键,Scanner和最上面的那一行都自动填充好了。
现在再来说一水:包里面其实存放的是好多好多的类,而类中又会有好多好多的方法,对于我们的Java来说一切皆对象,我们有的时候根本不需要自己去动手写一些方法,前人之述备矣,我们需要做的就是学习这些方法的使用,并且确保我们在打开前辈的知识宝库的之前,导入了对应包中的类即可!
所以我们导入的并不是包,而是包中的类!!!
当然了,一般情况下是不需要我们自己可以去记忆我们要使用的类在哪个类里面,这个类又在哪个方法里面,这样子对于解放程序猿的双手也太不友好了!当然了,如果我们是在不乐意去导包,那就只能为委屈一下自己了:
java.util.Scanner scanner=new Scanner(System.in);
这样子虽然不错,但是不太正规,你懂我意思吧……
Static到底是什么
大名鼎鼎的psvm中的s就是这里的static,static代表着静态的。
private int age;
private String name;
private String sex;
public String country="China";
这里我们加上一个国籍:
我们通过调试可以看到这个person的具体的信息,可以看到此时我们的国籍还是属于person指向的对象的。那么现在呢:
public static String country="China";
看到没,这个国籍就这么硬生生没了。其实不是没了,只是不再属于我们的对象了,静态的属性和方法此时不是属于某一个对象的,而是属于有这个类创建出来的所有对象的,也可以说是属于类的了!不信你看:
刚才我偷偷把sex这个类的权限改了一下,给兄弟们打个样!我们可以通过person引用访问到sex这个属性,但是没有办法直接通过Person这个类名访问到sex,可是我们可以通过Person直接访问到country这个被static修饰的静态属性。接下来我们再来看点骚的:
我们试图通过引用访问静态成员属性,此时编译器并没有给我们提示,但是我们自己如果强行输完,此时是不会报错的。我想这也算是编译器想表达的一种态度吧:不遵守规则的人我凭什么给你便利呢?
经典之我抄我自己,这是我在前几篇博客的时候手绘的,算不得侵权!之前我们说过,我们new出来的对象都是放在堆上的,那我们对象中的成员属性也沾了光放到了堆上,但是成员方法本身是放在了内存中的代码段里面,只有调用方法的时候才会给它们分配内存,而我们的静态成员属性则是被放到了方法区上面。
根据我们静态方法的性质我们可以这么说:我们的静态属性啊,方法啊,都是不依赖对象的,可以直接通过类名给它点出来,但是普通的成员方法就没有那么自由了,她=他们都是依赖对象的。那么问题来了:我们可不可以在非静态的方法中调用静态的属性呢?
我们也不燃那些繁琐的概念,我们就抓住一点,我们的静态属性是不依赖对象的,如果放在了一个非静态方法的内部,那是不是就和它一荣俱荣一损俱损了?所以我们说,我们是不可以在一个非静态的方法中访问一个静态的成员的。翻过来我们可以在静态方法中访问非静态的属性吗?理论上应该不可以的,因为我们的静态方法是不需要通过new对象来实现的,但是如果我们真的就在静态方法中new上一个对象,还是可以勉强使用非静态的方法的,但是这就有点刻意为了非静态而静态了……
最后在给兄弟们补充一点算作的离别的小礼物:
Person person1=new Person();
System.out.println(Person.country);
Person.country+=1;
System.out.println(Person.country);
Person person2=new Person();
System.out.println(Person.country);
Person.country+=2;
System.out.println(Person.country);
兄弟们看了这个代码是不是会一眼以为不就是国籍后面分别加上一和二,对不对,我们来见证奇迹!
看到没,有没有感觉虽然我们new了那么多个对象,但好像就在实际上效果上其实我们都是在对同一个country进行操作?这就是阿涛最后想讲的,我们的静态属性只会在方法区内部储存一份,只要我们使用到了静态方法,那么无论使用几次,都是操作的同一份!
好了,希望我的这篇博客能够帮助到兄弟们!
百年大道,你我共勉!!