java 异常面试问题
Java provides a robust and object-oriented approach to handle exception scenarios known as Java Exception Handling.
Java提供了一种健壮且面向对象的方法来处理称为Java异常处理的异常情况。
Sometime back I wrote a long post on Exception Handling in Java and today I am listing some important Java Exceptions Questions with Answers to help you in interviews.
有时我写了一篇有关Java异常处理的长篇文章,今天我列出一些重要的Java异常问题和答案,以帮助您进行面试。
Exception is an error event that can happen during the execution of a program and disrupts it’s normal flow. Exception can arise from different kind of situations such as wrong data entered by user, hardware failure, network connection failure etc.
Whenever any error occurs while executing a java statement, an exception object is created and then JRE tries to find exception handler to handle the exception. If suitable exception handler is found then the exception object is passed to the handler code to process the exception, known as catching the exception. If no handler is found then application throws the exception to runtime environment and JRE terminates the program.
Java Exception handling framework is used to handle runtime errors only, compile time errors are not handled by exception handling framework.
异常是在程序执行期间可能发生的错误事件,它会破坏其正常流程。 异常可能源于各种情况,例如用户输入的错误数据,硬件故障,网络连接故障等。
只要在执行Java语句时发生任何错误,就会创建一个异常对象,然后JRE尝试查找异常处理程序来处理该异常。 如果找到合适的异常处理程序,则将异常对象传递到处理程序代码以处理异常,称为捕获异常 。 如果未找到处理程序,则应用程序将异常抛出给运行时环境,并且JRE终止程序。
Java异常处理框架仅用于处理运行时错误,异常处理框架不处理编译时错误。
There are four keywords used in java exception handling.
throws
keyword. We can provide multiple exceptions in the throws clause and it can be used with main() method also.java异常处理中使用了四个关键字。
throws
关键字将其传播到其调用方方法。 我们可以在throws子句中提供多个异常,它也可以与main()方法一起使用。 Java Exceptions are hierarchical and inheritance is used to categorize different types of exceptions. Throwable
is the parent class of Java Exceptions Hierarchy and it has two child objects – Error
and Exception
. Exceptions are further divided into checked exceptions and runtime exception.
Errors are exceptional scenarios that are out of scope of application and it’s not possible to anticipate and recover from them, for example hardware failure, JVM crash or out of memory error.
Checked Exceptions are exceptional scenarios that we can anticipate in a program and try to recover from it, for example FileNotFoundException. We should catch this exception and provide useful message to user and log it properly for debugging purpose. Exception
is the parent class of all Checked Exceptions.
Runtime Exceptions are caused by bad programming, for example trying to retrieve an element from the Array. We should check the length of array first before trying to retrieve the element otherwise it might throw ArrayIndexOutOfBoundException
at runtime. RuntimeException
is the parent class of all runtime exceptions.
Java异常是分层的, 继承用于对不同类型的异常进行分类。 Throwable
是Java Exceptions层次结构的父类,它具有两个子对象– Error
和Exception
。 异常进一步分为检查异常和运行时异常。
错误是超出应用程序范围的特殊情况,无法预见并从中恢复,例如硬件故障,JVM崩溃或内存不足错误。
Checked Exception是我们可以在程序中预期并尝试从程序中恢复的异常情况,例如FileNotFoundException。 我们应该捕获此异常,并向用户提供有用的消息,并正确记录它以进行调试。 Exception
是所有“检查的异常”的父类。
运行时异常是由错误的编程引起的,例如,尝试从Array中检索元素。 在尝试检索元素之前,我们应该首先检查数组的长度,否则它可能会在运行时引发ArrayIndexOutOfBoundException
。 RuntimeException
是所有运行时异常的父类。
Exception and all of it’s subclasses doesn’t provide any specific methods and all of the methods are defined in the base class Throwable.
getMessage()
method to return the exception message.异常及其所有子类均未提供任何特定方法,并且所有方法均在基类Throwable中定义。
getMessage()
方法即可返回异常消息。 If you are catching a lot of exceptions in a single try block, you will notice that catch block code looks very ugly and mostly consists of redundant code to log the error, keeping this in mind Java 7 one of the feature was multi-catch block where we can catch multiple exceptions in a single catch block. The catch block with this feature looks like below:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
Most of the time, we use finally block just to close the resources and sometimes we forget to close them and get runtime exceptions when the resources are exhausted. These exceptions are hard to debug and we might need to look into each place where we are using that type of resource to make sure we are closing it. So java 7 one of the improvement was try-with-resources where we can create a resource in the try statement itself and use it inside the try-catch block. When the execution comes out of try-catch block, runtime environment automatically close these resources. Sample of try-catch block with this improvement is:
Read more about this at Java 7 ARM.
如果您在单个try块中捕获了很多异常,则会注意到catch块代码看起来非常丑陋,并且主要由用于记录错误的冗余代码组成,请记住,Java 7的功能之一是多捕获块我们可以在单个catch块中捕获多个异常。 具有此功能的catch块如下所示:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
在大多数情况下,我们使用finally块只是为了关闭资源,有时我们忘记关闭它们并在资源耗尽时获取运行时异常。 这些异常很难调试,我们可能需要调查使用该类型资源的每个位置,以确保将其关闭。 因此,java 7的改进之一是try-with-resources ,我们可以在try语句本身中创建资源,并在try-catch块内使用它。 当执行从try-catch块执行时,运行时环境会自动关闭这些资源。 具有这种改进的try-catch块示例为:
在Java 7 ARM上了解有关此内容的更多信息。
Exception
is the super class of all checked exceptions whereas RuntimeException
is the super class of all unchecked exceptions. Note that RuntimeException is the child class of Exception.FileNotFoundException
and we must catch it in the try-catch block or throw it again to the caller method. Unchecked exceptions are mostly caused by poor programming, for example NullPointerException when invoking a method on an object reference without making sure that it’s not null. For example, I can write a method to remove all the vowels from the string. It’s the caller responsibility to make sure not to pass null string. I might change the method to handle these scenarios but ideally the caller should take care of this.Exception
是所有检查的异常的超类,而RuntimeException
是所有未检查的异常的超类。 请注意,RuntimeException是Exception的子类。 FileNotFoundException
,我们必须将其捕获在try-catch块中,或再次将其抛出给调用方方法。 未检查的异常通常是由不良的编程引起的,例如,调用对象引用上的方法而不确保其不为null时,会引发NullPointerException。 例如,我可以编写一种方法来删除字符串中的所有元音。 确保不传递空字符串是呼叫者的责任。 我可能会更改处理这些情况的方法,但理想情况下,调用方应注意这一点。 throws keyword is used with method signature to declare the exceptions that the method might throw whereas throw keyword is used to disrupt the flow of program and handing over the exception object to runtime to handle it.
throws关键字与方法签名一起使用,以声明该方法可能抛出的异常,而throw关键字用于中断程序流,并将异常对象移交给运行时进行处理。
We can extend Exception
class or any of it’s subclasses to create our custom exception class. The custom exception class can have it’s own variables and methods that we can use to pass error codes or other exception related information to the exception handler.
A simple example of custom exception is shown below.
package com.journaldev.exceptions;
import java.io.IOException;
public class MyException extends IOException {
private static final long serialVersionUID = 4664456874499611218L;
private String errorCode="Unknown_Exception";
public MyException(String message, String errorCode){
super(message);
this.errorCode=errorCode;
}
public String getErrorCode(){
return this.errorCode;
}
}
我们可以扩展Exception
类或它的任何子类来创建我们的自定义异常类。 自定义异常类可以具有自己的变量和方法,可用于将错误代码或其他与异常相关的信息传递给异常处理程序。
自定义异常的一个简单示例如下所示。
OutOfMemoryError in Java is a subclass of java.lang.VirtualMachineError and it’s thrown by JVM when it ran out of heap memory. We can fix this error by providing more memory to run the java application through java options.
$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
Java中的OutOfMemoryError是java.lang.VirtualMachineError的子类,当JVM堆内存不足时,它会被JVM抛出。 我们可以通过提供更多内存以通过java选项运行java应用程序来解决此错误。
$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m
Some of the common main thread exception scenarios are:
Read more about these at Java Exception in Thread main.
一些常见的主线程异常情况是:
在Thread main中的Java Exception上了解有关这些内容的更多信息。
final and finally are keywords in java whereas finalize is a method.
final keyword can be used with class variables so that they can’t be reassigned, with class to avoid extending by classes and with methods to avoid overriding by subclasses, finally keyword is used with try-catch block to provide statements that will always gets executed even if some exception arises, usually finally is used to close resources. finalize() method is executed by Garbage Collector before the object is destroyed, it’s great way to make sure all the global resources are closed.
Out of the three, only finally is related to java exception handling.
final和final是Java中的关键字,而finalize是一种方法。
final关键字可以与类变量一起使用,以使它们不能被重新分配; class可以避免通过类进行扩展; find关键字可以与方法避免被子类覆盖; finally关键字可以与try-catch块一起使用,以提供将始终执行的语句即使出现某些异常,通常最终还是会用来关闭资源。 finalize()方法在对象被销毁之前由垃圾收集器执行,这是确保关闭所有全局资源的好方法。
在这三个中,只有最后一个与Java异常处理有关。
When exception is thrown by main() method, Java Runtime terminates the program and print the exception message and stack trace in system console.
当main()方法引发异常时,Java Runtime将终止程序并在系统控制台中打印异常消息和堆栈跟踪。
We can have an empty catch block but it’s the example of worst programming. We should never have empty catch block because if the exception is caught by that block, we will have no information about the exception and it wil be a nightmare to debug it. There should be at least a logging statement to log the exception details in console or log files.
我们可以有一个空的catch块,但这是最糟糕的编程示例。 我们永远不应该有空的catch块,因为如果异常被该块捕获,我们将没有有关该异常的信息,调试它将是一场噩梦。 至少应该有一条日志记录语句,以将异常详细信息记录在控制台或日志文件中。
Some of the best practices related to Java Exception Handling are:
Read more about them in detail at Java Exception Handling Best Practices.
与Java异常处理有关的一些最佳实践是:
在Java异常处理最佳实践中详细了解有关它们的更多信息。
In this section, we will look into some programming questions related to java exceptions.
package com.journaldev.exceptions;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestException {
public static void main(String[] args) {
try {
testExceptions();
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
}
public static void testExceptions() throws IOException, FileNotFoundException{
}
}
Above program won’t compile and you will get error message as “The exception FileNotFoundException is already caught by the alternative IOException”. This is because FileNotFoundException is subclass of IOException, there are two ways to solve this problem.
First way is to use single catch block for both the exceptions.
Another way is to remove the FileNotFoundException from multi-catch block.
try {
testExceptions();
}catch (IOException e) {
e.printStackTrace();
}
You can chose any of these approach based on your catch block code.
The program won’t compile because FileNotFoundException is subclass of IOException, so the catch block of FileNotFoundException is unreachable and you will get error message as “Unreachable catch block for FileNotFoundException. It is already handled by the catch block for IOException”.
You need to fix the catch block order to solve this issue.
try {
go();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
Notice that JAXBException is not related to IOException or FileNotFoundException and can be put anywhere in above catch block hierarchy.
The program won’t compile because JAXBException is a checked exception and foo() method should throw this exception to catch in the calling method. You will get error message as “Unreachable catch block for JAXBException. This exception is never thrown from the try statement body”.
To solve this issue, you will have to remove the catch block of JAXBException.
Notice that catching NullPointerException is valid because it’s an unchecked exception.
package com.journaldev.exceptions;
public class TestException3 {
public static void main(String[] args) {
try{
bar();
}catch(NullPointerException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
foo();
}
public static void bar(){
}
public static void foo() throws NullPointerException{
}
}
This is a trick question, there is no problem with the code and it will compile successfully. We can always catch Exception or any unchecked exception even if it’s not in the throws clause of the method.
Similarly if a method (foo) declares unchecked exception in throws clause, it is not mandatory to handle that in the program.
The above program won’t compile because start() method signature is not same in subclass. To fix this issue, we can either change the method singnature in subclass to be exact same as superclass or we can remove throws clause from subclass method as shown below.
@Override
public void start(){
}
The above program won’t compile because exception object in multi-catch block is final and we can’t change it’s value. You will get compile time error as “The parameter e of a multi-catch block cannot be assigned”.
We have to remove the assignment of “e” to new exception object to solve this error.
Read more at Java 7 multi-catch block.
在本节中,我们将研究与Java异常相关的一些编程问题。
package com.journaldev.exceptions;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestException {
public static void main(String[] args) {
try {
testExceptions();
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
}
public static void testExceptions() throws IOException, FileNotFoundException{
}
}
上面的程序无法编译,并且您会收到错误消息,“备用IOException已捕获异常FileNotFoundException”。 这是因为FileNotFoundException是IOException的子类,有两种方法可以解决此问题。
第一种方法是对两个异常使用单个catch块。
另一种方法是从多捕获块中删除FileNotFoundException。
try {
testExceptions();
}catch (IOException e) {
e.printStackTrace();
}
您可以根据捕获代码选择任何一种方法。
该程序将无法编译,因为FileNotFoundException是IOException的子类,因此FileNotFoundException的catch块不可访问,您将收到错误消息“ FileNotFoundException的Unreachable catch块。 它已经由IOException的catch块处理”。
您需要修复catch块顺序才能解决此问题。
try {
go();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
请注意,JAXBException与IOException或FileNotFoundException不相关,可以放置在以上catch块层次结构中的任何位置。
该程序将无法编译,因为JAXBException是一个已检查的异常,并且foo()方法应抛出此异常以捕获调用方法。 您将收到错误消息“ JAXBException的不可达捕获块。 不会从try语句主体中引发此异常。
要解决此问题,您将必须删除JAXBException的catch块。
注意,捕获NullPointerException是有效的,因为它是未经检查的异常。
package com.journaldev.exceptions;
public class TestException3 {
public static void main(String[] args) {
try{
bar();
}catch(NullPointerException e){
e.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}
foo();
}
public static void bar(){
}
public static void foo() throws NullPointerException{
}
}
这是一个技巧问题,代码没有问题,它将成功编译。 我们总是可以捕获Exception或任何未经检查的异常,即使它不在方法的throws子句中也是如此。
同样,如果方法(foo)在throws子句中声明未经检查的异常,则在程序中处理该异常不是强制性的。
上面的程序无法编译,因为子类中的start()方法签名不相同。 要解决此问题,我们可以将子类中的方法特性更改为与超类完全相同,也可以从子类方法中删除throws子句,如下所示。
@Override
public void start(){
}
上面的程序将无法编译,因为多捕获块中的异常对象是最终对象,我们无法更改其值。 由于“无法分配多捕捉块的参数e”,将导致编译时错误。
我们必须删除对新异常对象的“ e”分配以解决此错误。
在Java 7 multi-catch块中了解更多信息。
Thats all for java exception interview questions, I hope you will like it. I will be adding more to the list in future, make sure you bookmark it for future use.
多数民众赞成在Java异常面试问题,希望您会喜欢。 我将来会在列表中添加更多内容,请确保将其添加为书签,以备将来使用。
翻译自: https://www.journaldev.com/2167/java-exception-interview-questions-and-answers
java 异常面试问题