谁会用java编程题库写出这个题啊!求大佬帮帮忙! 银行账户类的设计---定义类

上图可以简单展示一下异常类实现结构图,当然上图不是所有的异常,用户自己也可以自定义异常实现。上图已经足够帮我们解释和理解异常实现了:

1.所有的异常都是从Throwable继承而来的,是所有异常的共同祖先。

2.Throwable有两个子类,Error和Exception。其中Error是错误,对于所有的编译时期的错误以及系统错误都是通过Error抛出的。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。

3.Exception,是另外一个非常重要的异常子类。它规定的异常是程序本身可以处理的异常。异常和错误的区别是,异常是可以被处理的,而错误是没法处理的。 

可检查的异常,这是编码时非常常用的,所有checked exception都是需要在代码中处理的。它们的发生是可以预测的,正常的一种情况,可以合理的处理。比如IOException,或者一些自定义的异常。除了RuntimeException及其子类以外,都是checked exception。

在编写代码处理异常时,对于检查异常,有2种不同的处理方式:使用try…catch…finally语句块处理它。或者,在函数签名中使用throws 声明交给函数调用者caller去解决。

//try块中放可能发生异常的代码。 //如果执行完try且不发生异常,则接着去执行finally块和finally后面的代码(如果有的话)。 //如果发生异常,则尝试去匹配catch块。 //每一个catch块用于捕获并处理一个特定的异常,或者这异常类型的子类。Java7中可以将多个异常声明在一个catch中。 //catch后面的括号定义了异常类型和异常参数。如果异常与之匹配且是最先匹配到的,则虚拟机将使用这个catch块来处理异常。 //在catch块中可以使用这个块的异常参数来获取异常的相关信息。异常参数是这个catch块中的局部变量,其它块不能访问。 //如果当前try块中发生的异常在后续的所有catch中都没捕获到,则先去执行finally,然后到这个函数的外部caller中去匹配异常处理器。 //如果try中没有发生异常,则所有的catch块将被忽略。 //无论异常是否发生,异常是否匹配被处理,finally都会执行。 //一个try至少要有一个catch块,否则, 至少要有1个finally块。但是finally不是用来处理异常的,finally不会捕获异常。 //finally主要做一些清理工作,如流的关闭,数据库连接的关闭等。

1、try块中的局部变量和catch块中的局部变量(包括异常变量),以及finally中的局部变量,他们之间不可共享使用。

2、每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的,只有第一个匹配的catch会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义。

3、java中,异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方去。也就是说:当一个函数的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。
有的编程语言当异常被处理后,控制流会恢复到异常抛出点接着执行,这种策略叫做:resumption model of exception handling(恢复式异常处理模式 )

throws声明:如果一个方法内部的代码会抛出检查异常(checked exception),而方法自己又没有完全处理掉,则javac保证你必须在方法的签名上使用throws关键字声明这些可能抛出的异常,否则编译不通过。

throws是另一种处理异常的方式,它不同于try…catch…finally,throws仅仅是将函数中可能出现的异常向调用者声明,而自己则不具体处理。

采取这种异常处理的原因可能是:方法本身不知道如何处理这样的异常,或者说让调用者处理更好,调用者需要为可能发生的异常负责。

finally块不管异常是否发生,只要对应的try执行了,则它一定也执行。只有一种方法让finally块不执行:System.exit()。因此finally块通常用来做资源释放操作:关闭文件,关闭数据库连接等等。

良好的编程习惯是:在try块中打开资源,在finally块中清理释放这些资源。

1、finally块没有处理异常的能力。处理异常的只能是catch块。

2、在同一try…catch…finally块中 ,如果try中抛出异常,且有匹配的catch块,则先执行catch块,再执行finally块。如果没有catch块匹配,则先执行finally,然后去外面的调用者中寻找合适的catch块。

3、在同一try…catch…finally块中 ,try发生异常,且匹配的catch块中处理异常时也抛出异常,那么后面的finally也会执行:首先执行finally块,然后去外围调用者中寻找合适的catch块。

