Java 内部类与异常类

第七章 内部类与异常类

7.1 内部类

在一个类(设为类1)中定义另一个类(设为类2)。类2就叫做内部类类1叫做外嵌类

  • 内部类与外嵌类的关系:

外嵌类对内部类:

  1. 外嵌类中可以声明内部类的示例对象作为自己的成员变量。且如果外嵌类要访问内部类,需要通过内部类的实例对象访问。

内部类对外部类:

  1. 内部类可以访问到外嵌类的成员变量和成员方法。
  2. 内部类仅供它的外嵌类使用,其他类不可使用某个类的内部类声明对象。
  • 内部类的一些特性:
  1. 内部类的类体中不可以声明静态成员和静态方法。
  2. 一般的类有 p u b l i c public public 友好的 \text{友好的} 友好的两种访问修饰符,内部类可以有四种访问修饰符 p u b l i c public public, p r o t e c t e d protected protected, 友好的 \text{友好的} 友好的, p r i v a t e private private。但是由于内部类仅供外嵌类使用,对内部类的访问修饰符一般无效。
  3. j a v a java java编译器生成的内部类字节码的文件名格式为:$\text{外嵌类名$内部类名}.class$。
  • 如何打破内部类仅供外嵌类使用的限制

可以将内部类声明为静态类,即加上修饰符 s t a t i c static static。此时内部类会作为外嵌类的一种静态数据类型。由此便可以使用内部类在别的类中声明实例对象。

注意:非内部类不可以是 s t a t i c static static类。

7.2 匿名类

主要是2个方面:和子类有关的匿名类和接口有关的匿名类

Lambda表达式代替匿名类函数接口与Lambda表达式相差不大,不做记录。

  • 和子类有关的匿名类

当没有给出子类的定义时,想声明子类对象,那么就需要通过匿名类。

匿名类的特点:

  1. 承接上一小节:匿名类一定是内部类。因为 j a v a java java是完全面向对象的语言,匿名类一定是在另外一个类中出现的。
  2. 由于匿名类是内部类,所以匿名类中不能有 s t a t i c static static成员和 s t a t i c static static方法。
  3. 匿名类无名字,也无构造方法,所以需要借用父类构造方法创建对象。如Bank为一父类。创建子类对象: n e w   B a n k ( ) { 匿 名 类 的 类 体 } new\ Bank()\{匿名类的类体\} new Bank(){}
  4. 匿名类可以继承和重写父类方法。
  5. 匿名对象的引用可以传给匹配的参数,比如:其父类的对象变量。这里可以是: B a n k   b a n k   =   n e w   B a n k ( ) { 匿 名 类 的 类 体 } ; Bank \ bank\ =\ new\ Bank()\{匿名类的类体\}; Bank bank = new Bank(){};
  6. 编译器会给匿名类一个名字。虽然匿名类无名,但是编译器会给匿名类一个类名,可以通过匿名类实例对象的getClass()方法来得到该对象的类名。匿名类的类名格式为外嵌类类名$数字。对于匿名类,其外嵌类即为匿名类体所在的类。
    为了验证第6点,这里给出一段代码:
package chap7;

class ClassOne{
   InnerClass incls;
   ClassOne(){
   	incls = new InnerClass();
   }
   public void speak() {
   	System.out.println("Hello");
   }

   class InnerClass{
   	int height;
   	public void say() {
   		System.out.println("ok");
   	}
   }
}

public class Hidename {

   public static void main(String[] args) {
   	// TODO 自动生成的方法存根
   	ClassOne cls1 = new ClassOne();
   	System.out.println(cls1.getClass());

   	ClassOne cls2 = new ClassOne() {
   		public void speak() {
   			System.out.println("这是第一个匿名类");
   		}
   	};
   	System.out.println(cls2.getClass());

   	ClassOne cls3 = new ClassOne() {
   		public void speak() {
   			System.out.println("这是第二个匿名类");
   		}
   	};
   		
   	System.out.println(cls3.getClass());
   	System.out.println(cls1.incls.getClass());
   }

}

运行结果如下:

class chap7.ClassOne
class chap7.Hidename$1
class chap7.Hidename$2
class chap7.ClassOne$InnerClass
  • 和接口有关的匿名类

j a v a java java允许直接使用接口名类体创建一个匿名对象。假设 C o m p u t a b l e Computable Computable是一个接口:

