Java的异常机制有三种:

一.Error类以及其子类表示的是错误,它是不需要程序员处理也不能处理的异常.比如VirtualMachineError虚拟机错误,ThreadDeath线程僵尸等.

二.RuntimeException类及其子类表示的是非受检查异常,是系统可能会抛出的异常,程序员可以去处理,也可以不去处理,最经典的就是NullPointerException空指针异常和IndexOutOfBoundsException越界异常.

三.Exception类及其子类(不包含非受检查异常)表示的是受检异常,这是程序员必须处理的异常,不处理则程序不能通过编译,比如IOException表示I/O异常,SQLException表示数据库访问异常.

我们知道 一个对象的创建,需要经过内存分配,静态代码初始化,构造函数执行等过程,对象生成的关键步骤是构造函数,那是不是允许在构造函数中抛出异常呢?从Java语法上来说,完全可以在构造函数中抛出异常,三类 异常都可以,

但是从系统设计和开发的角度来分析,则尽量不要在构造函数中抛出异常,我们以三种不同类型的异常来说明:

(1)构造函数抛出错误是程序员无法处理的

(2)构造函数不应该抛出非受检查异常

看如下的例子:

class Person{public Person(int _age){//不满18岁得用户对象不能建立if(_age<18){//throw new RuntimeException("年龄必须大于18岁。");
        }        }//看限制级的电影public void seeMovie(){System.out.println("看限制级电影");}
}

代码的意图很明显,不满18岁的用户根本就不会生成一个Person实例对象,没有对象,类行为seeMovie方法就不可以执行,想法很好,但这会导致不可预测的结果,比如我们这样引用Person类.

    public static void main(String[] args) {while(true){Person p = new Person(17);p.seeMovie();}/*其他的逻辑处理*/}

很明显,p对象不能建立,因为是一个RuntimeException异常,开发人员可以捕捉也可以不捕捉,代码看上去逻辑很正确,没有任何的瑕疵,但是事实上,这段程序会抛出异常,无法执行,这段代码给了我们两个警示:

  ①加重了上层代码编写者的负担.

  ②后续代码不会执行.

(3)构造函数尽可能不要抛出受检查异常

//父类
class Base{//父类抛出IOExceptionpublic Base() throws IOException{throw new IOException();}//父类方法抛出Exceptionpublic void method() throws Exception{}
}
//子类
class Sub extends Base{//子类抛出Exception异常public Sub() throws Exception {}//子类方法的异常类型必须是覆写方法的子类型
    @Overridepublic void method() throws IOException{}
}

就这么一段代码,展示了在构造函数中抛出受检查异常的三个不利方面.

①导致子类代码膨胀

  上面的例子中,子类的无参构造函数不能省略,原因是父类的无参构造函数抛出了IOException异常,子类的无参构造函数默认调用的是父类的构造函数,所以子类的无参构造函数必须抛出IOException或其父类.

 ②违背了里氏替换原则

    里氏替换原则说"父类能出现的地方子类就可以出现,而且将父类替换为子类也不会产生任何异常",那我们回过头来看看Sub类是否可以替换Base类,比如我们的上层代码是这样写的:

    public static void main(String[] args) {try{Base base = new Base();}catch(IOException e){//异常处理
        }}

然后我们希望把new Base()替换成new Sub(),而且代码能够正常编译和运行.非常可惜编译不通过..原因是Sub的构造函数抛出了Exception异常,它比父类的构造函数抛出的异常范围要宽,必须增加新的catch块才能解决.

 1 import java.io.IOException;
 2
 3 public class Client {
 4     public static void main(String[] args) {
 5         try{
 6             Base base = new Base();
 7             //Base base = new Sub();这样是编译不通过的,因为Sub的构造抛出Exception,它比父类的构造函数
 8             //抛出的异常范围要宽,必须增加新的catch块才能解决.
 9         }catch(IOException e){
10             //异常处理
11         }
12     }
13 }
14
15 class Base{
16     //父类抛出IOException
17     public Base() throws IOException{
18         throw new IOException();
19     }
20 }
21
22 class Sub extends Base{
23     //子类抛出Exception异常
24     public Sub() throws Exception {
25
26     }
27 }

可能读者会问,为什么Java的构造函数允许子类的构造函数抛出更广泛的异常类呢?这正好与类方法的异常机制相反,类方法的异常是这样要求的:

class Base{//父类方法抛出Exceptionpublic void method() throws Exception{}
}class Sub extends Base{//子类方法的异常类型必须是覆写方法的子类型
    @Overridepublic void method() throws IOException{}
}

子类方法可以抛出多个异常,但是都必须是覆写方法的子类型,对我们的例子来说,Sub类的method方法抛出的异常必须是Exception的子类或者Exception类,这是Java覆写的要求.构造函数之所以与此相反,是因为构造函数没有覆写的概念,只是构造函数间的引用调用而已,所以在构造函数中抛出受检查异常会违背里氏替换原则,使我们的程序缺乏灵活性. 

③子类构造函数扩展有限

以上汇总起来就是:非受检查异常不要抛出,抛出了对人对己都是有害的...受检查异常尽量不抛出.总之一句话:在构造函数中尽可能的不出现异常.

