首页 > 其他分享 >异常详解

异常详解

时间:2024-03-20 15:59:54浏览次数:19  
标签:java String 错误 方法 详解 异常 public

1.ArithmeticException:算数错误情形

常见异常场景:

1.当除数为0时,这种情况比较常见,所以我们在进行除法运算之前先判断下除数是否为0

2.如果运算的结果是无线循环的小数,并且在除的时候没有对结果设置精确的位数,这时就会抛出异常,这种情况比较容易被忽视,抛出异常后一般都会考虑是否为0,因此,要特别注意!!

3.当我们设置了BigDecimal结果的舍入模式是:ROUND_UNNECESSARY模式时,如果确保了计算的结果是精确的,则不会抛出异常,否则,就会抛出ArithmeticException异常!

注:ROUND_UNNECESSARY模式:舍入模式可以断言所请求的操作具有准确的结果,因此不需要舍入。如果在产生不精确结果的操作上指定了这种舍入模式,则会引发ArithmeticException。

超过精度则报错:例如 0.123456789保留4位小数则抛出异常

2.ArraylndexOutOfBoundsException: 数组下标越界

当你使用不合法的索引访问数组时会报数组越界这种错误,数组arr的合法错误范围是[0, arr.length-1];当你访问这之外的索引时会报这个错。例如:

public class Test {

public static void main(String[] args) {

int[] arr = {1, 2, 3};

for (int i = 0; i <= arr.length; i++) {

System.out.println(arr[i]);

}

}

}

控制台输出的错误提示:

java.lang.ArrayIndexOutOfBoundsException: 3

at Test.main(Test.java:5)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:606)

at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)

这种错误很像我们下面即将说的字符串索引越界,这种错误的错误信息后面部分与错误不大相关。但是,第1行就告诉我们错误的原因是数组越界了,在我们上面的例子,非法的索引值是3,下面一行的错误信息告诉你错误发生在Test类的第5行上,在main方法之内

3.NullPointerException: 尝试访问nul对象成员

当应用试图在要求使用对象的地方使用了null时,抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用throw语句抛出null等等。

比如说:

NewUserTotalInfoPO userTotalInfo = userDao.getMyTotalInfoByUuid(userId);

BigDecimal myGold = userTotalInfo.getGold();

很常用的,查找一个类型的数据,然后调用它的成员变量或方法。

但是我们一般需要在这里加一个:

if (userTotalInfo == null) {

throw new MyBusinessException(StatusCodeEnum.BUSSINESS_ERROR, "用户详细信息查询出错");

}

因为如果不判断,那么当userTotalInfo == null时(没有查找到该条数据)userTotalInfo.getGold();就会报错。更简单粗暴一点:

clipboard.png

如果需要使用的对象为null,就会报这个错误。

4.ClassNotFoundException: 不能加载所需的类:

说明

无法找到指定的类异常

这个异常提示名字已经非常友好了,就是告诉我们使用类加载器就加载某个类的时候,发现所有的path下面都没有找到,从引导类路径,扩展类路径到当前的classpath下全部没有找到,就会抛出上面的异常,最常见的例子就是加载JDBC驱动包的时候,它的依赖jar并不在classpath里面

当应用程序试图使用以下方法通过字符串名加载类时,抛出该异常:

* Class 类中的 forName 方法。

* ClassLoader 类中的 findSystemClass 方法。

* ClassLoader 类中的 loadClass 方法。

但是没有找到具有指定名称的类的定义。

常见的原因

1 所需要的支持类库放错了地方,并没有放在类路径(CLASSPATH环境变量)里面。

2 使用了重复的类库,且版本不一致。导致低版本的被优先使用。

3 类名错了,一般是使用Class.forName的时候,手工指定了类名的情况。

4 没有导入纯JAVA驱动包。

解决方案

1 确认你的类库在系统的CLASSPATH下面,如果是Tomcat,则可以放在tomcat/lib/目录下面。

