一、什么是封装呢?
封装是面向对象的三大特征之一。
隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
①封装就是将面对对象的状态和行为看成是一个整体,将二者存放在一个独立的模块中,比如说类
②封装也是信息隐藏,把不需要让外界知道的信息隐藏起来,尽肯能隐藏对象功能实现细节,向外暴露方法,保证外界的安全访问,比如说方法
public static void SaveMan(int PhoneNumber,String name,int QQnumber,String Email,String wechant) {//我们在添加联系人时,需要传进的数据非常多而且很长,这就导致了参数列表的冗长 }
class LinkMan{int PhoneNumber;String name;int QQnumber;String Email;String wechant;//这样我们就将联系人信息封装起来了,封装到了一个类里 }
二、为什么要封装呢?
1.我们先来看下边这段代码
public class FengZhuang { public static void main(String[] args) {Person p=new Person();p.name="asa";p.age=-17; //设置年龄的时候负数不合理,应该判断输入值是否正常//这个值是可以通过圆点运算符.来进行存取修改的,设置的数据不安全 }} class Person{String name;int age; }
那我们怎么解决上述问题呢?
class Person{String name;//将年龄用权限修饰符设置为私有的,只能在本类中访问,外界无法访问。//既然我们已经将年龄设置成私有的,外界无法访问,那我们怎么去设置它的值呢?//我们专门给age提供一个公共的方法,来对他进行访问,这就是Setter和Getter方法private int age;public int getAge() {return age;}//我们可以通过set方法来对age进行访问,并且对传入的数据进行了筛选,这样就提高了数据的安全性public void setAge(int age) {if(age<0) {System.out.println("年龄不能为负数");return;//结束程序}else {this.age = age;}} }
public class FengZhuang { public static void main(String[] args) {Person p=new Person();p.setAge(-18); }
当我们输入一个负数年龄时,系统会给我们返回一个提示,提示我们不能是负数,但是我们并不知道它是怎么返回来的值,怎么去判断的这些细节,我们只知道结果。
①封装提高了代码的安全性。
②隐藏了实现细节,对外提供可以访问的方式。便于调用者的使用。
③提高了代码的复用性。
三、权限访问修饰符
封装让有些类看不到一些类里边具体做了什么,所以java提供了访问权限修饰符来一个类里边可以看到什么暴露什么,不可以看到什么暴露什么。
java中有四种访问权限修饰符,分别是private私有的,default不写,protected受保护的,public公共的
他们的访问权限如下
public | protected | default | private | |
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ |
|
不同包的子类 | √ | √ |
|
|
不同包中的无关类 | √ |
|
|
注意:private只能在本类中访问,离开本类后不能直接访问,在其他类中是可以访问但不能直接访问,比如上边代码中的set和get方法就是一种间接访问private修饰符的字段方法
一般字段都是使用private修饰符来修饰,达到隐藏和安全的要求。
2.那么什么情况该用什么修饰符呢?
从作用域来看,public能够使用所有的情况。 但是又不会真正全部都使用public,那么到底什么情况该用什么修饰符呢?
1. 属性通常使用private封装起来
2. 方法一般使用public用于被调用
3. 会被子类继承的方法,通常使用protected
再就是作用范围最小原则
简单说,能用private就用private,不行就放大一级,用package,再不行就用protected,最后用public。 这样就能把数据尽量的封装起来,没有必要露出来的,就不用露出来了
四、this关键字
现在有一辆自行车,小雨和小颖分别骑了一会这辆自行车,小雨说,这辆车我骑起来真重,那么当前“我”即这辆车的使用者就是小雨,小颖说,我骑起来还好,那么当前“我”即这辆车的使用者就是小颖。this就相当于我这个字,代表的是当前对象。
class Person{String name;private int age;public int getAge() {return age;}public void setAge(int n) {if(n<0) {System.out.println("年龄不能为负数");return;}else { //这里的n具体指什么呢?age = n;}} }
n指我们要传入的age,当我们把它换成age
class Person{String name;private int age;public int getAge() {System.out.println(age);return age;}public void setAge(int age) {if(age<0) {System.out.println("年龄不能为负数");System.out.println(age);return;}else {System.out.println(age);age = age;System.out.println(age);}} }
我们看到如上的输出结果,这表明get方法中的age获取到的是成员变量中的age,默认赋值0,这是因为程序遵循就近原则。
那怎么解决呢?
当成员变量和局部变量同名时,就可以用this关键字来区分,谁调用这个函数this就指的谁。
class Person{String name;private int age;public int getAge() {System.out.println(age);return age;}public void setAge(int age) {if(age<0) {System.out.println("年龄不能为负数");System.out.println(age);return;//结束程序}else {System.out.println(age);this.age = age;System.out.println(age);}} }
public static void main(String[] args) {Person p=new Person();p.setAge(18);System.out.println(p.getAge());Person p2=new Person();p2.setAge(20);System.out.println(p2.getAge()); }
程序输出结果如上图,当p对象调用时this就指的p这个对象,p2调用时this指的p2这个对象
那程序不是就近原则吗?为什这里的get方法获取到了我们传的这个值呢?
五、构造方法
1.什么是构造方法?它有什么作用?
构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成
其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。
class Person{String name;int age;//无参构造,会默认就有,只是隐藏了我们看不见public Person() {super();} }
在Java中,任何变量在被使用前都必须先设置初值.Java提供了为类的成员变量赋初值的专门方法。
java中创建对象时会调用类的构造方法,如果我们不重写这个构造方法,它默认的是一个无参数的构造方法
2.实例化对象
当我们重写这个构造方法后再实例化对象
如果我们不传值,编译器会报错。
当我们也将无参构造写出来后,便可以不在实例化时就传值
内存图解
3.特殊性
8.自定义类中,如果不写构造方法,java系统会默认添加一个无参的构造方法。如果写了一个有参的构造方法,就一定要写无参构造方法。