Java 内部类和异常类(详细版)
lipiwang 2024-12-01 00:41 5 浏览 0 评论
1 内部类
Java支持在一个类中声明另一个类,这样的类称作内部类,而包含内部类的类成为内部类的外嵌类。
内部类的类体中不可以声明类变量和类方法。外嵌类的类体中可以用内部类声明对象,作为外嵌类的成员。
内部类的使用规则:
(1)声明内部类如同在类中声明方法或变量一样,一个类把内部类看作是自己的成员。
(2)外嵌类的类体中可以用内部类声明的对象,作为外嵌类的成员。
(3)外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。
(4)内部类的类体中不可以声明类变量和方法。
(5)外嵌类和内部类在编译时,生成两个.class文件。
例如:某种类型的农场饲养了一种特殊种类的牛,但不希望其他农场饲养这种特殊种类的牛,那么这种类型的农场就可以将创建这种特殊种牛的类作为自己的内部类。
下面的例子1(Example1.1.java)中有一个RedCowForm(红牛农场)类,该类中有一个名字为RedCow (红牛)的内部类。
RedCowForm.java
public class RedCowForm {
static String formName;
RedCow cow; //内部类声明对象
RedCowForm() {
}
RedCowForm(String s) {
cow = new RedCow(150, 112, 5000);
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);
}
} //内部类结束
}
Example1.1.java
public class Example1_1 {
public static void main(String[] args) {
RedCowForm form = new RedCowForm("红牛农场");
form.showCowMess();
form.cow.speak();
}
}
需要特别注意的是,Java编译器生成的内部类的字节码文件的名字和通常的类不同,内部类对应的字节码文件的名字格式是“外嵌类名$ 内部类名”,例如,例子1中内部类的字节码文件是RedCowForm$RedCow.class。因此,当需要把字节码文件复制给其他开发人员时,不要忘记了内部类的字节码文件。
内部类可以被修饰为static 内部类,例如,例子1中的内部类声明可以是static classRedCow。类是一种数据类型,那么static内部类就是外嵌类中的一-种静 态数据类型,这样一来,程序就可以在其他类中使用static内部类来创建对象了。但需要注意的是,static 内部类不能操作外嵌类中的实例成员变量。
假如将例子1中的内部类RedCow更改成static内部类,就可以在例子1的Example1_ 1
主类的main方法中增加如下的代码。
RedCowForm.RedCow redCow = new RedCowForm.RedCow(180,119,6000);
redCow.speak();
注意:非内部类不可以是static类
2 匿名类
2.1 和子类有关的匿名类
创建子类对象时,除了使用父类的构造方法外还有类体,此类体被认为是一个子类去掉类声明后的类体,称作匿名类。
假设Bank是类,那么下列代码就是用Bank的一个子类(匿名类)创建对象:
new Bank() {
匿名类的类体
};
和子类有关的匿名类:
(1)匿名类是一个子类,由于无名可用,所以不可能用匿名类声明对象,但却可以直接用匿名类创建一个对象。
(2)匿名类可以继承父类的方法也可以重写父类的方法。
(3)使用匿名类时,必然是在某个类中直接用匿名类创建对象,因此,匿名类一定是内部类。
(4)匿名类可以访问外嵌类中的成员变量和方法,匿名类的类体中不可以声明static成员变量和static方法。
(5)由于匿名类是一个子类,但没有类名,所以在用匿名类创建对象时,要直接使用父类的构造方法。
例子2:该类共有4个类: (Example2_1. java)、ShowBoard类、
OutputAlphabet类型、 OutputEnglish. java 。该匿名类的对象负责输出希腊字母表。
OutputAlphabet.java
abstract class OutputAlphabet {
public abstract void output();
}
OutputAlphabet .java
public class OutputEnglish extends OutputAlphabet { //输出英文字母子类
public void output(){
for (char c='a';c<='z';c++){
System.out.printf("%3c",c);
}
}
}
ShowBoard .java
public class ShowBoard {
void showMess(OutputAlphabet show) { //参数show是OutputAlphabet类型的对象
show.output();
}
}
Example2_1.java
public class Example2_1 {
public static void main(String[] args) {
ShowBoard board = new ShowBoard();
board.showMess(new OutputEnglish());//向参数传递OutputAlphabet的子类OutputEnglish的对象
board.showMess(new OutputAlphabet() { //向参数传递OutputAlphabet的匿名子类的对象
@Override
public void output() {
for (char c = 'α'; c <= 'ω'; c++) //输出希腊字母
System.out.printf("%3c", c);
}
});//分号在这里
}
}
2.2 和接口有关的匿名类
和接口有关的匿名类
假设Computable是一个接口,那么,Java允许直接用接口名和一个类体创建一个匿名对象,此类体被认为是实现了Computable接口的类去掉类声明后的类体,称作匿名类。
下列代码就是用实现了Computable接口的类(匿名类)创建对象:
new Computable(){
实现接口的匿名类的类体
};
下面例子演示了和接口有关的匿名类的用法:
interface SpeakHello {
void speak();
}
class HelloMachine {
public void turnOn(SpeakHello hello) {
hello.speak();
}
}
public class Example7_3 {
public static void main(String[] args) {
HelloMachine machine = new HelloMachine();
machine.turnOn(new SpeakHello() {
@Override
public void speak() {
System.out.println("hello,you are welcome!");
}
});
machine.turnOn(new SpeakHello() {
@Override
public void speak() {
System.out.println("你好,欢迎光临!");
}
});
}
}
3 异常类
所谓异常就是程序运行时可能出现一些错误,比如试图打开一个根本不存在的文件等,异常处理将会改变程序的控制流程,让程序有机会对错误作出处理。程序运行出现异常时,Java运行环境就用异常类Exception的相应子类创建一个异常对象,并等待处理。异常对象可以调用如下方法得到或输出有关异常的信息:
异常对象可以调用如下方法得到或输出有关异常的信息:
public String getMessage();
public void printStackTrace();
public String toString();
3.1 try-catch语句
Java使用try-catch语句来处理异常,将可能出现的异常操作放在try-catch语句的try部分,将发生异常后的处理放在catch部分。
try-catch语句的格式如下:
try{
包含可能发生异常的语句
}
catch(ExceptionSubClass1 e){
...
}
catch(ExceptionSubClass2 e){
...
}
下面一个例子给出了try-catch语句的用法:
public class Example3_1 {
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);
try {
System.out.println("故意抛出I/O异常!");
throw new java.io.IOException("我是故意的");
//System.out.println("这个输出语句肯定没有机会执行,所以必须注释掉,否则编译出错");
} catch (java.io.IOException e) {
System.out.println("发生异常:" + e.getMessage());
}
}
}
带finally子语句的try~catch语句,语法格式如下:
try{ }
catch(ExceptionSubClass e){ }
finally{}
其执行机制是在执行try~catch语句后,执行finally 子语句,也就是说,无论在try部分是否发生过异常,finally 子语句都会被执行
3.2 自定义异常类
(1)异常的声明
?一个方法不处理它产生的异常,而是沿着调用层次向上传递,由调用它的方法来处理这些异常,叫声明异常.
?声明异常的方法:
在产生异常的方法名后面加上要抛出(throws)的异常的列表:
如: void compute(int x) throwsAri thmeticException
{//这里有异常发生,但是并没有处理…}
(2)我们也可以扩展Exception类定义自己的异常类,然后规定哪些方法产生这样的异常。一个方法在声明时可以使用throws关键字声明要产生的若干个异常,并在该方法的方法体中具体给出产生异常的操
作,即用相应的异常类创建对象,并使用throw关键字抛出该异常对象,导致该方法结束执行。
(3)通常情况下,计算两个整数之和的方法不应当有任何异常放出,但是,对某些特殊应程序,可能不允许同号的整数做求和运算,比如当一个整数代表收入,一个整数代表支出时,这两个整数就不能是同号。
例子 (Example3_2. java)中,Bank类中有一个income(int in, int out)方法,对象调用该方法时,必须向参数in传递正整数、向参数out传递负数,并且int+out必须大于等于0,否则该方法就抛出异常( BankException. java )。因此,Bank类在声明income(int in, int out)方法时,使用throws关键字声明要产生的异常。
BankException.java
public class BankException extends Exception {
String message;
public BankException(int m, int n) {
message = "入账资金" + m + "是负数或支出" + n + "是正数,不符合系统要求.";
}
public String warnMess() {
return message;
}
}
Bank.java
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;
}
}
Example3_2.java
public class Example3_2 {
public static void main(String[] args) {
Bank bank = new Bank();
try {
bank.income(200, -100);
bank.income(300, -100);
bank.income(400, -100);
System.out.printf("银行目前有%d元\n", bank.getMoney());
bank.income(200, 100);
bank.income(99999, -100);
} catch (BankException e) {
System.out.println("计算收益的过程出现如下问题:");
System.out.println(e.warnMess());
}
System.out.printf("银行目前有%d元\n", bank.getMoney());
}
}
4 断言
?断言语句用于调试代码阶段。在调试代码阶段让断言语句发挥作用,这样就可以发现一些致命的错误,当程序正式运行时就可以关闭断言语句,但仍把断言语句保留在源代码中,如果以后应用程又需要调试,可以重新启用断言语句。
?使用关键字assert声明一条断言语句,断言语句有以下两种格式:
assert booleanExpression;
assert booleanExpression:messagelException;
?启用与关闭断言语句
当使用Java解释器直接运行应用程序时,默认地关闭断言语句,在调试程序时可以使用-ea启用断言语句,例如:
java -ea mainClass
例子4中,使用一个数组放着某学生5门课程的成绩,程序准备计算学生的成绩的总和。在调试程序时使用了断言语句,如果发现成绩有负数,程序立刻结束执行。程序调试开启断言语句运行效果如图4.1,关闭断言语句运行效果如图4.2。
import java.util.Scanner;
public class Example4 {
public static void main (String args[ ]) {
int [] score={-120,98,89,120,99};
int sum=0;
for(int number:score) {
assert number>0:"负数不能是成绩";
sum=sum+number;
}
System.out.println("总成绩:"+sum);
}
}
图4.1
图4.2
5 综合案例
下面的例子5中模拟向货船上装载集装箱,如果货船超重,那么货船认为这是一个异常将拒绝装载集装箱,但无论是否发生异常,货船都需要正点启航
DangerException.java
public class DangerException extends Exception {
final String message = "超重";
public String warnMess() {
return message;
}
}
CargoBoat.java
public class CargoBoat {
int realContent; //装载的重量
int maxContent; //最大装载量
public void setMaxContent(int c) {
maxContent = c;
}
public void loading(int m) throws DangerException {
realContent += m;
if(realContent>maxContent) {
throw new DangerException();
}
System.out.println("目前装载了"+realContent+"吨货物");
}
}
Example5.java
public class Example5 {
public static void main(String[] args) {
CargoBoat ship = new CargoBoat();
ship.setMaxContent(1000);
int m =600;
try{
ship.loading(m);
m = 400;
ship.loading(m);
m = 367;
ship.loading(m);
m = 555;
ship.loading(m);
}
catch(DangerException e) {
System.out.println(e.warnMess());
System.out.println("无法再装载重量是"+m+"吨的集装箱");
}
finally {
System.out.printf("货船将正点启航");
}
}
}
相关推荐
- Qwen上新AI前端工程师!一句话搞定HTML/CSS/JS,秒变React大神
-
梦晨发自凹非寺量子位|公众号QbitAIQwen上新“AI前端工程师”WebDev,一句话开发网页应用。三大件HTML,CSS,JavaScript一个工具全包了,定睛一看用的还是Reac...
- 程序员的 JavaScript 代码该如何让计算机搞懂?
-
出自程序员之手的JavaScript代码,该如何变成计算机所能理解的机器语言呢?本文将带你走进JavaScript引擎内部,一探究竟。作者|LydiaHallie译者|弯月,责编|...
- JavaScript:如何优雅的创建数组?
-
在JavaScript里,有多种方式可以创建数组,下面为你详细介绍:1.使用数组字面量这是最常用的创建数组的方法,使用方括号[]来创建数组。//创建一个空数组letemptyArray...
- Jquery 详细用法
-
1、jQuery介绍(1)jQuery是什么?是一个js框架,其主要思想是利用jQuery提供的选择器查找要操作的节点,然后将找到的节点封装成一个jQuery对象。封装成jQuery对象的目的有...
- HTML页面基本结构和加载过程
-
大家好,我是皮皮。前言对于前端来说,HTML都是最基础的内容。今天,我们来了解一下HTML和网页有什么关系,以及与DOM有什么不同。通过本讲内容,你将掌握浏览器是怎么处理HTML内容的,...
- 【HarmonyOS Next之旅】兼容JS的类Web开发(一)
-
目录1->概述1.1->整体架构2->文件组织2.1->目录结构2.2->文件访问规则2.3->媒体文件格式3->js标签配置3....
- JavaScript初学者指南
-
如果你刚接触JavaScript,想必已经被“modulebundlersvs.moduleloaders”、“Webpackvs.Browserify”和“AMDvs.Common...
- 前端图片延迟加载详细讲解
-
原文链接:http://www.gbtags.com/gb/share/6366.htm?原本是打算昨天昨天下午的时候就写一篇关于前端图片延迟加载的详细技术的博客的,没想到下午公司项目出现了一些问题...
- selenium:操作滚动条的方法(8)
-
selenium支持几种操作滚动条的方法,主要介绍如下:使用ActionChains类模拟鼠标滚轮操作使用函数ActionChains.send_keys发送按键Keys.PAGE_DOWN往下滑动...
- jQuery 获取和设置HTML元素
-
jQuery中包含更改和操作HTML元素和属性的强大方法。我们可以通过这些方法来获取HTML元素中的文本内容、元素内容(例如HTML标签)、属性值等。text()方法text()方法可以用...
- JavaScript脚本如何断言select下拉框的元素内容?
-
使用JavaScript脚本断言select下拉框的元素内容,需要考虑页面元素是否加载成功,出错时打印等,主要实现功能功能需包括如下几点:1.等待下拉框元素加载完成(支持超时设置)2.获取下...
- JavaScript图片或者div拖动拖动函数的实现
-
/**拖动图片封装html格式:<imglay-src="${item.Resourcesurl}"alt="${item.ResourcesName}"...
- JavaScript代码怎样引入到HTML中?
-
JavaScript程序不能独立运行,它需要被嵌入HTML中,然后浏览器才能执行JavaScript代码。通过<script>标签将JavaScript代码引入到HTM...
- 当你在Vue.js中想要隐藏 `` 标签时,可以这样做:
-
在Vue.js里,要是你想要搞掉`<br>`(换行)标签的效果,通常有几种路子:1.使用CSS嗯,最简单的办法就是用CSS搞定,控制元素的样式,让<br>标签彻底不显示...
- php手把手教你做网站(三十)上传图片生成缩略图
-
三种方法:按比例缩小、图片裁切、预览图片裁切不管使用哪一个都是建立在图片已经上传的基础上;预览裁切上传,如果预览的图片就是原始大小,可以预览裁切以后上传(这里是个假象,下边会说明);1、上传以后按比例...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- maven镜像 (69)
- undefined reference to (60)
- zip格式 (63)
- oracle over (62)
- date_format函数用法 (67)
- 在线代理服务器 (60)
- shell 字符串比较 (74)
- x509证书 (61)
- localhost (65)
- java.awt.headless (66)
- syn_sent (64)
- settings.xml (59)
- 弹出窗口 (56)
- applicationcontextaware (72)
- my.cnf (73)
- httpsession (62)
- pkcs7 (62)
- session cookie (63)
- java 生成uuid (58)
- could not initialize class (58)
- beanpropertyrowmapper (58)
- word空格下划线不显示 (73)
- jar文件 (60)
- jsp内置对象 (58)
- makefile编写规则 (58)