概述
异常
异常:就是程序在运行时出现的不正常情况。
异常的由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述,并封装成对象。异常其实就是java对不正常情况进行描述后的对象体现。
异常的体系
对于问题的划分有两种:一种是严重的问题,一种是非严重的问题。
- 对于严重的,java通过
Error
类进行描述(通常出现重大问题如:运行的类不存在或者内存溢出等)。对于Error
一般不编写针对性的代码对其进行处理。
Error
是由系统底层发生的,它将告诉JVM,JVM告诉使用者。Error一旦出现不做针对性的处理,直接修改代码。 - 对于非严重的,java通过
Exception
类进行描述。Exception
是由JVM发生的,并告诉调用者,对于Exception
可以使用针对性的处理方式进行处理。
但无论Error
或者Exception
都具有一些共性内容,比如:不正常情况的信息,引发原因等。
异常的处理
java提供了两种对异常的处理方式:
- 遇到问题不进行具体的处理,而是继续抛给调用者。其实就是在函数上通过throws关键字声明异常,告诉调用者处理。
对这种处理方式的详细解释:在编写功能时,编写者会知道该功能有可能发生问题,而这个问题很容易来自于调用者传递的参数,而导致功能无法运行。这时发生的问题就应该让调用者知道,并最后让调用者有预先的处理方式,所以在定义功能时,需要在功能上对有可能发生的问题进行声明。声明问题需要使用关键字(throws):throws 异常类,声明的目的:就是让调用者可以进行处理。 针对性的处理方式:捕获!
try { // 有可能发生异常的代码 } catch(异常类 变量) { // 这是真正的捕获,处理异常的代码; } finally { // 一定会被执行的代码; }
对捕获到的异常对象进行常见方法操作
- getMessage();获取异常信息,返回字符串
- toString();获取异常类名和异常信息,返回字符串
- printStackTrace();获取异常类名和异常信息,以及异常出现在程序中的位置,返回值为void。JVM默认处理收到的异常就是调用这个方法,将信息显示在屏幕上
printStackTrace(PrintStream s);通常用该方法将异常内容保存在日志文件中,以便查阅
例,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)。便于提高安全性,让调用者进行处理,不处理编译失败。
对多异常的处理
- 声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最后。
建议在进行catch处理时,catch中一定要定义具体处理方式。不要简单定义一句:e.printStackTrace();
,也不要简单的就书写一条输出语句。
例,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
这个体系中独有的特点,只有这个体系中的类和对象才可以被throws
和throw
操作。
throws
和throw
的区别:
- 位置不同。
throws
使用在函数上,throws
后面跟的是异常类,可以跟多个,用逗号隔开。throw
使用在函数内,throw
后跟的是异常对象。
- 功能不同。
throws
用来声明异常,让调用者知道该功能有可能出现的问题,并由调用者可以给出预先的处理方式。throw
抛出具体的问题对象,执行到throw
,功能就已经结束了,跳转到调用者,并将具体的问题对象也抛给调用者。
例,
/*
需求:在本程序中,对于除数是-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
以及其子类)
例,
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捕获)。异常什么时候声明,什么时候捕获呢?功能内部可以解决,就捕获,不能解决或者解决了还必须告诉调用者问题,这时就应该声明。
现在来看一个异常的一个小练习:毕老师用电脑上课。
分析:开始思考上课中出现的问题。比如问题是:电脑蓝屏、电脑冒烟。要对问题进行描述,封装成对象。可是当冒烟发生后,出现讲课进度无法继续,出现了讲师的问题,课时计划无法完成。
// 蓝屏是可以处理的,继承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,
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,
class NoValueException extends Exception {
}
public void operate() throws NoValueException
{
// 连接数据库
try
{
// 数据操作 throw new SQLException();
}
catch (SQLException e)
{
// 解决了数据库异常
throw new NoValueException();
}
finally {
// 关闭数据库
}
}
记住一点:catch
是用于处理异常,如果没有catch
就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明。
异常在子父类覆盖中的体现
- 子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类或者不抛。
- 如果父类方法抛出多个异常,那么子类在覆盖这个方法时,只能抛出父类异常的子集(不抛也行)
- 如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须要进行
try
处理,绝对不能抛。
练习:有一个圆形和长方形,它们都可以获取面积,对于面积如果出现非法的数值,视为是获取面积出现问题。问题通过异常来表示。
解:先要对这个程序进行基本设计。
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");
}
}
总结
异常:对问题的描述,将问题进行对象的封装。
异常体系:
Throwable
|---Error
|---Exception
|---RuntimeException
异常体系的特点:异常体系中的所有类以及建立的对象都具有可抛性,也就是说可以被throw
和throws
关键字所操作。只有异常体系具备这个特点。
throw
和throws
的用法:
- throw定义在函数内,用于抛出异常对象。
- throws定义在函数上,用于抛出异常类,可以抛出多个,用逗号隔开。
当函数内容有throw
抛出异常对象,并未进行try
处理,必须要在函数上声明,否则编译失败。
注意:RuntimeException除外,也就是说,函数内如果抛出的是RuntimeException异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理,处理方式可以throws
也可以try
。
异常有两种:
- 编译时被检测异常
- 该异常在编译时,如果没有处理(没有抛也没有
try
),编译失败 - 该异常被标识,代表着可以被处理
- 该异常在编译时,如果没有处理(没有抛也没有
- 运行时异常(编译时不检测)
- 在编译时,不需要处理,编译器不检查
- 该异常的发生,建议不处理,让程序停止,需要对代码进行修正
异常处理语句:
try {
需要被检测的代码;
} catch() {
处理异常的代码;
} finally {
一定会指执行的代码;
}
有三种结合格式:
try { 需要被检测的代码; } catch() { 处理异常的代码; }
try { 需要被检测的代码; } finally { 一定会指执行的代码; }
try { 需要被检测的代码; } catch() { 处理异常的代码; } finally { 一定会指执行的代码; }
注意:
finally
中定义的通常是关闭资源代码,因为资源必须释放。finally
只有一种情况不会执行,当执行到System.exit(0);
,finally
不会被执行。
自定义异常:定义类继承Exception
或者RuntimeException
。
- 为了让自定义类具备可抛性
- 让该类具备操作异常的共性方法
当要定义自定义异常的信息时,可以使用父类已经定义好的功能。将异常信息传递给父类的构造函数。
class MyException extends Exception {
MyException(String message) {
super(message);
}
}
自定义异常:按照java的面向对象思想,将程序出现的特有问题进行封装。
异常的好处:
- 将问题进行封装
- 将正常流程代码和问题处理代码相分离,方便于阅读
异常的处理原则:
- 处理方式有两种:
try
或者throws
- 调用到抛出异常的功能时,抛出几个,就处理几个。一个
try
对应多个catch
- 多个
catch
,父类的catch
放到最下面 catch
内,需要定义针对性的处理方式,不要简单的定义printStackTrace
或者输出语句。也不要不写
当捕获到的异常,本功能处理不了时,可以继续在catch
中抛出。
try{
throw new AException();
} catch(AException e) {
throw e;
}
如果该异常处理不了,但并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。
try{
throw new AException();
} catch(AException e) {
throw new BException();
}
或者异常可以处理,但需要将异常产生后,和本功能相关的问题提供出去,让调用者知道并处理,即将捕获异常处理后,转换新的异常抛出。(比如,汇款的例子)
try{
throw new AException();
} catch(AException e) {
对AException处理
throw new BException();
}
异常的注意事项:在子父类覆盖时
- 子类抛出的异常必须是父类的异常的子类或者子集
- 如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛
包(package)
- 对类文件进行分类管理
- 给类提供多层命名空间
- 写在程序文件的第一行
- 类名的全称是
包名.类名
- 包也是一种封装形式
总结:
- 包与包之间进行访问,被访问的包中的类以及类中的成员,需要
public
修饰。 - 不同包中的子类还可以直接访问父类中被
protected
权限修饰的成员。 - 包与包之间可以使用的权限只有两种:
public
/protected(只给子类使用)
四种访问权限
╲ | public | protected | default | private |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中 | √ | √ | √ | |
子类 | √ | √ | ||
不同包中 | √ |
import
为了简化类名的书写,使用一个关键字——import
。import
导入的是包中的类,不导入包中的包。
建议:
- 不要写通配符
*
,需要用到包中的哪个类,就导入哪个类 - 定义包名不要重复,可以使用
url
来完成定义,url
是唯一的
例,
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命令行
环境中一屏显示不过来,可用如下命令:
C:myclass>jar -tf liayun.jar >c:1.txt
即将yelei.jar
包中的内容存放到c
盘下1.txt
文本文件中。
数据重定向——数据不想在一个地方(例如dos命令行)显示,而想在文件中显示。可用如下命令:
C:>dir >c:2.txt
即将c
盘目录下的文件信息存放在c
盘下2.txt
文本文件中。
最后
以上就是疯狂河马为你收集整理的面向对象——异常异常包(package)的全部内容,希望文章能够帮你解决面向对象——异常异常包(package)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复