Java基础笔记七

一、内部类

1.定义:Java支持在一个类中声明另一个类,这样的类称作内部类,包含此类的类叫外部类。

2.例如:

  1.  class Circle {
     //    外嵌类
         double radius = 0;//成员变量
     
         public Circle(double radius) {//构造方法
             this.radius = radius;
         }
         class Draw {
     //        内部类
             public void drawShape() {
                 System.out.println("drawshape");
             }
         }
     }
    
  • 声明内部类如同在类中声明方法或变量一样,一个类把内部类看作是自己的成员(称作成员类)
  • 内部类的类体中不可以声明类变量和类方法(即不能使用static声明变量和方法)
  • 外嵌类的类体中可以用内部类声明的对象,作为外嵌类的成员。
  • 外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。
  • 外嵌类和内部类在编译时,生成两个.class文件。

3.重名成员变量的访问方法

内部类与外嵌类中成员变量重名时:

  • 如需在内部类方法中访问内部类的重名成员变量,使用 this 关键字,例:

System.out.println(this.name);

  • 如需在内部类方法中访问外部类的重名成员变量,使用外部类名加 this 关键字,例如:

System.out.println(Outer.this.name);

4.分类

内部类可以分四种,分别是:

  1. 静态内部类
  2. 普通(成员)内部类
  3. 局部(方法)内部类
  4. 匿名内部类
public class Demo {    

    private static class StaticNestedClass {
    }    //1,静态内部类

    private class FieldInnerClass {
    }   //2,普通内部类(成员内部类)

    void Hello() {
        
        class LocalClass { 
        }//3,方法内部类
        
        
        Runnable runnable = new Runnable() {
            public void run() {
            }// 4,匿名内部类 
        };
    }
}

二、匿名类

  • 匿名类没有定义类的名称。是一种内部类。

  • 匿名内部类适合创建那种只需要使用一次的类。

1.与子类有关的匿名类:继承父类的匿名内部类

​ Java允许我们直接使用一个类的子类的类体创建一个子类对象。(子类这时只有类体,没有类名,所以是匿名类。)

​ 除了可以使用父类的构造方法创建子类对象,还可以使用类体创建子类对象,此类体被认为是一个子类去掉类声明后的类体,称作匿名类。

new Bank () {
	匿名类的类体
};

2.与接口有关的匿名类:实现接口的匿名内部类

假设Computable是一个接口,那么,Java允许直接用接口名和一个类体创建一个匿名对象,此类体被认为是实现了Computable接口的类去掉类声明后的类体,称作匿名类。

下列代码就是用实现了Computable接口的类(匿名类)创建对象:

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

只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现。

三、异常类

在程序运行的过程中,会发生各种非正常状况,

比如程序运行时磁盘空间不足、网络连接中断、被装载的类不存在等。

针对这种情况,在Java语言中,引入了异常,以异常类的形式对这些非正常情况进行封装,通过异常处理机制对程序运行时发生的各种问题进行处理。

Java提供了大量的异常类,这些类都继承自java.lang.Throwable类。

Error****类称为错误类,它表示Java运行时产生的系统内部错误或资源耗尽的错误,是比较严重的,仅靠修改程序本身是不能恢复执行的。

  • 例如:使用java命令去运行一个不存在的类就会出现Error错误。

Exception****类称为异常类,它表示程序本身可以处理的错误,在开发Java程序中进行的异常处理,都是针对Exception类及其子类。

  • 在Exception类的众多子类中有一个特殊的RuntimeException类,该类及其子类用于表示运行时异常,除了此类,Exception类下所有其他的子类都用于表示编译时异常。

Java对异常处理的机制:

  1. 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。

  2. 运行时异常: 运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。

  3. 错误: 错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。

Throwable类中的常用方法

方法声明 功能描述
String getMessage() 返回异常的消息字符串
String toString() 返回异常的简单信息描述
void printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置,把信息输出在控制台。

异常捕获

  • 如果程序的执行过程中出现异常,系统会将异常的信息封装成一个异常对象,该异常对象将被提交给Java虚拟机,这个过程称为抛出(throw)异常。

  • 当Java虚拟机接收到异常对象后,会寻找能处理这一异常的代码并把当前异常对象交给其处理,这一过程称为捕获(catch)异常。

  • 使用try和catch关键字组合可以捕获异常。

  • 如果程序中没有可以捕获异常的代码,出现异常时程序运行将终止。

对异常的处理的两种方式

  1. 在方法内使用try-catch语句来处理方法本身所产生的异常。

    try{
    	//可能发生异常的程序代码块
    }
    catch ( ExceptionType e ) {  // ExceptionType为Exception类及其子类
    	//针对异常进行处理的代码
    } 
    

    • 当try代码块中的程序发生了异常,系统会将异常的信息封装成一个异常对象,并将这个对象传递给catch代码块进行处理。

    • catch代码块需要一个参数指明它所能够接收的异常类型,这个参数的类型必须是Exception类或其子类

    • 需要注意的是,在try代码块中,发生异常语句后面的代码是不会被执行

public class Example7_5 {
    public static void main(String[] args) {
        int n = 0, m = 0, t = 1000;
        try {
            m = Integer.parseInt("8888");
            n = Integer.parseInt("ab89"); //发生异常,转向catch
            t = 7777;  //t没有机会被赋值
        } catch (NumberFormatException e) {
            System.out.println("发生异常:" + e.getMessage());
        }
        System.out.println("n=" + n + ",m=" + m + ",t=" + t);
    }
}
发生异常:For input string: "ab89"
n=0,m=8888,t=1000
  1. 如果不想在当前方法中使用try-catch语句来处理异常,也可以由程序自己来抛出异常:
  • 在方法内部使用throw语句

  • 在方法声明的头部使用throws

