Fork me on GitHub

Java 8 抽象类 接口 内部类 异常处理

注意:所有文章除特别说明外,转载请注明出处.

Java 8 抽象类 接口 内部类 异常处理

[TOC]

Java 异常处理

  1. 声明异常

注意:如果方法没有在父类中声明异常,那么就不能在子类中对其进行覆盖来声明异常。

  1. 抛出异常

注意:通常JAVA API 中的每个异常类至少有两个构造方法:1.无参构造方法。

  1. 一个带可描述此异常的String参数的构造方法。(该参数称为异常消息,可以使用getMessage()获取)

注意:声明异常的关键字:throws 抛出异常的关键字:throw。

  1. 捕获异常

    注意:

    1.从一个通用父类可以派生出各种异常类,如果一个catch块可以捕获一个父类的异常对象,那么它就能够父类的所有子类的异常对象。
    
    2.在catch块中异常被指定的顺序非常重要,如果父类的catch块出现在子类的catch块之前,就会导致编译错误。
    
    3.Java强迫程序员必须处理必检异常,如果方法中声明了一个必须检验的异常(error或runtimeException),就必须在try-catch块中调用它,或者在调用方法中声明要抛出异常。
    
    4.使用异常的时机
    
        注意:异常处理过程中通常需要更多的时间和资源。
    
        1.异常出现在方法中,如果想让该方法的调用者处理异常,应该创建一个异常对象并将其抛出。如果能在发生异常的方法中处理异常,那么就不需要抛出异常或使用异常。
    

注意:不要将异常处理用作简单的逻辑测试。而在哪种情况下使用异常需要我们自己判断。

  1. 重新抛出异常

前提:如果异常处理器没有处理某个异常,或者处理器只是希望其调用者注意该异常,Java就允许处理器重新抛出异常。在try-catch块中最后使用throw关键字。这样就方便其他的调用者获得处理抛出异常的机会。

  1. 链式异常
  1. 自定义异常

注意:因为Java提供了很多的异常类,所以在不是特殊的情况下尽量避免使用自定义异常类。

通过派生Exception类或其子类(如:IOException)来创建自定义异常类。

1. 异常类Throwable

该异常类中对应的相应的方法,toString()方法表示输出该异常类名+错误信息。getMessage()方法输出异常信息,需要通过构造方法传入异常信息(返回创建throwable的异常信息)。printStackTrace()方法打印异常的栈信息。

throws/throw抛出处理的细节:1.如果一个方法的内部抛出一个编译时异常对象,那么必须在方法上声明抛出。

public static void div(int a,int b) throws Exception{
    //函数方法执行体
}

2.如果调用了一个声明抛出异常的方法,那么调用者必须处理该抛出的异常。3.如果一个方法内部抛出了一个异常对象,那么throw语句后面的程序就不会再执行。4.在一种情况下只能抛出一种异常对象。

throw关键字用于在方法体内部抛出异常对象,throws关键字用于在方法声明上声明抛出异常类型。一个try块后面可以跟多个catch块,也就是一个try块可以捕获多种异常类型,但是捕获的异常类型必须从小到大进行捕获(不然在执行大的异常对象之后,小的异常不会被执行)。

运行时异常(RuntimeException/RuntimeException子类):如果一个方法内部抛出一个运行时异常,那么方法上可以声明也可以不声明,调用者可以处理也可以不处理。

编译时异常(非运行时异常、受捡异常):如果一个方法内部抛出了一个编译时异常对象,那么方法上就必须要声明,而且调用者也必须要处理。

运行时异常都是程序员良好的编程习惯去避免的,所以Java编译器就没有严格要求处理运行时异常。

总结:
    1.异常处理能够使得一个方法给它的调用者抛出一个异常。
    2.异常发生在一个方法的执行过程中,RuntimeException/Error都是免检异常,其他所有的异常都是必须检验的异常。
    3.当声明一个方法时,如果这个方法抛出一个必须检验的异常,则必须声明为必须检验异常,告诉编译器可能会出现什么错误。
    4.声明异常的关键字:throws,抛出异常的关键字:throw

    5.异常处理是将处理代码从正常的程序中分离出来,这样的话,程序更容易处理和理解。
    6.我们不应该使用异常处理代替简单的测试,应该尽可能的测试简单异常,将异常处理保留为处理那些无法使用if语句处理的异常。