2 删除重复的类库,只保留最新的。

3 尽可能不使用这种编译器无法为你检查的方式。

5.InputMismatchException: 欲得到的数据类型与实际输入的类型不匹配

一、写在前面

InputMismatchException异常是输入不匹配异常,即输入的值数据类型与设置的值数据类型不能匹配。

二、异常的出现原因

在使用Scanner进行输入时,报出InputMismatchException异常,其代码如下:

这种异常往往都和scanner类型的对象相关

public static void main(String[] args)

{

Scanner sc=new Scanner(System.in);

System.out.println("请输入一个数字:");

int x=sc.nextInt();

System.out.println("请输入一个字符串:");

String str=sc.nextLine();

System.out.println("请再输入同一个数字:");

int y=sc.nextInt();

}

从Java 1.5开始引入Scanner类。此类接受File,InputStream,Path和String对象,使用正则表达式逐个令牌读取所有原始数据类型和String(从给定的源)令牌。

读取用来自源的各种数据类型nextXXX()由该类即提供的方法,nextInt(),nextShort(),nextFloat(),nextLong(),nextBigDecimal(),nextBigInteger(),nextLong(),nextShort(),nextDouble(),nextByte(),nextFloat(),next()。

每当您使用Scanner类从用户那里获取输入时。如果传递的输入与方法不匹配,则引发InputMisMatchException。例如,如果使用该nextInt()方法和在String中传递的值读取整数数据,则会发生异常。

6.llegalArgumentException: 方法接受到非法参数

抛出这个异常说明方法传入一个非法的或者不合适的参数。

举个例子:getUser(int username)方法,不允许传入空字符串或者null。但是有个调用的方法,没做检查,传入了null或者空字符串,这时候getUser方法就应该要抛出IllegalArgumentException告诉调用者:hi!这个参数不能为empty或者null。

java.lang.IllegalArgumentException继承至RuntimeException,所以它是一个unchecked异常,它不需要在方法里加throws声明!

如果在系统中出现这个异常,你唯一要做的就是检查传入的参数是否合法!所有的unchecked异常必须要用log记录下来的,所以exception message必须要描述的清楚--具体是哪个参数出错了。

再举一个生动一点的例子:

public static void main(String[] args) {

Date day = new Date();

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String date = df.format(day);

SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM");

String format = dateFormat.format(date);

System.out.println(format);

}

clipboard.png

比如说这个就是参数不合法导致的,提示中的19行指的是这句话:String format = dateFormat.format(date);这个函数的参数是符合格式要求的object,一般就是Date类型的数据,date是一个String数组,写入时不会编译错误,但是运行时会报错。

7.ClassCastException: 对象强制类型转换出错

ClassCastException是JVM在检测到两个类型间转换不兼容时引发的运行时异常。此类错误通常会终止用户请求。在执行任何子系统的应用程序代码时都有可能发生ClassCastException异常。通过转换,可以指示Java编译器将给定类型的变量作为另一种变量来处理。对基础类型和用户定义类型都可以转换。Java语言规范定义了允许的转换,其中大多数可在编译时进行验证。不过,某些转换还需要运行时验证。如果在此运行时验证过程中检测到不兼容,JVM就会引发ClassCastException异常。

出现这个异常的原因如下:

1.一个类是数字类,而由于误操作,错误的将数字类向数字类转换改写成了数字类向字符串类的转换,从而产生了异常。

2.大部分原因是因为强制转换或者是SQL映射时发生了这个异常。

clipboard.png

如果时SQL出现了问题,那么很可能是这里的result类型和DAO层接口的接收参数类型不同

clipboard.png

8.NumberFormatException: 数字格式转换异常

当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常.

情况一,超出转换数值类型范围

情况二,转换值类型没有考虑值为空的状况

情况三,由于进制不同

总之这个异常的出现场景与数据类型转换紧密相连

