一、异常与异常处理
1. 异常简介
在Java中,**异常是程序在执行过程中出现的问题或意外情况,导致程序无法按照预期的流程进行。**异常处理是Java中用于处理程序中出现的异常的一种机制。
Java中的异常可以分为两大类:受检查的异常(Checked Exceptions)和未受检查的异常(Unchecked Exceptions)。
1. 受检查的异常(Checked Exceptions):这些异常在编译时会被检查,必须显式地处理它们。例如,IOException、ClassNotFoundException等。
如果一个方法可能会抛出受检查的异常,那么该方法要么必须通过try-catch块来捕获并处理该异常,要么必须在方法签名中使用throws关键字来声明该异常。
try {
// 可能会抛出IOException的代码
} catch (IOException e) {
// 处理IOException的代码
}
2. 未受检查的异常(Unchecked Exceptions):这些异常在编译时不会进行检查,它们通常表示程序中的逻辑错误或运行时错误。例如,NullPointerException、ArrayIndexOutOfBoundsException等。如果一个方法可能会抛出未受检查的异常,那么该方法不需要在方法签名中使用throws关键字来声明该异常。
try {
// 可能会抛出NullPointerException的代码
} catch (NullPointerException e) {
// 处理NullPointerException的代码
}
除了try-catch块外,Java还提供了其他几种异常处理机制,包括:
- throws关键字:用于声明一个方法可能会抛出哪些受检查的异常。
- finally块:无论try块中是否发生异常,finally块中的代码都会执行。通常用于资源的清理操作,如关闭文件、数据库连接等。
- throw关键字:用于在方法内部手动抛出异常。当程序中发生异常时,可以使用throw关键字抛出异常,然后将其传递给调用该方法的代码进行处理。
- Java标准库中提供的多种异常类:Java标准库中提供了许多预定义的异常类,如IOException、SQLException等。这些异常类可以用于表示各种不同的错误情况,并且可以自定义新的异常类来表示应用程序特有的错误情况。
2.异常处理
在Java中,我们使用try-catch-finally语句块来处理异常。
try块包含可能会引发异常的代码,catch块用于捕获并处理特定的异常,而finally块包含的代码无论是否发生异常都会执行。下面是一个简单的例子:
public class Main {
public static void main(String[] args) {
try {
// 可能会引发异常的代码
int result = divide(10, 0);
System.out.println("The result is " + result);
} catch (ArithmeticException e) {
// 处理特定的异常
System.out.println("Cannot divide by zero!");
} finally {
// 无论是否发生异常都会执行的代码
System.out.println("This code is executed in every case.");
}
}
public static int divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Divisor cannot be zero");
}
return a / b;
}
}
结论:在这个例子中,我们有一个方法divide,如果除数为0,它会抛出一个ArithmeticException。在main方法中,我们调用divide方法,并使用try-catch-finally语句块来处理可能发生的异常。
- 如果除数不为0,那么程序会正常执行,并打印出结果。
- 如果除数为0,那么会触发ArithmeticException,程序会跳到catch块,打印出"Cannot divide by zero!"。
- 无论是否发生异常,finally块中的代码都会执行,打印出"This code is executed in every case."。
注意:如果可能抛出多个异常类型,你可以添加多个catch块来处理不同的异常。例如:
try {
// 可能会引发多种异常的代码
} catch (ArithmeticException e) {
// 处理ArithmeticException
} catch (NullPointerException e) {
// 处理NullPointerException
} finally {
// 无论是否发生异常都会执行的代码
}
3.异常抛出与自定义异常
在Java中,当一个方法遇到错误条件时,它会抛出一个异常。这是通过使用throw关键字完成的。
public class Main {
public static void main(String[] args) {
try {
// 创建一个新的Exception异常并抛出
throw new Exception("自定义异常");
}// 捕捉异常
catch (Exception e) {
e.printStackTrace();
}
}
}
自定义异常,你也可以创建自定义的异常类,这通常是通过继承Exception类或其子类来完成的。下面是一个自定义异常的例子:在这个例子中,我们创建了一个新的MyException类,它继承了Exception类。然后我们在try-catch块中抛出并捕获这个自定义异常。
class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
public class Main {
public static void main(String[] args) {
try {
throw new MyException("这是一个自定义异常");
} catch (MyException e) {
e.printStackTrace();
}
}
}
4. 异常链
在Java中,异常链(Exception chaining)是一种机制,通过它可以将一个异常与导致它的异常(或多个异常)关联起来。
作用:提高了代码的可维护性和可读性。详细如下几点
- 提供更多的上下文信息:通过将多个异常关联在一起,可以提供关于异常发生时的更多上下文信息。这有助于更准确地诊断和解决问题。
- 追踪异常来源:通过使用异常链,可以在处理异常时更方便地追踪异常的来源。这有助于确定问题的根本原因,以及如何采取适当的措施来避免或解决该问题。
- 简化异常处理:异常链使开发人员能够将多个异常处理逻辑集中在一个地方,而不是为每个异常单独编写处理代码。这有助于简化异常处理逻辑,并提高代码的可维护性。
- 提供更详细的错误报告:通过将多个异常关联在一起,可以提供更详细的错误报告。这有助于开发人员更好地理解问题的性质和范围,从而能够更快地解决问题。
实现:
异常链可以通过Throwable类的initCause(Throwable cause)方法实现。该方法允许在创建新的异常时,将一个已存在的异常作为原因(cause)与它关联起来。
这样,在捕获并处理异常时,我们可以使用Throwable类的getCause()方法获取导致当前异常的原始异常。
public class ExceptionChainExample {
public static void main(String[] args) {
try {
// 引发第一个异常
throw new Exception("First exception");
} catch (Exception e) {
// 在第一个异常的基础上引发第二个异常
e = new Exception("Second exception", e);
throw e;
}
}
}
在上面的代码中,我们首先抛出一个新的Exception对象,然后在捕获该异常时,我们创建一个新的Exception对象,并将原始的异常对象作为第二个参数传递给构造函数。这样,第二个异常就包含了导致它的原始异常。然后我们重新抛出这个新的异常。
当调用getCause()方法时,我们可以获取导致第二个异常的原始异常。
try {
// 引发第一个异常
throw new Exception("First exception");
} catch (Exception e) {
// 在第一个异常的基础上引发第二个异常
e = new Exception("Second exception", e);
throw e;
} catch (Throwable t) {
// 获取导致第二个异常的原始异常
Throwable cause = t.getCause();
System.out.println("Caused by: " + cause.getMessage());
}
例如在上面的代码中,我们捕获了第二个异常,并使用getCause()方法获取导致该异常的原始异常。然后我们打印出原始异常的消息。输出结果为:“Caused by: First exception”。
二、字符串
1、什么是字符串
在程序开发中字符串无处不在,如用户登陆时输入的用户名、密码等使用的就是字符串。其实,在前面的章节中我们就已经使用了字符串,例如我们在控制台中输出的 "Hello World" 、 "imooc" 、"爱慕课"等。
2、String类
在java语言中,字符串必须包含在一对双引号(" ")之内。
在Java中由双引号(" ")包围的都是字符串,不能作为其他数据类型来使用。
可以通过String str;语句来声明字符串变量。String:指定该变量为字符串类型。str:任意有效的标识符,表示字符串变量的名称。
声明的字符串变量必须经过初始化才能使用,否则编译器会报出“变量未被初始化错误”。
3、StringBuilder类
在Java中,除了可以使用 String 类来存储字符串,还可以使用 StringBuilder 类或 StringBuffer 类存储字符串。
程序运行时会额外创建一个对象,保存 "helloworld"。当频繁操作字符串时,就会额外产生很多临时变量。使用 StringBuilder 或 StringBuffer 就可以避免这个问题。至于 StringBuilder 和StringBuffer ,它们基本相似,不同之处,StringBuffer 是线程安全的,而 StringBuilder 则没有实现线程安全功能,所以性能略高。因此一般情况下,如果需要创建一个内容可变的字符串对象,应优先考虑使用 StringBuilder 类。
三、常用类库
在Java中,基本类型的包装类是对应于基本数据类型的类。它们可以将基本类型转换为对象,以便在需要对象参数的场合使用。这些包装类包括:Integer、Double、Boolean等等。
1. 基本类型的包装类:
基本类型的包装类是将基本类型封装成对象,以便在需要对象参数的场合使用。
每个基本类型都有一个对应的包装类,例如Integer、Double、Boolean等。
包装类的主要作用是提供了一些方法来操作基本类型,例如将基本类型转换为字符串、进行算术运算等。
2. Date类:
基本类型的包装类是将基本类型封装成对象,以便在需要对象参数的场合使用。
每个基本类型都有一个对应的包装类,例如Integer、Double、Boolean等。
包装类的主要作用是提供了一些方法来操作基本类型,例如将基本类型转换为字符串、进行算术运算等。
3. SimpleDateFormat类:
SimpleDateFormat类是一个日期时间格式化类,它可以将日期时间对象转换为字符串,也可以将字符串解析为日期时间对象。
你可以使用SimpleDateFormat类的构造方法创建一个格式化对象,并指定日期时间的格式。
SimpleDateFormat类提供了一些方法来格式化日期时间,例如format()方法将日期时间对象格式化为字符串。
另外,SimpleDateFormat类还提供了一些方法来解析字符串为日期时间对象,例如parse()方法将字符串解析为Date对象。
4. Calendar类:
Calendar类是Java的日期时间辅助类,它提供了一种方便的方式来处理日期和时间。
Calendar类提供了一些静态常量来表示日期和时间的各个部分,例如ERA、YEAR、MONTH、DAY_OF_MONTH等。
你可以使用Calendar类的构造方法创建一个Calendar对象,并使用set()方法设置日期和时间的各个部分。
Calendar类还提供了一些方法来获取当前日期和时间的各个部分,例如get()方法获取指定字段的值。
5. Math类:
Math类是Java的数学辅助类,它提供了一些静态方法来执行常见的数学运算,例如sqrt()方法计算平方根、log()方法计算自然对数等。
Math类还包含一些常量和常用函数的值,例如PI表示π的值、E表示自然对数的底数等。
你可以使用Math类的静态方法来执行数学运算,例如Math.sqrt(x)计算x的平方根。
总结:
通过学习这些常用类,你将能够更深入地理解Java中的基本数据类型,并能够进行基本类型和包装类之间的转换。你还可以掌握这些常用类的使用方法,以便在实际编程中更好地处理日期、时间和数学计算等问题。