菜鸟BUG之常见异常(一)

雷声炸响, 天地倾斜,海啸山崩,黎明前的曙光迟迟不现,群魔乱舞霍乱人间,有仙师集群英之心血,持剑出山,剑斩群魔,终于仙巅同最后一大魔同归于尽,然有人的江湖便有魔,为警示后人,群贤集巨力书群魔以息,吾初入江湖,不懂是非挫折,对错难学,借此抄录,以备他日与同道之友交流。

目录

    • 一、空指针异常
      • 1、我是谁
      • 2、实例说明
      • 3、解决避免
        • 1)检查
        • 2)使用 Optional 类
        • 3)默认值
        • 4)优先使用String.valueOf()而不是toString()
        • 5)使用三元运算符
    • 二、数组下标越界异常
      • 1、下标越界
      • 2、解决避免
        • 1‌)范围检查‌
        • 2)异常处理‌
        • 3)增强for循环或迭代器遍历集合
        • 4)Stream API‌
        • 5)无效变量
        • 6)Arrays.copyOf
    • 三、类型转换异常
      • 1、异常原因
        • 1)上转型与下转型
        • 2)非兼容类型的强制转换
      • 2、解决避免
        • 1)使用 instanceof 检查
        • 2)泛型的使用
        • ‌3)检查类型兼容性‌
        • 4)适当的类型转换操作符‌
    • 四、非法参数异常
      • 1、说明
      • 2、常见异常及其解决
        • 1‌)空引用(Null Reference)‌
        • 2)‌参数越界‌
        • 3)不支持的参数类型‌
        • 4)参数格式错误‌
    • 五、字格式化异常
      • 1、说明
      • 2、常见原因
        • 1)字符串包含非数字字符‌
        • 2)空字符串或null
        • 3)字符串表示的数字超出范围
      • 3、解决方法
        • 1)try-catch块捕获
        • 2)检查格式
        • 3)字符串不为空
    • 总结

一、空指针异常

1、我是谁

1)空指针异常(NullPointerException),就是应用程序试图在需要对象的地方时其所需为null;或当程序试图使用一个未初始化的对象或者一个空对象时抛出此异常。
2)运行时异常,会编译通过不报错,但是运行时Runtime阶段会抛出NullPointException
3)什么是null,null就是没有地址

注意:

"“是有地址但是里面的内容是空的
好比做饭 null说明连锅都没有 而”"则是有锅没米

2、实例说明

1)数据库连接

	Connection con = DriverManager.forName(url,root,password);	

当url对应端口号、root用户、passwowd密码,有一个不正确时,数据库都不会正确连接,数据库连接对象con可能为空(null);若con为空时,调用数据库连接对象的close()方法就会抛出空指针异常

con.close()

2)String中对象为空
当执行String类的length()方法时,Str为null,没有长度,也会抛出空指针异常

String str = null;
str.length()

String中每次new(可以等价为1)中的 = 号类型),都是开辟了一个新的内存,都有一个新的内存地址。
这两种写法,效果一样,都是new了一个String类对象str,即在堆内存中开辟了一个新的空间。

String str = “abcd”;
String str = new String(“abcd”);

3)null为数组,访问长度,也会抛空指针异常。
注:成员变量,引用类型的默认值为null

private static String str; (str = null,默认 )
private static Connection con ;(con = null,不写默认为null)

3、解决避免

1)检查

在使用该对象时先对其进行检查判断,大大减少空指针异常的出现

	public class Main {
		
		public static void main(String[] args) {
  			String str = null;
    		if (str == null) {
        		throw new NullPointerException("str is null");
    		}
    		// 使用 str
    		String text = null;
    		int length = text.length();  
    		System.exit(0); //success
  		}
  		
} 
2)使用 Optional 类

Java 8引入的 Optional 类可以用于表示可能为 null 的值。这有助于避免直接使用 null。

import java.util.Optional;
public class Main {
 
  public static void main(String[] args) {
       // 获取一个可能为 null 的字符串
        Optional<String> optionalString = Optional.ofNullable(getStringValue());
 
        // 检查 Optional 对象是否有值
        if (optionalString.isPresent()) {
            // 如果有值,则打印它
            System.out.println(optionalString.get());
        } else {
            // 如果没有值,打印默认消息
            System.out.println("No value present");
        } 
    System.exit(0); //success
  }
   // 模拟一个可能返回 null 的方法
   public static String getStringValue() {
        // 模拟条件,可以返回 null 或非 null 值
        boolean returnsNull = Math.random() < 0.5;
 
        if (returnsNull) {
            return null;
        } else {
            return "Hello, World!";
        }
    }
    
}
3)默认值

