Java基础—面向对象(五)

面向对象(五)

一、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
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()调用的是子类SubClassmethod()方法;由于父类抛出的是AException,在Test类中用try catch进行捕捉,并且catch语句只能处理AExceptionAException的子类;如果子类的method()方法抛出的是CExceptionCExceptionAException没有任何关系,catch语句无法处理,程序无法编译;如果子类的method()方法抛出的是AExceptionBExceptionAException是父类方法抛出的异常,BException是父类方法异常的子类,那么catch语句中捕捉AException就能处理子类方法抛出的异常;这是为什么子类复写父类的方法,只能抛出父类方法的异常,或父类方法异常的子类。

2.如果父类方法抛出多个异常,那么子类复写该方法时,只能抛出父类方法异常或其子集
父类抛出ABC异常,子类只能抛出ABC异常或ABC异常的子集

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

异常体系中的所有类,以及建立的对象,都具备可抛性,可以被throwthrows关键字操作。

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)包与包之间可以使用的权限只有两种:publicprotected

小扩展
不同范围内,成员在不同权限下的访问情况总结

publicprotecteddefaultprivate
同一类中YYYY
同一包中YYYN
子类YYNN
不同包中YNNN

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