一、什么是封装呢?
封装是面向对象的三大特征之一。
隐藏对象的属性和实现细节,仅对外提供公共的访问方式。
①封装就是将面对对象的状态和行为看成是一个整体,将二者存放在一个独立的模块中,比如说类
②封装也是信息隐藏,把不需要让外界知道的信息隐藏起来,尽肯能隐藏对象功能实现细节,向外暴露方法,保证外界的安全访问,比如说方法
public static void SaveMan(int PhoneNumber,String name,intQQnumber,String Email,String wechant) {//我们在添加联系人时,需要传进的数据非常多而且很长,这就导致了参数列表的冗长
}
classLinkMan{intPhoneNumber;
String name;intQQnumber;
String Email;
String wechant;//这样我们就将联系人信息封装起来了,封装到了一个类里
}
二、为什么要封装呢?
1.我们先来看下边这段代码
public classFengZhuang {public static voidmain(String[] args) {
Person p=newPerson();
p.name="asa";
p.age=-17;//设置年龄的时候负数不合理,应该判断输入值是否正常//这个值是可以通过圆点运算符.来进行存取修改的,设置的数据不安全
}
}classPerson{
String name;intage;
}
那我们怎么解决上述问题呢?
classPerson{
String name;//将年龄用权限修饰符设置为私有的,只能在本类中访问,外界无法访问。//既然我们已经将年龄设置成私有的,外界无法访问,那我们怎么去设置它的值呢?//我们专门给age提供一个公共的方法,来对他进行访问,这就是Setter和Getter方法
private intage;public intgetAge() {returnage;
}//我们可以通过set方法来对age进行访问,并且对传入的数据进行了筛选,这样就提高了数据的安全性
public void setAge(intage) {if(age<0) {
System.out.println("年龄不能为负数");return;//结束程序
}else{this.age =age;
}
}
}
public classFengZhuang {public static voidmain(String[] args) {
Person p=newPerson();
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就相当于我这个字,代表的是当前对象。
classPerson{
String name;private intage;public intgetAge() {returnage;
}public void setAge(intn) {if(n<0) {
System.out.println("年龄不能为负数");return;
}else{//这里的n具体指什么呢?
age =n;
}
}
}
n指我们要传入的age,当我们把它换成age
classPerson{
String name;private intage;public intgetAge() {
System.out.println(age);returnage;
}public void setAge(intage) {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就指的谁。
classPerson{
String name;private intage;public intgetAge() {
System.out.println(age);returnage;
}public void setAge(intage) {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 voidmain(String[] args) {
Person p=newPerson();
p.setAge(18);
System.out.println(p.getAge());
Person p2=newPerson();
p2.setAge(20);
System.out.println(p2.getAge());
}
程序输出结果如上图,当p对象调用时this就指的p这个对象,p2调用时this指的p2这个对象
那程序不是就近原则吗?为什这里的get方法获取到了我们传的这个值呢?
五、构造方法
1.什么是构造方法?它有什么作用?
构造方法是一种特殊的方法,它是一个与类同名且返回值类型为同名类类型的方法。对象的创建就是通过构造方法来完成
其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。
classPerson{
String name;intage;//无参构造,会默认就有,只是隐藏了我们看不见
publicPerson() {super();
}
}
在Java中,任何变量在被使用前都必须先设置初值.Java提供了为类的成员变量赋初值的专门方法。
java中创建对象时会调用类的构造方法,如果我们不重写这个构造方法,它默认的是一个无参数的构造方法
2.实例化对象
当我们重写这个构造方法后再实例化对象
如果我们不传值,编译器会报错。
当我们也将无参构造写出来后,便可以不在实例化时就传值
内存图解
3.特殊性
1.构造方法作用:(1).构造出来一个类的实例 (2).对构造出来个一个类的实例(对象)初始化。
2.构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有。
3.主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用new操作进行的。
4.类中必定有构造方法,若不写,系统自动添加无参构造方法。接口不允许被实例化,所以接口中没有构造方法。
5.不能被static、final、synchronized、abstract和native修饰。
6.构造方法在初始化对象时自动执行,一般不能显式地直接调用.当同一个类存在多个构造方法时,java编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动一一对应。完成构造函数的调用。
7.构造方法分为两种:无参构造方法 有参构造方法
构造方法可以被重载。没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。
8.自定义类中,如果不写构造方法,java系统会默认添加一个无参的构造方法。如果写了一个有参的构造方法,就一定要写无参构造方法。