前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 异常面试问题与解答

Java 异常面试问题与解答

作者头像
淡定的蜗牛
修改2019-11-01 17:40:34
9030
修改2019-11-01 17:40:34
举报
文章被收录于专栏:Java知己Java知己

Java 提供了一种健壮且面向对象的方法来处理称为 Java异常处理的异常情况。

1. Java中的异常是什么?

异常是在程序执行期间可能发生的错误事件,它会破坏其正常流程。异常可能源于各种情况,例如用户输入的错误数据,硬件故障,网络连接故障等。

每当执行 Java 语句时发生任何错误,都会创建一个异常对象,然后 JRE尝试查找异常处理程序来处理该异常。如果找到了合适的异常处理程序,则将异常对象传递到处理程序代码以处理异常,称为捕获异常。如果未找到处理程序,则应用程序将异常抛出给运行时环境,并且 JRE 终止程序。

Java 异常处理框架仅用于处理运行时错误,异常处理框架不处理编译时错误。

2.Java 中的异常处理关键字是什么?

java 异常处理中使用了四个关键字。

  1. throw:有时我们明确地想要创建异常对象,然后将其抛出以停止程序的正常处理。throw 关键字用于向运行时抛出异常以进行处理。
  2. throws:当我们在方法中抛出任何已检查的异常并且不对其进行处理时,我们需要在方法签名时使用 throws 关键字,以使调用方程序知道该方法可能抛出的异常。调用方方法可以处理这些异常,也可以使用throws关键字将其传播到其调用方方法。我们可以在 throws 子句中提供多个异常,它也可以与 main()方法一起使用。
  3. try-catch:我们在代码中使用 try-catch 块进行异常处理。try 是块的开始,catch 是 try 块的末尾,用于处理异常。我们可以使用 try 捕获多个 catch 块,并且 try-catch 块也可以嵌套。catch 块需要一个应为 Exception 类型的参数。
  4. finally:finally 块是可选的,只能与 try-catch 块一起使用。由于异常会暂停执行过程,因此我们可能会打开一些不会关闭的资源,因此可以使用 finally 块。无论是否发生异常,finally 块都会始终执行。3.解释Java异常层次结构?Java 异常是分层的,继承用于对不同类型的异常进行分类。Throwable是 Java 异常层次结构的父类,它有两个子对象– ErrorException。异常进一步分为检查异常和运行时异常。

Error是超出应用程序范围的特殊情况,无法预见并从中恢复,例如硬件故障,JVM 崩溃或内存不足错误。

Checked Exception 是我们可以在程序中预期并尝试从程序中恢复的异常情况,例如 FileNotFoundException。我们应该捕获该异常,并向用户提供有用的消息,并正确记录下来以进行调试。Exception是所有 “检查的异常” 的父类。

Runtime Exception是由错误的编程引起的,例如,尝试从 Array 中检索元素。在尝试检索元素之前,我们应该首先检查数组的长度,否则它可能ArrayIndexOutOfBoundException在运行时抛出。RuntimeException是所有运行时异常的父类。

准备面试的同学有福了,为大家收集整理了最新的BATJ面试资料、面试视频攻略,有需要的可以在公众号:「Java 知己」,发送「面试」获取。

4.Java异常类的重要方法是什么?

Exception及其所有子类均未提供任何特定方法,并且所有方法均在基类 Throwable 中定义。

  1. String getMessage() –此方法返回 Throwable 消息字符串,并且可以在通过其构造函数创建异常时提供该消息。
  2. String getLocalizedMessage() –提供此方法,以便子类可以重写它以向调用程序提供特定于语言环境的消息。此方法的 Throwable 类实现只需使用getMessage()方法即可返回异常消息。
  3. synchronized Throwable getCause() - 此方法返回异常原因或 null (原因未知)。
  4. String toString() –此方法以 String 格式返回有关 Throwable 的信息,返回的 String 包含 Throwable 类的名称和本地化消息。
  5. void printStackTrace() –此方法将堆栈跟踪信息打印到标准错误流,此方法已重载,我们可以传递 PrintStream 或 PrintWriter 作为参数,以将堆栈跟踪信息写入文件或流。5.解释 Java 7 ARM Feature和多捕获块?如果您在单个 try 块中捕获了很多异常,则您会注意到 catch 块代码看起来非常丑陋,并且主要由用于记录错误的冗余代码组成,请记住,Java 7 的功能之一就是多捕获块我们可以在单个 catch 块中捕获多个异常。具有此功能的 catch 块如下所示:
代码语言:txt
复制
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 块示例为:

代码语言:txt
复制
try (MyResource mr = new MyResource()) {
	System.out.println("MyResource created in try-with-resources");
} catch (Exception e) {
	e.printStackTrace();
}

6.Java中的 Checked 和 Unchecked 异常有什么区别?

