Java 内部类与异常类

目录

[1.Java 内部类](#1.Java 内部类)

[2.Java 匿名类](#2.Java 匿名类)

[1. 匿名类继承一个父类](#1. 匿名类继承一个父类)

[2. 匿名类实现一个接口](#2. 匿名类实现一个接口)

[3.Java 异常类](#3.Java 异常类)

[4.Java 异常的分类](#4.Java 异常的分类)

[1. Throwable类](#1. Throwable类)

[2. Error类](#2. Error类)

[3. Exception类](#3. Exception类)

[5.Java 常见的异常](#5.Java 常见的异常)

[1. NullPointerException(空指针异常)](#1. NullPointerException(空指针异常))

[2. ClassCastException(类转换异常)](#2. ClassCastException(类转换异常))

[3. IndexOutOfBoundsException(数组下标越界异常)](#3. IndexOutOfBoundsException(数组下标越界异常))

[4. IllegalAccessException(访问权限异常)](#4. IllegalAccessException(访问权限异常))

[5. IOException(输入输出异常)](#5. IOException(输入输出异常))

[6.Java 处理异常](#6.Java 处理异常)

1.try...catch

2.try...catch...finally

3.throws

[7.Java 自定义异常类](#7.Java 自定义异常类)

[8.Java 断言语句](#8.Java 断言语句)

1.断言语句的语法格式

2.作用条件

3.启用与关闭断言语句


Java内部类与异常类这一章主要介绍Java内部类、Java匿名类、Java异常类、Java异常的分类、Java常见的异常、Java处理异常1.try...catch、Java处理异常2.try...catch...finally、Java处理异常3.throws、Java自定义异常类、Java try...catch...finally语句里return语句的执行顺序以及Java断言语句。通过以往的学习,我们已经知道,类可以有两种重要的成员:成员变量和方法,实际上,类还有一种成员:内部类。在一个类中定义另一个类,我们把这样的类称作内部类,包含内部类的类称作内部类的外嵌类。

1.Java 内部类

通过以往的学习,我们已经知道,类可以有两种重要的成员:成员变量方法 ,实际上,类还有一种成员:内部类。在一个类中定义另一个类,我们把这样的类称作内部类 ,包含内部类的类称作内部类的外嵌类

内部类和外嵌类之间的关系:

1)内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。

2)内部类的类体中不可以声明类变量和类方法,外嵌类的类体中可以用内部类声明对象作为外嵌类的成员。

3)内部类仅供它的外嵌类使用,其他类不可以用某个类的内部类声明对象。

因为内部类的外嵌类的成员变量在内部类中有效,所以使得内部类和外嵌类的交互十分方便。

例如:

java 复制代码
class RedCowForm {
    static String formName;
    RedCow cow; //内部类声明对象
    RedCowForm() {
    }
    RedCowForm(String s){
        cow = new RedCow(88,66,2000);
        formName = s;
    }
    public void showCowMess() {
        cow.speak();
    }
    class RedCow{ //内部类的声明
        String cowName = "小牛";
        int height,weight,price;
        RedCow(int h,int w,int p) {
            height = h;
            weight = w;
            price = p;
        }
        void speak() {
            System.out.println("我是"+cowName+",身高"+height+"cm,体重"+weight+"kg,生活在"+formName);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        RedCowForm form = new RedCowForm("csdn农场");
        form.showCowMess();
        form.cow.speak();
    }
}

运行结果如下:

java 复制代码
我是小牛,身高88cm,体重66kg,生活在csdn农场
我是小牛,身高88cm,体重66kg,生活在csdn农场

注意 :Java编译器生成的内部类的字节码文件的名字和平常的类的名字不同,内部类对应的字节码文件的名字格式是"**外嵌类名内部类名**"。例如:上面例子中内部类的字节码文件的名字应该是RedCowFormRedCow.class。

内部类可以被修饰为static内部类,static内部类是外嵌类中的一种静态数据类型,程序可以在其他类中使用static内部类来创建对象,但是,static内部类不能操作外嵌类中的实例成员变量。

2.Java 匿名类

上一节我们学习了内部类,这一节我们来学习匿名类。那什么叫做匿名类呢?顾名思义,匿名类就是不能有名字的类,它们不能被引用,只能在创建时用new语句来声明它们。

使用匿名内部类我们必须要继承一个父类或者实现一个接口。

需要注意的是:

  • 匿名内部类中是不能定义构造函数的。
  • 匿名内部类中不能存在任何的静态成员变量和静态方法。
  • 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。

匿名类语法格式如下:

java 复制代码
class outerClass {
    // 定义一个匿名类
    object1 = new Type(parameterList) {
        // 匿名类代码
    };
}

注意:因为匿名类是表达式形式定义的,所以末尾以**分号;**来结束。

1. 匿名类继承一个父类

例如:

java 复制代码
class Dotcpp {
    public void display() {
        System.out.println("在Dotcpp类内部");
    }
}
class AnonymousDemo {
    public void createClass() {
        //创建的匿名类继承了Dotcpp类
        Dotcpp d1 = new Dotcpp() {
            public void display() {
                System.out.println("在匿名类内部");
            }
        };
        d1.display();
    }
}
class Main {
    public static void main(String[] args) {
        AnonymousDemo an = new AnonymousDemo();
        an.createClass();
    }
}

运行结果如下:

java 复制代码
在匿名类内部

2. 匿名类实现一个接口

例如:

java 复制代码
interface Dotcpp {
    public void display();
}
class AnonymousDemo {
    public void createClass() {
        //创建的匿名类实现了Dotcpp接口
        Dotcpp d1 = new Dotcpp() {
            public void display() {
                System.out.println("在匿名类内部");
            }
        };
        d1.display();
    }
}
class Main {
    public static void main(String[] args) {
        AnonymousDemo an = new AnonymousDemo();
        an.createClass();
    }
}

运行结果如下:

java 复制代码
在匿名类内部

3.Java 异常类

什么叫做异常?所谓异常就是程序运行时可能出现的一些错误,比如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误做出处理。所以,这一节我们将初步了解异常。

Java使用throw 关键字抛出一个Exception子类的实例表示异常发生。

例如:java.lang包中的Integer类调用其类方法public static int parseInt(String s)可以将"数字"格式的字符串,比如"123456",转化为int型数据,但是,当试图将字符串"dot123"转换成数字时,代码如下:

java 复制代码
int number = Integer.parseInt("dot123");

方法parseInt()在执行过程中就会使用throw关键字抛出一个NumberFormatException对象,此时也就意味着程序运行出现NumberFormatException异常。

Java允许定义方法时声明该方法调用过程中可能出现的异常,即允许方法调用过程中抛出异常对象,终止当前方法的继续执行。

异常对象可以调用如下方法得到或输出有关异常的信息:

java 复制代码
public String getMessage(); //得到异常的详细信息
public void printStackTrace(); //得到堆栈跟踪输出(企业一般不允许输出此项,可以得到异常的全部信息)
public String toString(); //以文本形式表示以上信息
getCause(); //得到异常原因

4.Java 异常的分类

1. Throwable类

什么是Throwable类?Throwable类就是Java语言中所有错误或异常的超类,是对所有异常进行整合的一个普通类,其作用是提取保存在堆栈中的错误信息。

2. Error类

Error类是Throwable类的子类,包括系统异常、虚拟机异常等用户无法阻止的问题。

3. Exception类

Exception类也是Throwable类的子类,它是程序本身可以处理的异常,分为运行时异常(checked)和非运行时异常(unchecked)。其中运行时异常可处理,也可不处理;非运行时异常必须处理。

运行时异常

运行时异常都是RuntimeException类及其子类异常,比如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。

当出现RuntimeException的时候,我们可以不处理,一般由虚拟机接管。

出现运行时异常后,如果没有捕获处理这个异常(即没有catch),系统会把异常一直往上层抛,一直到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是Exception类的子类,也有一般异常的特点,就是可以被catch块处理。只不过往往我们不对它处理,也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。

如果不想终止,则必须捕获所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据,正常的处理应该是把异常数据舍弃,然后记录日志。不应该因为异常数据的存在而影响下面对正常数据的处理。

非运行时异常

非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。比如:IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,Java编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,都要写一大堆catch块去处理可能的异常。

5.Java 常见的异常

除了上一节提到的运行时异常和非运行时异常,还有很多常见的异常,比如:

算术异常:ArithmeticExecption

空指针异常:NullPointerException

类转换异常:ClassCastException

数组负下标异常:NegativeArrayException

数组下标越界异常:IndexOutOfBoundsException

违背安全原则异常:SecturityException

访问权限异常:IllegalAccessException

文件已结束异常:EOFException

文件未找到异常:FileNotFoundException

字符串转换为数字异常:NumberFormatException

操作数据库异常:SQLException

输入输出异常:IOException

方法未找到异常:NoSuchMethodException

1. NullPointerException(空指针异常)

空指针异常在编程时也经常遇到,该异常的出现意味着"程序遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在调用数组的操作中,一般是刚开始学编程的人常犯的错误,即把数组的初始化和数组元素的初始化混淆了。

数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是空的,所以如果要调用的话,需要对每个元素都进行初始化。

2. ClassCastException(类转换异常)

数据类型转换错误,比如:

String temp="abc";

如果设为int temp就会报错,因为它们类型不一样,但是设为object temp就可以,因为object是它们的父类。

3. IndexOutOfBoundsException(数组下标越界异常)

我们在操作数组的时候经常会遇到这个异常,该异常的意思是"数组下标越界",现在程序中大多都有对数组的操作,因此在调用数组的时候一定要认真检查,看自己调用的下标是不是超出了数组的范围。一般来说,直接用常数当下标调用不太容易出现这样的错误,但用变量当下标调用就容易出现这样的错误,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时候,最好先查看一下数组的长度,以免出现这个异常。

4. IllegalAccessException(访问权限异常)

该异常的解释是"没有访问权限",当应用程序要调用一个类,但当前的方法对该类没有访问权限便会出现该异常,在程序中使用package的情况下要注意这个异常。

5. IOException(输入输出异常)

一般读写文件会出现这个异常,比如你想从磁盘上读一个文件到你写的程序,如果硬盘上没有这文件,Java虚拟机就会报这个异常。

6.Java 处理异常

1.try...catch

我们可以使用try...catch语句来处理异常,将可能出现的异常操作放在try...catch语句的try部分,一旦try部分抛出异常对象,或调用某个可能抛出异常对象的方法,并且该方法抛出了异常对象,那么try部分将立刻结束执行,转向执行相应的catch部分。所以,程序可以将发生异常后的处理放在catch部分。

try...catch语句可以由几个catch组成,分别处理发生的相应异常。

try...catch语句的格式如下:

java 复制代码
try {
    //包含可能发生异常的语句
}
catch(ExceptionSubClass1 e) {
    ...
}
catch(ExceptionSubClass2 e) {
    ...
}

注意:各个catch参数中的异常类都是Exceptin的某个子类,表明try部分可能发生的异常,这些子类之间不能有父子关系,否则只保留一个含有父类参数的catch即可。

2.try...catch...finally

我们处理异常还可以使用try...catch...finally语句,当程序执行到错误代码的地方,系统会抛出一个异常对象,程序转入catch块进行逐个匹配,如果匹配成功,程序则执行catch代码,如果匹配失败,程序则还给Java虚拟机处理。

java 复制代码
try...catch...finally语句的格式如下:
try {
    //包含可能发生异常的语句
}
catch(异常类名 异常对象) {
    //异常处理的代码
}
finally {
    //一定执行的代码
}

注意事项:

  • try块代码尽量越少越好。
  • 一旦try块代码中出现异常,无论try块后面有多少行代码,都不会被执行。
  • catch块中异常参数匹配同样满足多态Exception e = new ArithmeticException("/by zero");
  • try块 只能够有一个,catch 可以有多个,try可以和catch组合,try可以和finally组合,try可以和catch和finally组合。
  • 一般会把Exception作为catch的参数类型放在异常处理格式的最后。
  • Execption作为父类异常参数只能够出现在异常的最后面,先子类后父类。
  • finally修饰的代码块一定会被执行,除非在执行到finally之前程序异常退出或者调用了系统退出的方法。
  • 在try语句中,在执行return语句时,要返回的结果已经准备好了,就在此时,程序转到finally执行了。在转去之前,try中先把要返回的结果存放到不同于x的局部变量中去,执行完finally之后,在从中取出返回结果,因此,即使finally中对变量x进行了改变,但是不会影响返回结果,应该使用栈保存返回值。

3.throws

除了可以使用try...catch语句和try...catch...finally语句处理异常以外,还可以使用throws处理异常。

在开发中,有的时候我们没有权限处理该异常,我们不知道该如何处理异常,或者不想处理异常,这种情况下我们可以将异常抛出,抛出给调用者处理。

throws处理异常的格式:

java 复制代码
[访问权限修饰符] 返回值类型 方法名(参数列表) [throws 异常类名]{
    方法体;
    [return 返回值];
}

注意事项:

1)抛出异常的处理方法千万不能抛出给JVM处理[主方法]。

2)如果一个方法抛出的是一个编译时异常,那么调用者必须处理。

3)如果一个方法抛出的是一个运行时异常,可以处理也可以不处理,建议处理,提高程序的安全性。

4)子类重写的方法声明的异常不能够被扩大。

5)throws表示一种异常发生的可能性,可以声明多个异常类。

throw异常处理方法:

java 复制代码
格式:
throw 异常对象;

注意:我们可以发现其实throw和throws的作用都是将异常抛出给调用者或者虚拟机来处理,但是两者有个根本区别就是throw抛出的是异常对象,而throws声明的是异常类。

throw和throws区别:

1)throw抛出的是异常对象,throws声明的是异常类。

2)throw只能够抛出一个对象,throws可以声明多个异常类。

3)throw表示异常已经发生,throws是一种异常的可能性。

4)throw在方法体内出现,throws在方法的声明上。5

7.Java 自定义异常类

我们要知道,使用Java内置的异常类可以描述在编程时的大部分异常,除此之外,我们在编程时还可以扩展Exception类定义自己的异常类,然后根据程序的需要来规定哪些方法产生这样的异常。

自定义异常类的格式:

java 复制代码
public class 异常类名 extends Exception {
    无参构造
    带参构造
}

例如:

java 复制代码
public class DotcppException extends Exception {
    //无参构造
    public DotcppException() {
    } //带参构造
    public DotcppException(String message) {
        //异常错误消息
        super(message);
    }
}

一个方法在声明时可以使用throws关键字声明要产生的若干个异常,并在该方法的方法体中具体给出产生异常的操作,即用相应的异常类创建对象,并使用throw关键字抛出该异常对象,导致该方法结束执行。程序必须在try-catch块语句中调用可能发生异常的方法,其中catch的作用就是捕获throw关键字抛出的异常对象。

注意:throw是Java的关键字,该关键字的作用就是抛出异常,throw和throws是两个不同的关键字。

总结:

(1)处理运行时异常的时候,采用逻辑去规避的同时辅助try-catch去处理;

(2)在多重catch块的后面,可以加个**catch(Exception)**来处理可能遗漏的异常;

(3)对于不确定的代码,也可以用try-catch处理潜在的异常;

(4)尽量去处理异常,切记只是简单地调用**printStackTrace()**去输出打印;

(5)具体如何去处理异常,要根据不同的业务需求和异常的类型去处理;

(6)尽量添加finally语句去释放占用的资源。

8.Java 断言语句

如果程序不准备通过捕获异常 来处理的错误,这时该怎么办呢?我们可以通过断言语句来解决。

断言语句在调试代码阶段非常有用,且一般用于程序不准备通过捕获异常来处理的错误。

例如:当发生某个错误时,比如,当账号交易时,支出金额为正数或收入金额为负数,此时要求程序必须立即停止执行。在调试代码阶段让断言语句发挥作用,这样就可以发现一些致命的错误,当程序正式运行时就可以关闭断言语句,但仍把断言语句保留在源代码中,如果以后应用程序又需要调试,可以重新启用断言语句。

1.断言语句的语法格式

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

java 复制代码
assert booleanExpression; //求值为boolean类型的表达式
assert booleanExpression:messageException; //求值为字符串类型的表达式

2.作用条件

1)booleanExpression

当值为true时,程序从断言语句处继续执行。

当值为false时,程序从断言语句处停止执行。

2)booleanExpression:messageExpception

当值为true时,程序从断言语句处继续执行。

当值为false时,程序从断言语句处停止执行,并输出messageException表达式的值,提示用户出现了怎样的问题。

例如,对于断言语句:

java 复制代码
assert i >= 0;

如果表达式i >= 0的值为true,程序继续执行;如果表达式i >= 0的值为false,程序立刻结束执行。

3.启用与关闭断言语句

当使用Java解释器直接运行应用程序时,默认地关闭断言语句,在调试程序时可以使用**-ea**启用断言语句,例如:

java 复制代码
java -ea mainclass

例如:

java 复制代码
public class Main {
    public static void main(String[] args) {
        int [] score = {-120,98,96,94,92};
        int sum = 0;
        for(int number:score){ //数组用for遍历
            assert number>=0:"负数不能是成绩";
            sum = sum+number;
        }
        System.out.println("总成绩:"+sum);
    }
}

运行结果如下:

java 复制代码
总成绩:260
相关推荐
重生之绝世牛码1 小时前
Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解
java·大数据·开发语言·设计模式·命令模式·设计原则
晚风_END2 小时前
node.js|浏览器插件|Open-Multiple-URLs的部署和使用,实现一键打开多个URL的强大工具
服务器·开发语言·数据库·node.js·dubbo
java排坑日记3 小时前
poi-tl+kkviewfile实现生成pdf业务报告
java·pdf·word
V+zmm101344 小时前
校园约拍微信小程序设计与实现ssm+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
_周游4 小时前
【C语言】_指针与数组
c语言·开发语言
猿来入此小猿4 小时前
基于SpringBoot小说平台系统功能实现四
java·spring boot·毕业设计·毕业源码·在线小说阅读·在线小说平台·免费学习:猿来入此
SyntaxSage5 小时前
Scala语言的数据库交互
开发语言·后端·golang
疯狂小料5 小时前
Python3刷算法来呀,贪心系列题单
开发语言·python·算法
Cosmoshhhyyy5 小时前
LeetCode:2274. 不含特殊楼层的最大连续楼层数(排序 Java)
java·算法·leetcode
码力全開5 小时前
C 语言奇幻之旅 - 第14篇:C 语言高级主题
服务器·c语言·开发语言·人工智能·算法