举个例子:在这里使用的是BigDecimal的初始化方法,后面的字符串里只能识别数字,无法识别变量,因为没有数字这里就会报这个错误。

clipboard.png

9.ArrayStoreException : 试图将错误类型的对象存储到一个对象数组时抛出的异常

数据存储异常,写数组操作时,对象或数据类型不兼容,所以报这个异常的时候需要注意自己的数组是不是出现了问题:

如下所示:x[0]是字符串类型数组的一部分,当试图使用初始化整形的方式去初始化它的时候就会报错

clipboard.png

clipboard.png

在出现ArrayStoreException异常时应该对应着数组中的元素类型去查找错误,构造数组时应按照正确的类型来构造。

10.IndexOutOfBoundsException: 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出

ArrayIndexOutOfBoundsException的意思是数组索引越界异常,是因为在提取数据时在使用索引不正常导致的。

例如:

int[]nums={1,2,3,4,5,6,7,8,9};

int num=nums[9];//引发ArrayIndexOutOfBoundsException异常

上述代码中 int num=nums[9] 语句将会引发ArrayIndexOutOfBoundsException异常,原因是nums数组的容量为9,其访问的索引范围为0~8,因此产生索引越界异常。

注意:在使用循环语句访问数组需要特别注意,因为如果边界值控制不好,将会很容易产生ArrayIndexOutOfBoundsException异常。

另外需要注意的是String的spit用法,也很容易出现这样的问题:

clipboard.png

把spit划分之后的字符串放入数组,如果操作不当或者是在循环里面,就很容易出现数组下表越界的错误。

11.NoSuchElementException: 表明枚举中没有更多的元素

如果您尝试从空对象获取元素,或者使用Enumeration,Iterator或tokenizer的访问器方法(例如next()或nextElement())访问集合,数组或其他对象的内容,则尝试在到达对象(集合,数组或其他对象)的末尾后获取下一个元素,将生成NoSuchElementException。

情景:

Enumeration的nextElement()方法-Vector,HashTable等集合具有名为elements()的方法,该方法返回包含集合中所有元素的Enumeration(接口)对象。

使用此对象,可以使用nextElement()方法一个接一个地获取元素。

如果在空集合上调用此方法,或者在到达集合末尾后,将在运行时生成NosuchElementException。

实例:

import java.util.Enumeration;

import java.util.Vector;

public class EnumExample {

   public static void main(String args[]) {

      //实例化向量

      Vector<Integer> vec = new Vector<Integer>( );

      //填充向量

      vec.add(1254);

      vec.add(4587);

      //使用枚举检索元素

      Enumeration<Integer> en = vec.elements();

      System.out.println(en.nextElement());

      System.out.println(en.nextElement());

      //到达末尾后检索下一个元素

      System.out.println(en.nextElement());

   }

}

clipboard.png

12.IllegalThreadStateException - 试图非法改变线程状态,比方说试图启动一已经运行的线程

一般这个错误只会出现在多线程,队列等并行开发的情况中

源代码如下:

ThreadTest thread1 = new ThreadTest();

thread1.start();

thread1.start();

thread1.start();

But,今天测试上段demo的时候报错,如下:

Exception in thread "Main Thread" java.lang.IllegalThreadStateException

at java.lang.Thread.start(Thread.java:595)

at thread.ThreadTest.main(ThreadTest.java:19)

原因:

1. 同一个Thread不能重复调用start方法,跟线程的4中状态有关系....

2. 线程的4种状态:新生状态;可运行状态;阻塞状态;死亡状态

a. 新生状态:在调用start()方法之前

b. 可运行状态:调用start()方法后,系统为该线程分配除cpu外的所需资源,对于只有一个cpu的机器而言,任何时刻只能有一个处于可运行的线程占用处理机,获得cpu资源,此时系统正正运行线程的run()方法....

c. 阻塞状态:一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态。这是【不可运行】的状态,处于这种状态的线程在得到一个特定的事件后会转回可运行状态

