您的位置:首页 > 编程语言 > Java开发

Java基础---异常,包

2015-09-08 15:40 447 查看

异常

1.定义

异常指的是在程序运行过程中发生的异常事件,通常是由硬件问题或者程序设计问题所导致的。在Java等面向对象的编程语言中异常属于对象。


Java异常类层次结构图:



2.异常由来:

编程中对于那些会出现的问题,Java采用异常机制来解决。
最常使用的就是try{}catch{}

本质:java对不正常情况进行描述后的对象体现。
程序可能出现的错误或问题:
a、用户输入错误导致的异常:如用户不正常使用程序,输入一些非法参数
b、设备硬件等发生的错误:如硬盘损坏等
c、物理限制:如存储空间不足等
d、代码错误:在程序编写的方法可能不正确,数组越界,返回错误参数等。


3.异常体系

Throwable 类

是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。

有两个重要的子类:Exception(异常)和 Error(错误)


Error(错误)

是程序无法处理的错误,表示运行程序中较严重的问题。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。


Exception(异常)

是程序本身可以处理的异常。
RuntimeException类是他的一个比较特殊的类。

RuntimeException 类:
RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。


注意:异常和错误的区别:异常能被程序本身处理,错误是无法处理。

4.异常分类

1.Java的异常

Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和可不查的异常(unchecked exceptions)。


可查异常(编译器要求必须处置的异常):

程序在运行时,在一定程度上可以预知的异常,并可以采取某种方式进行处理。
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。


可不查异常(编译器不要求强制处置的异常):

包括运行时异常(RuntimeException与其子类)和错误(Error)。
这类异常编译时,编译器不会去检查。


2.Exception异常

Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。


运行时异常:

RuntimeException及其子类,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等。这些异常编译器不检查,即使不使用try-catch捕获,或使用throws抛出,编译器也不会报错,但会在运行时触发。
这些异常一般出在逻辑上,在程序设计时应该从逻辑角度尽可能避免这类异常。


非运行时异常 (编译异常):

除RuntimeException及其子类外的异常,类型上属于Exception类及其子类。
编译器会检查此类一场,如果不处理,程序是无法编译通过的。


总结:根据编译器是否检查来进行划分。

总的来说,RuntimeException及其子类外的异常编译器不进行检查,其他Exception都需要处理。

异常处理

对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同:

a.运行时异常:java允许可以不抛出,不捕获;运行时由系统由系统抛出。
b.Error,不抛出,不捕获,因为Error是java所不允许发生的。
c.可查行异常,必须捕获或者抛出。


一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。

异常处理有两种方式:捕捉异常(try-catch),抛出异常(throws)

1.捕捉异常

java提供了特有的语句进行处理:

try

{

需要被检测的代码。

}

catch(异常类  变量)

{

处理异常的代码;(处理方式)

}

finally

{

一定会执行的语句;

}


注意:

1)finally中定义的通常是关闭资源代码。因为资源必须释放。

2)如果在一个功能中,定义了一些必须要执行的代码,可以用try{}finally{}的方式,将一定执行的代码放在finally代码块中。

3)finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。


public static void main(String[] args) {
int a = 6;
int b = 0;
try {
System.out.println("a/b的值是:"+ a / b);
} catch (ArithmeticException e) {
System.out.println("程序出现异常,变量b不能为0。");
}
System.out.println("程序正常结束。");
}
}


分析:此例中由try中监控区,检测到“除数为0”从而引发ArithmeticException异常,由异常处理器catch捕获,并处理。

但是,实际上,”除数为0“ArithmeticException异常是RuntimeException子类,会由系统自动抛出,不需要使用throw语句。

需要注意的是,一旦某个catch捕获到匹配的异常类型,将进入异常处理代码。一经处理结束,就意味着整个try-catch语句结束。其他的catch子句不再有匹配和捕获异常类型的机会。

对于有多个catch子句的异常程序而言,应该尽量将捕获底层异常类的catch子 句放在前面,同时尽量将捕获相对高层的异常类的catch子句放在后面。否则,捕获底层异常类的catch子句将可能会被屏蔽。



小结:

try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。
catch 块:用于处理try捕获到的异常。


finally块:无论是否捕获或处理异常,finally块里的语句都会被执行。当在try块或catch块中遇到return语句时,finally语句块将在方法返回之前被执行。在以下4种特殊情况下,finally块不会被执行:

1)在finally语句块中发生了异常。

2)在前面的代码中用了System.exit()退出程序。

3)程序所在的线程死亡。

4)关闭CPU。

2.抛出异常

可以通过throws和throw抛出异常。

1)throws

定义:

如果一个方法可能会出现异常,但没有能力处理这种异常,可以在方法声明处用throws子句来声明抛出异常。例如汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理。


throws语句用在方法定义时声明该方法要抛出的异常类型,如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。throws语句的语法格式为:

methodname throws Exception1,Exception2,..,ExceptionN
{
}


方法名后的throws Exception1,Exception2,…,ExceptionN 为声明要抛出的异常列表。当方法抛出异常列表的异常时,方法将不对这些类型及其子类类型的异常作处理,而抛向调用该方法的方法,由他去处理。例如:

import java.io.*;

public class Test1 {

public static void method() throws IOException {
File f = new File("r:\\");
}

public static void main(String[] args) {
//此处报错,Unhandled exception type IOException未处理异常
method();
}

}


原因:IOException是Exception子类,是编译异常,必须捕获,method()方法使用throws向上层调用(main函数)抛出了,但是main函数未处理,所以造成了错误。

解决:使用try-catch捕获并处理。

Throws抛异常的原则:

