1.捕获
在Java中,可以使用try-catch语句来捕获和处理异常。try块用于包含可能会引发异常的代码,catch块用于捕获和处理异常。如果在try块中发生了异常,程序将会跳转到对应的catch块,执行catch块中的代码来处理该异常。如果没有适配的catch块来处理异常,异常将会沿着调用栈一直向上抛出,直到被适配的catch块捕获或者程序终止。
以下是一个简单的示例,演示如何捕获和处理异常:
try {
// 可能会引发异常的代码
int result = 10 / 0; // 这里会抛出一个ArithmeticException异常
} catch (ArithmeticException e) {
// 捕获并处理异常
System.out.println("发生了算术异常: " + e.getMessage());
}
在上面的代码中,try块中的代码尝试计算10除以0,这会引发一个ArithmeticException异常。catch块使用了一个ArithmeticException的参数e来捕获该异常,并将异常信息打印出来。
除了使用catch块来处理异常外,Java还提供了finally块,该块中的代码无论是否发生了异常都会被执行。finally块通常用于释放资源或者执行一些清理操作。以下是一个带有finally块的示例:
try {
// 可能会引发异常的代码
int result = 10 / 0; // 这里会抛出一个ArithmeticException异常
} catch (ArithmeticException e) {
// 捕获并处理异常
System.out.println("发生了算术异常: " + e.getMessage());
} finally {
// 无论是否发生异常,都会执行这里的代码
System.out.println("finally块被执行");
}
在上面的代码中,无论是否发生了异常,finally块中的代码都会被执行。
除了使用catch块来捕获指定类型的异常外,还可以使用多个catch块来捕获不同类型的异常,并分别进行处理。可以根据异常的类型来决定如何处理异常。以下是一个使用多个catch块的示例:
try {
// 可能会引发异常的代码
int result = 10 / 0; // 这里会抛出一个ArithmeticException异常
} catch (ArithmeticException e) {
// 捕获并处理算术异常
System.out.println("发生了算术异常: " + e.getMessage());
} catch (NullPointerException e) {
// 捕获并处理空指针异常
System.out.println("发生了空指针异常: " + e.getMessage());
} catch (Exception e) {
// 捕获并处理其他类型的异常
System.out.println("发生了其他类型的异常: " + e.getMessage());
}
在上面的代码中,如果发生了算术异常,将会执行第一个catch块中的代码;如果发生了空指针异常,将会执行第二个catch块中的代码;如果发生了其他类型的异常,将会执行最后一个catch块中的代码。
抛出
Java中的异常是通过throw关键字抛出的。使用throw关键字后面跟随一个异常对象,表示要抛出的异常。例如:
public class Example {
public static void main(String[] args) {
try {
throw new Exception("This is an example exception.");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
在上述代码中,我们使用throw关键字抛出了一个Exception异常,并在try-catch块中捕获并处理了这个异常。
自定义异常类
在Java中,可以通过继承Exception或者RuntimeException类来自定义异常类。以下是一个自定义异常类的示例:
public class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}
在上述代码中,我们创建了一个名为CustomException的自定义异常类,它继承自Exception类。构造函数接受一个String类型的参数message,调用父类的构造函数来设置异常信息。
我们可以在程序中使用这个自定义异常类,例如:
public class Example {
public static void main(String[] args) {
try {
throw new CustomException("This is a custom exception.");
} catch (CustomException e) {
System.out.println(e.getMessage());
}
}
}
在上述代码中,我们使用throw关键字抛出了一个CustomException的实例,并在try-catch块中捕获并处理了这个自定义异常。
2.包装类
Java中的包装类是一种用于将基本数据类型封装为对象的类。每种基本数据类型都有对应的包装类,可以通过包装类来进行基本类型和对象类型之间的转换。
Java中的包装类分为两种:基本类型的包装类和大整数和大浮点数的包装类。
基本类型的包装类包括:
- Boolean:对应boolean类型
- Byte:对应byte类型
- Short:对应short类型
- Integer:对应int类型
- Long:对应long类型
- Float:对应float类型
- Double:对应double类型
- Character:对应char类型
大整数和大浮点数的包装类包括:
- BigInteger:用于表示任意大小的整数
- BigDecimal:用于表示任意大小的浮点数
包装类提供了一些常用的方法来操作基本类型的值,例如解析字符串、转换为字符串、比较大小等。
使用包装类的一个常见场景是在集合类中存储基本类型的值,因为集合类只能存储对象而不能存储基本类型。通过包装类,可以将基本类型的值封装为对象,然后存储到集合中。
以下是一个使用包装类的示例:
import java.util.ArrayList;
public class Example {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(10); // 自动装箱,将基本类型的值封装为对象
numbers.add(Integer.valueOf(20)); // 使用包装类的构造方法手动封装为对象
int x = numbers.get(0); // 自动拆箱,将对象转换为基本类型的值
int y = numbers.get(1).intValue(); // 使用包装类的方法手动获取基本类型的值
System.out.println(x); // 输出 10
System.out.println(y); // 输出 20
}
}
在上述代码中,我们创建了一个ArrayList对象来存储整数。通过使用Integer包装类,我们可以把整数封装为对象并存储到集合中。然后,我们可以通过自动拆箱或者手动调用包装类的方法来获取基本类型的值。
String(buffer、builder)
在Java中,有两个主要的字符串包装类:StringBuffer和StringBuilder。
- StringBuffer(字符串缓冲区): StringBuffer是一个可变的字符序列。它是线程安全的,这意味着可以同时由多个线程访问和修改,而不会发生问题。它提供了追加、插入、删除和修改字符的方法。StringBuffer比StringBuilder慢,因为它是同步的。
下面是使用StringBuffer的示例:
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("你好");
stringBuffer.append("世界");
stringBuffer.insert(2, "Java");
stringBuffer.deleteCharAt(7);
String result = stringBuffer.toString();
System.out.println(result); // 输出:你好Java世界
- StringBuilder(字符串构建器): StringBuilder也是一个可变的字符序列。它不是线程安全的,因此应该在单线程环境中使用。StringBuilder提供了与StringBuffer相同的一组方法,但由于没有同步,所以它更快。
下面是使用StringBuilder的示例:
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("你好");
stringBuilder.append("世界");
stringBuilder.insert(2, "Java");
stringBuilder.deleteCharAt(7);
String result = stringBuilder.toString();
System.out.println(result); // 输出:你好Java世界
在大多数情况下,StringBuffer和StringBuilder可以互相替换使用。在多线程环境中使用StringBuffer,在单线程环境中使用StringBuilder以获得更好的性能。
BigDecimal
Java中的BigDecimal类用于进行高精度和准确度的算术运算。它在处理不能使用原始数据类型(如double或float)准确表示的小数值时特别有用。
下面是一个简单的Java中使用BigDecimal的示例:
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("10.5");
BigDecimal num2 = new BigDecimal("2.3");
// 加法
BigDecimal sum = num1.add(num2);
System.out.println("和: " + sum);
// 减法
BigDecimal diff = num1.subtract(num2);
System.out.println("差: " + diff);
// 乘法
BigDecimal product = num1.multiply(num2);
System.out.println("积: " + product);
// 除法
BigDecimal quotient = num1.divide(num2, 2, BigDecimal.ROUND_HALF_UP);
System.out.println("商: " + quotient);
}
}
在上面的示例中,我们创建了两个BigDecimal对象num1和num2,分别用小数值"10.5"和"2.3"进行初始化。然后,我们使用BigDecimal类提供的方法执行加法、减法、乘法和除法等算术运算。
请注意,在执行除法时,我们指定了精度(小数位数)和舍入模式。在这个例子中,我们使用精度2和舍入模式ROUND_HALF_UP将结果四舍五入到2位小数。
3.泛型简介
泛型是Java中一种用于增强类型安全性并实现代码重用的机制。它允许在类或方法中使用类型参数,以在编译时指定具体的类型。通过使用泛型,可以在编译时捕获潜在的类型错误,并提供更好的代码复用性和可读性。
在Java中,泛型类和泛型方法可以在其定义中包含一个或多个类型参数。这些类型参数可以在类或方法的声明中使用,并在实例化或调用时传入具体的类型。使用泛型类或泛型方法时,可以确保只使用兼容的类型,并避免强制类型转换。
例如,可以创建一个泛型类来表示一个箱子,可以在其中存储任何类型的对象。这个箱子类可以定义一个类型参数,在实例化时指定具体的类型。这样一来,只能向箱子中存储指定类型的对象,并且可以在取出对象时避免进行类型转换。
泛型还可以与继承一起使用,以便在泛型类或方法中使用更具体的类型。通过使用通配符,可以在泛型类或方法中接受多个类型的参数,并将它们视为共同的父类类型。
总之,泛型是Java中一种强大的机制,可以增强类型安全性,提高代码的可读性和可维护性。它是现代Java编程中不可或缺的一部分。
列表
泛型列表是指能够存储任意类型对象的列表结构,使用泛型可以提供更灵活的数据结构,并且能够在编译时进行类型检查,避免类型错误。
在 Java 中,可以使用泛型类来实现泛型列表,例如:
public class GenericList<T> {
private List<T> list;
public GenericList() {
list = new ArrayList<>();
}
public void add(T item) {
list.add(item);
}
public T get(int index) {
return list.get(index);
}
// 其他操作方法...
}
使用泛型列表时,可以指定具体的类型参数,例如:
GenericList<String> stringList = new GenericList<>();
stringList.add("hello");
stringList.add("world");
String item = stringList.get(0); // "hello"
泛型列表可以存储任意类型的对象,例如字符串、整数、自定义类等,提供了更灵活的数据存储和访问方式。同时,由于泛型提供了类型检查,可以避免在编译时出现类型错误。
set
泛型set是指在编程语言中使用泛型机制来定义一个集合或容器,其中存储的元素可以是任意类型。
泛型set的好处是可以提高代码的复用性和灵活性。通过使用泛型,我们可以定义一个可以存储任意类型的集合,而不需要针对每种类型都定义一个单独的集合类。这使得集合类可以更加通用,并且可以在不同的场景中重复使用。
使用泛型set时,我们可以在定义集合对象时指定集合中元素的类型。例如,我们可以定义一个泛型set,其中只能存储整数类型的元素:
Set<Integer> intSet = new HashSet<Integer>();
这样,intSet对象只能存储整数类型的元素,如果尝试存储其他类型的元素,编译器会发出类型错误。
泛型set可以在编译时进行类型检查,确保集合中只能存储指定类型的元素,避免在运行时出现类型转换错误。它还可以提供更好的代码提示和类型安全,减少了运行时错误的可能性。
总结来说,泛型set是一种可以存储任意类型元素的集合,通过使用泛型机制,它可以提供更好的代码复用性、灵活性和类型安全性。
map
泛型map指的是能够存储任意类型键值对的数据结构,其中键和值的类型可以是任意类型。在Java中,可以使用泛型类来实现泛型map。例如:
public class GenericMap<K, V> {
private Map<K, V> map;
public GenericMap() {
map = new HashMap<>();
}
public void put(K key, V value) {
map.put(key, value);
}
public V get(K key) {
return map.get(key);
}
public boolean containsKey(K key) {
return map.containsKey(key);
}
}
这样,就可以创建一个泛型map对象,并存储不同类型的键值对:
GenericMap<String, Integer> map1 = new GenericMap<>();
map1.put("key1", 10);
map1.put("key2", 20);
int value1 = map1.get("key1");
GenericMap<Integer, String> map2 = new GenericMap<>();
map2.put(1, "value1");
map2.put(2, "value2");
String value2 = map2.get(2);
在上面的例子中,GenericMap
类是一个泛型类,使用了K
和V
作为占位符来表示键和值的类型。在创建map1
和map2
对象时,分别指定了不同的类型参数来表示键和值的类型。这样就可以在map对象中存储不同类型的键值对,而且在使用时会进行类型检查,避免了类型转换的问题。