当预期的引用可能为 null 时,提供一个默认值。

import java.util.Optional;
public class Main {
  public static void main(String[] args) {
       // 获取一个可能为 null 的字符串
       String text = Optional.ofNullable(getStringValue()).orElse("default");
        System.out.println(text);
        int length = text.length();
        System.out.println(length);
         System.exit(0); //success
  }
   // 模拟一个可能返回 null 的方法
    public static String getStringValue() {
        // 模拟条件,可以返回 null 或非 null 值
        boolean returnsNull = Math.random() < 0.5;
 
        if (returnsNull) {
            return null;
        } else {
            return "Hello, World!";
        }
    }
}
4)优先使用String.valueOf()而不是toString()

当你的应用程序代码如要一个对象的字符串来描述时,避免使用对象的toString方法。如果你的对象的引用为null,NullPointerException将会被抛出。反之,考虑使用静态方法String.valueOf(),该方法不会抛出任何异常并且在函数参数为null的情况下会打印null。

5)使用三元运算符

三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:
  boolean expression ? value1 : value2;
三元运算符能帮助我们避免NullPointerException.运算符具有这样的形式:首先,计算布尔表达式,如果表达式为true,value1被返回,否则value2被返回。我们能使用三元运算符来处理null指针,例如:
  String message = (str == null) ? “” : str.substring(0, 10);

二、数组下标越界异常

遇到过一个这样问题,数据导出时,一直报下标越界,查了老半天才发现发现表头和字段属性对不上。

1、下标越界

ArrayIndexOutOfBoundsException:指在访问数组时,使用的下标超出了数组的实际范围,导致程序运行时出现异常。其实就是我有三个糖,你非得要4个。
通常有下面几种情况
1)访问数组时下标超出数组长度‌:例如,一个数组有5个元素,其下标范围是0到4,如果尝试访问array,就会抛出。
2)负数作为下标‌:数组的下标不能为负数,尝试使用负数下标访问数组也会导致此异常。
3)遍历集合时错误的迭代器或索引‌:在遍历集合时,如果迭代器或索引使用不当,也可能导致下标越界异常。
4)并发修改错误:在多线程或并发环境中,当多个线程同时修改同一个数组或列表时,可能会导致下标越界问题。这是因为一个线程修改了数组或列表的长度,而另一个线程仍在使用旧的索引值访问该数据结构。

2、解决避免

1‌)范围检查‌

在访问数组元素之前,使用条件语句(如if语句)检查下标是否在合法范围内。


	if (i >= 0 && i < array.length) {
	    System.out.println(array[i]);
	}

2)异常处理‌

	try {
	    int value = array; // 越界访问
	} catch (ArrayIndexOutOfBoundsException e) {
	    System.out.println("数组下标越界异常");
	}

3)增强for循环或迭代器遍历集合

避免直接使用下标访问集合元素,减少下标越界的风险。

4)Stream API‌

通过Java 8的Stream API来操作集合,避免直接操作下标。

5)无效变量

确保用作下标的变量始终包含有效的数字,并且在使用前已正确初始化。

6)Arrays.copyOf

如果需要创建比原始数组大的副本,使用Arrays.copyOf方法,它会创建一个新的数组并调整长度,避免下标越界问题。

三、类型转换异常

最常见的类型转换异常是ClassCastException。当试图将一个对象强制转换为不兼容的类型时,就会抛出这个异常,尤其是在处理多态性和泛型时常见。
就好像将一个父类的对象强制转换为一个子类,而该对象并不实际是子类类型的实例,就会引发此异常。

1、异常原因

1)上转型与下转型

上转型(Upcasting):将一个子类对象赋值给父类引用。这种转换是隐式且安全的,因为子类对象总是可以视为父类的实例

Parent p = new Child();  // 上转型,合法且安全

下转型(Downcasting):将一个父类引用强制转换为子类引用。这种转换在语法上是允许的,但只有当对象本身确实是子类实例时才是合法的,否则会抛出 ClassCastException

	Parent p = new Child();
	Child c = (Child) p;  // 下转型,合法且安全
	
	Parent p2 = new Parent();
	Child c2 = (Child) p2;  // 下转型,不安全,抛出 ClassCastException
	