2. 常见的Error以及Exception

1.RuntimeException

    1.NullPointerException 空指针引用异常

    2.ClassCastException 类型强转异常

    3.IllegalArgumentException 传递非法参数异常

    4.IndexOutOfBoundsException 下标越界异常

    5.NumberFormatException 数字格式异常

2.非RuntimeException

    1.ClassNotFoundException 找不到指定class异常

    2.IOException IO操作异常

3.Error

    1.NoClassDefFoundError 找不到class定义异常

        1.类依赖的class或者jar不存在

        2.类文件存在,但存在不同的域中

        3.大小写问题,javac编译的时候是无视大小写的,可能编译出来的class文件与想要的不一样

    2.StackOverflowError 深递归导致栈被耗尽抛出的异常

    3.OutOfMemoryError 内存溢出异常

3.Java异常处理机制

1.抛出异常:创建异常对象,交由运行时系统处理

2.捕获异常:寻找合适的异常处理器处理异常,否则终止运行

断言

断言是防御性编程中一种常见用法。Java中断言用于调试目的以检验内部假设,不是一种强制合约。

1.使用断言
assert 条件

    assert <boolean表达式>
        如果<boolean表达式>为true,则程序继续执行。
        如果为false,则程序抛出AssertionError,并终止执行。

assert 条件 : 表达式

    assert <boolean表达式> : <错误信息表达式>
        如果<boolean表达式>为true,则程序继续执行。
        如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。

assert 语句会计算条件表达式的值,如果是false,则会抛出一个AssertionError异常。

2.启用和禁用断言

在默认情况下,断言是被禁用的。在运行程序时加上命令 -ea | -enableassertion 启用断言。


抽象类和接口

抽象类

注意:抽象类和常规类很像,但是不能使用new关键字创建其实例。抽象方法只有定义没有实现,它的实现由子类提供,一个包含抽象方法的类必须声明为抽象类。

抽象类的构造方法定义为protected,其只能被子类使用。

注意:

    1.抽象方法不能定义在非抽象类中,如果抽象父类的子类不能实现所有的抽象方法,那么子类必须定义为抽象,同时注意抽象方法是 非静态 的。

    2.抽象类不能使用new关键字来初始化,但可以定义其构造方法,这个构造方法在它的子类的构造方法中可以被调用。

    3.包含抽象对象的类必须是抽象的,但可以定义一个不包含抽象方法的抽象类。此时不能使用new操作符创建该类的实例。

    4.如果一个类是具体的,但是其子类可以是抽象的。

接口

注意:由于接口中所有的数据域都是public final static而且所有的方法都是public abstract,所以Java允许忽略这些修饰符。

提示:接口中定义的常量可以使用语法:接口名.常量名(如:T.k)来访问。

多态

多态表示对象的多种状态,多态可以作为形参接受范围更广的对象,避免函数重载或过度使用。同时多态可以作为返回值类型。抽象类和接口都可以作为多态中的父类引用类型。

提示:1.当父类和子类具有相同的非静态成员变量,那么在多态下访问的是父类的成员变量。2.当父类和子类具有相同的静态成员变量,那么在多态下访问的是父类的静态成员变量。所以父类和子类有相同的成员变量,多态下访问的是父类的成员变量。3.当父类和子类具有相同的非静态方法(就是子类重写父类方法),多态下访问的是子类的成员方法。4.当父类和子类具有相同的静态方法(就是子类重写父类静态方法),多态下访问的是父类的静态方法。

总结:多态情况下,子父类存在同名的成员时,访问的都是父类的成员,只有在同名非静态函数时才是访问子类的。多态情况下,不能访问子类特有的成员。

注意:使用多态的前提是类与类之间存在有关系,如:继承或实现关系。

总结:

    1.抽象类和常规类一样,都有数据和方法,但是不能使用new操作符创建抽象类的实例。
    2.非抽象类中不能包含抽象方法。如果抽象类的子类没有实现所有被继承的父类抽象方法,就必须将子类也定义为抽象类。
    3.包含抽象方法的类必须是抽象类,但抽象类可以不包含抽象方法。

    4.接口中只包含常量和抽象方法,接口与抽象类很类似,但是抽象类除了包含常量和抽象方法之外,还包含变量和具体方法。

    5.接口java.lang.Comparable定义了compareTo()方法,Java类库中许多类都实现了Comparable。

    6.

