java学习笔记11

1、异常就是Exception

异常也是对象,每一种问题都是一种类。但是他们都有共同的父类,throwable类,他下面的子类都可往外抛出,让调用者知道有问题,可以处理。


2、


3、异常的发生也是可以结束程序的


当执行到Demo类的method方法中Sop()那句时,虚拟机JVM发现数组下标越界,new出来一个 ArrIndex类型异常,并抛出给main函数,main函数中没有相应的处理代码,所以就继续向上抛给虚拟机,虚拟机没法处理,抛给控制台显示出错误的信息给代码作者。

下图中因为异常抛出,所以划红线的语句都不再执行了。


碰见异常,虚拟机会自动new出异常对象并抛出,但是你也可以人工new出异常对象并抛出,如下图所示:

数组越界异常类的构造方法由于参数不同,共有三种


下面的方法是第三种构造方法:注意字符串和任何变量连接起来都是字符串!


通过自定义错误信息,这样错误的界面就显得很友善,容易看懂错误的原因:


同理还有数组引用为空类的异常,详见Api文档。

4、自定义异常类

上面讲了数字下表越界的自定义错误信息,这里是自定义异常类。一般继承Exception,这样方便catch并进行处理(包括在catch处理方法中将异常的类型改变为调用者能处理的问题)


在检测错误时,javac先检查语法错误,java运行时再检测逻辑错误。

注意自定义的异常类如果想在函数中使用,就必须现在函数外面用关键字throws来声明下,下面的函数有可能抛出这个异常,真抛出了就按对应的方法来处理,而在函数内部是用的关键字throw来抛出一个具体的异常对象。



其中NullPointException是RuntimeException的子类,故不需要声明即可。而FuShuIndexException是继承的Exception类,不属于RuntimeException,故还需声明。

5、异常的分类:


异常的处理方式有两种:捕捉或声明。我们这里讲的是声明即throws,声明要抛异常,只管往外抛。

Exception的子类中除了RuntimeException,其余的只要在编译过程中发现错误,都会报错,使编译失败 ,故在程序中必须要声明处理:也就是 在调用的函数外部写上throws 自定义异常。Exception中的编译异常通常类似非致命的错误,在编译的时候爆出来,修改一下即可。

而RuntimeException 是虚拟机正常运行期间抛出的异常。而Error是虚拟机不正常时的。编译器不检测RuntimeException类错误,故是否在编译时出现RuntimeException类错误都不会报错,只会在运行时报错。而RuntimeException则类似致命的错误,编译时不会爆异常,一到关键运行时,直接让你整个程序挂掉。RuntimeException类的错误就不用再函数外面写throws +自定义异常

6、异常的捕捉


真正的处理必须有catch{ } ,catch{ }处理完,就可以接着执行异常所在行后面的代码,不影响后面代码的执行。

能处理的问题就catch,不能处理的问题就不去catch,直接在方法外面声明throws往外抛,让程序编写者去处理。


printStackTrace()是异常类对象所特有的方法,所以直接e.printStackTrace( )就ok,打印出异常的详细信息。

当抛被调用的函数可能抛多个不同类的异常时,就在try调用函数代码的地方针对抛出的不同异常写下多个对应的catch处理语句即可。


当有可能抛出的没事先声明的异常时,可以在后面补充写下catch(Exception e),这样就会编译失败,所有异常都是Exception的子类,必定会执行里面的代码。但是注意要放到所以特定catch的后面,要不前面的catch就都无法执行了,注意:之所以加一句catch(Exception e){ },里面代码是空也就是没做处理,所以编译都没法通过其实就是防止出乎意外的异常的发生,一旦捕捉到意料之外的异常就让编译挂掉提醒程序员。

下图就是catch(Exception e){ }放前和放后的区别。因为之前的异常都没有声明,所以这里catch(Exception e){ }捕捉后没处理就会编译不通过。要是之前声明异常了,应该就ok,编译用过,当然运行还是会挂掉。


什么地方才写try?例如有些函数声明会抛异常,执行这些函数之前就可以先写下try{ 会抛异常的函数代码},提前做好预防工作。


再一次强调只要执行了return这句指令,main函数就整个结束了!!!

finally就算是放在return后面也依然会被执行。finally是一定会执行的代码,除非把return写成System.exit(0)这样就直接退出JVMfinally的代码就无法执行。