这是正常的情况,但是也有特例。关于finally有很多恶心,偏、怪、难的问题,详细看参考

程序员也可以通过throw语句手动显式的抛出一个异常。throw语句的后面必须是一个异常对象。

throw 语句必须写在函数中,执行throw 语句的地方就是一个异常抛出点,它和由JRE自动形成的异常抛出点没有任何差别。

在一些大型的,模块化的软件开发中,一旦一个地方发生异常,则如骨牌效应一样,将导致一连串的异常。假设B模块完成自己的逻辑需要调用A模块的方法,如果A模块发生异常,则B也将不能完成而发生异常,但是B在抛出异常时,会将A的异常信息掩盖掉,这将使得异常的根源信息丢失。异常的链化可以将多个模块的异常串联起来,使得异常信息不会丢失。

异常链化:以一个异常对象为参数构造新的异常对象。新的异对象将包含先前异常的信息。这项技术主要是异常类的一个带Throwable参数的函数来实现的。这个当做参数的异常,我们叫他根源异常(cause)。

查看Throwable类源码,可以发现里面有一个Throwable字段cause,就是它保存了构造时传递的根源异常参数。这种设计和链表的结点类设计如出一辙,因此形成链也是自然的了。

下面是一个例子,演示了异常的链化:从命令行输入2个int,将他们相加,输出。输入的数不是int,则导致getInputNumbers异常,从而导致add函数异常,则可以在add函数中抛出

//获取输入的2个整数返回

如果要自定义异常类,则扩展Exception类即可,因此这样的自定义异常都属于检查异常(checked exception)。如果要自定义非检查异常,则扩展自RuntimeException。

按照国际惯例,自定义的异常应该总是包含如下的构造函数:

  • 一个带有String参数的构造函数,并传递给父类的构造函数。
  • 一个带有String参数和Throwable参数,并都传递给父类构造函数
  • 一个带有Throwable 参数的构造函数,并传递给父类的构造函数。

下面是IOException类的完整源代码,可以借鉴。

1、当子类重写父类的带有 throws声明的函数时,其throws声明的异常必须在父类异常的可控范围内——用于处理父类的throws方法的异常处理器,必须也适用于子类的这个带throws方法 。这是为了支持多态。

至于为什么?我想,也许下面的例子可以说明。

//那么这里的try。。catch就不能处理Son中的异常。 //多态就不能实现了。

2、Java程序可以是多线程的。每一个线程都是一个独立的执行流,独立的函数调用栈。如果程序只有一个线程,那么没有被任何代码处理的异常 会导致程序终止。如果是多线程的,那么没有被任何代码处理的异常仅仅会导致异常所在的线程结束。

也就是说,Java中的异常是线程独立的,线程的问题应该由线程自己来解决,而不要委托到外部,也不会直接影响到其它线程的执行。

java里对异常的处理

java里对异常的处理有三种.

1 程序猿对有可能出现的异常使用try catch处理.

在函数中对可能出现的异常的代码进行try catch处理后,  程序会执行catch里的代码. 而且不会中断整个程序, 继续执行try catch后面的代码.

3.2 函数里并不处理异常, 使用throw or throws 关键字 把可能出现的异常抛给调用该函数的上级函数处理.

3 交给jvm虚拟机处理

如果没有处理异常,程序会抛给jvm处理.

jvm怎么处理呢,  就是中断整个程序, 并把异常信息输出到屏幕上.

首先会检查当前函数有没有try catch处理, 如果无检查上一级函数有无try..catch处理....
这样在函数栈里一级一级向上检查, 如果直至main函数都无try..catch, 则抛给jvm..

项目中强烈建议尽量手动处理, 不要把异常交给jvm.

可能出异常的若干行代码; 无论如何, 最终肯定会执行的代码

这种情况很简单, 就是try{}里面的代码被完整执行, 因为没有抛出任何异常, 就不会尝试执行catch里的部分, 直接到finally部分了.

