面向对象(五)
一、finally关键字
1.定义finally
代码块,定义了无论异常发生与否,一定会执行的代码。通常用于关闭资源。流操作,数据库操作等,最后都应该用finally
关闭流和数据库连接,以确保资源释放。
2.异常处理的分层设计
分层设计是模块式开发的体现,每个开发者负责相应的模块。如果异常出现,各开发者负责处理各自模块的异常,并封装好能够被其他模块开发者解决的异常对象(层内封装),抛出给相应开发者。这样的开发模式,让异常处理合理化,每个异常都能被有效解决,提高开发效率。
3.异常处理语句格式
1)try catch
示例代码:
try {} catch {}
2)try catch finally
示例代码:
try {} catch {} finally {}
3)try finally
示例代码:
try {} finally{}
该格式用于,在程序其他地方处理异常,但在此try fianlly
语句中一定要关闭资源的情况,将关闭资源的代码,放在finally
中。
小扩展
finally在其之前异常处理阶段出现了System.exit(0);这行代码的情况下,不会被执行示例代码:
package com.heisejiuhuche;
public class Test {
public static void main(String[] args) {
T t = new T();
try {
t.method();
} catch(AException e) {
System.out.println("AException occured...");
//出现System.exit(0);虚拟机停止运行的时候,finally不会执行
System.exit(0);
} finally {
System.out.println("Will not execute...");
}
}
}
class AException extends Exception {
}
class T {
void method() throws AException {
throw new AException();
}
}
程序输出结果为:
AException occured...
二、异常在继承状态中的特点
1.子类在复写父类方法时,如果父类的方法抛出异常,那么子类复写的方法只能抛出父类异常或其异常的子类
示例代码:
class AException extends Exception {}
class BException extends AException {}
class CException extends Exception {}
异常结构图:
- Exception
- AException
- BException
- CException
- AException
class Parent extends AException {
void method() throws AException {}
}
class SubClass extends Parent{
/*
* 由于父类抛出的异常机场了AException,所以子类复写的方法,只能
* 抛出AException或者BException
*/
void method() throws AException {}
//void method() throws BException
}
子类继承父类,子类不能比父类出现的异常还多;其出现的异常,也只能是父类的异常,或父类异常的子类。
示例代码:
class Parent extends AException {
void method() throws AException {}
}
class SubClass extends Parent{
void method() throws AException {}
//void method() throws BException {}
}
class Test {
void function(Parent p) {
try {
p.method();
//catch只处理AException和AException的子类
} catch(AException e) {
System.out.println("AException...");
}
}
}
class TestMain {
public static void main(String[] args) {
Test t = new Test();
//将子类对象传给父类引用,function()方法接受父类作为参数
t.function(new SubClass());
}
}
上述代码,在main
方法中将SubClass
的对象传给function()
方法,而function()
方法接受一个父类对象作为参数,即父类引用指向子类对象;那么p.method()
调用的是子类SubClass
的method()
方法;由于父类抛出的是AException
,在Test
类中用try catch
进行捕捉,并且catch
语句只能处理AException
及AException
的子类;如果子类的method()
方法抛出的是CException
,CException
和AException
没有任何关系,catch
语句无法处理,程序无法编译;如果子类的method()
方法抛出的是AException
或BException
,AException
是父类方法抛出的异常,BException
是父类方法异常的子类,那么catch
语句中捕捉AException
就能处理子类方法抛出的异常;这是为什么子类复写父类的方法,只能抛出父类方法的异常,或父类方法异常的子类。
2.如果父类方法抛出多个异常,那么子类复写该方法时,只能抛出父类方法异常或其子集
父类抛出A
,B
,C
异常,子类只能抛出A
,B
,C
异常或A
,B
,C
异常的子集
3.如果父类或者接口的方法中没有抛出异常,子类复写的方法也不能抛出异常
通用规则,如果子类方法可能会发生父类方法中没有的异常,只能在子类方法内部进行catch
处理,不能抛出。
4.运行时异常练习
写一个程序,获取长方形面积;如果初始化的时候传入的长或宽的值小于等于0,抛出异常。
示例代码:
package com.heisejiuhuche;
public class CircleExceptionTest {
public static void main(String[] args) {
Rectangle rec = new Rectangle(0, 4);
System.out.println("Area = " + rec.getArea());
}
}
class Rectangle {
private int length;
private int width;
Rectangle(int length, int width) {
/* 如果长或宽小于等于0,抛出非法参数异常 */
if(length <=0 || width <= 0) {
throw new IllegalArgumentException("Illegal Argument...");
}
this.length = length;
this.width = width;
}
public int getArea() {
return length * width;
}
}
/* 由于出现非法参数异常时,程序无法继续运算,所以该异常应继承运行时异常 */
class IllegalArgumentException extends RuntimeException {
IllegalArgumentException(String message) {
super(message);
}
}
创建Rectangle
对象,传入0,4
,程序运行结果为:
Exception in thread "main" com.heisejiuhuche.IllegalArgumentException: Illegal Argument...
at com.heisejiuhuche.Rectangle.<init>(CircleExceptionTest.java:16)
at com.heisejiuhuche.CircleExceptionTest.main(CircleExceptionTest.java:5)
异常机制的出现,让问题处理代码和正常流程代码分离,代码阅读性更强。
三、异常机制总结
1.异常的定义
异常是对问题的描述,并将问题封装成对象。
2.异常的优点
1)将问题进行封装;
2)将正常流程代码和问题处理代码分析
3.异常处理原则
1)异常有两种处理方式:try catch
或者throws
;
2)调用抛出异常的方法时,抛出了几个异常,就要处理几个异常;
3)多个catch
语句,处理异常父类的catch
语句放在最下面;
4)catch
内,定义针对性的处理方式,不要简单打印,也不要什么都不定义;
5)捕获的异常,如果处理不了,可以继续在catch
中抛出;
6)在抛出异常时,尽量结合分层设计思想,将异常转化为其他模块可以处理的异常,封装后再抛出
4.异常注意事项
1)子类复写父类的方法时,子类复写的方法抛出的异常必须是父类方法抛出的异常或父类方法抛出异常的子类或者子集;
2)如果父类或者接口的方法没有抛出异常,子类复写的方法不能抛出异常;如有异常,只能内部解决
5.异常体系
- Throwable
- Error
- Exception
- RuntimeException
异常体系中的所有类,以及建立的对象,都具备可抛性,可以被throw
和throws
关键字操作。
6.throw和throws的区别
1)throw
定义在方法内,用于抛出异常对象
方法内抛出的异常对象(非运行时异常),必须在方法上声明,或用try catch
处理,否则编译失败;throw
单独存在时,下面不要定义语句,因为执行不到
2)throws
定义在方法上,用于抛出异常类
方法上声明了异常,调用这必须进行处理,可以抛出,也可以try catch
7.异常的分类
1)编译时异常(编译时被检测)
该异常在编译时,如果没有处理(没有抛出,也没有try catch
),编译失败
2)运行时异常(编译时不检测)
该异常在编译时不需要声明或者处理,编译都通过;该异常的发生,建议不处理,让程序停止,由方法调用者对代码进行修正
8.异常处理代码try {需要被检测代码} catch {处理异常的代码} finally {一定会执行的语句}
finally
中通常定义关闭资源代码,因为资源必须释放;finally
只有在遇到System.exit(0);
的时候,不会被执行
9.自定义异常
自定义异常类继承Exception
或者RuntimeException
,为了:
1)让该自定义异常类具备可抛性;
2)让该自定义异常类具备操作异常共性方法的能力
要定义自定义异常类的信息时,可以使用父类已经定义好的功能,将自定义异常信息传给父类的构造方法
示例代码:
class MyException extends Exception {
MyException(String message) {
super(message);
}
}
10.自定义异常的好处
自定义异常是按照Java的面向对象思想,将程序中出现的特有问题,进行封装,符合Java一切皆对象的理念。
四、包(package)
1.定义
Java中的包,其实就相当于文件系统中的文件夹。包也是一种封装形式。包(package)
的声明写在程序代码的第一行。
2.包的作用
1)对类文件进行分类管理;
2)给类文件提供多层命名空间
3)将类文件和源文件分离
3.包的应用
示例代码:
package com.heisejiuhuche;
class TestPackage {
public static void mian(String[] args) {
System.out.println("Hello Package...");
}
}
用命令行编译上述代码时,要加上参数:javac -d . TestPackage.java
-d
指的是这个类文件的目录结构,如上就是:com/heisejiuhuche(linux)
,com\heisejiuhuche(windows)
.
指的是将这个类文件的目录结构存放在硬盘的当前目录下
如果要将类文件目录结构存在当前目录之外的位置,如c:\myclass
,要将c:\myclass
设置进classpath
:set classpath=c:\myclass
4.包与包之间的访问
1)包与包之间进行访问时,被访问的包中的类和类中的成员需要被public
修饰;
2)包与包之间进行访问时,不同包中的子类可以直接访问父类中被protected
权限修饰的成员;
3)包与包之间可以使用的权限只有两种:public
,protected
小扩展
不同范围内,成员在不同权限下的访问情况总结
public | protected | default | private | |
同一类中 | Y | Y | Y | Y |
同一包中 | Y | Y | Y | N |
子类 | Y | Y | N | N |
不同包中 | Y | N | N | N |
5.包名定义规则
为了保证包名不重复,包名使用url
倒序来定义。如:package com.itheima.tools;
五、import关键字
1.import关键字的作用
为了简化类名的书写,使用import
关键字导入类(常用)
import com.heisejiuhuche.Test; //导入com/heisejiuhuche目录下的Test类
如果目录下有多个类,想要全部导入,使用通配符*
(不常用)
import com.heisejiuhuche.*; //导入com/heisejiuhuche目录下所有类
六、Jar包
1.定义
Jar包是Java的压缩包,它能方便项目的携带。
2.Jar包的使用
1)将类文件夹打包格式:jar [参数] [打包之后的包文件名] [需要打包的文件\文件夹名]
首先切换到该类文件夹所在目录,然后执行:jar -cvf myJar.jar package1 package2
2)查看Jar包中的内容格式:jar [参数] [打包之后的包文件名]
jar -tf myJar.jar
3)输出结果重定向
如果查看时输出内容较多,dos界面不好浏览,可以将输出结果重定向到txt文件jar -tf myJar.jar > c:\myJar.txt