2)非兼容类型的强制转换

将不相关或非兼容的类进行强制转换也会导致 ClassCastException


	Object obj = "This is a string";
	Integer number = (Integer) obj;  // 抛出 ClassCastException
	

2、解决避免

1)使用 instanceof 检查

进行类型转换之前,使用 instanceof 关键字检查对象是否为目标类型的实例


	if (myAnimal instanceof Cat) {
	    Cat myCat = (Cat) myAnimal;
	    // Safe to use myCat
	} else {
	    System.out.println("myAnimal is not an instance of Cat");
	}

2)泛型的使用

Java 中,泛型可以帮助在编译时检测类型不兼容的情况,从而减少运行时类型转换错误的可能性。泛型提供了更强的类型安全性,避免了不必要的强制类型转换

‌3)检查类型兼容性‌

在进行类型转换之前,确保源类型与目标类型之间存在兼容关系。

4)适当的类型转换操作符‌

使用适当的类型转换操作符进行转换。例如,使用(double)将整数转换为浮点数,使用intValue()将浮点数转换为整数‌。

四、非法参数异常

1、说明

非法参数异常(IllegalArgumentException)‌通常表示在方法或构造函数中传递了不合法或不允许的参数,这可能是由于参数的值不在预期范围内、类型不匹配或其他原因导致的。

2、常见异常及其解决

1‌)空引用(Null Reference)‌

如果传递了一个null参数,而方法或构造函数不允许接受null,可以添加对null的检查和处理。


	if (parameter == null) {
	    throw new IllegalArgumentException("Parameter cannot be null");
	}

2)‌参数越界‌

如果传递的参数值不在预期范围内,例如负数或超出数组边界,可以添加范围检查。

	
	if (value < minValue || value > maxValue) {
	    throw new IllegalArgumentException("Value out of range");
	}

3)不支持的参数类型‌

如果传递的参数类型不符合方法或构造函数的预期类型,可以进行类型检查。

	
	if (!(parameter instanceof ExpectedType)) {
	    throw new IllegalArgumentException("Invalid parameter type");
	}

4)参数格式错误‌

如果传递的字符串参数无法正确解析为所需的格式,可以添加格式检查和解析逻辑。

	
	try {
	    int parsedValue = Integer.parseInt(parameter);
	} catch (NumberFormatException e) {
	    throw new IllegalArgumentException("Invalid integer format");
	}

五、字格式化异常

1、说明

数字格式化(NumberFormatException)即尝试将一个格式不正确的字符串转换为数字类型

2、常见原因

1)字符串包含非数字字符‌

如果字符串中包含字母、特殊字符或空格等非数字字符,转换时会抛出NumberFormatException。例如,字符串"123a"包含字母"a",无法转换为整数‌。

2)空字符串或null

尝试将空字符串或null转换为数字时,会抛出NumberFormatException。例如,Integer.parseInt(null)或Integer.parseInt(“”)都会抛出异常‌。

3)字符串表示的数字超出范围

如果字符串表示的数字超出了目标类型的范围,例如将一个超出int范围的大整数字符串转换为int类型时,也会抛出NumberFormatException‌。

3、解决方法

1)try-catch块捕获

在进行字符串到数字的转换时,可以使用try-catch块来捕获NumberFormatException,并在catch块中处理异常情况。

	
	try {
	    int number = Integer.parseInt(numberStr);
	} catch (NumberFormatException e) {
	    System.out.println("格式错误,无法将字符串转换为数字");
	}

2)检查格式

在转换前使用正则表达式或其他验证方法检查字符串是否只包含数字字符。例如,使用String.matches(“\d+”)来检查字符串是否只包含数字。


	if (numberStr.matches("\\d+")) {
	    int number = Integer.parseInt(numberStr);
	} else {
	    System.out.println("字符串格式不正确");
	}

3)字符串不为空

在转换前检查字符串是否为null或空,以避免NumberFormatException。


	if (numberStr != null && !numberStr.isEmpty()) {
	    int number = Integer.parseInt(numberStr);
	} else {
	    System.out.println("字符串不能为空或null");
	}

总结

借贤基础夯实,以心细如发,思逻辑之完整,索思维须严谨,
多法得以尝试,代码求精炼,debug手中剑,群魔皆退散。

你可能感兴趣的:(菜鸟BUG,bug,数据库,java)