如何确定要捕捉的异常名字.

也许有人会问, 我们怎么知道到底会抛出什么异常?

1.看代码凭经验, 例如看到1段除法的代码, 则有可能抛出算术异常.

3. 观察被调用函数的函数定义, 如果有throws后缀, 则可以尝试捕捉throws 后缀抛出的异常

包括我在内很多人会觉得finally语句简直多勾余, 既然是否捕捉到异常都会执行, 上面那个例子里的h()为什么不跟下面的k() 写在一起呢.

上面的例子的确看不出区别.

但下面两种情况下就体现了finally独特的重要性.

1 抛出了1个异常, 但是没有被任何catch子句捕捉成功.

例如try里面抛出了1个A异常,  但是只有后面只有捕捉B异常, 和C异常的子句. 

这种情况下, 程序直接执行finally{}里的子句,  然后中断当前函数, 把异常抛给上一级函数, 所以当前函数finally后面的语句不会被执行.

这种情况是编程的低级错误, 在项目中是不允许出现.

也就说, 这种情况下finally里的子句会在return回上一级function前执行. 而后面的k()就被放弃了.

可以看出, finally里的语句, 无论如何都会被执行.

至有两种情况除外, 一是断电, 二是exit函数.

在项目中, 我们一般在finally编写一些释放资源的动作, 例如初始化公共变量. 关闭connections, 关闭文件等.

1 无论如何最多只有1个catch被执行

这个上面提到过了, 一旦捕捉到1个异常, 就不会尝试捕捉其他异常.

首先看它先抛出哪个异常, 如果先抛出A,  如果捕捉到A, 那么就执行catch(A)里的代码. 然后finally.. B和C就没有机会再抛出了.

如果捕捉不到A, 就执行finally{}里的语句后中断当前函数, 抛给上一级函数...(应该避免)

2 有可能所有catch都没有被执行

两种情况, 1就是没有异常抛出, 另一种就是抛出了异常但是没有捕捉不到(应该避免)

3 先捕捉子类异常, 再捕捉父类异常, 否则编译失败

加入try 里面尝试捕捉两个异常, 1个是A, 1个是B, 但是A是B的父类.

原因也很简单, 加入把catch(A)写在前面, 因为多态的存在, 即使抛出了B异常, 也会被catch(A)捕捉, 后面的catch(B)就没有意义了.

也就是说如果捕捉Exception这个异常基类, 应该放在最后的catch里,  项目中也强烈建议这么做, 可以避免上述4.3.1的情况出现.

这个没什么好说的. 语法规则

每1个异常对象只能由catch它的catch子句里访问.

跟if类似, 不多说了.

下面开始详讲异常另一种处理方法throw 和 throws了.

注意的是, 这两种用法都没有真正的处理异常, 真正处理的异常方法只有try catch, 这两种方法只是交给上一级方法处理.

就如一个组织里 , 有1个大佬, 1个党主, 1个小弟.

大佬叫党主干活, 堂主叫小弟干活,  然后小弟碰上麻烦了,   但是小弟不会处理这个麻烦, 只能中断工作抛给党主处理, 然后堂主发现这个麻烦只有大佬能处理, 然后抛给大佬处理..

这里注意throw 出的是1个异常对象, 所以new不能省略

作用就是手动令程序抛出1个异常对象.

throw会中断当前函数, 当前函数执行失败(不完整)

当这个函数的if 判断了b=0时, 就利用throws手动抛出了1个异常.  这个异常会中断这个函数. 也就是说f()执行不完整, 是没有返回值的.

接下来哪个调用这个函数就会在调用这个函数的语句上收到异常.

例如上没的g()函数, 在调用f() 会收到1个异常.

这时g()函数有三种选择.

这时, g()收到f()里抛出的异常就会打断g()执行, 也就是说g()里面的k(); 被放弃了, 然后程序会继续把这个函数抛给调用g()函数.