d. 死亡状态:一个线程的run()运行完毕,stop()方法被调用或者在运行过程中出现了未捕获的异常时,线程进入死亡状态。

3. 线程的4中状态除了【可运行状态】与【阻塞状态】可以来回切换,其余的不可逆转

13.SecurityException: 如果Applet试图执行一被WWW浏览器安全设置所禁止的操作

定义:

SecurityException当调用方没有访问资源所需的权限时,将引发异常。 以下示例实例化一个对象,该对象包含一个PermissionSetUIPermission对象,该对象允许访问 UI 对象和剪贴板以及RegistryPermission阻止注册表访问的对象。 对方法的 PermissionSet.PermitOnly 调用意味着,无论分配给调用方的权限如何,这些权限都将适用。 因此,尝试创建注册表项会引发一个 SecurityException

构造函数:

SecurityException()

使用默认属性初始化 SecurityException 类的新实例。

SecurityException(SerializationInfo, StreamingContext)

用序列化数据初始化 SecurityException 类的新实例。

SecurityException(String)

用指定的错误消息初始化 SecurityException 类的新实例。

SecurityException(String, Exception)

使用指定的错误消息和对作为此异常原因的内部异常的引用来初始化 SecurityException 类的新实例。

SecurityException(String, Type)

利用指定错误消息以及引发异常的权限类型来初始化 SecurityException 类的新实例。

SecurityException(String, Type, String)

使用指定的错误消息、引发异常的权限类型和权限状态来初始化 SecurityException 类的新实例。

14.IncompatibleClassChangeException : 如改变了某一类定义,却没有重新编译其他引用了这个类的对象。

如某一成员变量的声明被从静态改变为非静态,但其他引用了这个变量的类却没有重新编译,或者相反。如删除了类声明中的某一域或方法,但没有重新编译那些引用了这个域或方法的类:

错误场景1

在项目中遇到此报错的实例。这个错误官方解释是:在某些类定义发生不兼容的类更改时发生,当前执行方法所依赖的某个类的定义已更改。

public class B extends A{

}

public class A{

// 这是更改前的代码

public transient final Logger log = LoggerFactory.getLogger(getClass);

// 这是更改后的代码

public static final Logger log = LoggerFactory.getLogger(A.Class);

}

在这种情况下就有可能会出现java.lang.IncompatibleClassChangeError 这个异常;

.getClass()是一个对象实例的方法,只有对象实例才有这个方法,具体的类是没有的。类的Class类实例是通过.class获得的,显然,类没有.getClass()方法。

最主要的原因是:**Class.forName()和getClass()是在运行时加载;Class.class是在编译器加载,即.class是静态加载,.getClass()是动态加载。**在更改代码之后java虚拟机在编译时期以及运行时期会认为获取的对象并不是同一个。

错误场景2

1:项目中导入的jar包冲突;或者同一个jar包依赖了两个不同的版本号

2:jar包位置在maven中的顺序有问题,导致找不到依赖

<dependency>

<groupId>org.apache.shiro</groupId>

<artifactId>shiro-quartz</artifactId>

<version>1.2.4</version>

</dependency>

<dependency>

<groupId>org.shiro-scheduler</groupId>

<artifactId>quartz</artifactId>

<version>2.2.4</version>

</dependency>

15.OutOfMemoryException - 内存不足,通常发生于创建对象之时

16.NoClassDefFoundException - JAVA运行时系统找不到所引用的类

NoClassDefFoundError这个异常,严格来说不能叫异常,这种级别属于JVM的ERROR错误了,其严重级别要更高。

这个错误,主要有两种情况:

(1)编译时存在某个类,但是运行时却找不到,如下:

public class A {

public void hello(){

System.out.println("A hello");

}

}

class B {

public static void main(String[] args) {

A a=new A();

}

}

上面的Java类编译后会生成两个类文件,一个A.class,一个B.class,现在我在编译后,删掉了A的class文件,然后直接执行B的main方法,就会抛出 NoClassDefFoundError错误,因为当执行到 A a=new A();这一步的时候,jvm认为这个类肯定在当前的classpath里面的,要不然编译都不会通过,更不用提执行了。既然它存在,那么在jvm里面一定能找到,如果不能找到,那就说明出大事了,因为编译和运行不一致,所以直接抛出这个ERROR,代表问题很严重。

(2)第二种情况,类根本就没有初始化成功,结果你还把它当做正常类使用,所以这事也不小,必须抛出ERROR告诉你不能再使用了。

看下面的一段代码:

public class Loading {

static double i=1/0;//故意使得类初始化失败.

public static void print(){

System.out.println("123");

}

}

调用如下:

public static void main(String[] args) {

try {

double i=Loading.i;

}catch (Throwable e){

//此处,必须用Throwable,用Exception会直接退出.

System.out.println(e);

}

//继续使用.

Loading.print();

}

结果如下:

Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class class_loader.exception.Loading

java.lang.ExceptionInInitializerError

at class_loader.exception.NoClassFoundErrorTest.main(NoClassFoundErrorTest.java:18)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

注意这种情况比较特殊,并不是因为编译时和运行时环境不一致导致的,而是对于一个类如果初始化失败后,你还继续使用,那么JVM会认为是不正常的,由于它第一次调用已经失败,JVM就会假设后面继续调用肯定仍然会失败,所以直接抛ERROR给客户端。

这里需要注意,类初始化失败的异常是:

java.lang.ExceptionInInitializerError

也是一个严重级别的错误。

17.IncompatibleTypeException

18.BufferOverflowException

错误原因: 写入的长度超出了允许的长度:

例如下面的代码:

ByteBuffer params = ByteBuffer.allocate(2);// 这里只分配了2个字节,下面的params.put(tmp);却put了3个字节的数据。所以导致 java.nio.BufferOverflowException 异常

params.order(ByteOrder.LITTLE_ENDIAN);

byte[] tmp = new byte[3];

tmp[0] = (byte) data1;

tmp[1] = (byte) data2;

tmp[2] = (byte) data3;

params.put(tmp);

但实际使用中 ByteBuffer 的使用没有这么简单。

如何解决这个问题呢?

添加写入长度与 ByteBuffer 中可写入的长度的判断,例如:

while (writeBuffer.remaining() > 0) {

writeBuffer.put((byte)0);

}

注意:你每次只写入一个字节,那就判断大于0就好了,如果不是一个记得修改条件哦!

总结

当 ByteBuffer.remaining() 小于要读取或写入的长度时,再执行读取或写入操作都会产生异常;

读取则产生 java.nio.BufferUnderflowException 异常,

写入则产生 java.nio.BufferOverflowException 异常。

当 ByteBuffer.remaining() 等于 0 时,不能再执行读取或写入操作,需要执行:clear() 操作,否则将产生异常。

19.NoSuchFieldException: 请求的变量不存在

有时候使用反射进行Field相关操作的时候会出现这样异常,一般原因有两种:

1.本身就没有该Field;

2.有该Field,但是该Field是使用private修饰的,而在获取该Field的时候,需要使用getDeclaredField这个方法。

字段 (Field),是 Java 编程语言中类的一个成员,主要用来存储对象的状态(如同某些编程语言中的变量),所以有时也可称为成员字段或成员变量。

20.NoSuchMethodException:请求的方法不存在

21.llegalAccessException: 拒绝访问一个类的时候,抛出该异常。

22.StringIndexOutOfBoundsException |此异常由String方法抛出,指示索引或者为负,或者超出字符串的大小。

23.UnsupportedOperationException: 当不支持请求的操作时,抛出该异常。

标签:java,String,错误,方法,详解,异常,public
From: https://www.cnblogs.com/052160fh/p/18085392

