### 8. 包装类的应用场景
#### 8.1 集合框架
包装类在Java集合框架中得到了广泛应用,因为集合只能存储对象而不能存储基本数据类型。
```java
 import java.util.HashMap;
public class CollectionExample {
     public static void main(String[] args) {
         HashMap<Integer, String> map = new HashMap<>();
         map.put(1, "one");  // 自动装箱
         map.put(2, "two");
         map.put(3, "three");
        for (Integer key : map.keySet()) {
             System.out.println("Key: " + key + ", Value: " + map.get(key));  // 自动拆箱
         }
     }
 }
 ```
在上述代码中,`Integer`包装类用于将基本类型`int`转换为对象,以便将其存储在`HashMap`中。
#### 8.2 类型转换
包装类提供了许多静态方法用于在不同类型之间进行转换。例如,`Integer`类的`parseInt`方法可以将字符串转换为整数,而`toString`方法可以将整数转换为字符串。
```java
 public class TypeConversionExample {
     public static void main(String[] args) {
         String strNumber = "100";
         int number = Integer.parseInt(strNumber);  // 字符串转整数
         String str = Integer.toString(number);  // 整数转字符串
        System.out.println("String to int: " + number);
         System.out.println("Int to string: " + str);
     }
 }
 ```
#### 8.3 数字格式化
包装类提供的方法可以帮助我们进行数字格式化和比较操作。例如,`Double`类中的`compareTo`方法可以用于比较两个双精度浮点数。
```java
 public class NumberFormattingExample {
     public static void main(String[] args) {
         Double num1 = 10.25;
         Double num2 = 20.50;
        int comparisonResult = num1.compareTo(num2);
         if (comparisonResult < 0) {
             System.out.println(num1 + " is less than " + num2);
         } else if (comparisonResult > 0) {
             System.out.println(num1 + " is greater than " + num2);
         } else {
             System.out.println(num1 + " is equal to " + num2);
         }
     }
 }
 ```
### 9. 包装类的常见问题和解决方案
#### 9.1 性能问题
频繁的装箱和拆箱操作会导致性能下降。在性能敏感的应用中,建议尽量使用基本数据类型而不是包装类。
```java
 public class PerformanceIssueExample {
     public static void main(String[] args) {
         long start = System.nanoTime();
         Integer sum = 0;
         for (int i = 0; i < 1000000; i++) {
             sum += i;  // 频繁的装箱和拆箱
         }
         long end = System.nanoTime();
         System.out.println("Sum: " + sum);
         System.out.println("Time taken: " + (end - start) + " ns");
     }
 }
 ```
解决方案是使用基本数据类型来避免不必要的装箱和拆箱。
```java
 public class PerformanceOptimizationExample {
     public static void main(String[] args) {
         long start = System.nanoTime();
         int sum = 0;
         for (int i = 0; i < 1000000; i++) {
             sum += i;  // 使用基本数据类型
         }
         long end = System.nanoTime();
         System.out.println("Sum: " + sum);
         System.out.println("Time taken: " + (end - start) + " ns");
     }
 }
 ```
#### 9.2 NullPointerException
在使用包装类时,如果包装类对象为`null`,在进行拆箱操作时会抛出`NullPointerException`。
```java
 public class NullPointerExceptionExample {
     public static void main(String[] args) {
         Integer integer = null;
         try {
             int intValue = integer;  // 自动拆箱,抛出NullPointerException
         } catch (NullPointerException e) {
             System.out.println("Caught NullPointerException");
         }
     }
 }
 ```
解决方案是在进行拆箱操作之前,确保包装类对象不为`null`。
```java
 public class SafeUnboxingExample {
     public static void main(String[] args) {
         Integer integer = null;
         if (integer != null) {
             int intValue = integer;  // 先检查是否为null
             System.out.println("intValue: " + intValue);
         } else {
             System.out.println("integer is null");
         }
     }
 }
 ```
### 10. Java 8中的Optional类
为了更好地处理可能为`null`的值,Java 8引入了`Optional`类。`Optional`是一个容器类,可以包含一个值或没有值,通过它可以避免显式的空值检查。
```java
 import java.util.Optional;
public class OptionalExample {
     public static void main(String[] args) {
         Optional<Integer> optional = Optional.ofNullable(null);
        // 使用orElse提供默认值
         int value = optional.orElse(0);
         System.out.println("Value: " + value);
        // 使用ifPresent执行操作
         optional.ifPresent(v -> System.out.println("Value is present: " + v));
     }
 }
 ```
### 11. 包装类的线程安全性
包装类是不可变类,因此它们是线程安全的,可以在多线程环境中安全地使用。
```java
 public class ThreadSafetyExample {
     public static void main(String[] args) {
         Integer counter = 0;
        Runnable task = () -> {
             for (int i = 0; i < 1000; i++) {
                 synchronized (counter) {
                     counter++;  // 由于Integer不可变,这种方式不会改变原始对象
                 }
             }
         };
        Thread thread1 = new Thread(task);
         Thread thread2 = new Thread(task);
        thread1.start();
         thread2.start();
     }
 }
 ```
### 12. 包装类的使用示例
以下是一个综合示例,展示了如何使用包装类进行集合操作、类型转换和错误处理。
```java
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Optional;
public class WrapperClassExample {
     public static void main(String[] args) {
         // 集合操作
         ArrayList<Integer> list = new ArrayList<>();
         list.add(10);  // 自动装箱
         list.add(20);
         list.add(30);
        for (Integer value : list) {
             System.out.println("List value: " + value);  // 自动拆箱
         }
        // 类型转换
         String strNumber = "100";
         int number = Integer.parseInt(strNumber);  // 字符串转整数
         String str = Integer.toString(number);  // 整数转字符串
        System.out.println("String to int: " + number);
         System.out.println("Int to string: " + str);
        // 错误处理
         try {
             String invalidNumber = "abc";
             int invalidValue = Integer.parseInt(invalidNumber);
             System.out.println("Parsed value: " + invalidValue);
         } catch (NumberFormatException e) {
             System.out.println("Invalid number format");
         }
        // 使用Optional避免NullPointerException
         Optional<Integer> optional = Optional.ofNullable(null);
         int value = optional.orElse(0);
         System.out.println("Optional value: " + value);
     }
 }
 ```
### 总结
Java中的包装类提供了一种将基本数据类型转换为对象的方法,使得基本数据类型可以用于需要对象的场景,如集合框架。此外,包装类提供了许多有用的方法,用于类型转换、比较和数字操作。自动装箱和拆箱功能使得包装类的使用更加方便,但也需要注意其带来的性能开销和潜在的`NullPointerException`问题。通过合理使用包装类,可以提高代码的可读性和可维护性,同时也要注意性能优化和错误处理。