然后一级一级寻求处理, 如果都不处理, 则抛给jvm处理.  jvm会中断程序, 输出异常信息. 这个上没提到过了.

如果catch成功, 则g()函数能完整执行, 而且这个异常不会继续向上抛.

如果catch失败(尽量避免), 则跟情况1相同.

注意 这里, IOException虽然逻辑上是错误的(完全不是IO的问题嘛), 但是在程序中完全可行, 因为程序猿可以根据需要控制程序指定抛出任何1个异常.

也就是上面这样,在方法定义里加上了throws子句.  告诉调用它的函数我可能抛出这个异常.

不过,这里调用f()方法的方法则必须处理这个异常

需要注意的是, catch里面要么写上throws对应的异常(这里是 IOException), 要么写上这个异常的超类, 否则还是编译失败.

这时候调用g()的函数也要考虑上面的这两种处理方法了... 

但是最终上级的方法(main 方法)还是不处理的话, 就编译失败, 上面说过了, 非runtimeException无法抛给jvm处理.

虽然这两种处理方法都能通过编译, 但是运行效果是完全不同的.

第一种, g()能完整执行.

也就是讲, thorws可以加上多个异常, 注意这里抛出的不是对象, 不能加上new.

而且不是告诉别人这个函数有可能抛出这么多个异常. 而是告诉别人, 有可能抛出这些异常的其中一种.

如果为f()函数加上throws后续, 则告诉调用f()的方法, f()函数有可能抛出这些异常的一种.

如果f() throws的都是RuntimeException, 则调用f()的函数可以不处理, 也能通过编译, 但是实际上还是强烈建议处理它们.

那么它有可能不抛出任何异常.(程序运行状态良好)

也有能抛出C异常(应该避免, 最好在throws上加上C)

什么时候应该用throws

这个是强制, 告诉别人这个函数内有炸弹.

2 一个函数内有可能由系统抛出异常.

这个是非强制的, 但是如果你知道一个函数内的代码有可能抛出异常, 最好还是写上throws 后缀

一般情况下,调用1个带有throws方法时怎么办

那么你就在当前函数写上

这样能处理能保证你的函数能完整执行, 不会被收到的异常中断.

当然如果你允许你的函数可以被中断, 那么就可以在当前函数定义加上throws A, B 继续抛给上一级的函数.

重写方法时, throws的范围不能大于超类的对应方法.

原因也是由于多态的存在.

因为1个超类的引用可以指向1个派生类的对象并调用不同的方法.  如果派生类throws的范围加大

面试问得多,单独拉出来写了:

6.3 一个方法最多只能throw1个异常, 但是可以throws多个种类异常

因为一旦一个函数throw出1个异常, 这个函数就会被中断执行, 后面的代码被放弃, 如果你尝试在函数内写两个throw, 编译失败.

而throws 是告诉别人这个函数有可能抛出这几种异常的一种. 但是最多只会抛出一种.

在任何一门面向对象编程的语言里,类(class)是非常基础、但也是非常重要的一项组成,通俗的说就是万般皆对象,而所说的对象就是我们生成的类。Kotlin也是如此,下面详细为大家介绍Kotlin中的类的组成结构、函数、声明等。

声明类的关键字为class

当类没有结构体的时候,大括号可以省略。即:

  • Kotlin中,允许有一个主构造函数和多个二级构造函数(辅助构造函数)。其中主构造函数是类头的一部分。
  • 主构造函数是类头的一部分,类名的后面跟上构造函数的关键字以及类型参数。

轻量级开源框架 目录 上一篇:轻量级开源框架 入门篇: 修改数据详解 ...

  • 在开发过程中,经常会碰到进行请求大量的网络图片的样例.假设处理的不好.非常easy造成oom.对于避免oom的方法,无非就是进行图片的压缩.及时的回收不用的图片.这些看似简单可是处理起来事实上涉及的知 ...

我要回帖

更多关于 java编程题库 的文章

 

随机推荐