第一讲 多态
1、 定义
可以理解为事物存在的多种体现形态。
在java中,当函数的功能内容不确定时,可以将此方法定义为抽象方法,让其子类去实现。当子类对象不同时,调用同一个函数名,会执行不同的函数体,得到不同的结果,从而体现了多态性。
2、 多态的体现形式
- 父类的引用指向了自己的子类对象:Fu f = new Zi();
- 父类的引用也可以接受自己的子类对象;
3、 多态的前提条件
- 必须是类与类之间有关系,要么继承,要么实现(接口);
- 函数之间存在覆盖(重写);
4、 多态的好处
大大的提高了程序的扩展性。——当子类对象增加时,尽可能的少该代码。
5、 多态缺陷
提高了扩展性,但只能使用父类的引用访问父类中的成员。父类的引用不能访问子类中的成员。
如下,父类的引用an1访问了子类特有方法kanjia();
6、 子父类类型转换
Fu f = new Zi();————类型自动提升,向上转型,将子类型转成父类型。
Zi z = (Cat) f ; ————强制将父类的引用转成子类类型,向下转型。
注意:不能将父类型对象转成子类型。
7、 多态的应用
建立两个类:基础班学生 和 高级班学生,都有学习、睡觉功能。要求将这两类事物进行抽取。
8、 多态的出现,代码中的特点——多态使用的注意事项
1) 多态中非静态成员函数的特点
编译时期:参阅引用类型变量所属的类中是否有调用的方法,若有,编译通过,否则编译失败。因为:编译时,对象还没被创建,父 类和子类还没有建立关系。
运行时期:参阅对象所属的类中是否有调用的方法,若有,则执行对象所属类中的功能,否则,执行父类中的功能。
总结:成员函数在多态调用时,编译看左边(引用类型),运行看右边(对象所属的类)。
2) 多态中成员变量的特点
无论编译还是运行,都参考左边(引用型变量所属的类。如果引用型变量所属的类中没有此成员变量,则编译失败。运行时,也会调用引用型变量所属类中的变量。
在多态中访问子类变量方法:当需要访问子类中的成员变量时,可以用强制类型转换,将父类型的引用强制转换成子类型:zi x = (zi)y,其中y代表指向子类型的父类型的应用变量
3) 多态中,静态成员函数的特点
无论编译还是运行,都参考左边(引用型变量所属的类)。
原因:非静态方法和静态在内存中存储的位置不同,非静态方法区中有两个引用(this和super),而静态方法区中只有类名引用.
第二讲 Object类
1、 概念
Object是所有对象的直接或间接父类。该类中定义的肯定是多有对象都具备的功能。
2、 Object类应用
Object类中已经提供了对对象是否相同的比较方法equals(),如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可——这就是覆盖。
第三讲 内部类
1、 定义
2、 访问规则
1) 内部类可以直接访问外部类中的成员,包括私有的,因为此时,内部类处于成员位置上,可以任务是外部类中的一个成员,内部类中持有了一个外部类的引用,格式:Outer.this.x——这里的this代表的是内部类对象。这就是内部类能够直接访问外部类成员的原因。
2) 外部类要访问内部类,就必须建立内部对象:
Inner inner = new Inner();
3) 其他外部类访问内部类的方式
当内部类定义为非私有,可以在外部其他类中直接建立内部类对象进行访问,格式如下:
Outer.Inner inner = new Outer().new Inner();
当内部类在成员位置上时,可以被成员修饰符锁修饰
如,private修饰:将内部类在外部类进行封装,只能外部类访问;
Static 修饰:内部类就具备了static的特性。此时,内部类只能访问外部类中的static成员,出现了访问局限。
外部其他类访问static修饰的内部类非静态成员方法如下:
————new Outer.Inner().function();——Inner类是Outer类的静态成员,可以直接用类名调用。
外部其他类直接访问static修饰的内部类的静态成员方法如下:
————Outer.Inner.function();——静态成员可以直接被类名调用。
注意:当内部类中定义了静态成员,该内部类必须是静态的;当外部类中的静态方法访问内部类时,内部类也必须是静态的。
——一个大原则:静态只能访问静态成员。
内部类在局部位置上时:
不能被static修饰;
可以访问外部类中的成员,因为还持有外部类中的引用。但是不能访问它所在的局部中的变量,只能访问被final修饰的局部变量。
如下:a 只有被final修饰后,才能被内部类访问。
如下,内部类被定义在了局部位置上。系统默认给内部类一个外部类的引用Outer.this
总结:不管内部类定义在成员位置还是局部位置上,外部类需要内部类对象才能访问内部类中成员,内部类得到了外部类对象(系统默认提供外部类引用Outer.this)才能访问外部类成员。
3、 匿名内部类
定义:匿名内部类其实就是内部类的简写格式。
定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
第四讲 异常
1、 定义
异常:程序运行时出现的不正常情况。
异常由来:问题也是现实生活中的一个具体的事物,也可以通过java类的形式进行描述,并封装成对象,即,对不正常情况进行描述后的对象体现。
异常划分:严重问题 和 非严重问题。
严重问题:java通过Error类进行描述,对于Error一般不编写针对性的代码进行处理。
非严重问题:java通过Exception进行描述,可以使用针对性的处理方式进行处理。
其中,Error和Exception同为Throwable的子类。
2、 异常处理
异常处理目的:把异常处理掉,让try外面的后续语句继续执行。若不处理,程序就会被停下来,不处理后续语句。
原因:如果虚拟机调用的程序没有的处理此项异常的功能,该异常会被抛给虚拟机,而虚拟机处理异常的默认机制是:直接把此程序停掉。
异常处理代码格式如下:
处理异常有两种方式:
第一种是:向上(向调用者)抛出异常;
第二种是:自己内部捕获异常并处理。
3、 多异常处理
1) 函数中只要有异常发生,函数就停下了;
2) 被调用函数声明了几个异常,调用者就对应有几个catch块,如果多个catch块中的异常出现继承关系,父类异常catch块必须放在最下面;
3) 若程序出现了被调用函数所声明以外的异常,最好将此异常抛给虚拟机,将程序停掉;
4) 建议进行catch处理时,catch中一定要定义具体的处理方式,而不是简单的打印异常。异常信息可以输出到硬盘中相应的文档中,方便后续异常查找及处理;
4、 自定义异常
可以自定义java机制中没有定义的异常。
注意:Java不会自动识别自定义异常,所以,需要手动建立自定义异常对象并抛出(java本身定义的异常可以被默认抛出)
1) 自定义异常信息
因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息通过super语句传递给父类,然后就可以直接通过 getMessage方法获取自定义的异常信息了
2) 自定义异常特点
必须继承Exception。因为:异常体系有一个特点:异常类和异常对象都被抛出,它们都具备可抛性,这是Throwable体系中独有的特点。只有这个体系中的类和对象才可以被throws和throw操作。
5、 Throws和throw的区别
1) Throws使用在函数上;Throw使用在函数内;
2) Throws后面跟着异常类,可以多个,用逗号隔开;Throw后面跟着异常对象;
注意:Throw下面不应跟其他语句,因为异常抛出后,下面语句不会再执行。Throw和return作为函数的结束标识。但是系统退出(System.exit(0))时不会执行。
6、 RuntimeException
定义:函数内抛出异常,则函数上必须声明抛出异常,否则编译不通过,但RuntimeException不需要函数声明抛出。如果函数上声明了该异常,调用者可以不用进行异常处理,编译也能通过。
RuntimeException不需要在函数上声明的原因是:此异常不需要调用者处理。此类异常发生时,希望程序停止,因为在程序运行时出现了无法继续运算的情况,希望停止程序后,对代码进行修正。
7、 异常覆盖时的特点
异常在子父类覆盖中的体现:
1)子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖类方法只能抛出父类的异常或者该异常的子类,或者不抛出异常;
2)如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集;
3)如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,绝对不能抛出。
知识点总结
1、 继承类和实现接口
父类中定义了某类事物的通用属性,而接口中往往定义的是某类事物的扩展功能。
2、 Throw 和 throws的用法
1) Throw定义在函数内,用于抛出异常对象;
2) Throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开;
3、 异常分两种:编译时异常 和 运行时异常
1) 编译时被检测的异常:函数内被抛出,则函数上必须要声明,且在调用者中必须处理或向外抛出;
2) 编译时不被检测的异常(即,运行时异常,RuntimeException)
函数上不需要声明,不需要调用者进行处理。
4、 异常处理中finally块中语句特点
1) finally中定义的通常是:关闭资源代码。因为资源必须被释放。
2) finally只有一种情况不会执行:当执行到System.exit(0);时,finally中的语句不会执行。