1)不可查异常(unchecked exception)RuntimeException和Error异常可以不抛出,但是可查异常(checked exception)必须被抛出或者被捕获,否则编译会报错。

2)仅当抛出了异常,该方法的调用者才必须处理或者重新抛出该异常。当方法的调用者无力处理该异常的时候,应该继续抛出,而不是囫囵吞枣。


public class Test1 {

void method() throws IOException {
File f = new File("r:\\");
}

// 编译错误,必须捕获或者声明IOException
void method1() {
method();
}

// 合法,声明抛出了IOException
void method2() throws IOException {
method();
}

// 合法,声明抛出Exception,IOException是Exception的子类
void method3() throws Exception {
method();
}

// 合法,捕获了IOException
void method4() {
try {
method();
} catch (IOException e) {
}
}

// 不合法,又抛出了一个IOException,必须抛出或者再次捕获
void method5() {
try {
method();
} catch (IOException e) {
throw new IOException();
}
}

// 合法,再次抛出的新的异常
void method6() throws Exception {
try {
method();
} catch (IOException e) {
throw new Exception();
}
}
}


3)在子父类覆盖时:
a,子类抛出的异常必须是父类的异常的子类或者子集。
b,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。


class T1 {
void method() throws IOException {
}
}
class T2 extends T1{
//错误,子类抛出的异常不是父类抛出异常的子类
void method()throws Exception {
}
}


2)throw抛出异常

在函数体内使用,即抛出一个一场对象。形如:

throw new Throwable();


该对象是人为抛出的,虽然和程序运行产生的不同,但是仍是需要抛出或者捕获的。

Throwable

Throwable中的方法:

1.getMessage():获取异常信息,返回字符串。
2.toString():获取异常类名和异常信息,返回字符串。
3.printStackTrace():获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void。
4.printStackTrace(PrintStreams):通常用该方法将异常内容保存在日志文件中,以便查阅。


自定义异常:

/***
* 自定义异常
*/
class Demo{
//除法,抛出我的自定义异常
int div(int a, int b) throws MyException{
if(b==0){
throw new MyException("除数不能为负数!");
}
return a/b;
}
}
public class Test3 {

public static void main(String[] args) {
int a = 10;
int b = 0;
try {
Demo d = new Demo();
int s = d.div(a, b);
} catch (MyException e) {
// TODO: handle exception
e.printStackTrace();
System.out.println(e.getMessage());
}
}
}

class MyException extends Exception {
/***
* 自定义异常的构造方法,信息的传递通过有参构造方法,
*  父类通过有参构造方法传递的参数来打印消息
*/
public MyException(String MyMessage) {
super(MyMessage);
}
}


小测试:

import java.util.*;

/***
*  老师使用电脑讲课。
*
*         描述电脑: 1、电脑运行 2、电脑重启 描述电脑问题: 1、电脑蓝屏了 2、电脑起火了
*
*         描述老师: 1、老师使用电脑 2、老师讲课。
*
*         描述老师可能出现的问题:
*         1、老师不能继续讲课了。
*         2.电脑蓝屏,重新启动
*                  a.多次重启后,成功
*                  b.多次蓝屏重启后,电脑着火了
*         3.一次启动成功,老师开始讲课
*/
//蓝屏异常
class BlueScreenException extends Exception {
public BlueScreenException(String message) {
super(message);
}
}

//电脑着火
class FireBreakException extends Exception {
public FireBreakException(String message) {
super(message);
}
}
//电脑类
class Computer {
// 随机产生一个数,来模拟电脑启动
int i;
//启动
void run() throws BlueScreenException, FireBreakException {
i = (int) (Math.random()*3+1);
if(1==i)
{
System.out.println("电脑正常启动");
} else if(2==i)
{
throw new BlueScreenException("电脑蓝屏了!");//蓝屏异常
} else
{
throw new FireBreakException("电脑着火了!");//着火异常
}
}
//重启
void reset() {
System.out.println("电脑重新启动");
try {
run();
} catch (BlueScreenException e) {
System.out.println(e.getMessage());
reset();
} catch (FireBreakException e) {

System.out.println("多次重启,着火了!");
}
}
}

//无法上课的异常
class BreakTeachingException extends Exception{
public BreakTeachingException(String message){
super(message);
}
}

//老师类
class Teacher{
private Computer c = new Computer();
void teach() throws BreakTeachingException{
try {
c.run();
System.out.println("老师开始上课!");
} catch (BlueScreenException e) {

System.out.println(e.getMessage());
c.reset();
} catch (FireBreakException e) {

throw new BreakTeachingException("老师无法上课,原因"+e.getMessage());
}
}
}
public class Test4 {
public static void main(String[] args) {
Teacher t = new Teacher();
try {
t.teach();
} catch (BreakTeachingException e) {

e.printStackTrace();
System.out.println("暂停上课,电脑着火了!");
}
}
}


一次启动成功,老师开始讲课:



一次启动,电脑着火:



多次蓝屏重启后成功



多次蓝屏重启后电脑着火



确保类的唯一性,使得同类名的类可以同时存在,使用包进行划分。

权限问题:



规则

1、包必须写在程序的第一行。因为要先有包,才知道类文件的存放地方。

2、类的全称:包名.类名。

3、编译定义了包的程序文件时,在编译时要指定包的存储目录。

如:javac –d c:\mypack类名.java


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包:



进入cmd:



编译:



javac -d . Demo.java和javac -d f:\JavaDemo Demo.java的不同在于指定的目录不同。

jar包生成:



运行:把生成的jar包放到D盘下,设置classpath路径,并运行。



多个不同包下的类建jar包:

同理:javac –d . Demo.java分别编译



建好后:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: