黑马程序员——Java学习日记(六)异常、包

时间:2022-01-09 12:29:59
一、异常

先看一个示例:

class Demo {
int div(int a, int b) {
return a / b;
}
}

class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
int x = d.div(4, 1);
System.out.println(x);
int y = d.div(4, 0);
System.out.println(y);
System.out.println("over");
}
}

运行结果为:

4

Exceptionin thread "main" java.lang.ArithmeticException: / by zero

    at Demo.div(ExceptionDemo.java:14)

    at ExceptionDemo.main(ExceptionDemo.java:6)

附注:当程序运行出现异常后,出现异常位置后的代码就不再运行

1.概念:就是程序在运行时出现的不正常情况

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

3.异常的体系:

       Throwable

              ·Error

                     ----通常出现重大问题如:运行的类不存在或者内存溢出等

                     ----不编写针对代码对其处理

              ·Exception

                     ----在运行时运行出现的一起情况,可以通过针对性的处理方式进行处理

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

Exception和Error的子类名都是以父类名作为后缀

4.异常的处理格式:

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

try{

       需要被检测的代码;

}catch(异常类变量){

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

}finally{

       一定会执行的语句;

}

针对上面除法出现的异常,我们给出相应的解决方式:

class Demo {
//在功能上通过throws的关键字声明了该功能有可能会出现问题。
int div(int a, int b)throws Exception {
return a / b;
}
}

class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try{
int x = d.div(4, 1);
System.out.println(x);
int y = d.div(4, 0);
System.out.println(y);
System.out.println("over1");
}catch (Exception e) {
System.out.println("除0了");
//获取错误信息
System.out.println(e.getMessage());
//异常名称和异常信息
System.out.println(e.toString());
//异常名称,异常信息和异常出现的位置。jvm默认调用就是printStackTrace()
e.printStackTrace();
}
System.out.println("over2");
}
}

运行结果:

4

0

/ by zero

java.lang.ArithmeticException: / by zero

java.lang.ArithmeticException: / by zero

    at Demo.div(ExceptionDemo.java:26)

    at ExceptionDemo.main(ExceptionDemo.java:7)

over2

总结:当程序运行出现异常后,出现异常位置后的代码就不再运行,在函数上声明异常,便于提高安全性,让调用者进行处理。

5.Throwable中的方法

       ·getMessage()----获取异常信息,返回字符串

       ·toString()----获取类名和异常信息,返回字符串

       ·printStackTrace()----获取类名和异常信息,以及异常出现在程序中的位置,返回值void

       ·printStackTrace(PringStrean s)----通常用该方法将异常内容保存在日志文件中,以便查阅

6.对异常的处理:

★声明异常时,建议声明更为具体的异常。这样处理的可以更具体。

★对方声明几个异常,就对应有几个catch块,不要定义多余的catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。

注意:在进行catch处理时,catch中一定要定义具体处理方式,不要简单定义一句 e.printStackTrace(),也不要简单的就书写一条输出语句。

示例:

class Demo {
//在功能上通过throws的关键字声明了该功能有可能会出现问题。
void div(int a, int b) throws ArithmeticException,
ArrayIndexOutOfBoundsException{
System.out.println(a/ b);
int[] arr = new int[a];
System.out.println(arr[4]);
}
}

class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try{
d.div(6,2);
System.out.println("-------");
//被零除了!!
d.div(5,0);
System.out.println("-------");
//角标越界啦!!
d.div(4,2);
}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("hahah:"+ e.toString());
}
System.out.println("over");
}
}

运行结果:

3

0

-------

java.lang.ArithmeticException: / by zero

被零除了!!

over

7.自定义异常:

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装,所以对于这些特有的问题可以按照java对问题封装的思想将特有问题进行自定义的异常封装。

当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作,要么在内部try…catch处理,要么在函数上声明让调用者处理

一般情况下,函数内出现异常,函数上需要声明

如果发现打印的结果中只有异常的名称,却没有异常的信息,是因为自定义的异常并为定义信息。