1、检查异常应在代码中使用 try-catch 块进行处理,否则方法应使用 throws 关键字使调用者知道该方法可能抛出的检查异常。未经检查的异常不需要在程序中处理,也不需要在方法的 throws 子句中提及。

2.、Exception是所有Checked 异常的超类,而RuntimeException是所有Unchecked 的异常的超类。请注意,RuntimeException 是 Exception 的子类。

3、Checked 异常是需要在代码中处理的错误方案,否则您将获得编译时错误。例如,如果您使用 FileReader 读取文件,则可能会抛出该文件FileNotFoundException,我们必须将其在 try-catch 块中捕获,或再次将其抛出给调用方方法。Unchecked 异常通常是由不良的编程引起的,例如,在调用对象引用中的方法而不确保其不为 null 时,会引发 NullPointerException。例如,我可以编写一种方法来删除字符串中的所有元音。确保不传递空字符串对象是调用者的责任。我可能会更改处理这些情况的方法,但理想情况下,调用方应注意这一点。

7.Java中 throw 和 throws 之间的区别是什么?

throws 关键字与方法一起使用,以声明该方法可能抛出的异常,而 throw 关键字用于中断程序流,并将异常对象移交给运行时进行处理。

8.如何用 Java 编写自定义异常?

我们可以扩展Exception类或它的任何子类来创建我们的自定义异常类。自定义异常类可以具有自己的变量和方法,可用于将错误代码或其他与异常相关的信息传递给异常处理程序。

自定义异常的一个简单示例如下所示。

代码语言:txt
复制
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;
	}
	

}

9.什么是 Java 中的 OutOfMemoryError?

Java 中的 OutOfMemoryError 是 java.lang.VirtualMachineError 的子类,当 JVM 堆内存不足时,它会被 JVM 抛出。我们可以通过修改 java 选项提供更多内存来解决此错误。

$>java MyProgram -Xms1024m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=256m

10.有哪些不同的情况导致 “主线程异常”?

一些常见的主线程异常情况是:

  • main 线程中的 java.lang.UnsupportedClassVersionError 异常:当您的 Java 类是从另一个 JDK 版本编译的,而您试图从另一个 Java 版本运行它时,将发生此异常。
  • main 线程中的 java.lang.NoClassDefFoundError 异常:此异常有两种变体。第一个是您以. class 扩展名提供类全名的位置。第二种情况是找不到类时。
  • main 线程中的 java.lang.NoSuchMethodError 异常:当您尝试运行不具有 main 方法的类时,将发生此异常。
  • main 线程中的 java.lang.ArithmeticException 异常:每当从 main 方法抛出任何异常时,它都会打印控制台异常。第一部分说明从 main 方法抛出异常,第二部分打印异常类名称,然后在冒号后打印异常消息。

11.Java中的 final,finally 和 finalize 有什么区别?

final 和 finally 是 Java 中的关键字,而 finalize 是一种方法。

  • final 关键字可以与类变量一起使用,以使它们不能被重新分配; class 可以避免通过类进行扩展; final 关键字可以与方法避免被子类覆盖;
  • finally 关键字可以与 try-catch 块一起使用,以提供将始终执行的语句即使出现某些异常,通常最终还是会用来关闭资源。
  • finalize()方法在对象被销毁之前由垃圾回收器执行,这是确保关闭所有全局资源的好方法。

在这三个中,只有finally 与 Java 异常处理有关。

12.当 main 方法抛出异常时会发生什么?

当 main()方法引发异常时,Java Runtime 将终止程序并在系统控制台中打印异常消息和堆栈跟踪。

13.我们可以有一个空的捕获块吗?

我们可以有一个空的 catch 块,但这是最糟糕的编程示例。我们永远不应该有空的 catch 块,因为如果异常被该块捕获,我们将没有有关该异常的信息,调试它将是一场噩梦。至少应该有一条日志记录语句,以将异常详细信息记录在控制台或日志文件中。

14.提供一些 Java 异常处理最佳实践吗?

与 Java 异常处理有关的一些最佳实践是:

  • 捕获特定异常可以简化调试。
  • 在程序中尽早抛出异常(Fast-Fast)。
  • 在程序后期捕获异常,让调用者处理异常。
  • 使用 Java 7 ARM 功能来确保资源被关闭,或者使用 finally 块来正确地关闭它们。
  • 始终记录异常消息以进行调试。
  • 使用多捕获块让代码更加清洁。
  • 使用自定义异常可以从应用程序 API 中引发单一类型的异常。
  • 遵循命名约定,始终以 Exception 结尾。
  • 使用 javadoc 中的 @throws 记录由方法引发的异常。
  • 异常的代价很高,因此仅在有意义时才抛出异常。否则,您可以捕获它们并返回null或不响应。

15.以下程序有什么问题,我们该如何解决?

在这里,我们将研究与 Java 异常相关的一些编程问题。

1). 下面的程序有什么问题?

代码语言:txt
复制
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{
		
	}
}

