Java异常-小记01

最近学习了java的异常,小结一下,有问题欢迎大佬指出。

基础概念

在说到异常之前,先说一下异常的关系网。

异常(Exception)和错误(Error)所属包分别是java.lang.Exception和java.lang.Error。这两个都是java.lang.Throwable这个类的子类。

异常:指java在运行过程,因为某些问题,程序突然停止并且抛出异常。

错误:指严重的问题带我们只能通过修改代码或者提高电脑性能去解决。比如我们创建一个数组,长度是int的最大值,理论上这是可以的,但我的电脑是16G内存,它无法在内存中创建这么长的数组,所以这种错误目前我们无法去改变,只能去尽力避免。

图1.Error的实例

对于异常,我们分两个大类:运行期异常和编译期异常。

运行期异常(RuntimeException):指所属RuntimeException类以及其子类的异常。我理解为,在编译期间编译器并没有给我报错,但是在运行程序时,程序却突然中断。比如数组的越界异常(ArrayIndexOutOfBoundsException)。假设还是一个数组arr,长度是5,但是我现在要输出arr[10]的数字,从语法角度看,没有问题,但是当程序运行时,JVM找不到这个位置所以才会报错。

图2. 运行期异常的实例

编译期异常(CheckedException):指非RuntimeException类以及其子类的异常。我理解为。在编译期间编译器就会给我们提示需要解决这个异常,我们必须解决或者抛出这个异常,程序才能执行。比如我们创建一个线程,当我们使用thread.sleep()方法时,我们需要用try catch去解决这个异常。

      图3.编译期异常的实例

 图4. 解决编译器异常后的正常输出

从图三图四,我们必须解决这个异常,那么为什么要解决呢?因为thread.sleep()这个方法的参数指的是毫秒,这个数据肯定是一个大于0的数,如果我们不小心输入了一个负数,一旦运行程序会直接崩溃并且报错,这时候如果有处理异常的操作,我们会知道这个异常是什么并且能找到它的位置快速解决这种问题。

 图5.处理异常最大的好处

小结:异常不是说一定有错,而是某些代码我们或者程序认为可能会发生错误,所以我们需要处理它,如果发生异常,它抛出了异常,但是后面代码会继续执行。

如何处理异常

我们通过5个关键字去处理异常:try     catch     finally     throw     throws

try catch:这两个关键字一般一起使用,具体的语法格式是

try{ 可能发生错误的代码 }catch(什么类型的错误  ){  如果出错,输出的代码 }

这里“可能发生错误的代码 ”可以是一行代码或者具有逻辑的几行代码。如果很多代码,没有逻辑关系,可以这样写

try{ 可能发生错误的代码 }catch(什么类型的错误 1 ){  如果出错,输出的代码 1}catch(什么类型的错误 2){  如果出错,输出的代码 2}catch(什么类型的错误 3){  如果出错,输出的代码 4}

try catch finally:

try{ 可能发生错误的代码 }catch(什么类型的错误  ){  如果出错,输出的代码 }finally{一定会输出的代码}

 finally内的代码不管抛错还是不跑错,它都一定执行,可以理解为,抛错前我就执行了,只是代码位置在后面。

throw:

throw new 异常类型(参数);

这个参数可以是字符串去说明是什么异常,我们用throw是将错误抛给调用者并不是说,这个异常被处理了,只是抛给了调用者,也就是调用的方法或者类,调用者还是要处理这个异常或者继续抛出调用者的调用者,总之异常一定要处理,抛出异常只是向调用者说明是什么异常

throws:

语法例子:public void 方法名 (参数) throws 异常类型1, 异常类型2...{    }

与throw类似,只是throws只能写在方法的格式中,不能用在方法内,同时也是抛出异常不处理异常。

关于继承关系的异常

java的继承关系很重要的点,那么子类与父类的异常需要遵循一定的规则

a>如果父类没有声明异常,子类可以不声明异常或者声明运行期异常,但不能声明编译器异常。

b>如果父类声明运行期异常,子类可以不声明异常或者声明运行期异常,但不能声明编译器异常。

c>如果父类声明编译期异常,子类可以不声明异常或者声明运行期异常,如果什么编译期异常,只能声明与父类相同的编译期异常或者这个编译期异常的子类。

总结

异常是一个很重要的点,通过处理异常,我们能很快找到代码中出问题的地方以及具体的原因,对于规范代码以及维护软件十分重要。

Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.javaJava类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值