那么如何定义异常信息呢?

因为父类中已经把异常信息的操作都完成了,所以子类只要在构造时,将异常信息传递给父类通过super语句,那么就可以直接通过getMessage()方法获取自定义的异常信息了。

自定义类继承Exception或者其子类

继承Exceprion的原因:

异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。

通过构造函数定义异常信息

throws和throw

              throws用于标识函数暴露出的异常

              throw用于抛出异常

       throws和throw的区别:

              throws用在函数上,后面跟异常类名

              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关键字抛出一个自定义异常对象
throw new FuShuException(“出现了除数是负数的情况----/by fushu”,b);
return a/b;
}
}

class ExceptionDemo{
public static void main(String[] args){
Demo d=new Demo();
try{
int x=d.div(4,-9);
System.out.println(x);
}catch(FuShuExceptione){
System.out.println(e.toString());
System.out.println(“错误的负数是:”+e.getValue());
}
System.out.println(“over”);
}
}

运行结果是:

FuShuException:出现了除数是负数的情况----/by fushu

错误的负数是:-9

over

8.RuntimeException讲解:

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

注意:

异常细节:自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException

异常分两种:

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

示例:

class FuShuException extendsRuntimeException {
FuShuException(String msg) {
super(msg);
}
}

class Demo {
int div(int a, int b) throws ArithmeticException {
if(b < 0)
throw new ArithmeticException("出现了除数为负数了");
if(b == 0)
throw new ArithmeticException("被零除啦");
return a / b;
}
}

class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
int x = d.div(4, 2);
System.out.println("x="+ x);
int y = d.div(4, -2);
System.out.println("y="+ y);
System.out.println("over");
}
}

运行结果:

x=2

Exceptionin thread "main" java.lang.ArithmeticException:出现了除数为负数了

    at Demo.div(ExceptionDemo.java:20)

    at ExceptionDemo.main(ExceptionDemo.java:6)

总结:

·RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明

·一个方法被覆盖时,覆盖它的方法必须抛出相同的异常或异常的子类

·如果父类抛出多个异常的一个子集,不能抛出新的异常

·介绍异常在分层设计时的层内封装

练习:(自定义异常,对上课可能出现的意外情况进行处理)

假设问题有:电脑蓝屏、电脑冒烟(要对问题进行描述,封装成类),当出现不同的问题,要进行相应的处理

代码实现如下:

class LanPingException extends Exception {
LanPingException(String msg) {
super(msg);
}
}

class MaoYanException extends Exception {
MaoYanException(String msg) {
super(msg);
}
}

class NoPlanException extends Exception {
NoPlanException(String msg) {
super(msg);
}
}

class Computer {
private int state = 3;
public void run() throws LanPingException, MaoYanException {
if(state == 2)
throw new LanPingException("蓝屏了");
if(state == 3)
throw new MaoYanException("冒烟了");
System.out.println("电脑运行");
}
public void reset() {
state= 1;
System.out.println("电脑重启");
}
}

class Teacher {
private String name;
private Computer cmpt;
Teacher(String name) {
this.name= name;
cmpt= new Computer();
}
public void prelect() throws NoPlanException {
try{
cmpt.run();
} catch (LanPingException e) {
System.out.println(e.getMessage());
cmpt.reset();
}catch (MaoYanException e) {
thrownew NoPlanException("课时无法继续.." + e.getMessage()+"..."+this.test());
}
System.out.println("继续讲课");
}
publicString test() {
return"学生自己练习";
}
}

class ExceptionDemo {
public static void main(String[] args) {
Teachert = new Teacher("王老师");
try{
t.prelect();
}catch (NoPlanException e) {
System.out.println(e.toString());
}
}
}

运行结果:

NoPlanException:课时无法继续..冒烟了...学生自己练习

9. finally代码块

定义一定执行的代码,通常用于关闭资源。(比如数据库的关闭,流的关闭等等)

示例:

class FuShuException extends Exception {
FuShuException(String msg) {
super(msg);
}
}