上面的程序无法编译,并且您会收到错误消息,“The exception FileNotFoundException is already caught by the alternative IOException”。这是因为 FileNotFoundException 是 IOException 的子类,有两种方法可以解决此问题。

第一种方法是对两个异常都使用单个 catch 块。

代码语言:txt
复制
try {
	testExceptions();
}catch(FileNotFoundException e){
	e.printStackTrace();
}catch (IOException  e) {
	e.printStackTrace();
}

另一种方法是从多捕获块中删除 FileNotFoundException。

代码语言:txt
复制
try {
	testExceptions();
}catch (IOException  e) {
	e.printStackTrace();
}

您可以根据情况选择任何一种方法。

2). 下面的程序有什么问题?

代码语言:txt
复制
package com.journaldev.exceptions;

import java.io.FileNotFoundException;
import java.io.IOException;

import javax.xml.bind.JAXBException;

public class TestException1 {

	public static void main(String[] args) {
			try {
				go();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (JAXBException e) {
				e.printStackTrace();
			}
	}

	public static void go() throws IOException, JAXBException, FileNotFoundException{
		
	}
}

该程序将编译错误,因为 FileNotFoundException 是 IOException 的子类,因此 FileNotFoundException 的 catch 块不可访问,并且您将收到错误消息 “ Unreachable catch block for FileNotFoundException. It is already handled by the catch block for IOException”。

您需要修复 catch 块顺序才能解决此问题。

代码语言:txt
复制
try {
	go();
} catch (FileNotFoundException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
} catch (JAXBException e) {
	e.printStackTrace();
}

请注意,JAXBException 与 IOException 或 FileNotFoundException 不相关,可以放置在以上 catch 块层次结构中的任何位置。

3). 下面的程序有什么问题?

代码语言:txt
复制
package com.journaldev.exceptions;

import java.io.IOException;

import javax.xml.bind.JAXBException;

public class TestException2 {

	public static void main(String[] args) {
		try {
			foo();
		} catch (IOException e) {
			e.printStackTrace();
		}catch(JAXBException e){
			e.printStackTrace();
		}catch(NullPointerException e){
			e.printStackTrace();
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	public static void foo() throws IOException{
		
	}
}

该程序将无法编译,因为 JAXBException 是一个已检查的异常,并且 foo()方法应抛出此异常以捕获调用方法。您将收到错误消息 “ JAXBException 无法访问的捕获块。不会从 try 语句主体中引发此异常。

要解决此问题,您将必须删除 JAXBException 的 catch 块。

注意,捕获 NullPointerException 是有效的,因为它是未经检查的异常。

4). 下面的程序有什么问题?

代码语言:txt
复制
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 子句中声明未经检查的异常,则在程序中处理该异常不是强制性的。

5). 下面的程序有什么问题?

代码语言:txt
复制
package com.journaldev.exceptions;

import java.io.IOException;

public class TestException4 {

	public void start() throws IOException{		
	}

	public void foo() throws NullPointerException{
		
	}
	}

	class TestException5 extends TestException4{

	public void start() throws Exception{
	}

	public void foo() throws RuntimeException{
		
	}
}

上面的程序无法编译,因为子类中的start()方法签名不同。要解决此问题,我们可以将子类中的方法特性更改为与超类完全相同,也可以从子类方法中删除throws子句,如下所示。

代码语言:txt
复制
@Override
public void start(){
}

6). 下面的程序有什么问题?

代码语言:txt
复制
package com.journaldev.exceptions;

import java.io.IOException;

import javax.xml.bind.JAXBException;

public class TestException6 {

	public static void main(String[] args) {
		try {
			foo();
		} catch (IOException | JAXBException e) {
			e = new Exception("");
			e.printStackTrace();
		}catch(Exception e){
			e = new Exception("");
			e.printStackTrace();
		}
	}

	public static void foo() throws IOException, JAXBException{
		
	}
}

上面的程序无法编译,因为多捕获块中的异常对象是最终对象,我们无法更改其值。由于“无法分配多捕获块的参数e”,将导致编译时错误。

我们必须删除对新异常对象的“ e”分配以解决此错误。


“不积跬步,无以至千里”,希望未来的你能:有梦为马 随处可栖!加油,少年!

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Java中的异常是什么?
  • 2.Java 中的异常处理关键字是什么?
  • 4.Java异常类的重要方法是什么?
  • 6.Java中的 Checked 和 Unchecked 异常有什么区别?
  • 7.Java中 throw 和 throws 之间的区别是什么?
  • 8.如何用 Java 编写自定义异常?
  • 9.什么是 Java 中的 OutOfMemoryError?
  • 10.有哪些不同的情况导致 “主线程异常”?
  • 11.Java中的 final,finally 和 finalize 有什么区别?
  • 12.当 main 方法抛出异常时会发生什么?
  • 13.我们可以有一个空的捕获块吗?
  • 14.提供一些 Java 异常处理最佳实践吗?
  • 15.以下程序有什么问题,我们该如何解决?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档