内部类

  1. 内部类可以直接访问外部类的成员属性。

  2. 外部类需要访问内部类的成员属性时需要创建内部类的对象:

    1. 在外部类的成员函数中创建内部类的对象,通过内部类的对象直接访问内部类的成员变量。

    2. 在其他类中创建内部类的对象 创建的格式:外部类.内部类 变量名=new 外部类();

1.内部类的共性

(1)内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。

(2)内部类不能用普通的方式访问。

(3)内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量 。

(4)外部类不能直接访问内部类的的成员,但可以通过内部类对象来访问

注意:如果是静态内部类,其在其他类的创建对象的方式:外部类.内部类 变量名=new 外部类.内部类();

2.静态内部类的作用

1.只是为了降低包的深度,方便类的使用,静态内部类适用于包含类当中,但又不依赖与外在的类。

2.由于Java规定静态内部类不能用使用外在类的非静态属性和方法,所以只是为了方便管理类结构而定义。于是我们在创建静态内部类的时候,不需要外部类对象的引用。

3.非静态内部类的作用

1.内部类继承自某个类或实现某个接口,内部类的代码操作创建其他外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。

2.使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。

4.普通内部类与静态内部类的区别

1.普通内部类不能声明static的方法和变量

2.静态内部类不依赖外部类

3.静态内部类不持有外部类的引用

总结:普通内部类不能使用静态变量是因为成员内部类是类实例的一部分,不是类的一部分。如果想在内部类内声明静态字段,就需要声明该内部类是静态的。

成员内部类要注意的事项:

  1. 成员内部类可以直接访问外部类成员。

  2. 如果成员内部类与外部类存在同名的成员,在内部类中默认是访问内部类的成员,成员通过”外部类.this.成员”指定访问外部类的成员。

  3. 如果成员内部类出现了静态的成员,那么该成员内部类也必须使用static修饰。

  4. 如果成员内部类是私有的,那么创建内部类的对象就只能在外部类提供方法创建。

使用内部类的时间:当我们分析事物时,发现事物的内部还有具体的事物,这时就应该定义内部类。优势:成员内部类作为外部类的成员,可以访问外部类的任意成员。成员内部类访问细节:

1.私有的成员内部类不能在其他类中直接创建内部类对象来访问。

2.如果内部类中包含静态成员,那么Java规定内部类必须声明为静态的访问静态类的形式,Out.Inner in=new Outer.Inner();

总结:成员内部类(成员)属性、成员方法的特点:

1.私有的成员内部类,不能在其它类中直接创建内部类对象来访问

2.静态的成员内部类,如果内部类中包含有静态成员,那么Java规定内部类必须声明为静态的访问静态类的形式。

局部内部类

定义:包含在外部类的函数中定义的内部类称之为局部内部类

访问:在包含局部内部类的方法中直接创建局部内部类的对象调用局部内部类的成员(即直接在该内部类存在的方法中创建对象,对其成员进行访问)。

局部内部类不能用public或private访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。

局部类的优势,对外界可以完全隐藏起来。

注意:局部内部类只能访问所在函数的final属性

匿名内部类

该类是没有名称的内部类。类似于Java 8新特性中。

new SuperType(construction parameters){
    inner class methods and data
}

提示:匿名内部类不能有构造函数。匿名类没有类名。

静态内部类

在有时候,使用静态内部类的目的在于将一个类隐藏在另外一个类的内部,并不需要内部类引用外围类的对象。所以我们可以将该类声明为static,以便取消产生的引用。

提示:只有内部类可以被声明为static。静态内部类除了没有对生成它的外围对象的引用特权外,与其它内部类一样。

本文标题:Java 8 抽象类 接口 内部类 异常处理

文章作者:Bangjin-Hu

发布时间:2018年12月05日 - 09:22:26

最后更新:2020年03月30日 - 08:09:30

原始链接:http://bangjinhu.github.io/undefined/Java 8 抽象类 接口 内部类 异常处理/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.