class Demo {
int div(int a, int b) throws FuShuException {
if(b < 0)
throw new FuShuException("除数为负数");
returna / b;
}
}

class ExceptionDemo {
public static void main(String[] args) {
Demo d = new Demo();
try{
int x = d.div(4, -1);
System.out.println("x="+ x);
}catch (FuShuException e) {
System.out.println(e.toString());
return;
//System.exit(0);//系统,退出。jvm结束。
}finally {
System.out.println("finally");//finally中存放的是一定会被执行的代码。
}
System.out.println("over");
}
}

运行结果:

FuShuException:除数为负数

finally

总结:

System.exit(0);语句打开后,系统就会退出,jvm结束,finally语句不会执行。

return语句关闭后,System.out.println("over");也会执行。

示例2:(关于数据库的使用)

class NoException extends Exception{
}

处理数据库的方法:
public void method()throws NoException{
//连接数据库;
//数据操作;//throw new SQLException();
//关闭数据库;//该动作,无论数据操作是否成功,一定要关闭资源。
try{
连接数据库;
数据操作;//throw new SQLException();
}catch(SQLException e){
会对数据库进行异常处理;
throw new NoException();
}finally{
关闭数据库;
}
}


10.try、catch、finally的组合形式

第一种格式:

try{

 

}catch(){

 

}

第二种格式:

try{

 

}catch(){

 

}finally{

 

}

第三种格式:

try{

 

}finally{

 

}

附注:catch是用于处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么必须声明.

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

⑴子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法只能抛出父类的异常或者该异常的子类

⑵如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。

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

示例:

class AException extends Exception {}

class BException extends AException {}

class CException extends Exception {}

class Fu {
void show() throws AException, CException {}
}

class Zi extends Fu {
//子类覆盖父类方法时,抛出父类的异常或者该异常的子类
void show() throws AException, BException, CException {}
}

class Test {
voidfunction(Fu f) {
try{
f.show();
}catch (AException | CException e) {
e.printStackTrace();
}
}
}

练习:(有一个圆形和长方形,都可以获取面积,对于面积如果出现非法的数值,视为是获取面积出现问题,问题通过异常来表示)

代码如下:

interface Shape {
void getArea();
}

class NoValueException extendsRuntimeException {
NoValueException(String message) {
super(message);
}
}

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(intradius) {
if(radius <= 0)
throw new NoValueException("圆形半径非法");
this.radius= radius;
}
public void getArea() {
System.out.println(radius* radius * PI);
}
}
class ExceptionDemo {
public static void main(String[] args) {
Recr1 = new Rec(3, 4);
r1.getArea();
Circlec1 = new Circle(4);
c1.getArea();
System.out.println("-------");
Recr2 = new Rec(3, -4);
r2.getArea();
Circlec2 = new Circle(-4);
c2.getArea();
}
}

运行结果:

12

50.24

-------

Exceptionin thread "main" NoValueException:长方形出现非法值

    at Rec.<init>(ExceptionDemo.java:27)

    at ExceptionDemo.main(ExceptionDemo.java:8)

 

二、包(package)

1.特点:

·对类文件进行分类管理

·给类提供多层命名空间

·卸载程序文件的第一行

·类名的全名是 包名.类名

·包也是一种封装形式

2.包之间的访问:

·被访问的包中类的权限必须是public的

·类中的成员权限:public或者protected

·protected是为其他包中的子类提供一种权限

3.四种权限:

黑马程序员——Java学习日记(六)异常、包

import作用:

·简化包名

·一个程序文件中只有一个package,可以有多个import

·用来导入包中的类,不导入包中的包

·通常写importmypack.Demo(如果写importmypack.*的话,jvm会依次寻找,降低运行速度)

附注:(常用包)

java.lang: java的核心包 jdk1.2版本以后,该包中的类自动导入。

java.awt:用于制作图形界面。

java.io:用于操作设备上的数据。

java.util:这里定义是java的工具类。(集合,日期……)

java.net:用于网络通讯的。