new Computable(){
    实现接口的匿名类的类体
}

Computable com = new Computale(){
    实现接口的匿名类的类体
}

这里匿名类的类体必须重写接口的全部抽象方法。

  • Lambda表达式代替匿名类


匿名类的实例对象一般作为参数被传递。在本书中,主要用于事件响应。


7.3 异常类

关于异常,此处仅做简单记录。

异常:所谓异常就是程序运行时可能出现的一些错误。

  • 错误:当程序不能正常运行或者运行结果不正确时,表明程序中有错误。按照错误的性质可将程序错误分成3类:语法错逻辑错运行时错误(语义错)

    • 语法错:违反语法规范的错误。一般编译时会被编译器指出。在IDE中一般会在程序编写的过程中指出。

    • 逻辑错:程序可以通过编译并运行。但是运行结果不符合预期。这种错误一般只能通过程序员的经验修改。

    • 运行时错误:也叫做语义错。程序在语法上正确,但是在运行过程中会报错。如:除数为0,数组下标越界,变量赋值超过其数据类型的表示范围等。

      语义错又有两种:

      1. 能够被程序事先处理:比如,除数为0,数组下标越界等,我们可以通过if语句来事先判断。
      2. 不能被程序事先避免的:比如,程序崩溃,网络连接中断,打开文件不存在等。

      语义错还有一种划分方式:

      1. 错误(Error):指程序运行时遇到的硬件或操作系统的错误。如内存溢出、虚拟机错误,系统崩溃等。错误对程序而言是致命性的,导致程序无法运行,只能依靠外界干预。
      2. 异常(Exception):指在硬件和操作系统正常时,程序遇到的运行错,如整数进行除法运算时除数为0,或操作数超出数据范围,或打开一个文件时发现文件不存在,或网络连接中断等。异常对程序非致命,能导致程序终止。但 j a v a java java的异常处理机制可以处理异常,让程序继续运行。

在这里插入图片描述

  • try-catch-finally语句

语法规范:

try{
    运行语句块(包含可能会发生异常的语句)
}
catch(ExceptionSubClass1 e){
    
}
catch(异常类名 异常类对象名){
    
}
finally{
    
}

try语句块中,一旦遇到throw抛出的异常,那么后面的语句都不会执行。

catch子句编写顺序:一旦在try语句块中抛出异常,那么会按照catch子句的编写顺序从上到下依次匹配,如果抛出异常的类型catch子句参数的类型其子类,则异常被该catch子句捕获
因此,异常类的子类应该尽可能的写在父类的前面,否则子类catch代码段将永远不可达。

  • catch子句异常捕获规则:

    1. 捕获异常与catch子句类型相同。
    2. 捕获异常是catch子句类型的子类。
    3. 一个异常被多个catch子句匹配时,按语句顺序匹配第一个。
  • 关于finally
    try-catch语句执行后,程序便会执行finally语句块。不管try是否抛出了异常,finally都会被执行。
    这里有两个特殊情况:

  1. 如果在try-catch语句中执行了return语句,那么finally语句仍然会被执行。注意return出现在try语句块中还是出现在catch语句块中,最后finally都会执行。
  2. 如果在try-catch语句中执行了程序退出代码,即执行了System.out.exit(0);,则不会执行finally子句(当然也包括System.out.exit(0)之后的所有代码)。

自定义异常类

我们可以自己定义异常类,自己定义的异常类继承自其他异常父类。比如Exception等。

同时我们可以指定哪些方法可以跑出哪些异常,这需要使用关键字throws。注意throwsthrow的区别。

throw是在程序中指定抛出一个异常类的对象,这个对象一般被用来捕获。
throws是指定某个方法可以跑出哪些类。比如:

public void fun() throws Exception1,Exception2,Exception3{
    
}

如果一个方法可以跑出多个异常类,这些类之间用逗号分隔开。

断言

语法格式:

assert booleanExpression;
assert booleanExpression:messageException;

booleanExpression为布尔表达式,如果结果为true,则程序继续执行,为false,程序停止。

messageException:为一表达式。当断言结果为false时,程序停止,并输出messageException表达式的值。

  • 启用断言:
java -ea 主类名

这里的-ea参数表示开启断言。

参考资料

[1] java2 实用教程(第六版)(耿祥义 张跃平 主编)

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值