1 封装
1.1 面相对象的三大特征
封装
继承
多态
有了封装,才能继承,有了继承,才能说多态
1.2 面相对象的首要特征:封装
什么是封装?有什么用?
现实生活中有很多现实的例子都是封装的,例如:
手机,电视机,笔记本电脑,照相机,这些都是外部有一个坚硬的壳儿。
封装起来,保护内部的部件。保证内部的部件是安全的。另外封装了以后,
对于我们使用者来说,我们是看不见内部的复杂结构的,我们也不需要关心内部有多么复杂,我们只需要操作外部壳儿上的几个按钮就可以完成操作。
那么封装,你觉得有什么用呢?
封装的作用有两个:
第一个作用:保证内部结构的安全。
第二个作用:屏蔽复杂,暴露简单。
在代码级别上,封装有什么用呢?
一个类体当中的数据假设封装之后,对于代码的调用人员来说,不需要关心代码的复杂实现,只需要通过一个简单地入口就可以访问了。
另外,类体中的安全级别较高的数据封装起来,外部人员不能随意访问,来保证数据的安全性。
1.3 怎么进行封装,代码怎么实现?
第一步:属性私有化(使用private关键字进行修饰。)
第二步:对外提供简单地操作入口。
java中最难学习的是javase。
javase中最难学习的是面相对象。
封装的代码实现两步:
第一步:属性私有化
第二步:2个属性对外提供两个set和get方法。外部程序只能通过set方法修改,只能通过get方法获取。
可以在set方法中设立关卡来保证数据的安全性。
在强调一下:
set和get方法都是实例方法,不能带static
不带static的方法称为实例方法,实例方法的调用必须先new对象。
set和get方法写的时候有严格的规范要求:(大家要符合规矩)
set方法长这个样子:public 返回值类型 set+属性名首字母大写(无参){
return xxx;
}
get方法长这个样子:public 返回值类型 get+属性名首字母大写(1个参数){
xxx = 参数; //↑ 就是他(他就是参数)
}
案例1:
// 在外部程序中访问Person这个类型中的数据 public class PersonTest{ public static void main(String[] args){ //创建Person对象 Person p = new Person(); // 访问人的年龄 // 访问一个对象的属性,通常包括两种操作,一种是读数据,一种是改数据。 System.out.println(p.age);// (get表示获取) // 修改数据(set表示修改/设置) p.age = 50; // 再次读取 System.out.println(p.age); // 在PersonTest这个外部程序中目前是可以随意对age属性进行操作的。 // 一个人的年龄值不应该为负数。 // 程序中给年龄赋值了个一个负数,按说是不符合业务要求的,但是程序目前还是让他通过了 // 其实,这就是一个BUG p.age = -100;// 改(随意在这里对Person内部的数据进行访问,导致了不安全。) System.out.println("您的年龄值是:" + p.age);// 读 } }
案例2:
public class PersonTest02{ public static void main(String[] args){ // 创建对象 Person p = new Person(); // Person的age,彻底在外部不能访问了。但是这难免优点太安全了。 // age不能访问,这个程序就意义不大了。 /* // 读age属性的值 System.out.println(p.age); // 修改age属性的值 p.age = 20; // 读age System.out.println(p.age); */ // 通过“类名.”可以调用set和get方法吗?不行。 // 只有方法修饰符列表中有static的时候,才能使用“类名.”的方式访问。 // 错误的。 // Person.getAge(); // 读调用getAge()方法 int nianLing = p.getAge(); System.out.println(nianLing); //0 //以上代码联合 System.out.println(p.getAge()); //0 // 改调用setAge()方法 p.setAge(20); System.out.println(p.getAge()); // 你折腾半天了,这不是结果还是没控制住吗???? p.setAge(-100); // System.out.println(p.getAge());// -100 System.out.println(p.getAge());// 20 } } 创建实例: /* Person表示人类: 每一个人都有年龄这样的属性。 年龄 age,int类型 我这里先不使用封装机制,分许程序存在什么缺点? Person类的age属性对外暴露,可以再外部程序中随意访问,导致了不安全。 怎么解决这个问题? 封装。 */ // 这是没有封装的Person /*public class Person{ // 实例变量(属性) int age;// age属性是暴露的,在外部程序中可以随意访问。导致了不安全。 }*/ // 尝试封装以下 // 不在对外暴露复杂的数据,封装起来 // 对外只提供简单地操作入口 // 优点:第一数据安全了,第二调用者也方便了。 public class Person{ // private 表示私有的,被这个关键字修饰之后,该数据只能在被类中访问。 // 出了这个类,age属性无法访问了,私有的。 private int age;// 每一个人年龄值不同,对象级别的属性。 // 对外提供简单地入口(电视机的遥控器就相当于是电视机的访问入口,简单明了) // 外部程序只能通过调用以下的代码来完成访问。 // 思考:你应该对外提供几个访问入口。 // 思考:这些操作入口是否应该是方法呢? // 写一个方法专门来完成读(get) // 写一个方法专门来完成写 (set) // get和set方法应该带有static,还是不应该有static,get和set方法应该定义为实例方法。 // get读年龄,set改年龄,这个读和改都是操作的一个对象的年龄。(没有对象何来的年龄) // 封装的第二步:对外提供公开的set方法和get方法作为操作入口。并且都不带static。都是实例方法。 /* [修饰符列表] 返回值类型 方法名(形式参数列表){ } 注意: java开发规范中有要求,set方法和get方法要满足以下格式。 get方法的要求: public 返回值类型 get+属性名首字母大写(无参){ return xxx; } set方法的要求: public void set+属性名首字母大写(有1个参数){ xxx = 参数; } 大家尽量按照java规范中要求的格式提供set和get方法。 如果不按照这个规范格式来,那么你的程序将不是一个通用的程序。 */ // get方法 public int getAge(){ return age; } public void setAge(int nianLing){ // 能不能在这个位置上设置关卡!!!!! if(nianLing < 0 || nianLing > 150){ System.out.println("对不起,年龄值不合法,请重新赋值!"); return;//直接终止程序的执行。 } // 程序能够执行到这里,说明年龄一定是合法的。 age = nianLing; } }
案例3:
// 带有static的方法 // 没有static的方法 // 分别怎么调用? // 带有static的方法是怎么调用?通过“类名.”的方式访问 // 对象被成为实例。 // 实例相关的有:实例变量、实例方法。 // 实例变量是对象变量。实例方法是对象方法。 // 实例相关的都要先new对象,通过“引用.”的方式去访问。 // 方法带static需要用类名. 去访问 不带static 需要先new之后才能访问。 public class MethodTest{ public static void main(String[] args){ MethodTest.doSome(); // 类名. 可以省略(在同一个类中。) doSome(); // 尝试使用"类名."的方式访问"实例方法" // 错误: 无法从静态上下文中引用非静态 方法 doOther() // MethodTest.doOther(); // 创建对象 MethodTest mt = new MethodTest(); // 通过引用.的方式访问实例变量。 mt.doOther(); } // 带有static public static void doSome(){ System.out.println("do some!"); } // 这个方法没有static,这样的方法被称为:实例方法。(对象方法,对象级别的方法) // 这个没发解释,大家目前死记硬背。 public void doOther(){ System.out.println("do Other!"); } } 空指针异常案例: /* 空指针异常导致的最本质的原因是? 空引用访问"实例相关的数据",会出现空指针异常 实例相关的包括:实例变量 + 实例方法。 */ public class NullPrinterTest{ public static void main(String[] args){ User u = new User(); System.out.println(u.id); // 0 u.doSome(); // 引用变成空null u = null; //System.out.println(u.id); // 空指针异常 // 一个实例方法的调用也必须有对象的存在。 u.doSome(); } } // 类 = 属性 + 方法 // 属性描述状态 // 方法描述行为动作 class User{ // 实例变量 int id; // 实例方法(对象相关的方法,对象级别的方法,应该是一个对象级别的行为。) // 方法模拟的是对象的行为动作。 public void doSome(){ System.out.println("do some!"); } // 考试的行为,由于每一个人考试之后的分数不一样,所以考试行为应该必须有对象的参与。 public void exam(){ } }