Java精选笔记_面向对象(多态、异常)

多态

概述

可以理解为事物存在的多种体现形态。同样的引用调用同样的方法却做了不同的事情

多态的本质是:一个程序中同名的不同方法

多态的体现

父类的引用指向子类的对象,父类的引用接收子类的对象

多态可以表现在很多方面,例如可以通过子类对父类方法的覆盖实现多态,也可以通过一个类中方法的重载实现多态,还可以将子类的对象作为父类的对象实现多态。

多态的前提

类与类之间必须是继承或者实现的关系。通常还有一个前提 就是覆盖

多态的利与弊

大大的提高了程序的扩展性,但是只能使用父类的引用访问父类中的成员

多态中成员的特点

非静态成员函数:在编译时期,参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。在运行时期,参阅对象所属的类中是否有调用的方法。

总结,成员函数在多态调用的时候,编译看左边父类,运行看右边子类

成员变量:无论编译和运行,都参考左边父类。

静态成员函数:无论编译和运行都参考左边父类。

如何使用子类特有方法:多态转型

Animal  a=new Cat();
//类型提升,向上转型

a.eat(); //父类的共有方法

多态事例与扩展事例

学生例

/*
* 基础班学生:
* 学习 、睡觉
* 高级班学生:
* 学习、睡觉
*/
abstract class Student {
public abstract void study();
public static void sleeps() {
System.out.print("睡觉");
}
}
class jichu extends Student {
public void study() {
System.out.print("学习基础");
}
public static void sleeps() {
System.out.print("站着");
}
}
class gaoji extends Student {
public void study() {
System.out.print("学习高级");
}
public static void sleeps() {
System.out.print("趴着");
}
}
class DoStudent {
public void dosome(Student stu) {
stu.study();
stu.sleeps();
}
}
public class duotai {
public static void main(String[] args) {
DoStudent ds=new DoStudent();
ds.dosome(new jichu());//传的是子类对象
ds.dosome(new gaoji());
}
}

电脑运行实例

/*
* 需求;主板事例
* 电脑运行实例,电脑运行基于主板
*/
interface PCI {
public void open();
public void close();
}
class MainBoard {
public void run() {
System.out.println("主板运行");
}
public void usePCI(PCI p) {
if(p!=null) {
p.open();
p.close();
}
}
}
class netcard implements PCI {
public void open() {
System.out.println("网卡运行");
}
public void close() {
System.out.print("网卡关闭");
}
}
public class duotai {
public static void main(String[] args) {
MainBoard mb=new MainBoard();
mb.run();
mb.usePCI(new netcard());
}
}

实现

方法重写:不同的子类对父类的同一方法给出不同的实现版本
对象造型:用父类型的引用引用子类型的对象

方法的重载

方法的重载就是在同一个类中允许同时存在一个以上的同名方法,只要它们的参数个数或类型不同即可,在这种情况下,该方法就叫被重载了,这个过程称为方法的重载。与方法的覆盖不同,重载不是子类对父类同名方法的重新定义,而是类对自身已有的同名方法的重新定义。

Object类

在Object类中定义了toString()方法,在该方法中输出了对象的基本信息

匿名内部类

new 外部类名或者接口名() {
       覆盖类或者接口中的代码(也可以自定义内容)
};

是内部类的简化格式
首先它是内部类,它最大的特点就是没有名字,而且我们不能显示的通过代码为它添加构造方法。
前提:内部类必须继承或者实现一个外部类或者接口
就是建立一个带有内容的外部类或者接口的子类匿名对象
匿名内部类中定义的方法最好不要超过3个

异常

什么是异常

异常属于程序在运行时出现的状况,编译器无法检查
异常是低耦合的处理运行时状况的方式,不打乱原有的业务逻辑

异常也称为例外,是在程序运行中发生的、会打断程序正常执行的非正常事件

Error类称为错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠修改程序本身是不能恢复执行的。

Exception类称为异常类,它表示程序本身可以处理的错误,在开发Java程序中进行的异常处理,都是针对Excption类及其子类。在Exception类的众多子类中有一个特殊的RuntimeException类,该类及其子类用于表示运行时异常,除了此类,Exception类下所有其它的子类都用于表示编译时异常。