举个例子来说明finally的用途;在连接数据库的时候如果发生了异常,如果没有finally,那么关闭连接的代码就无法执行的到,相当于一直在连接着数据库,占据着资源。

而把关闭连接的代码写在finally里面则保证了和数据库的连接一定会被关闭。 


finally的用法如下:


第一种是正常用法,第二种是针对可能抛出多种异常而有多个catch,第三种:举个例子,如果发生了异常,但是无法处理,所以不写catch,直接抛给调用者,但是数据库的连接必须要关掉,所以要有finally。


程序运行中抛出A类的异常,但是直接抛出去,调用程序的人可能无法处理,这时就可以先将抛出的A类异常捕获,在catch的语句中再重新抛出一个调用者可以处理的异常,这个过程也称为异常的封装,对于程序的调用者来讲,他不需要了解或者处理他不熟悉的异常,只需处理他能处理的问题即可。


10、异常的应用:电脑冒烟,蓝屏的例子




运行结果如下:(state = 2时的情况)


11、异常的注意事项:子类抛的异常必须是父类抛的异常或者异常的子类,当然子类也可以不抛异常。



简单的的理解为父类出问题,子类不能出更大范围的问题。


12、所有类都直接或间接是object类子类。

如果抛了异常就会在编译的时候挂掉。因为子类在覆盖的时候抛别的异常,没有对应的catch 或者声明,就一定会报错。

object类有equal方法,由于所有的类都是继承自object类,故所有类的对象都有equal方法,但是这个默认的equal方法比较的是两个对象是否是同一个对象。p.equal(p2),如果p和p2指向的是同一个对象,即p和p2里的地址值是一样的,那么结果就是true,否则返回false。每个对象都具有地址,而且是唯一的,这才是可以比较的共性(不管传进来的是什么类型的对象,均可用这个方法进行比较。),所以equal函数比较的是两个对象的引用地址是否一致。

静态代码块不管是否创建对象,随着类的加载都直接执行。

13、用父类引用指向子类对象,也就是类型提升向上转型,向上转型后子类特有的成员都不能使用了。如果非想用特有的功能(成员),那就必须再向下转型。下图中的eauql方法已经重写覆盖了。



ClassCastException类型转换异常,是RuntimeException的子类,也是java自带的异常类。

equal是继承自object类,所以不管你覆盖还是没覆盖都是存在的。



14、直接打印一个对象时会得到对象的哈希值,@后面的部分都是16进制的数字,e.hashCode( )的作用是将对象e的十六进制值转换为十进制数。


一般比较两个对象相同,不仅比较内容相同,还要求他们的哈希值相同,之前没有覆盖hashcode()方法时,哈希值是地址,当然hashCode()也可以覆盖,例如在比较2个Person类对象是否相同(年龄是否相同)时,就可以覆盖掉hashCode(),让其返回年龄age,注意返回值仍是16进制数,而不是16进制地址值。 


15、java中万物皆是对象,连类也是不例外,因为有个类是 class Class,它提前了所有类的共性,而升华来的类,类似于类是对同一类型对象的的升华,Class类专门用来产生各式各样的类,这些类.class文件一加载,就在内存中生产了对应的类。下图中的field就是属性的意思,指一个类中的成员变量。


例如当加载Person.class文件时,会在堆中生成一个Person.class字节码文件对象,后面的各种Person类型的对象都是有这个Person.class字节码文件对象创建的。而p.getClass(),得到的就是当前对象的字节码文件对象,就是创建当前对象的字节码文件对象。

下图是有图有真相,大写Class类,专门用来创建各种类。


Class类有一个getName()的方法,就是返回当前字节码对象的名字。


例如下图:


p1.getClass()和p2.getClass()得到的是同一个对象,就是创建p1和p2对象的Person类字节码对象。所以p1 == p2 是对的。而clazz1.getName()得到的是Person类字节码对象的名字,也就是Person。

16、java中的toString,java中所有的对象都能转为字符串形式

由于object类中有toString()方法,故所有的类的对象都可以调用toString()方法,在用System.out.println打印某个对象的时候,输出的一定是字符串,因为在打印对象时那个对象默认调用了toString的方法,所以显示出来的是字符串。如下图中两个划红线的指令执行出来的效果是一样的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值