转载于:https://www.cnblogs.com/DreamDrive/p/5621276.html

[改善Java代码]不要在构造函数中抛出异常相关推荐

  1. java 代码解析工具_改善 Java 代码质量的工具与方法

    原标题:改善 Java 代码质量的工具与方法 我们可能见过上面的有关代码质量的图片,究竟如何衡量一段代码好坏? 代码质量是什么?为什么它很重要? 作家通过他的著作来讲述了一个清晰的.令人信服的故事.他 ...

  2. 改善Java代码有哪些方法?

    前言 Java是一门优秀的面向对象的编程语言,针对遇到同样的一个问题会有很多中解法哪种实现方法是最好的呢,还需要不断的探究JDK的底层原理.我会例出Java改善的建议哦,希望大家可以在平时开发工作去使 ...

  3. 27.能否在构造函数中抛出异常?析构函数呢?

    首先,我们要明确一点!一个函数执行的过程中,如果抛出异常,会导致函数提前终止! 在C++构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生.因为在构造函数中抛出异常,在概念上 ...

  4. Jvm处理Java Thread 的run方法中抛出异常的流程

    Jvm处理Java Thread 的run方法中抛出异常的流程 参考文章: (1)Jvm处理Java Thread 的run方法中抛出异常的流程 (2)https://www.cnblogs.com/ ...

  5. java代码怎么在cmd中运行?cmd怎么打开java代码?

    java代码怎么在cmd中运行是一个比较简单的问题,但还是有很多人频繁询问,今天本篇文章为大家统一解答一下这个问题. java代码怎么在cmd中运行? 1.首先用记事本写一个简单的Java程序,保存成 ...

  6. js 中 java 代码_在js中嵌套java代码

    jsp中有时候在js中操作某些java后台传递过来的数据逻辑比较复杂,比如list内容的遍历,可以直接在页面上添加java脚本来执行内容,代码如下: //在js中插入java代码操作 //取出java ...

  7. Java代码如何在虚拟机中运行?

    写在前面 本文隶属于专栏<100个问题搞定Java虚拟机>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和文献引用请见100个问题搞定Java ...

  8. idea java代码格式化_intellij Idea中的Java代码格式化(链式方法调用)

    我对Intellij Idea 14.1.4中的 java代码格式有一个小问题. 我有一段由我手动格式化的代码,对我来说很好看: public class Test { private static ...

  9. java向mysql写入数据慢_通过java代码往mysql数据库中写入日期相关数据少13个小时...

    通过show variables like '%time_zone%'; 查看时区: CST 时区 名为 CST 的时区是一个很混乱的时区,有四种含义: 美国中部时间 Central Standard ...

  10. 反转二叉树 Java代码 (二叉树,中序遍历,层序遍历)【PAT甲级1102】

    输入样例: 8 1 - - - 0 - 2 7 - - - - 5 - 4 6 输出样例: 3 7 2 6 4 0 5 1 6 5 7 4 3 2 0 1 算法思路: 要将二叉树翻转,可以先按题意建好 ...

最新文章

  1. leetcode算法题--煎饼排序
  2. mysql 5.5半同步复制_MySQL5.5配置安装半同步复制
  3. 笔记-信息系统开发基础-CMMI组织能力成熟度模型-连续式和阶梯式的分组
  4. Spring 多线程下注入bean问题
  5. 为什么说学人工智能一定要学Python?
  6. 20155216 Exp5 MSF基础应用
  7. Python 爬虫利器 Beautiful Soup 4 之文档树的搜索
  8. java:退出功能_Java 8:功能VS传统
  9. Mysql错误2003 -Can't connect toMySQL server on 'localhost'(10061)解决办法
  10. 人脸识别技术已成考勤门禁行业发展趋势
  11. 【Java】随机姓名的生成
  12. linux 终端复制剪贴板,命令行剪贴板复制和粘贴工具?
  13. 中国电信物联网开发平台北向开发获取设备ID及其历史产生的数据
  14. 让你越来越值钱的秘密:目标清单
  15. 计算机启动 滴的一声,电脑开机后滴的一声是什么意思?
  16. 基于Opencv的简单双摄像头图像实时拼接
  17. 2021考研数学汤家凤大纲解析
  18. 数据通信与计算机网络课后习题
  19. np.random.rand()函数
  20. 华为校招上机Java_2014年华为校园招聘Java上机笔试题

热门文章

  1. Codeforces 832 D Misha, Grisha and Underground
  2. Web开发HTTP中URI和URL的情感纠葛
  3. 借Java EE守护者联盟之力拯救Java EE
  4. Linux下模拟多线程的并发并发shell脚本
  5. CLR读书笔记--第三章 共享程序集和强命名程序集
  6. 【分析】浅谈C#中Control的Invoke与BeginInvoke在主副线程中的执行顺序和区别(SamWang)...
  7. 9 内存模型和名称空间
  8. Interpreting and Disentangling Feature Components of Various Complexity from DNNS论文解读
  9. 开发必学的验证码,教你从零写一个验证码
  10. centos7安装最新稳定版nginx