异常的分类

Throwable
        Error
                IOError
                AssertionError
               VirtualMachineError
               
OutOfMemoryError
               
*Error
               AWTError
       
Exception
               
受检异常(编译器会检查该类异常并且强制性的要求处理)
               
ClassNotFoundException
               
IOException
               
CloneNotSupportedException
               
InterruptedException
               
IllegalAccessException
               
NoSuchFieldException
               
NoSuchMethodException
               
SQLException
       
RuntimeException
               
NullPointerException空指针异常
               
IndexOutOfBoundsException
               
ArrayIndexOutOfBoundsException数组下标越界
               
ArithmeticException算数异常
               
ClassCastException
               
NegativeArraySizeException
               
SecurityException
               
IllegalArgumentException
               
NumberFormatException字符串转换为数字异常
               
ConcurrentModificationException

运行时异常

运行时异常大多数是由于程序设计不当而引发的错误,但是这种错误要在运行时才会发生和被发现,如零作除数、数组下标越界、访问空对象等。这类错误可以通过改进程序加以克服,不需对其进行捕获。如果发生了这类异常,系统可以自行处理。

检查型异常

也是在运行时发生的,但是编译器会在编译时进行检查,一旦发现某些语句使得此类异常有产生的“可能”,就会强制要求用户进行处理,否则不能通过编译

try...catch和finally

try调用声明受检异常的方法必须使用try块进行保护,否则调用者也要进行异常声明

自行编写程序代码来捕捉异常的最大好处是:可以灵活操控程序的流程,且可以做出最适当的处理。

catch
一个try后面可以跟0个或多个catch
并列的catch最多只有一个有机会执行
异常的捕获遵循里氏替换原则
并列的catch应当先捕获子类型异常再捕获父类异常

没有父子关系的异常类型对catch的顺序没有要求

finally定义总是执行代码块,最适合释放外部资源
需要注意的是,finally中的代码块有一种情况下是不会执行的,那就是在try...catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了。

throw

在程序出现状况的地方可以创建异常对象并用throw抛出
    catch捕获到异常之后也可以用throw将异常对象再次抛出
        再次抛出时可以将受检异常包装成运行时异常
注意:抛出异常时,throw关键字所抛出的是异常类的实例对象,因此我们要先用new关键字来产生一个对象

throws关键字

子类重写的方法不能比父类被重写方法声明更多的异常
    可以用throws为方法声明一个或多个异常,多个异常用逗号隔开
    方法声明异常时需要遵循重写三原则

运行时异常和编译时异常

经常会在程序编译时期产生一些异常,而这些异常必须要进行处理,这种异常被称为编译时期异常,也称为checked异常。
编译时异常的特点是Java编译器会对其进行检查,如果出现异常就必须对异常进行处理,否则程序无法通过编译
处理编译时期的异常有两种方式,具体如下:
    使用try…catch语句对异常进行捕获
    使用throws关键字声明抛出异常,调用者对其处理。

另外还有一种异常是在程序运行时期产生的,这种异常即使不编写异常处理代码,依然可以通过编译,因此我们称之为运行时异常,也称为unchecked异常。
运行时异常的特点是Java编译器不会对其进行检查
运行时异常一般是由于程序中的逻辑错误引起的,在程序运行时无法恢复。比如通过数组的角标访问数组的元素时,如果超过了数组的最大角标,就会发生运行时异常

自定义异常

在实际开发中,如果没有特殊的要求,自定义的异常类只需继承Exception类,在构造方法中使用super()语句调用Exception的构造方法即可
class 异常名称 extend Exception { 类主体}

异常设计原则

不要将异常处理用于正常的控制流
    对可以恢复的情况使用受检异常,对编程错误使用运行时异常
    避免不必要的对受检异常的使用
    优先使用标准异常
    每个声明(抛出)异常的方法都要有文档
    不要在catch中忽略掉捕获到的异常
    保持异常的原子性
    异常发生后对象能够恢复到异常发生之前的状态
    避免过于庞大的try块
    不要写一个catch(Exception e) {}捕获所有的异常,异常的捕获要有针对性

上一篇:dtrace4linux


下一篇:第一次尝试使用JAVA编写的ATM机程序