为了使代码更加规范以便于协同工作效率的提升,可以在代码中手动使用throw关键字抛出一个异常对象。手动抛出的异常对象与Java虚拟机自动抛出的异常对象相同。

public class Example7_5 {
    public static void main(String[] args) {
        try {
            System.out.println("故意抛出I/O异常!");
            throw new java.io.IOException("我是故意的");
            //System.out.println("不会执行到,所以必须注释掉,否则编译出错");
        } catch (java.io.IOException e) {
            System.out.println("发生异常:" + e.getMessage());
        }
    }
}

自定义异常

Java中允许用户自定义异常,编写自定义异常类时需要注意以下几点:

  • 所有异常都必须是Throwable的子类

  • 如果希望写一个检查性异常类,需要继承Exception类

  • 如果希望写一个运行时异常类,需要继承RuntimeException类

格式:

class MyException extends Exception{
	//程序代码
}

例如:

class WrongInputException extends Exception {
    // 自定义的异常类    
    WrongInputException(String s) {
        super(s);
    }
}

class Input {
    void method() throws WrongInputException {
        throw new WrongInputException("Wrong input"); // 抛出自定义的类
    }
}

class A {
    public static void main(String[] args) {
        try {  //if(…….)                
            new Input().method();    // 在try语句中调用抛出异常方法           
        } catch (WrongInputException wie) {// 在catch中捕捉自定义的异常类                
            System.out.println(wie.getMessage());
        }
    }
}

使用throws抛出异常:

先定义一个异常类:

public class BankException extends Exception {
    String message;

    public BankException(int m, int n) {
        message = "入账资金" + m + "是负数或支出" + n + "是正数,不符合系统要求.";
    }

    public String warnMess() {
        return message;
    }
} 

使用throws抛出异常:

public class Bank {
    private int money;

    public void income(int in, int out) throws BankException {
        if (in <= 0 || out >= 0 || in + out <= 0) {
            throw new BankException(in, out); //方法抛出异常,导致方法结束
        }
        int netIncome = in + out;
        System.out.printf("本次计算出的纯收入是:%d元\n", netIncome);
        money = money + netIncome;
    }

    public int getMoney() {
        return money;
    }
}

finally语句

在程序中,有时候会希望有些语句无论程序是否发生异常都要执行,这时就可以在try…catch语句后,加一个finally代码块。

try{
//可能发生异常的程序代码块
        }catch(ExceptionType(Exception类及其子类)e){
//针对异常进行处理的代码
        }finally{
//无论是否发生异常都要执行的代码
        }

也就是说不论程序是发生异常还是使用return语句结束,finally中的语句都会执行。因此,在程序设计时,通常会使用finally代码块处理完成必须做的事情,如释放系统资源。

finally中的代码块在一种情况下是不会执行的,那就是在try...catch中执行了System.exit(0)语句。System.exit(0)表示退出当前的Java虚拟机,Java虚拟机停止了,任何代码都不能再执行了。

异常小结:

  1. 异常类可分为两大类,分别为java.lang.Exception与java.lang.Error类。

  2. 程序代码没有编写处理异常时,Java语言的默认异常处理机制是:

    (1)抛出异常;(2)停止程序的执行。

  3. 当异常发生时,有两种处理方式:

    (1)交由Java语言默认的异常处理机制做处理;

    (2)自行编写try-catch-finally语句块来捕获异常。

  4. try语句块若有异常发生时,程序的运行便会中断,抛出“由异常类所产生的对象”,并按下列步骤来运行:

    (1)抛出的对象如果属catch()括号内所欲捕获的异常类,catch会捕获此异常,然后进到catch语句块内继续运行;

    (2)无论try语句块是否捕获到异常,或者捕获到的异常是否与catch()括号里的异常类相匹配,最后一定会运行finally语句块里的程序代码;

    (3)finally块运行结束后,程序转到try-catch-finally语句之后的语句继续运行。

  5. RuntimeException不编写异常处理的程序代码,仍然可以编译成功,它是在程序运行时才有可能发生;而IOException一定要进行捕获处理才可以,它通常用来处理与输入输出有关的操作。

  6. catch()括号内只接收由Throwable类的子类所产生的对象,其他的类均不接收。

  7. 抛出异常有下列两种方式:(1)系统自动抛出异常;(2)指定方法抛出异常。

  8. 方法中没有使用try-catch语句来处理异常,可在方法声明的头部使用throws语句或在方法内部使用throw语句将它送往上一层调用机构去处理。即如果一个方法可能会抛出异常,则可将处理此异常的try-catch-finally语句写在调用此方法的程序块内。

四、断言

断言语句用于调试代码阶段。在调试代码阶段让断言语句发挥作用,这样就可以发现一些致命的错误,当程序正式运行时就可以关闭断言语句,但仍把断言语句保留在源代码中,如果以后应用程又需要调试,可以重新启用断言语句。

使用关键字assert声明一条断言语句,断言语句有以下两种格式:

assert <boolean表达式>    

​ 如果<boolean表达式>为true,则程序继续执行。

​ 如果为false,则程序抛出AssertionError,并终止执行。

assert <boolean表达式> : <错误信息表达式>    

​ 如果<boolean表达式>为true,则程序继续执行。

​ 如果为false,则程序抛出java.lang.AssertionError,并输入<错误信息表达式>。

posted @ 2024-03-24 20:21  YJQING  阅读(10)  评论(0)    收藏  举报