我是靠谱客的博主 疯狂河马,这篇文章主要介绍面向对象——异常异常包(package),现在分享给大家,希望可以做个参考。

异常

异常:就是程序在运行时出现的不正常情况。
异常的由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。异常其实就是java对不正常情况进行描述后的对象体现。

异常的体系

对于问题的划分有两种:一种是严重的问题,一种是非严重的问题。

  • 对于严重的,java通过Error类进行描述(通常出现重大问题如:运行的类不存在或者内存溢出等)。对于Error一般不编写针对性的代码对其进行处理。
    Error是由系统底层发生的,它将告诉JVM,JVM告诉使用者。Error一旦出现不做针对性的处理,直接修改代码。
  • 对于非严重的,java通过Exception类进行描述。Exception是由JVM发生的,并告诉调用者,对于Exception可以使用针对性的处理方式进行处理。

但无论Error或者Exception都具有一些共性内容,比如:不正常情况的信息,引发原因等。

异常的处理

java提供了两种对异常的处理方式:

  • 遇到问题不进行具体的处理,而是继续抛给调用者。其实就是在函数上通过throws关键字声明异常,告诉调用者处理。
    对这种处理方式的详细解释:在编写功能时,编写者会知道该功能有可能发生问题,而这个问题很容易来自于调用者传递的参数,而导致功能无法运行。这时发生的问题就应该让调用者知道,并最后让调用者有预先的处理方式,所以在定义功能时,需要在功能上对有可能发生的问题进行声明。声明问题需要使用关键字(throws):throws 异常类,声明的目的:就是让调用者可以进行处理。
  • 针对性的处理方式:捕获!

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    try { // 有可能发生异常的代码 } catch(异常类 变量) { // 这是真正的捕获,处理异常的代码; } finally { // 一定会被执行的代码; }

对捕获到的异常对象进行常见方法操作

  • getMessage();获取异常信息,返回字符串
  • toString();获取异常类名和异常信息,返回字符串
  • printStackTrace();获取异常类名和异常信息,以及异常出现在程序中的位置,返回值为void。JVM默认处理收到的异常就是调用这个方法,将信息显示在屏幕上
  • printStackTrace(PrintStream s);通常用该方法将异常内容保存在日志文件中,以便查阅
    例,

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Demo { int div(int a, int b) throws Exception { // 在功能上通过throws的关键字声明了该功能有可能会出现问题 return a/b; // new ArithmeticException(); } } class ExceptionDemo { public static void main(String[] args) { Demo d = new Demo(); try { int x = d.div(4, 1); // new ArithmeticException(); System.out.println("x="+x); } catch(Exception e) { // Exception e = new ArithmeticException(); System.out.println("除零啦!"); System.out.println(e.getMessage()); // / by zero System.out.println(e.toString());// 异常名称:异常信息 e.printStackTrace(); // 异常名称,异常信息,异常出现的位置 // 其实JVM默认的异常处理机制,就是在调用printStackTrace(),打印异常在堆栈中的跟踪信息 } System.out.println("over"); } }

    在函数上声明异常(throws)。便于提高安全性,让调用者进行处理,不处理编译失败。

对多异常的处理

  1. 声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
  2. 对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最后。
    建议在进行catch处理时,catch中一定要定义具体处理方式。不要简单定义一句:e.printStackTrace();,也不要简单的就书写一条输出语句。
    例,

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Demo { int div(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException { // 在功能上通过throws的关键字声明了该功能有可能会出现问题 int[] arr = new int[a]; System.out.println(arr[4]); return a/b; // new ArithmeticException(); } } class ExceptionDemo { public static void main(String[] args) { Demo d = new Demo(); try { int x = d.div(5, 0); // new ArithmeticException(); System.out.println("x="+x); } catch(ArithmeticException e) { System.out.println(e.toString()); System.out.println("除零啦!"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("角标越界啦!"); } catch(Exception e) { System.out.println("haha:"+e.toString()); } System.out.println("over"); } }

自定义异常

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题,进行自定义的异常封装。
当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。要么在内部try catch处理,要么在函数上声明让调用者处理。一般情况下,函数内出现异常,函数上需要声明。
自定义异常如何定义异常信息呢?
答:因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类,通过super语句,那么就可以直接通过getMessage()获取自定义的异常信息。
自定义异常必须是自定义类继承Exception。继承Exception的原因:异常体系有一个特点,因为异常类和异常对象都被抛出,它们都具备可抛性,这个可抛性是Throwable这个体系中独有的特点,只有这个体系中的类和对象才可以被throwsthrow操作。
throwsthrow的区别:

  • 位置不同。
    • throws使用在函数上,throws后面跟的是异常类,可以跟多个,用逗号隔开。
    • throw使用在函数内,throw后跟的是异常对象。
  • 功能不同。
    • throws用来声明异常,让调用者知道该功能有可能出现的问题,并由调用者可以给出预先的处理方式。
    • throw抛出具体的问题对象,执行到throw,功能就已经结束了,跳转到调用者,并将具体的问题对象也抛给调用者。

例,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* 需求:在本程序中,对于除数是-1,也视为是错误的,是无法进行运算的,那么就需要对这个问题进行自定义的描述 */ class FuShuException extends Exception { private int value; FuShuException() { super(); } FuShuException(String msg, int value) { super(msg); this.value = value; } public int getValue() { return value; } } class Demo { int div(int a, int b) throws FuShuException { if(b < 0) throw new FuShuException("出现除数是负数的情况----- / by fushu", b); // 手动通过throw关键字抛出一个自定义异常对象 return a/b; } } class ExceptionDemo2 { public static void main(String[] args) { Demo d = new Demo(); try { int x = d.div(4, -9); System.out.println("x="+x); } catch(FuShuException e) { System.out.println(e.toString()); // System.out.println("除数出现负数了"); System.out.println("错误的负数是:"+e.getValue()); } System.out.println("over"); } }

RuntimeException

Exception中有一个特殊的子类异常RuntimeException(运行时异常)。

  • 如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。之所以不用在函数上声明,是因为不需要让调用者处理,当该异常发生,希望程序停止。因为在运行时,出现了无法继续运算的情况,希望停止程序后,希望程序员对代码进行修正。
  • 如果在函数上声明了该异常,调用者可以不用进行处理,编译一样通过。

自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义异常继承RuntimeException。所以,对于异常可分为两种:

  • 编译时被检测的异常
  • 编译时不被检测的异常(运行时异常,RuntimeException以及其子类)

例,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class FuShuException extends RuntimeException { FuShuException(String msg) { super(msg); } } class Demo { int div(int a, int b) { if(b < 0) throw new FuShuException("出现了除数为负数啦!"); if(b == 0) throw new ArithmeticException("被零除啦!"); return a/b; } } class ExceptionDemo3 { public static void main(String[] args) { Demo d = new Demo(); int x = d.div(4, -9); System.out.println("x="+x); System.out.println("over"); } }

异常的小结:异常其实就是将问题封装成对象,并抛给调用者。如果声明了,就需要调用者处理(继续声明or捕获)。异常什么时候声明,什么时候捕获呢?功能内部可以解决,就捕获,不能解决或者解决了还必须告诉调用者问题,这时就应该声明。
现在来看一个异常的一个小练习:毕老师用电脑上课。
分析:开始思考上课中出现的问题。比如问题是:电脑蓝屏、电脑冒烟。要对问题进行描述,封装成对象。可是当冒烟发生后,出现讲课进度无法继续,出现了讲师的问题,课时计划无法完成。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 蓝屏是可以处理的,继承Exception class LanPingException extends Exception { LanPingException() { super(); } LanPingException(String message) { super(message); } } // 冒烟 class MaoYanException extends Exception { MaoYanException() { super(); } MaoYanException(String message) { super(message); } } // 课时无法进行 class NoPlanException extends Exception { NoPlanException() { super(); } NoPlanException(String message) { super(message); } } class Computer { private int state = 2; // 0:正常状态 public void run() throws LanPingException, MaoYanException { if (state == 1) throw new LanPingException("电脑蓝屏啦!"); if (state == 2) throw new MaoYanException("电脑冒烟啦!"); System.out.println("电脑运行"); } public void reset() { System.out.println("电脑重启"); state = 0; } } class Teacher { private String name; private Computer comp; Teacher(String name) { this.name = name; comp = new Computer(); } // 讲课 public void prelect() throws NoPlanException { try { comp.run(); System.out.println("讲课"); } catch (LanPingException e) { System.out.println(e.toString()); comp.reset(); // 继续讲课 prelect(); } catch (MaoYanException e) // MaoYanException e = new MaoYanException("..."); { System.out.println(e.toString()); test(); throw new NoPlanException("课时进度停止"); // 继续抛,但进行异常转换。 } } public void test() { System.out.println("练习"); } } class ExceptionTest { public static void main(String[] args) { Teacher t = new Teacher("毕老师"); try { t.prelect(); } catch (NoPlanException e) { System.out.println("换老师"); } } }

finally代码块

定义一定执行的代码。通常用于关闭资源,即无论是否有异常发生,都要对资源进行释放。释放资源的动作就定义在finally代码块中。
例1,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ExceptionDemo { public static void main(String[] args) { try { int num = 4 / 0; System.out.println("num = " + num); } catch (Exception e) { System.out.println(e.toString()); return; // System.exit(0); // 退出JVM,只有这种情况,finally才不执行。 } finally { System.out.println("finally"); } System.out.println("over"); } }

例2,

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class NoValueException extends Exception { } public void operate() throws NoValueException { // 连接数据库 try { // 数据操作 throw new SQLException(); } catch (SQLException e) { // 解决了数据库异常 throw new NoValueException(); } finally { // 关闭数据库 } }

记住一点:catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明。

异常在子父类覆盖中的体现

  • 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类或者不抛。
  • 如果父类方法抛出多个异常,那么子类在覆盖这个方法时,只能抛出父类异常的子集(不抛也行)
  • 如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行try处理,绝对不能抛。

练习:有一个圆形和长方形,它们都可以获取面积,对于面积如果出现非法的数值,视为是获取面积出现问题。问题通过异常来表示。
解:先要对这个程序进行基本设计。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class NoValueException extends RuntimeException { NoValueException(String message) { super(message); } } interface Shape { void getArea(); } class Rec implements Shape { private int len, wid; Rec(int len, int wid) { if(len <= 0 || wid <= 0) throw new NoValueException("出现非法值"); this.len = len; this.wid = wid; } public void getArea() { System.out.println(len*wid); } } class Circle implements Shape { private int radius; public static final double PI = 3.14; Circle(int radius) { if(radius <= 0) throw new NoValueException("非法值"); this.radius = radius; } public void getArea() { System.out.println(radius*radius*PI); } } class ExceptionTest { public static void main(String[] args) { Rec r = new Rec(3, 4); r.getArea(); Circle c = new Circle(-8); System.out.println("over"); } }

总结

异常:对问题的描述,将问题进行对象的封装。


异常体系:

复制代码
1
2
3
4
5
Throwable |---Error |---Exception |---RuntimeException

异常体系的特点:异常体系中的所有类以及建立的对象都具有可抛性,也就是说可以被throwthrows关键字所操作。只有异常体系具备这个特点。


throwthrows的用法:

  • throw定义在函数内,用于抛出异常对象。
  • throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开。

当函数内容有throw抛出异常对象,并未进行try处理,必须要在函数上声明,否则编译失败。
注意:RuntimeException除外,也就是说,函数内如果抛出的是RuntimeException异常,函数上可以不用声明。


如果函数声明了异常,调用者需要进行处理,处理方式可以throws也可以try
异常有两种:

  • 编译时被检测异常
    • 该异常在编译时,如果没有处理(没有抛也没有try),编译失败
    • 该异常被标识,代表着可以被处理
  • 运行时异常(编译时不检测)
    • 在编译时,不需要处理,编译器不检查
    • 该异常的发生,建议不处理,让程序停止,需要对代码进行修正

异常处理语句:

复制代码
1
2
3
4
5
6
7
try { 需要被检测的代码; } catch() { 处理异常的代码; } finally { 一定会指执行的代码; }

有三种结合格式:

  1. 复制代码
    1
    2
    3
    4
    5
    try { 需要被检测的代码; } catch() { 处理异常的代码; }
  2. 复制代码
    1
    2
    3
    4
    5
    try { 需要被检测的代码; } finally { 一定会指执行的代码; }
  3. 复制代码
    1
    2
    3
    4
    5
    6
    7
    try { 需要被检测的代码; } catch() { 处理异常的代码; } finally { 一定会指执行的代码; }

注意:

  • finally中定义的通常是关闭资源代码,因为资源必须释放。
  • finally只有一种情况不会执行,当执行到System.exit(0);finally不会被执行。

自定义异常:定义类继承Exception或者RuntimeException

  1. 为了让自定义类具备可抛性
  2. 让该类具备操作异常的共性方法

当要定义自定义异常的信息时,可以使用父类已经定义好的功能。将异常信息传递给父类的构造函数。

复制代码
1
2
3
4
5
class MyException extends Exception { MyException(String message) { super(message); } }

自定义异常:按照java的面向对象思想,将程序出现的特有问题进行封装。


异常的好处:

  1. 将问题进行封装
  2. 将正常流程代码和问题处理代码相分离,方便于阅读

异常的处理原则:

  1. 处理方式有两种:try或者throws
  2. 调用到抛出异常的功能时,抛出几个,就处理几个。一个try对应多个catch
  3. 多个catch,父类的catch放到最下面
  4. catch内,需要定义针对性的处理方式,不要简单的定义printStackTrace或者输出语句。也不要不写

当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。

复制代码
1
2
3
4
5
try{ throw new AException(); } catch(AException e) { throw e; }

如果该异常处理不了,但并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。

复制代码
1
2
3
4
5
try{ throw new AException(); } catch(AException e) { throw new BException(); }

或者异常可以处理,但需要将异常产生后,和本功能相关的问题提供出去,让调用者知道并处理,即将捕获异常处理后,转换新的异常抛出。(比如,汇款的例子)

复制代码
1
2
3
4
5
6
try{ throw new AException(); } catch(AException e) { 对AException处理 throw new BException(); }

异常的注意事项:在子父类覆盖时

  1. 子类抛出的异常必须是父类的异常的子类或者子集
  2. 如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛

包(package)

  • 对类文件进行分类管理
  • 给类提供多层命名空间
  • 写在程序文件的第一行
  • 类名的全称是包名.类名
  • 包也是一种封装形式

总结:

  • 包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。
  • 不同包中的子类还可以直接访问父类中被protected权限修饰的成员。
  • 包与包之间可以使用的权限只有两种:public/protected(只给子类使用)

四种访问权限

publicprotecteddefaultprivate
同一类中
同一包中
子类
不同包中

import

为了简化类名的书写,使用一个关键字——importimport导入的是包中的类,不导入包中的包
建议:

  • 不要写通配符*,需要用到包中的哪个类,就导入哪个类
  • 定义包名不要重复,可以使用url来完成定义,url是唯一的

例,

复制代码
1
2
3
4
5
6
7
8
9
package pack; import packb.haha.hehe.heihei.*; import packa.*; class PackageDemo { public static void main(String[] args) { DemoC c = new DemoC(); } }
  • 编译:javac -d . PackageDemo.java.指定的是当前目录,如果编译成功,会在当前目录下生成一个pack的文件夹,里面是编译的class文件。当然了也可以指定其他你想指定的任何目录,如:c:myclass
  • 运行:java pack.PackageDemo

Jar包

Java的压缩包:

  • 方便项目的携带
  • 方便于使用,只要在classpath设置jar路径即可
  • 数据库驱动, SSH框架等都是以jar包体现的

Jar包的操作
通过jar.exe工具对jar的操作。

  • 创建jar包
    • jar -cvf mypack.jar packa packb
  • 查看jar包
    • jar -tvf mypack.jar [>定向文件]
  • 解压缩
    • jar -xvf mypack.jar
  • 自定义jar包的清单文件
    • jar –cvfm mypack.jar mf.txt packa packb

jar包中的内容很多,在dos命令行环境中一屏显示不过来,可用如下命令:

复制代码
1
2
C:myclass>jar -tf liayun.jar >c:1.txt

即将yelei.jar包中的内容存放到c盘下1.txt文本文件中。
数据重定向——数据不想在一个地方(例如dos命令行)显示,而想在文件中显示。可用如下命令:

复制代码
1
2
C:>dir >c:2.txt

即将c盘目录下的文件信息存放在c盘下2.txt文本文件中。

最后

以上就是疯狂河马最近收集整理的关于面向对象——异常异常包(package)的全部内容,更多相关面向对象——异常异常包(package)内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(95)

评论列表共有 0 条评论

立即
投稿
返回
顶部