【java进阶08:异常】finally关键字、自定义异常类、用户业务作业、军队武器作业
-
java中的异常处理机制
-
异常在java中以类和对象的形式存在,那么异常的继承结构是怎样的?我们可以使用UML图来描述以下继承结构
画UML图的工具:Rational Rose、starUML等
Object下有Throwable(可抛出的)
Throwable下有两个分支:Error(不可处理,直接退出JVM)和Exception(可处理的)
Exception下有两个分支:
Exception的直接子类:编译时异常。(要求程序员在编写程序阶段必须预先对这些异常进行处理,如果不处理编译器报错,因此得名编译时异常)
RuntimeException:运行时异常。(在编写程序阶段程序员可以预先处理,也可以不管)
-
编译时异常和运行时异常,都是发生在运行阶段,编译阶段异常是不会发生的。编译时异常因为什么而得名?
因为编译时异常必须在编译(编写 )阶段预先处理,如果不处理编译器报错,因此得名。 所有异常都是在运行时发生的。因为只有程序运行阶段才可以new对象。
因为异常的发生就是new对象
-
编译时异常和运行时异常有什么区别?
-
编译时异常一般发生的概率较高。如:
你看到外面下雨了,倾盆大雨。出门前会预料:如果不打伞,很可能会生病(生病是一种异常)。而且这个异常发生的概率很高,所以我们出门前要那一把伞。“拿一把伞”就是对“生病异常”发生之前的一种处理方式。
对于一些发生概率较高的异常,需要再运行之前对其进行预处理。
-
运行时异常一般发生的概率较低。如:
小明走在大街上,可能会被天上的飞机轮子砸到。被飞机轮子砸到也算是一种异常。但是这种异常发生概率较低。再出门值卡吗你没必要提前对这种发生概率较低的异常进行预处理。如果预处理这种异常,将“活的很累”。
假设你在出门之前,把能够发生的异常都预先处理,你这个人会更加的安全,但是你这个人会活得很累。
假设java中没有对异常进行划分,没有分为编译时异常和运行时异常,所有的异常都需要在编写程序阶段对其进行预处理,将是怎样的效果?
首先,如果这样,程序肯定是绝对的安全的。但是程序员编写程序太累,到处都是处理异常的代码。
-
-
编译时异常还有其他名字:
- 受检异常:CheckedException
- 受控异常
-
运行时异常还有其他名字:
- 未受检异常:UnCheckedException
- 非受控异常
-
再次强调:所有异常都是发生在运行阶段的。
-
java语言中对异常的处理包括两种方式:
-
第一种方式:在方法生命的位置上,使用throws关键字,抛给上一级。
谁调用我,就抛给谁。抛给上一级。
-
第二种方式:使用try…catch语句进行异常的捕捉。
这件事发生了,谁也不知道,因为我抓住了
如:
我是某集团的一个销售员,因为我的失误,导致公司损失了1000元,”损失1000元“这就可以看作是一个异常发生了。我有两种处理方式。
第一种方式:我把这件事告诉我的领导【异常上抛】
第二种方式:我自己掏腰包把这个钱补上了。【异常的捕捉】
张三 - - - -> 李四 - - - - > 王五 - - - - > CEO
思考:
异常发生之后,如果我选择了上抛,抛给了我的调用者,调用者需要对这个异常继续处理,那么调用者处理这个异常同样有两种处理方式。
-
-
注意:java中异常发生之后如果一直上抛,最终抛给了main方法,main方法继续上抛,抛给了调用者JVM,JVM知道这个异常发生,只有一个结果:终止java程序的执行。
-
-
什么是UML?有什么用?
UML是一种统一建模语言。一种图标式语言(画图的)。
UML不是只有java中使用。只要是面向对象的编程语言,都有UML。一般画UML图的都是软件架构师或者是系统分析师,这些级别的人使用的。软件设计人员使用UML。
在UML图中可以描述类和类之间的关系、程序执行的流程、对象的状态等。
盖大楼和软件开发一样,一个道理。
盖大楼前,建筑师先画图纸。图纸上的一个一个符号都是标准符号,这个图纸画完,只要是搞建筑的都能看懂,因为这个图纸上标注的这些符号都是一种“标准语言”
在java软件开发中,软件分析师/设计师负责设计类,java软件开发人员必须要能看懂。
-
异常的继承结构图
-
什么是异常,java提供异常处理机制有什么用?
/*1、什么是异常,java提供异常处理机制有什么用?以下程序执行过程中发生了不正常的情况,而这种不正常的情况叫做:异常。java是很完善的语言,提供了异常的处理方式,以下程序执行过程中出现了不正常的情况,java把该异常信息供程序员参考。程序员看到异常信息之后,可以对程序进行修改,让程序更加的健壮。什么是异常:程序执行过程中的不正常情况异常的作用:增强程序的健壮性。2、以下程序执行控制台出现了:Exception in thread "main" java.lang.ArithmeticException: / by zeroat ExceptionText01.main(ExceptionText01.java:11)这个信息别我们成为:异常信息,这个信息是JVM打印的。*/ public class ExceptionText01 {public static void main(String[] args) {int a = 10;int b = 0;int c = a / b; //实际上JVM在执行到此处的时候,会new对象:new ArithmeticException("/ by zero");//并且JVM将new的异常对象抛出,打印输出信息到控制台了System.out.println(a+"/"+b+"="+c);//此处运行也会创建一个:ArithmeticException类型的异常对象//System.out.println(100/0);//观察到异常信息之后,对程序进行修改,更加健壮。 /* int a = 10;int b = 2;if(b == 0){System.out.println("除数不能为0");return;}//程序执行到此处表示除数一定不是0int c = a / b;System.out.println(a+"/"+b+"="+c);*/} }
-
java中异常是以什么形式存在的?
/*java语言中异常是以什么形式存在的呢?1、异常在java中以类的形式存在,每一个异常类都可以创建异常对象。2、异常在对应的现实生活这是怎样的?火灾(异常类):2008年8月8日 小明家着火了(异常对象)2008年8月9日 小刚家着火了(异常对象)2008年9月8日 小红家着火了(异常对象)类是: 模板对象是:实际存在的个体钱包丢了(异常类):2008年1月1日,小明的钱包丢了(异常对象)2008年1月9日,小芳的钱包丢了(异常对象)......*/ public class ExceptionText02 {public static void main(String[] args) {//通过异常类“实例化”异常对象NumberFormatException nfe = new NumberFormatException("数字格式化异常");System.out.println(nfe);//java.lang.NumberFormatException: 数字格式化异常//通过异常类“实例化”异常对象NullPointerException npe = new NullPointerException("空指针发生了");System.out.println(npe.toString());//java.lang.NullPointerException: 空指针发生了} }
-
运行时异常编写程序时可以不处理
//运行时异常编写程序时可以不处理 public class ExceptionText03 {public static void main(String[] args) {/*程序执行到此处发生了ArithmeticException异常,底层new了一个ArithmeticException异常对象,然后抛出了由于是main方法调用了100/0,所以这个异常ArithmeticException抛给了main方法,main方法没有处理将这个异常自动抛给了JVM。JVM最终终止程序的执行。ArithmeticException 继承 RuntimeException ,属于运行时异常。在编写阶段不需要对这种异常进行预先的处理。*/System.out.println(100/0);//这里的hello world 没有输出,没有执行。System.out.println("hello world");} }
-
编译时异常必须处理
/*以下代码报错的原因是什么?因为doSome()方法声明位置上使用了:throws ClassNotFoundException而ClassNotFoundException是编译时异常。必须编写代码时处理,如不处理,编译报错*/ public class ExceptionText04 {public static void main(String[] args) {//main方法中调用doSome()方法。因为doSome()方法声明位置上有:throws ClassNotFoundException//我们在调用doSome()方法的时候必须对这种异常进行预先的处理。// 如果不处理,编译器报错.报错信息:Unhandled exception: java.lang.ClassNotFoundException//doSome();}/*** doSome方法在方法声明的位置上使用了:throws ClassNotFoundException* 这个代码表示doSome()方法在执行过程中,有可能会出现ClassNotFoundException异常* 叫做:类没找到异常。这个异常直接父类是:Exception,所以ClassNotFoundException属于编译时异常。* @throws ClassNotFoundException*/public static void doSome() throws ClassNotFoundException{System.out.println("doSome!!!!");} }
-
异常的处理方式有两种
public class ExceptionText05 {//第一种处理方式:在方法声明的位置上继续使用:throws,来完成异常的继续上抛。抛给调用者//上抛类似于推卸责任。(继续把异常传递给调用者) /* public static void main(String[] args) throws ClassNotFoundException {doSome();}*///第二种处理方式:try..catch进行捕捉//捕捉等于把异常拦下了,异常真正解决了!(调用者是不知道的)public static void main(String[] args) {try{doSome();}catch (ClassNotFoundException e){e.printStackTrace();}}public static void doSome() throws ClassNotFoundException{System.out.println("doSome!!!!");} }
注意事项
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;/*处理异常的第一种方式:在方法声明的位置上使用throws关键字抛出,谁调用这个方法,我就抛给谁。抛给调用者来处理。在方法声明的位置上使用throws关键字抛出,谁调用我这个方法,我就抛给谁,抛给调用者来处理.这种处理异常的态度:上报.处理异常的第二种方式:使用try..catch语句对异常进行捕捉,这个异常不会上报,自己把这个事情解决了。异常抛出到此为止,不再上抛了。注意:只要异常没有捕捉,采用上抛的方式,此方法的后续代码不会执行另外需要注意:try语句块中的某一行出现异常,后面的代码不会执行try..catch捕捉异常之后,后续的代码可以执行.在以后的开发中,处理编译时异常,应该上抛还是应该捕捉呢?如果希望调用者来处理,选择throws上抛。其他情况使用捕捉的方式*/ public class ExceptionText06 {/*一般不建议在main方法上使用throws,因为这个异常如果真的发生了,一定会抛给JVM,JVM只有终止异常处理机制的作用是增强程序的健壮性。怎么能做到,异常发生了也不会影响程序的执行。所以一般main方法中的异常建议使用try..catch进行捕捉。main就不要继续上抛了。*/// public static void main(String[] args) throws FileNotFoundException {public static void main(String[] args) {//100/0是算术异常,这个异常是运行时异常,你在编译阶段,可以处理,也可以不处理。编译器不管//System.out.println(100/0);//不处理编译器也不管//处理以下也可以 /* try{System.out.println(100/0);}catch(ArithmeticException e){System.out.println("算术异常了!!!");}*/System.out.println("main begin");try {//try 尝试m1();//以上代码出现异常,直接进入catch语句进行捕捉System.out.println("helloworld");} catch (FileNotFoundException e) {//catch后面的好像一个形参//这个分支中可以使用e引用,e引用保存的的内存地址是那个new出的异常对象的内存地址.//catch是捕捉异常之后走的分支。//在catch分支中干什么?处理异常System.out.println("文件不存在,可能路径错误,也可能该文件被删除了");System.out.println(e.toString());}//try..catch把异常抓住之后,这里的代码会继续执行System.out.println("main over");}public static void m1() throws FileNotFoundException {System.out.println("m1 begin");m2();//以上代码出现异常,这里也不会执行.System.out.println("m1 over");}// private static void m2() throws ClassCastException {// 抛别的不行,抛ClassCastException说明你还是没有对FileNotFoundException进行处理// private static void m2() throws IOException {//抛FIleNotFoundException的父对象IOException,这样是可以的,因为IOException包括FileNotFoundException// private static void m2() throws Exception {//这样也可以,因为Exception包括所有的异常.// private static void m2() throws ClassCastException,FileNotFoundException {//throws也可以写多个异常,可以使用逗号隔开private static void m2() throws FileNotFoundException {System.out.println("m2 begin");//编译报错的原因是:m3()方法声明位置上有:throws FileNotFoundException//我们在这里调用m3()方法没有对异常进行预处理,所以编译报错m3();//以上如果出现异常,下面的代码是不会执行的System.out.println("m2 over");}private static void m3() throws FileNotFoundException {//调用SUN jdk中的某个类的构造方法//这个类还没接触过,后期IO流的时候就知道了。我们只是借助这个类学习一下异常处理机制。//创建一个输入流对象,该流指向一个文件。/*编译报错的原因是什么?第一:这里调用了一个构造方法:FileInputStream(String name)第二:这个构造方法的生命位置上有:throws FileNotFoundException第三:通过类的继承结构可以看到:FileNotFoundException父类是IOException,IOException的父类是Exception最终得知:FileNotFoundException是编译时异常。错误原因:编译时异常要求程序员编写程序阶段必须对他进行处理,不处理编译器就报错*///new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\dd.txt");//我们采用第一种处理方式:在方法声明的位置上使用throws继续上抛。//一个方法当中的代码出现异常之后,如果上报的话,此方法结束.new FileInputStream("D:\\360Downloads\\Softwaress\\漏洞补丁目录\\dd.txt");System.out.println("如果new FIleInputStream出现异常,则这里的代码也不会执行");}}
-
深入try…catch
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;/*深入try..catch1、catch后面的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型2、catch可以写多个。建议catch的时候,精确的一个一个处理,这样有利于程序的调试。3、catch写多个的时候,从上到小,必须遵守从小到大。*/ public class ExceptionText07 {public static void main(String[] args) { /* try {FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");System.out.println("以上出现异常,此处无法执行");} catch (FileNotFoundException e) {System.out.println("文件不存在");}System.out.println("helloworld");*//* try {FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");} catch (IOException e) {//多态:IOException e = new FileNotException();System.out.println("文件不存在");}*///不够精确 /* try {//创建输入流FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");//读文件fis.read();} catch (Exception e) {//所有的异常都走这个分支.System.out.println("文件不存在");}*//* try {//创建输入流FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");//读文件fis.read();} catch (FileNotFoundException e) {System.out.println("文件不存在");}catch (IOException e){System.out.println("读文件报错了");}*///编译报错:Exception 'java.io.FileNotFoundException' has already been caught// 已经被捕捉过了,因为IOException是FIleNotFoundException的父类型。 /* try {//创建输入流FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");//读文件fis.read();}catch (IOException e){System.out.println("读文件报错了");} catch (FileNotFoundException e) {System.out.println("文件不存在");}*//*JDK8的新特性:catch中的异常类型中间可以采用“或(|)”的方式*/try {//创建输入流FileInputStream fis = new FileInputStream("D:\\360Downloads\\Software\\漏洞补丁目录\\ddd.txt");//进行数学运算System.out.println(100/0);//这个异常是运行时异常,编写程序时可以处理,也可以不处理}catch (FileNotFoundException | ArithmeticException | NullPointerException e) {System.out.println("文件不存在?算术异常?空指针异常?都有可能!");}}}
-
异常对象的两个非常重要的方法
/*异常对象有两个非常重要的方法:获取异常简单的描述信息:String msg = exception.getMessage();打印异常追踪的堆栈信息:exception.printStackTrace();*/ public class ExceptionText08 {public static void main(String[] args) {//这里只是为了测试getMessage()方法和printStackTrace()方法//这里只是new了异常对象,但是没有将异常对象抛出。JVM会认为这是一个普通的java对象。NullPointerException npe = new NullPointerException("空指针异常对象npe");//获取异常简单描述信息:这个信息实际上就是构造方法上的String参数。String msg = npe.getMessage();System.out.println(msg);//打印异常堆栈信息。java后台打印异常堆栈追踪信息处理信息的时候,采用了异步线程的方式打印的npe.printStackTrace();for (int i = 0; i <500 ; i++) {System.out.println(i);}System.out.println("helloworld");} }
如何查看异常的追踪信息
import java.io.FileInputStream; import java.io.FileNotFoundException;/*异常对象的两个方法:String msg = e.getMessage();e.printStackTrace (一般使用这个)我们以后查看异常的追踪信息,应该怎么看,可以快速的调试程序呢?异常信息追踪信息,从上往下一行一行看。但是要注意的是:SUN写的代码就不用看了(看包名就知道是自己写的还是SUN写的)主要问题出现在自己编写的代码上面。*/ public class ExceptionText09 {public static void main(String[] args) {try {m1();} catch (FileNotFoundException e) {//获取异常的简单描述信息System.out.println(e.getMessage());//打印异常堆栈追踪信息!!!//在实际的开发中,建议使用这个,养成好习惯。这行代码要写上,不然出问题了都不知道e.printStackTrace();/*java.io.FileNotFoundException: D:\360驱动大师目录\下载保存目录\SeachDownload\eee.txt (系统找不到指定的文件。)at java.io.FileInputStream.open0(Native Method)at java.io.FileInputStream.open(FileInputStream.java:195)at java.io.FileInputStream.<init>(FileInputStream.java:138)at java.io.FileInputStream.<init>(FileInputStream.java:93)at ExceptionText09.m3(ExceptionText09.java:47)at ExceptionText09.m2(ExceptionText09.java:43)at ExceptionText09.m1(ExceptionText09.java:39)at ExceptionText09.main(ExceptionText09.java:16)因为47行出问题导致43行出问题,43行出问题导致39行出问题,49行出问题导致16行出问题,应该先看47行,47行是代码错误根源*///这里的程序不耽误执行,很健壮(服务器不会因为遇到异常而宕机)System.out.println("helloworld");}}private static void m1() throws FileNotFoundException {m2();}private static void m2() throws FileNotFoundException {m3();}private static void m3() throws FileNotFoundException {new FileInputStream("D:\\360驱动大师目录\\下载保存目录\\SeachDownload\\eee.txt");} }
-
关于try…catch的finally子句
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Parameter;/*关于try..catch中的finally子句:1、在finally子句中的代码是最后执行的,并且是一定会执行的,即使try..catch语句块中的代码出现了异常finally子句必须和try一起出现,不能单独编写2、finally语句通常使用在哪些情况下?通常在finally语句块中完成资源的释放/关闭,因为finally中的代码有保障。即使try语句块中的代码出现异常,finally中的代码也会执行。*/ public class ExceptionText10 {public static void main(String[] args) {FileInputStream fis = null;try {//创建输入流对象fis = new FileInputStream("D:\\360驱动大师目录\\下载保存目录\\SeachDownload\\ee.txt");//开始读文件....String s = null;//这里一定会出现空指针异常s.toString();System.out.println("helloworld");//流使用完需要关闭,因为流是占用资源的//即使以上程序出现异常,流也必须关闭。放在这里可能关闭不了fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (NullPointerException e){e.printStackTrace();} catch (IOException e){e.printStackTrace();} finally {System.out.println("hello paoke");//流的关闭放在这里比较保险,finally中的代码是一定会执行的。即使try中的代码出现了异常,也可以执行。//当fis为空时不执行if(fis != null) {try {//close()方法有异常,采用捕捉的方式fis.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println("hello kity");}}
-
try和finally,可以没有catch。
以及try中如果有return,finally怎么执行
//finally语句:放在finally语句块中的代码是一定会执行的。 public class ExceptionText11 {public static void main(String[] args) {/*try和finally,没有catch可以吗?可以try不能单独使用try finally可以联合使用以下代码的执行顺序:先执行try..在执行finally...最后执行return(return语句只要执行,方法必然结束)*/try{System.out.println("try....");return;}finally {//fianlly中的语句会执行,能执行到System.out.println("finally");}//Unreachable statement。这里不能写语句,因为这个代码是无法执行到的//System.out.println("helloworld");} }
使用System.exit(0);退出JVM时,finally…
//finally public class ExceptionText12 {public static void main(String[] args) {try{System.out.println("try....");//退出JVMSystem.exit(0);//退出JVM之后,finally语句中的代码就不会执行了。}finally {System.out.println("finally");}} }
-
finally面试题
//finally面试题 public class ExceptionText13 {public static void main(String[] args) {int result = m();System.out.println(result);//100}/*java语法规则(有一些规则是不能破坏的,一旦这么说了,必须这么做):java中有一条这样的规则:方法体中的代码必须遵循自上而下的顺序因此逐行执行(亘古不变的 语法)java中还有一条这样的语法规则:return语句一旦执行,整个方法必须结束。(更古不变的语法)*/private static int m() {int i =100;try{//这行代码出现在int i = 100; 的下面,所以最终结果必须返回100//return语句还必须保证是最后执行的,一旦执行,整个方法结束。return i;}finally {i++;}} }/* 反编译之后的结果public static int m(){int i = 100;int j = i;i++;return j;}*/
-
final、finally、finalize有什么区别?
/*final 、finally 、finalize有什么区别?final 关键字final修饰的类无法继承final修饰的方法无法覆盖final修饰的变量不能重新赋值finally 关键字finally与try一起联合使用finally语句块中的代码是一定会执行的finalize 标识符是一个Object类中的方法名这个方法是垃圾回收器GC负责调用的。*/ public class ExceptionText14 {public static void main(String[] args) {//final是一个关键字final int i = 100;//finally也是一个关键字,和try联合使用,使用在异常处理机制中,在finally语句块中的代码是一定会执行的try{}finally{System.out.println("finally");}//finalize()是Object类中的一个方法,作为方法名出线。所以finalize是标识符} }
-
如何自己定义异常?
异常类
/*1、SUN提供的JDK内置的异常肯定是不够用的。在实际的开发中,有很多业务,这些业务出现异常之后,JDK中都是没有的和业务挂钩的,这些异常类我们可以自己去定义2、java中怎么自定义异常呢?两步:第一步:编写一个类继承Exception或RuntimeException。第二步:提供两个构造方法,一个无参的,一个带有String参数的。死记硬背*/public class MyException extends Exception{//编译时异常:发生概率比较高的时候定义为编译时异常public MyException(){}public MyException(String s){super(s);}} //public class MyExceptio exception RuntimeException{ //运行时异常:发生概率比较低的定义为运行时异常比较好 // //}
创建异常对象
public class ExceptionText15 {public static void main(String[] args) {//创建异常对象(只是new对象,并没有手动抛出)MyException e = new MyException("用户名不能为空");//打印异常堆栈信息e.printStackTrace();//获取异常简单描述信息String msg = e.getMessage();System.out.println(msg);} }
-
对之前的数组模拟栈存储进行改进,使用异常进行错误的输出
改进后的栈类
public class MyStack {private Object[] elements ;private int index = -1;public MyStack() {this.elements = new Object[10];}public MyStack(int i) {this.elements = new Object[i];}public Object[] getElements() {return elements;}public void setElements(Object[] elements) {this.elements = elements;}//压栈public void push(Object object) throws MyStackOperationException {if(this.index >= this.elements.length-1){//学了异常之后对这个进行改进,不再使用输出语句,太low了/*System.out.println("栈已满,压栈失败");return;*//*//改进://创建异常对象MyStackOperationException e = new MyStackOperationException("栈已满,压栈失败");//手动将异常抛出去throw e; //这里不能使用try捕捉,自己new了一个异常,自己捕捉,没有意义。栈已满的消息需要传递出去*///合并throw new MyStackOperationException("栈已满,压栈失败");}elements[++index] = object;System.out.println("元素 "+object+" 压栈成功,栈帧此时指向"+index);}//弹栈public void pop() throws MyStackOperationException {if(index <= -1){/*System.out.println("栈已空,弹栈失败");return;*/throw new MyStackOperationException("栈已空,弹栈失败");}System.out.println("元素 " + elements[index] +" 弹栈成功,此时栈帧指向:"+ --index);}}
自定义的内存类
/*** 栈操作异常:自定义异常*/ public class MyStackOperationException extends Exception{//编译时异常public MyStackOperationException(){}public MyStackOperationException(String s){super(s);} }
测试类
//对改良之后的栈进行测试 //注意:最后这个例子,是异常最重要的案例,必须掌握,自定义异常在实际开发中的作用 public class ExceptionText16 {public static void main(String[] args) {//创建栈对象MyStack stack = new MyStack();//压栈、这里不能再上抛了,因为JVM发现异常之后,就会终止程序。try {stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());stack.push(new Object());//这里栈满了stack.push(new Object());} catch (MyStackOperationException e) {//输出异常的简单信息System.out.println(e.getMessage());//打印异常信息//e.printStackTrace();}//弹栈try {stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();stack.pop();//这里栈空了stack.pop();} catch (MyStackOperationException e) {//输出异常的简单信息System.out.println(e.getMessage());//打印异常信息//e.printStackTrace();}} }
-
方法重写时,重写后的方法不能比之前的方法抛出更多的异常
/*之前在讲方法覆盖时,遗留的问题:重写之后的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少。*/ public class ExceptionText17 {public static void main(String[] args) {} }class Animal{public void doSome(){}public void doOther()throws Exception{}}class Cat extends Animal{//编译报错//public void doSome() throws Exception{}//编译通过//public void doOther(){}//编译通过//public void doOther() throws Exception{}//编译通过public void doOther() throws NullPointerException{} }/*总结异常中的关键字:异常捕捉:trycatchfinallythrows 在方法声明位置上使用,表示上报异常信息给调用者throw 手动抛出异常*/
-
相关作业
编写程序模拟用户注册: 1、程序开始执行时,提示用户输入“用户名”和“密码”信息。 2、输入信息之后,后台java程序模拟用户注册。 3、注册时用户名要求长度在[6-14]之间,小于或者大于都表示异常。注意:完成注册的方法放到一个单独的类中。异常类自定义即可。class UserService {public void register(String username,String password){//这个方法中完成注册!}}编写main方法,在main方法中接收用户输入的信息,在main方法中调用UserService的register方法完成注册。
用户业务类
package homework; //用户业务类:处理用户相关的业务:例如登录、注册等功能 public class UserService {/*** 用户注册* @param username 用户名* @param password 密码* @throws IllegalNameException 当用户名为null,或者用户名长度<6,或者长度>14时,出现该异常*/public void register(String username , String password) throws IllegalNameException {//引用等于null的这个判断最好放到所有条件的最前面//if(username == null || username.length() < 6 || username.length() >14 ){}//再分享一个经验: 写成null ==username 比 username == null 要好。有时候 少一个=就成了:username = null,这种与我们想的不一样,但是这样写不会报错,采用前一种方法就比较保险// 写成"abc".equals(username) 比 username.equals("abc") 要好//if( null == username || username.length() < 6 || username.length() >14 ){}if( null == username || username.length() < 6 || username.length() >14 ){throw new IllegalNameException("用户名长度必须在[6-14]之间");}//程序能执行到这里,说明用户名没有问题System.out.println("欢迎["+username+"]");} }
异常类
package homework;public class IllegalNameException extends Exception{public IllegalNameException(){}public IllegalNameException(String s){super(s);} }
测试类
package homework;public class Text {public static void main(String[] args) {UserService us = new UserService();try {us.register("abcdef","123");} catch (IllegalNameException e) {e.printStackTrace();}} }
-
作业2
开放型题目,随意发挥:写一个类Army,代表一支军队,这个类有一个属性Weapon数组w(用来存储该军队所拥有的所有武器),该类还提供一个构造方法,在构造方法里通过传一个int类型的参数来限定该类所能拥有的最大武器数量,并用这一大小来初始化数组w。该类还提供一个方法addWeapon(Weapon wa),表示把参数wa所代表的武器加入到数组w中。在这个类中还定义两个方法attackAll()让w数组中的所有武器攻击;以及moveAll()让w数组中的所有可移动的武器移动。 写一个主方法去测试以上程序。 提示:Weapon是一个父类。应该有很多子武器。这些子武器应该有一些是可移动的,有一些是可攻击的。
可移动接口
package arrayarmy;//可移动的接口 public interface Moveable {//移动行为void move(); }
可攻击接口
package arrayarmy; //可射击的接口 public interface Shootable {//射击行为void shoot(); }
武器类
package arrayarmy;//所有武器的父类 public class Weapon {//武器的名字String name ;public Weapon(String name){this.name = name;}//重写toString方法@Overridepublic String toString() {return name;} }
坦克类
package arrayarmy;/*** 坦克是一个武器,可移动,可攻击*/ public class TanK extends Weapon implements Moveable,Shootable{public TanK(String name) {super(name);}@Overridepublic void move() {System.out.println("坦克移动");}@Overridepublic void shoot() {System.out.println("坦克攻击");} }
高射炮类
package arrayarmy;//高射炮是一个武器,但是不能移动,只能射击。 public class GaoShePao extends Weapon implements Shootable{public GaoShePao(String name) {super(name);}@Overridepublic void shoot() {System.out.println("高射炮开炮");} }
战斗机类
package arrayarmy;//战斗机:是武器,可移动、可攻击。 public class Fighter extends Weapon implements Shootable,Moveable{public Fighter(String name) {super(name);}@Overridepublic void move() {System.out.println("战斗机起飞");}@Overridepublic void shoot() {System.out.println("战斗机开炮");} }
物资飞机类
package arrayarmy;//物资飞机:只能运输物资 public class WuZiFeiJi extends Weapon implements Moveable{public WuZiFeiJi(String name) {super(name);}@Overridepublic void move() {System.out.println("物资飞机运输物资");} }
添加武器异常类
package arrayarmy;public class AddWeaponException extends Exception{public AddWeaponException(){}public AddWeaponException(String s){super(s);} }
军队类
package arrayarmy; /*开放型题目,随意发挥:写一个类Army,代表一支军队,这个类有一个属性Weapon数组w(用来存储该军队所拥有的所有武器),该类还提供一个构造方法,在构造方法里通过传一个int类型的参数来限定该类所能拥有的最大武器数量,并用这一大小来初始化数组w。该类还提供一个方法addWeapon(Weapon wa),表示把参数wa所代表的武器加入到数组w中。在这个类中还定义两个方法attackAll()让w数组中的所有武器攻击;以及moveAll()让w数组中的所有可移动的武器移动。写一个主方法去测试以上程序。提示:Weapon是一个父类。应该有很多子武器。这些子武器应该有一些是可移动的,有一些是可攻击的。*/ //军队 //类在强制类型转换过程中,如果是类转换成接口类型。那么类和接口之间不需要存在继承关系,也可以转换,java语法中允许public class Army {//武器数组Weapon[] weapons;/*** 创建军队的构造方法* @param count 武器数量*/public Army(int count){//动态初始化数组中的每一个元素默认值都是null,武器数组是有了,但是武器数组中没有放武器this.weapons = new Weapon[count];}/*** 将武器加入数组weapons中* @param weapon 要放入数组的武器*/public void addWeapon(Weapon weapon) throws AddWeaponException {for(int i = 0 ; i < weapons.length ; i++){if(null == weapons[i]){weapons[i] = weapon;System.out.println(weapon+"入队");return;}}//程序如果执行到这里,说明武器没有添加成功。throw new AddWeaponException("武器库已满,无法放入武器");}/*** 所有可攻击的武器攻击*/public void attackAll(){//遍历数组for(int i = 0 ; i < weapons.length ; i++){//Weapon是所有武器的父类,但是需要调用的是子类武器的方法,所以这里使用向下转型//看weapons[i]是否具有可攻击的方法,如果有,转型----> 调用该方法if ( weapons[i] instanceof Shootable){Shootable shootable = (Shootable)weapons[i];shootable.shoot();}}}/*** 所有可移动的武器移动*/public void moveAll(){//遍历数组for(int i = 0 ; i < weapons.length ; i++){if( weapons[i] instanceof Moveable){Moveable moveable =(Moveable)weapons[i];moveable.move();}}}}
测试类
package arrayarmy;public class Text {public static void main(String[] args) {//构建一个军队armyArmy army = new Army(4); //这个军队的武器库里只能存放四个武器//创建武器对象Fighter fighter = new Fighter("战斗机");GaoShePao gaoShePao = new GaoShePao("高射炮");TanK tanK = new TanK("坦克");WuZiFeiJi wuZiFeiJi = new WuZiFeiJi("物资飞机");WuZiFeiJi wuZiFeiJi2 = new WuZiFeiJi("物资飞机2");//添加武器try{army.addWeapon(fighter);army.addWeapon(gaoShePao);army.addWeapon(tanK);army.addWeapon(wuZiFeiJi);army.addWeapon(wuZiFeiJi2);}catch(AddWeaponException e){System.out.println(e.getMessage());}//让所有可移动的移动army.moveAll();//让所有可攻击的攻击army.attackAll();} }
相关文章:
【java进阶08:异常】finally关键字、自定义异常类、用户业务作业、军队武器作业
java中的异常处理机制 异常在java中以类和对象的形式存在,那么异常的继承结构是怎样的?我们可以使用UML图来描述以下继承结构 画UML图的工具:Rational Rose、starUML等 Object下有Throwable(可抛出的) Throwable下有两…...

#课程笔记# 电路与电子技术基础 课堂笔记 第6章 半导体器件的基本特性
6.1 半导体基础知识 6.1.1 本征半导体 完全纯净的、结构完整的半导体称为本征半导体。 常用的半导体材料有硅和锗,它们都是四价元素,原子最外层轨道有四个价电子。 若将纯净的半导体制成晶体,则原子形成排列整齐的点阵。 点阵是由共价键提供…...

skimage.filters.apply_hysteresis_threshold详解
本文内容均参考scipy1.9.1scipy1.9.1scipy1.9.1版本的源码,若有任何不当欢迎指出 我们截取官方注释如下: def apply_hysteresis_threshold(image, low, high):"""Apply hysteresis thresholding to image.This algorithm finds regions …...

一、基础算法5:前缀和与差分 模板题+算法模板(前缀和,子矩阵的和,差分,差分矩阵)
文章目录算法模板前缀和模板子矩阵的和模板差分模板差分矩阵模板模板题前缀和原题链接题目题解子矩阵的和原题链接题目题解差分原题链接题目题解差分矩阵原题链接题目题解算法模板 前缀和模板 S[i] a[1] a[2] ... a[i] a[l] ... a[r] S[r] - S[l - 1]子矩阵的和模板 S[i…...

Python矩阵分解之QR分解
文章目录QR和RQ分解其他函数QR和RQ分解 记AAA为方阵,P,QP, QP,Q分别为正交单位阵和上三角阵,则形如AQRAQRAQR的分解为QR分解;形如ARQARQARQ的分解为RQ分解。 在scipy.linalg中,为二者提供了相同的参数,除了待分解矩阵…...

随机森林程序
n_estimators:数值型取值 含义:森林中决策树的个数,默认是10 criterion:字符型取值 含义:采用何种方法度量分裂质量,信息熵或者基尼指数,默认是基尼指数 max_features:取值为int型, float型, string类型…...

每日一练2627——变态跳台阶快到碗里来不用加减乘除做加法三角形
文章目录变态跳台阶思路:代码:快到碗里来思路:代码:不用加减乘除做加法思路:代码:三角形思路:代码:变态跳台阶 题目链接: 思路: 这个题目很容易理解&#…...

LeetCode-146. LRU 缓存
目录LRU理论题目思路代码实现一代码实现二题目来源 146. LRU 缓存 LRU理论 LRU 是 Least Recently Used 的缩写,这种算法认为最近使用的数据是热门数据,下一次很大概率将会再次被使用。而最近很少被使用的数据,很大概率下一次不再用到。当缓…...

#课程笔记# 电路与电子技术基础 课堂笔记 第3章 电路分析的几个定理
3.1 叠加定理 激励:电流源或电压源 响应:电流或电压 叠加定理一般用于已知激励或响应中的一种,求另一种。做法就是,每次只求一个激励作用下的响应,将其他激励置零,置零的具体做法是,电压源变…...

推迟参数设计的自适应反步控制和自适应神经网络的反步控制设计
推迟参数设计的自适应反步控制和自适应神经网络的反步控制设计 目录推迟参数设计的自适应反步控制和自适应神经网络的反步控制设计前言匹配与非匹配1. 基于自适应反步控制的非匹配条件下的系统控制器设计问题描述控制器设计小结2. 基于自适应反步控制和推迟参数设计的非匹配条件…...

spring5.1+SmartInstantiationAwareBeanPostProcessor 解决循环依赖
SmartInstantiationAwareBeanPostProcessor 解决循环依赖的过程, 例如上面的 A依赖B, B依赖A SmartInstantiationAwareBeanPostProcessor 是 Spring 中的一个接口,它扩展了 InstantiationAwareBeanPostProcessor 接口并提供了对 Bean 的实例化和属性填充的更高级的…...

apply、call与bind
共同点: 都是函数对象的一个方法,作用是改变函数执行时的上下文,即改变函数体内部this的指向 var name "lucy"; var obj {name: "martin",say: function () {console.log(this.name);} }; obj.say(); // martin&…...

《Effective Objective-C 2.0 》 阅读笔记 item3
第3条:多用字面量语法,少用与之等价的方法 1. 字面数值 使用字面量能令代码更为简洁: NSNumber *someNumber 1; *** 字面量语法的好处! *** 令代码更为简洁。能够以NSNumber实例表示的所有数据类型(int、float、d…...

SSL/TLS 证书管理
SSL 证书发现 随着组织的 IT 基础架构的扩展,他们为每台计算机获取证书以保护其资源和域。此外,开发人员通常会创建许多自签名证书,以便在产品的开发阶段保护内部网络。组织通常最终会拥有数千个证书。自动发现证书提供了对证书基础结构的完…...

supersqli(SQL注入流程及常用SQL语句)
目录 一、SQL注入知识学习 1、判断注入类型 (1)数字型注入判断 (2)字符型注入判断 2、猜解sql查询语句中的字段数(order by 的使用) 3、判断显示位爆数据库的名字 4、注释(--的使用&#…...

【数据结构】用Java实现一棵二叉树
目录 前言 1. 创建MyBinaryTree类 2. 从前序与中序遍历序列构造二叉树 3. 从中序与后序遍历序列构造二叉树 4. 用层序遍历验证二叉树是否构建成功 5. 整体代码(构建二叉树、二叉树的基本功能和测试代码) 6. 测试结果 前言 前面两篇文章已经给出了…...

【面试】面试官问的几率较大的网络安全面试题
文章目录防范常见的 Web 攻击1、什么是SQL注入攻击2、什么是XSS攻击3、什么是CSRF攻击4、什么是文件上传漏洞5、DDos 攻击重要协议分布图1、arp协议的工作原理ARP协议工作原理:2、什么是RARP?工作原理3、dns是什么?dns的工作原理4、rip协议是…...

[Python] 循环语句
循环语句就是在符合条件的情况下,重复执行一个代码段 1.while循环 while语句可用于在条件为真时反复执行代码块 语法格式 while 条件语句:执行语句 当条件语句为真(True)时,就会执行while循环下的语句 示例 实现1到100 的累加并输出求和结果 …...

计算机网络考试复习——第一章 1.5 1.6
1.5 计算机网络的类别 1.5.1计算机网络的定义: 系统集合,连接起来,协议工作,资源共享 计算机网络主要是由一些通用的、可编程的硬件互连而成的,而这些硬件并非专门用来实现某一特定目的(例如࿰…...

3.29 最小生成树算法
最小生成树概念 参考:什么是最小生成树? Minimum Spanning Tree 何为生成树? 生成树是指一个联通图的极小的连通子图,它包含了图中的所有n个顶点,并只有n-1条边(构成一棵树) 生成树的一些性…...

计算机科班与培训开发编程的区别在哪里?
科班、培训班、科班培训班的模式都培养了很多编程技术人员进入IT行业,有的成为某个技术领域的专家,有的成为领导层,有的一直在默默无闻的敲代码等待35岁的到来。不管那种方式入行,这些类似的情况都存在,并且未来还会一…...

idea设置常用自设置快捷键及坐标
<!--mybatis 依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency…...

Vue 3.0 实例方法
#$watch 参数:{string | Function} source{Function | Object} callback{Object} [options] {boolean} deep{boolean} immediate{string} flush返回:{Function} unwatch用法: 侦听组件实例上的响应式 property 或函数计算结果的变化。回调函数…...

日撸 Java 三百行day1-10
文章目录说明day1 环境搭建1.1 开发环境1.2 package import 和 println1.3 编写HelloWorld.javaday2 基本算术操作2.1 加、减、乘、除、整除、取余.day3 基本if 语句3.1 if条件分支语句3.2 代码day4 闰年的计算4.1 思路整理:何为闰年?4.2 核心代码day5 基…...

Ubuntu Instant-ngp 训练自有数据集
1. 运行环境配置 conda create -n instant-ngp python3.10 conda activate instant-ngp pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple2. COLMAP稀疏重建生成transform.json colmap 环境配置参考文档; 终端定位在instant-ngp/da…...

k8s集群只一台节点,重启节点后命名空间找不到了
定位 如果您的Kubernetes集群只有一台节点,并且在重启节点之前您创建了一些命名空间和资源,那么在节点重启后,这些命名空间和资源可能会丢失。这是因为在Kubernetes中,资源和命名空间通常是存储在etcd中的。当节点重启时…...
MarkDown示例
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...

spring cloud 雪崩效应
什么是雪崩效应 雪崩就是塌方。在山坡上的积雪,如果积雪的内聚力小于重力或其他力量,则积雪便向下滑动,从而逐渐引起积雪的崩塌。 在微服务架构中,服务之间通常存在级联调用。比如,服务A调用服务B,而服…...

Python 自动化指南(繁琐工作自动化)第二版:三、函数
原文:https://automatetheboringstuff.com/2e/chapter3/ 您已经熟悉了前几章中的print()、input()和len()函数。Python 提供了几个这样的内置函数,但是您也可以编写自己的函数。函数就像一个程序中的一个小程序。 为了更好地理解函数是如何工作的&#…...

c++多线程 1
https://www.runoob.com/cplusplus/cpp-multithreading.html 两种类型的多任务处理:基于进程和基于线程。 基于进程的多任务处理是程序的并发执行。 基于线程的多任务处理是同一程序的片段的并发执行。 线程 c11以后有了 标准库 1 函数 2 类成员函数 3 lambda函…...