Java的异常、多态要点及抽象类和接口
一、java异常
如下图,异常分为两类,错误和异常;异常分为运行异常和可查异常。这里主要掌握异常,因为平时会见的比较多。Exception类在java.lang包下,它是Throwable的子类,同样的Error类也是其子类。Error 用来指示运行时环境发生的错误,例如:JVM 内存溢出。一般地,程序不会从错误中恢复。异常类有两个主要的子类:IOException 类和 RuntimeException 类。
Java 根据各个类库也定义了一些其他的异常,有常用检查性和非检查性异常。
异常 | 描述 |
---|---|
ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 |
ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 |
ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 |
ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 |
IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 |
IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 |
IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 |
IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 |
IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 |
NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 |
NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 |
NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 |
SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 |
UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 |
下面的表中列出了在 java.lang 包中的检查性异常类。
异常 | 描述 |
---|---|
ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 |
CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 |
IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 |
InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 |
InterruptedException | 一个线程被另一个线程中断,抛出该异常。 |
NoSuchFieldException | 请求的变量不存在 |
NoSuchMethodException | 请求的方法不存在 |
异常方法
提一个最常见的,public void printStackTrace(),打印toString()结果和栈层次到System.err,即错误输出流,有点类似错误追踪。
异常捕获
try/catch 代码块放在异常可能发生的地方,try/catch代码块中的代码称为保护代码,使用 try/catch 的语法如下:
try{
// 程序代码
}catch(ExceptionName e1){
//Catch 块
}
可以有多个catch语句,叫多重捕获。catch 语句包含要捕获异常类型的声明,当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块。
抛出异常
如果一个方法没有捕获到一个检查性异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部,也可以使用 throw 关键字抛出一个异常。需要注意的是,如果有必要抛出多个异常,则可以在后面继续添加用逗号隔开。
finally关键字
finally关键字用来创建在 try 代码块后面执行的代码块。无论是否发生异常,finally 代码块中的代码总会被执行。在finally代码块中,可以运行清理类型等收尾善后性质的语句。finally 代码块出现在 catch 代码块最后,语法如下:
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}finally{
// 程序代码
}
二、被搞糊涂的多态
存在必要条件:
- 继承
- 重写
- 父类引用指向子类对象
比如:
Parent p = new Child();
注意(容易忘,容易搞糊涂):当使用多态方式调用方法时,首先检查父类中是否有该方法,如果有,则去调用子类的同名方法,但不能调用子类独有的方法。多态的好处是可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。
多态的实现方式:
方式一:重写:
方式二:接口
方式三:抽象类和抽象方法
三、Abstract抽象类和接口
抽象类:
抽象类和其他普通类没什么区别,除了不能实例化外,其他功能都还好。由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。在Java中,抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
声明抽象方法会造成以下结果:
- 如果一个类包含抽象方法,那么该类必须是抽象类。
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
需要注意:抽象类不一定有抽象方法,而有抽象方法一定是抽象类; 构造方法,类方法(用static修饰的方法)不能声明为抽象方法;抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
接口:interface
接口并不是类,类描述对象的属性和方法,接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。接口没有构造方法,同样无法被实例化。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
接口与接口之间则是通过继承来关联,支持多继承!
import java.lang.*;
public interface NameOfInterface extends a,b,c{//a,b,c接口
public void w();
public void v();
public void e(int period);
public void o(int ot);
//任何类型 final, static 字段
//抽象方法(隐式)
}
接口特性:
- 接口中每一个方法是隐式抽象的,指定为public abstract(只能是public abstract,其他修饰符都会报错)
- 接口中可以含有变量,但是会被隐式的指定为public static final 变量(并且只能是public)
接口中每一个方法也是隐式抽象的,声明时不需要abstract关键字,接口中的方法都是公有的public。
抽象类和接口的区别:
- 抽象类中的方法可以有方法体,但是接口中的方法不行(jdk1.8)。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 接口中不能含有静态代码块以及静态方法(用static修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
注:JDK 1.8 以后,接口里可以有静态方法和方法体了
接口的实现:implements
与抽象类不同,当类实现接口的时候,类要实现接口中所有的方法,否则,类必须声明为抽象的类。
public class Mydog implements Animal,dog{
public void eat(){
System.out.println("Mydog eats");
}
}
重写接口中声明的方法时,需要注意以下:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意:
- 一个类可以同时实现多个接口
- 一个类只能继承一个类,但是能实现多个接口