相关文章

  • 一个入门级python爬虫教程详解
    前言当你需要每天对Excel做大量重复的操作,如果只靠人工来做既浪费时间,又十分枯燥,好在Python为我们提供了许多操作Excel的模块,能够让我们从繁琐的工作中腾出双手。今天就和大家分享一个快速处理Excel的模块openpyxl,它的功能相对与其他模块更为齐全,足够应对日常出......
  • C# 虚方法Virtual详解
    1.Virtual简介virtual关键字用于修改方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。Virtual方法可被任何继承它的类替代,虚拟成员的实现可由派生类中的替代成员更改。调用虚拟方法时,将为替代的成员检查该对象的运行时类型。将调用大部分派生类中的该替代成员,如果没......
  • Java数据类型详解(更新中)
    基本数据类型概览共8种:整型byte、short、int、long         浮点型float、double           字符型char           布尔型boolean大小1位即1bit,一字节(byte)等于8bit数据类型数据范围byte8位(一个字节)-127~128(2^7)short......
  • PCB板的技术详解和叠构剖析
    PCB板作为现代电子信息产业最重要的载体之一,应用在电子电路产业的方方面面,涵盖了智能手机,AI,显卡,电脑,家用电器,汽车电子等方方面面。本文就PCB板卡叠构做一些分析。1.PCB是什么?PCB也就是印刷电路板,通常指的是一种用于支持和连接电子组件的基板。PCB是电子设备中常见的组......
  • npm安装ionic出现异常:request to https://registry.npm.taobao.org/@ionic%2fcli fail
    异常: 异常是淘宝镜像过期了,现在淘宝镜像从https://registry.npm.taobao.org/换成了 https://registry.npmmirror.com查看npm的配置,查看淘宝镜像地址npmconfiglist 更换镜像地址npmconfigsetregistryhttps://registry.npmmirror.com再次运行ionic的安装命令成......
  • dotNet8 全局异常处理
    前言异常的处理在我们应用程序中是至关重要的,在dotNet中有很多异常处理的机制,比如MVC的异常筛选器,管道中间件定义trycatch捕获异常处理亦或者第三方的解决方案Hellang.Middleware.ProblemDetails等。MVC异常筛选器不太灵活,对管道的部分异常捕获不到,后两种方式大家项目应该......
  • 网络请求异常问题
    该篇文章记录总结一下,我在做前后端分离项目开发的过程中,所遇到的有关网络请求异常的前后端交互问题。(前端使用的是axios异步请求、后端使用fastAPI接口)一、段落上传部分最初报的错误如下图:   当时查阅了很多的资料,跟着网上所说的解答逐个排查错误,但是都还是没有解决......
  • nvm 下载新的Node(V18.19.0)版本,查看npm的版本出现异常Error: Cannot find module '@npm
    异常: 之前下载18.17.1查看npm也有问题ERROR:npmv9.6.7isknownnottorunonNode.jsv18.17.1. 大概意思是npm的版本是 v9.6.7单不能运行在v18.17.1的node上,但是node官网显示v18.17.1版本的node是适配v9.6.7的npm。这就很矛盾 最后找到的解决方案是升级nvm的版本......
  • 【一篇带你吃透接口】(详解版)
    这里写目录标题1.接口重要知识汇总2.接口使用的注意事项2.1重写的方法,子类的访问权限要大于等于父类2.2顺序:先继承再实现3.接口为什么能解决多继承问题4.类和接口之间的关系1.接口重要知识汇总1.接口是使用inteface方法来修饰的;2.接口当中不能有被实现的方法,只能有......
  • Vue3 Slot—插槽全家桶使用详解
    插槽是什么插槽slot就是子组件中提供给父组件使用的一个占位符,用<slot></slot>表示,父组件可以给这个占位符内填充任何模板代码,填充的内容会自动替换<slot></slot>标签。插槽被分为三种:匿名插槽、具名插槽、作用域插槽。1、匿名插槽没有名字的插槽就是匿名插槽,组件可以放......