(四)Java基础知识复习(权限修饰符以及常用类库)

58 阅读35分钟

一、权限修饰符

(一)权限修饰符

Java 语言一共有四种访问权限修饰符,不同的权限修饰符具有不同的访问权限。

  • public 公开的
  • protected 受保护的
  • default 默认的(编写代码时什么都不写,表示的就是 default 权限)
  • private 私有的
publicprotecteddefaultprivate
同一个类
同一个包(子类和无关类)
不同包的子类
不同包的无关类

(二)使用建议

  1. 访问控制的目的

    • 访问修饰符的主要目的是实现封装。通过控制访问级别,你可以保护类的内部数据和实现细节,防止不安全或不当的使用。
  2. 包访问级别

    • 默认的访问权限(package-private)在某些情况下是非常有用的,特别是在希望包内的类可以互相访问但又不想将它们公开给整个应用程序时。
  3. 组合使用

    • 在实际开发中,常常需要结合使用不同的访问修饰符。例如,可以将类的字段声明为 private,而提供 public 的 getter 和 setter 方法来控制对这些字段的访问。
  4. 继承中的 protected

    • 使用 protected 关键字可以让子类继承和访问父类中的成员,而不对外部类开放。这在需要让子类有能力访问和重用父类实现时非常有用。
  5. 接口中的访问修饰符

    • 在接口中声明的所有方法默认是 public 的(即使不明确地写出 public 关键字),因为接口是用来定义可供其他类实现的公共 API。

如果没有特殊的考虑,建议这样使用权限修饰符

  • 成员变量,使用 private(隐藏类的实现细节)
  • 构造方法,使用 public (方便创建对象)
  • 成员方法,使用 public (方便调用方法)

二、Object类

在介绍Java的常见类库前,我们先了解下Object类,因为该类是所有类的顶级父类

(一)Object 类概述

如果一个类没有显式的继承另一个类,那么它的父类默认是 Object 类,所以,Java 中所有的类都直接或间接地继承了 Object 类。
Object 类中定义了 11 个方法,这些方法是所有 Java 对象默认拥有的。以下是这些方法的列表:

方法描述
public final Class<?> getClass()返回对象的运行时类。
public int hashCode()返回对象的哈希码值。
public boolean equals(Object obj)指示其他某个对象是否与此对象“相等”。
protected Object clone()创建并返回对象的一个副本。
public String toString()返回对象的字符串表示。
public final void notify()唤醒在此对象监视器上等待的单个线程。
public final void notifyAll()唤醒在此对象监视器上等待的所有线程。
public final void wait(long timeout)使当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
public final void wait(long timeout, int nanos)使当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他线程中断当前线程,或者已超过指定的实际时间量。
public final void wait()使当前线程等待,直到另一个线程调用此对象的 notify() 方法或 notifyAll() 方法。
protected void finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。

这些方法提供了对象的基本行为,如对象的比较、复制、字符串表示、通知和等待机制等。

(二)Object类方法的使用

1. getClass()

描述: getClass() 方法用于返回一个对象的运行时类。它是 Object 类的一个 final 方法,不能被重写。这个方法返回的是一个 Class 对象,表示该对象的类信息。

使用场景: 在需要获取对象类型信息时非常有用,比如在日志记录、调试或动态类型检查中。

public class GetClassExample {
    public static void main(String[] args) {
        GetClassExample example = new GetClassExample();
        System.out.println("Class of example: " + example.getClass().getName());
    }
}

2. hashCode()

描述: hashCode() 方法返回对象的哈希码值。哈希码通常用于基于哈希的数据结构(例如 HashMap)中,以确定对象的存储位置。

使用场景: 在使用哈希表、哈希集合等数据结构时,hashCode() 可以帮助提高检索效率。需要注意,如果重写了 equals(),通常也需要重写 hashCode() 以保持两者的一致性。

public class HashCodeExample {
    public static void main(String[] args) {
        HashCodeExample example = new HashCodeExample();
        System.out.println("Hash code: " + example.hashCode());
    }
}

3. equals(Object obj)

描述: equals() 方法用于比较两个对象是否相等。默认实现是比较对象的内存地址值,但通常需要重写它以比较对象的内容。

使用场景: 当需要比较对象的实际内容而不是它们的内存地址时,应该重写 equals() 方法。这对于值对象(如 StringInteger)尤其重要。

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && Objects.equals(name, person.name);
}

4. clone()

描述: clone() 方法用于创建并返回对象的一个副本。要使用这个方法,类需要实现 Cloneable 接口,否则会抛出 CloneNotSupportedException

使用场景: 当需要创建对象的精确副本(浅拷贝)时,可以使用 clone() 方法。深拷贝则需要手动实现。

public class CloneExample implements Cloneable {
    private int value;

    public CloneExample(int value) {
        this.value = value;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) {
        try {
            CloneExample original = new CloneExample(10);
            CloneExample cloned = (CloneExample) original.clone();
            System.out.println("Original value: " + original.value);
            System.out.println("Cloned value: " + cloned.value);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

5. toString()

描述: toString() 方法返回对象的字符串表示形式。默认实现是对象的类名和哈希码,但通常需要重写以提供更有意义的信息。

使用场景: 在调试或日志记录时,toString() 方法可以提供对象的详细信息,帮助开发人员更好地理解对象的状态。

public class Person {
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" + "name='" + name + ''' + ", age=" + age + '}';
    }
}

6. notify()

描述: notify() 方法用于唤醒一个在对象上等待的线程。如果多个线程在同一对象上等待,则会随机选择一个线程进行唤醒。

使用场景: 在多线程编程中,当一个线程完成某项工作并需要通知另一个线程继续执行时,notify() 方法非常有用。

public class NotifyExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is waiting.");
                    lock.wait();
                    System.out.println("Thread is notified.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waitingThread.start();

        try {
            Thread.sleep(1000); // Ensure the waitingThread has time to wait
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            lock.notify();
            System.out.println("Notified one thread.");
        }
    }
}

7. notifyAll()

描述: notifyAll() 方法用于唤醒所有在对象上等待的线程。被唤醒的线程将竞争锁的控制权,只有一个线程会成功获得锁并继续执行。

使用场景: 当一个线程的操作影响到多个等待线程时,需要用 notifyAll() 来唤醒所有相关线程。

public class NotifyAllExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Runnable waitingTask = () -> {
            synchronized (lock) {
                try {
                    System.out.println(Thread.currentThread().getName() + " is waiting.");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() + " is notified.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread thread1 = new Thread(waitingTask, "Thread 1");
        Thread thread2 = new Thread(waitingTask, "Thread 2");

        thread1.start();
        thread2.start();

        try {
            Thread.sleep(1000); // Ensure the threads have time to wait
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            lock.notifyAll();
            System.out.println("Notified all threads.");
        }
    }
}

8. wait(long timeout)

描述: wait(long timeout) 方法让当前线程等待,直到另一个线程调用 notify()notifyAll() 方法,或者指定的时间已过。

使用场景: 在需要限制等待时间的多线程应用中使用,以防止线程无限期地等待。

public class WaitTimeoutExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is waiting with timeout.");
                    lock.wait(2000);
                    System.out.println("Thread is notified or timeout reached.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waitingThread.start();

        try {
            Thread.sleep(1000); // Optional sleep to demonstrate timeout
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            lock.notify();
            System.out.println("Notified one thread.");
        }
    }
}

9. wait(long timeout, int nanos)

描述: wait(long timeout, int nanos) 方法与 wait(long timeout) 类似,但提供了更精确的等待控制。

使用场景: 当需要非常精确地控制线程等待时间时,可以使用此方法。

public class WaitTimeoutNanosExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is waiting with timeout and nanos.");
                    lock.wait(2000, 500000);
                    System.out.println("Thread is notified or timeout reached.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waitingThread.start();

        try {
            Thread.sleep(1000); // Optional sleep to demonstrate timeout
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            lock.notify();
            System.out.println("Notified one thread.");
        }
    }
}

10. wait()

描述: wait() 方法使当前线程等待,直到另一个线程调用 notify()notifyAll() 方法来唤醒它。

使用场景: 在需要线程等待某个条件满足的场景中,wait() 方法通常与同步代码块结合使用。

public class WaitExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("Thread is waiting.");
                    lock.wait();
                    System.out.println("Thread is notified.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        waitingThread.start();

        try {
            Thread.sleep(1000); // Ensure the waitingThread has time to wait
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (lock) {
            lock.notify();
            System.out.println("Notified one thread.");
        }
    }
}

11. finalize()

描述: finalize() 方法在垃圾收集器删除对象之前被调用,用于释放资源。由于垃圾回收不保证及时性,该方法不推荐使用。

使用场景: 在现代 Java 编程中,应尽量避免使用 finalize(),而是采用 AutoCloseable 接口和 try-with-resources 语句来管理资源。

public class FinalizeExample {
    @Override
    protected void finalize() throws Throwable {
        System.out.println("Finalize method called.");
    }

    public static void main(String[] args) {
        FinalizeExample example = new FinalizeExample();
        example = null; // Make object eligible for garbage collection
        System.gc(); // Suggest JVM to run garbage collector
    }
}

三、字符串处理(StringStringBuilderStringBuffer

(一)String

1. String类的概述

String 类代表了字符串,在 Java 程序中,所有使用双引号括起来的内容默认都是 String 类的对象。
字符串的特点

不可变性:字符串对象一旦被创建,对象中的内容不能被改变。

内存共享:通过双引号创建字符串对象时,虚拟机会先到字符串常量池中查找是否有内容相同的对象,如果没有则创建,有则直接引用。

字符串底层存储原理
JDK8:char 数组
JDK9:byte 数组

2. Sting的构造方法

(1) 构造方法
构造方法说明
public String()创建一个空的字符对象
public String(byte[] bys)根据字节数组创建字符串对象
public String(char[] chs)根据字符数组创建字符串对象
public String(String original)根据一个原始的字符串来创建新的字符串对象
(2) 通过构造方法创建的字符串对象的特点

通过双引号直接创建的字符串对象是存在内存共享特性的。
但通过构造方法创建的字符串对象不存在内存共享,也就是说,每次 new 一个 String 对象,都会在内存中申请新的内存空间存储对象数据。

public static void main(String[] args){
    String s1 = "aaa";
    String s2 = "bbb";
    
    String s3 = new String("ccc");
    String s4 = new String("ccc");
    
    System.out.println(s1 == s2); //true
    System.out.println(s3 == s4); //false
}

3. String类的常用方法

方法描述
charAt(int index)返回指定索引处的字符。
compareTo(String anotherString)按字典顺序比较两个字符串。
concat(String str)将指定字符串连接到此字符串的末尾。
contains(CharSequence s)判断字符串中是否包含指定的字符序列。
endsWith(String suffix)判断字符串是否以指定的后缀结束。
equals(Object anObject)比较此字符串与指定对象是否相等。
equalsIgnoreCase(String anotherString)比较两个字符串(忽略大小写)是否相等。
indexOf(String str)返回指定子字符串在此字符串中第一次出现的索引。
isEmpty()判断字符串是否为空(长度为 0)。
length()返回字符串的长度(字符数)。
replace(char oldChar, char newChar)将字符串中的所有旧字符替换为新字符。
split(String regex)根据指定的正则表达式分割字符串。
substring(int beginIndex)返回从指定索引开始到字符串末尾的子字符串。
substring(int beginIndex, int endIndex)返回从指定的开始索引到结束索引之间的子字符串。
toLowerCase()将字符串中的所有字符转换为小写。
toUpperCase()将字符串中的所有字符转换为大写。
trim()去除字符串两端的空白字符。
valueOf(int i)返回 int 参数的字符串表示形式。
  1. charAt(int index)

描述: 返回指定索引处的字符。索引从 0 开始。

使用场景: 当需要访问字符串中的单个字符时使用。

public class CharAtExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        char ch = str.charAt(7);
        System.out.println("Character at index 7: " + ch);
    }
}
  1. compareTo(String anotherString)

描述: 按字典顺序比较两个字符串。如果字符串在字典中处于前面,返回负数;如果在后面,返回正数;相等则返回 0。

使用场景: 用于排序或比较字符串的场景。

public class CompareToExample {
    public static void main(String[] args) {
        String str1 = "apple";
        String str2 = "banana";
        int result = str1.compareTo(str2);
        System.out.println("Comparison result: " + result);
    }
}
  1. concat(String str)

描述: 将指定字符串连接到此字符串的末尾。

使用场景: 在需要连接多个字符串时使用。注意,String 的连接效率较低,大量连接操作建议使用 StringBuilder

public class ConcatExample {
    public static void main(String[] args) {
        String str1 = "Hello, ";
        String str2 = "World!";
        String result = str1.concat(str2);
        System.out.println("Concatenated string: " + result);
    }
}
  1. contains(CharSequence s)

描述: 判断字符串中是否包含指定的字符序列。

使用场景: 检查字符串中是否存在特定子字符串。

public class ContainsExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        boolean contains = str.contains("World");
        System.out.println("Contains 'World': " + contains);
    }
}
  1. endsWith(String suffix)

描述: 判断字符串是否以指定的后缀结束。

使用场景: 在需要检查字符串结尾部分是否匹配时使用。

public class EndsWithExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        boolean endsWith = str.endsWith("World!");
        System.out.println("Ends with 'World!': " + endsWith);
    }
}
  1. equals(Object anObject)

描述: 比较此字符串与指定对象是否相等。

使用场景: 判断两个字符串的内容是否相同时使用。

public class EqualsExample {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "Hello";
        boolean isEqual = str1.equals(str2);
        System.out.println("Strings are equal: " + isEqual);
    }
}
  1. equalsIgnoreCase(String anotherString)

描述: 比较两个字符串(忽略大小写)是否相等。

使用场景: 比较字符串时忽略大小写。

public class EqualsIgnoreCaseExample {
    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "hello";
        boolean isEqual = str1.equalsIgnoreCase(str2);
        System.out.println("Strings are equal (ignore case): " + isEqual);
    }
}
  1. indexOf(String str)

描述: 返回指定子字符串在此字符串中第一次出现的索引。如果没有找到,则返回 -1。

使用场景: 查找子字符串首次出现的位置。

public class IndexOfExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        int index = str.indexOf("World");
        System.out.println("Index of 'World': " + index);
    }
}
  1. isEmpty()

描述: 判断字符串是否为空(长度为 0)。

使用场景: 检查字符串是否为空。

public class IsEmptyExample {
    public static void main(String[] args) {
        String str = "";
        boolean isEmpty = str.isEmpty();
        System.out.println("String is empty: " + isEmpty);
    }
}
  1. length()

描述: 返回字符串的长度(字符数)。

使用场景: 获取字符串中的字符数。

public class LengthExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        int length = str.length();
        System.out.println("String length: " + length);
    }
}
  1. replace(char oldChar, char newChar)

描述: 将字符串中的所有旧字符替换为新字符。

使用场景: 替换字符串中的字符。

public class ReplaceExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        String replacedStr = str.replace('o', 'a');
        System.out.println("Replaced string: " + replacedStr);
    }
}
  1. split(String regex)

描述: 根据指定的正则表达式分割字符串。

使用场景: 分割字符串成数组。

public class SplitExample {
    public static void main(String[] args) {
        String str = "apple,banana,orange";
        String[] fruits = str.split(",");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

13. substring(int beginIndex)

描述: 返回从指定索引开始到字符串末尾的子字符串。

使用场景: 获取字符串的子字符串。

public class SubstringExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        String subStr = str.substring(7);
        System.out.println("Substring: " + subStr);
    }
}
  1. substring(int beginIndex, int endIndex)

描述: 返回从指定的开始索引到结束索引之间的子字符串。

使用场景: 获取字符串的特定部分。

public class SubstringRangeExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        String subStr = str.substring(7, 12);
        System.out.println("Substring: " + subStr);
    }
}
  1. toLowerCase()

描述: 将字符串中的所有字符转换为小写。

使用场景: 统一字符串的字符大小写。

public class ToLowerCaseExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        String lowerStr = str.toLowerCase();
        System.out.println("Lowercase string: " + lowerStr);
    }
}
  1. toUpperCase()

描述: 将字符串中的所有字符转换为大写。

使用场景: 统一字符串的字符大小写。

public class ToUpperCaseExample {
    public static void main(String[] args) {
        String str = "Hello, World!";
        String upperStr = str.toUpperCase();
        System.out.println("Uppercase string: " + upperStr);
    }
}
  1. trim()

描述: 去除字符串两端的空白字符。

使用场景: 清理用户输入或数据处理时去除多余的空格。

public class TrimExample {
    public static void main(String[] args) {
        String str = "   Hello, World!   ";
        String trimmedStr = str.trim();
        System.out.println("Trimmed string: '" + trimmedStr + "'");
    }
}
  1. valueOf(int i)

描述: 返回 int 参数的字符串表示形式。String 类提供了许多 valueOf 重载方法,可以将不同类型转换为字符串。

使用场景: 将基本数据类型转换为字符串。

public class ValueOfExample {
    public static void main(String[] args) {
        int number = 123;
        String str = String.valueOf(number);
        System.out.println("String value: " + str);
    }
}

(二)StringBuilder

1. StringBuilder类概述

由于字符串具有不可变性,在字符串拼接时会产生大量的内存垃圾,为了解决这个问题,Java 提供了 StringBuilder 类。 StringBuilder 类是一个可变的字符序列,它内部存储的字符串数据是可变的,在拼接时不会产生内存垃圾。

2. StringBuilder类的构造方法和常用方法

(1) StringBuilder类的构造方法
构造方法说明
public StringBuilder()创建一个空的StringBuilder对象
public StringBuilder(String s)根据一个字符串,创建一个StringBuilder对象
(2) StringBuilder类的常用方法
方法说明
StringBuilder append(String s)追加新的字符串内容到StringBuilder对象中
StringBuilder reverse()将StringBuilder对象中的内容反转
insert(int offset, String s)在指定位置插入字符串
delete(int start, int end)删除指定范围内的字符
replace(int start, int end, String s)用给定字符串替换指定范围内的内容
substring(int start, int end)返回指定范围内的字符串(不改变原对象)
length()返回当前 StringBuilder 对象的长度
setLength(int newLength)设置 StringBuilder 对象的新长度。如果新长度小于当前长度,则截断;如果大于当前长度,则填充空字符
charAt(int index)返回指定索引处的字符
setCharAt(int index, char ch)将指定索引处的字符设置为新的字符
capacity()返回当前容量
ensureCapacity(int minimumCapacity)确保容量至少为指定的最小容量
public class StringBuilderExample {
    public static void main(String[] args) {
        // 使用默认构造方法创建一个空的StringBuilder对象
        StringBuilder sb1 = new StringBuilder();
        System.out.println("初始sb1内容: '" + sb1.toString() + "'");

        // 使用带字符串参数的构造方法创建StringBuilder对象
        StringBuilder sb2 = new StringBuilder("Hello");
        System.out.println("初始sb2内容: '" + sb2.toString() + "'");

        // 使用append方法追加字符串内容
        sb2.append(" World");
        System.out.println("追加后的sb2内容: '" + sb2.toString() + "'");

        // 使用reverse方法将内容反转
        sb2.reverse();
        System.out.println("反转后的sb2内容: '" + sb2.toString() + "'");
    }
}

public class StringBuilderAdvancedExample {
    public static void main(String[] args) {
        // 创建一个StringBuilder对象
        StringBuilder sb = new StringBuilder("Java Programming");

        // 在指定位置插入字符串
        sb.insert(5, "is Fun ");
        System.out.println("插入后的内容: " + sb.toString()); // 输出: Java is Fun Programming

        // 删除指定范围内的字符
        sb.delete(5, 12);
        System.out.println("删除后的内容: " + sb.toString()); // 输出: Java Programming

        // 用给定字符串替换指定范围内的内容
        sb.replace(0, 4, "Python");
        System.out.println("替换后的内容: " + sb.toString()); // 输出: Python Programming

        // 返回指定范围内的字符串(不改变原对象)
        String subString = sb.substring(7, 18);
        System.out.println("子字符串: " + subString); // 输出: Programmin

        // 返回当前 StringBuilder 对象的长度
        int length = sb.length();
        System.out.println("当前长度: " + length); // 输出: 18

        // 设置 StringBuilder 对象的新长度
        sb.setLength(10);
        System.out.println("设置新长度后的内容: " + sb.toString()); // 输出: Python Pro

        // 返回指定索引处的字符
        char ch = sb.charAt(0);
        System.out.println("索引0处的字符: " + ch); // 输出: P

        // 将指定索引处的字符设置为新的字符
        sb.setCharAt(0, 'J');
        System.out.println("修改后的内容: " + sb.toString()); // 输出: Jython Pro

        // 返回当前容量
        int capacity = sb.capacity();
        System.out.println("当前容量: " + capacity);

        // 确保容量至少为指定的最小容量
        sb.ensureCapacity(50);
        System.out.println("扩容后的容量: " + sb.capacity());
    }
}

(三)StringBuffer

StringBuffer 构造方法和常用方法

构造方法
构造方法说明
StringBuffer()创建一个空的 StringBuffer 对象
StringBuffer(int capacity)创建指定容量的 StringBuffer 对象
StringBuffer(String str)创建一个内容为指定字符串的 StringBuffer 对象
常用方法
方法说明
append(String s)追加新的字符串内容到 StringBuffer 对象中
insert(int offset, String s)在指定位置插入字符串
delete(int start, int end)删除指定范围内的字符
replace(int start, int end, String s)用给定字符串替换指定范围内的内容
reverse()StringBuffer 对象中的内容反转
substring(int start, int end)返回指定范围内的字符串(不改变原对象)
length()返回当前 StringBuffer 对象的长度
setLength(int newLength)设置 StringBuffer 对象的新长度
charAt(int index)返回指定索引处的字符
setCharAt(int index, char ch)将指定索引处的字符设置为新的字符
capacity()返回当前容量
ensureCapacity(int minimumCapacity)确保容量至少为指定的最小容量

代码示例

public class StringBufferExample {
    public static void main(String[] args) {
        // 使用默认构造方法创建一个空的StringBuffer对象
        StringBuffer sb1 = new StringBuffer();
        System.out.println("初始sb1容量: " + sb1.capacity()); // 默认容量为16

        // 使用带字符串参数的构造方法创建StringBuffer对象
        StringBuffer sb2 = new StringBuffer("Hello");
        System.out.println("初始sb2内容: '" + sb2.toString() + "'");

        // 追加新的字符串内容
        sb2.append(" World");
        System.out.println("追加后的sb2内容: '" + sb2.toString() + "'");

        // 在指定位置插入字符串
        sb2.insert(6, "Beautiful ");
        System.out.println("插入后的sb2内容: '" + sb2.toString() + "'");

        // 删除指定范围内的字符
        sb2.delete(6, 16);
        System.out.println("删除后的sb2内容: '" + sb2.toString() + "'");

        // 替换指定范围内的内容
        sb2.replace(0, 5, "Hi");
        System.out.println("替换后的sb2内容: '" + sb2.toString() + "'");

        // 反转内容
        sb2.reverse();
        System.out.println("反转后的sb2内容: '" + sb2.toString() + "'");

        // 当前长度
        System.out.println("当前长度: " + sb2.length());

        // 设置新长度
        sb2.setLength(4);
        System.out.println("设置新长度后的内容: '" + sb2.toString() + "'");
    }
}

(四)String、StringBuilder、StringBuffer 之间的区别

  1. 可变性:

    • String: 是不可变的,每次对 String 的操作都会生成一个新的 String 对象。
    • StringBuilderStringBuffer: 是可变的,操作会改变对象自身而不是生成新的对象。
  2. 线程安全性:

    • String: 是线程安全的,因为它是不可变的。
    • StringBuffer: 是线程安全的,因为它的所有方法都是同步的,因此在多线程环境中使用是安全的。
    • StringBuilder: 不是线程安全的,适用于单线程环境。由于没有同步机制,它在单线程环境中比 StringBuffer 更快。
  3. 性能:

    • String: 在需要频繁修改字符串时性能较差,因为每次操作都需要创建新的对象。
    • StringBuilder: 在单线程环境中修改字符串时性能最佳。
    • StringBuffer: 在多线程环境中修改字符串时性能较好,但不如 StringBuilder 在单线程中的性能。
  4. 使用场景:

    • 使用 String 进行不频繁修改的字符串操作。
    • 使用 StringBuilder 进行频繁修改且在单线程环境下的字符串操作。
    • 使用 StringBuffer 进行频繁修改且在多线程环境下的字符串操作。

四、常用工具类(DateDateFormatCalendarMathRandomSystemBigDecimal

Java 语言提供了一个庞大而丰富的工具类库,帮助开发者处理各种编程任务。以下是 Java 工具类体系的一个全面总结,按照功能类别进行分类,大致分为13个类别:

  • 时间和日期工具类:

    • Date:表示特定的时间点。
    • Calendar:提供操作日期和时间字段的方法。
    • DateFormat:用于格式化和解析日期。
    • LocalDateTimeLocalDateLocalTime:用于表示日期和时间的新类(Java 8 引入)。
    • ZonedDateTimeZoneId:支持时区的日期时间类。
    • DurationPeriod:用于计算时间段的类。
  • 数学工具类:

    • Math:提供基本数学运算方法。
    • BigDecimalBigInteger:用于高精度计算的类。
  • 随机数工具类:

    • Random:用于生成伪随机数。
    • SecureRandom:用于生成加密强度的随机数。
  • 系统工具类:

    • System:包含一些有用的类字段和方法,提供与系统相关的操作。
    • Runtime:与 Java 虚拟机运行时环境交互。
  • 集合工具类:

    • Arrays:用于操作数组的实用方法。
    • Collections:提供集合操作的静态方法。
    • ListSetMapQueue:各种集合接口和实现类(如 ArrayListHashSetHashMap)。
  • 字符串处理工具类:

    • String:不可变字符串类。
    • StringBuilderStringBuffer:可变字符串类。
    • PatternMatcher:用于正则表达式操作。
  • 输入/输出工具类:

    • File:表示文件和目录路径名。
    • InputStreamOutputStream:字节输入和输出流。
    • ReaderWriter:字符输入和输出流。
    • Files:用于文件操作的实用方法(Java 7 引入)。
  • 并发工具类:

    • Thread:线程类。
    • Runnable:表示一个任务的接口。
    • ExecutorExecutorService:用于管理线程的执行。
    • ConcurrentHashMapCopyOnWriteArrayList:线程安全的集合类。
  • 网络工具类:

    • URLURLConnection:用于处理 URL 和连接。
    • SocketServerSocket:用于网络连接的类。
  • 日志工具类:

    • Logger:用于记录日志信息。
    • Level:定义日志级别。
  • 注解工具类:

    • Annotation:注解接口的父接口。
    • RetentionTarget:描述注解的保留策略和目标。
  • 反射工具类:

    • Class:表示类和接口。
    • MethodFieldConstructor:用于访问类的成员。
  • 安全和加密工具类:

    • MessageDigest:用于生成消息摘要。
    • KeyFactoryCipher:用于处理加密操作。

这些工具类大大增强了 Java 编程语言的功能和灵活性,使开发者能够高效地解决各种复杂的问题。在开发中,合理使用这些工具类可以提升代码的性能和可读性。

本文只对其中几种比较常用的工具类进行讲解

(一)Date 类

1. Date 类概述

java.util.Date 是日期类,它的对象用于封装一个特定的时间,精确到毫秒。

构造方法

image.png

public class DateDemo01 {

    /**
     * Date 类表示是日期类,它的对象封装了一个特定的时间,精确到毫秒
     *
     * 构造方法
     *      public Date()               //创建一个封装了从时间原点到现在经过的毫秒值
     *      public Date(long date)      //创建一个封装了指定毫秒值的日期对象
     *
     * 时间原点
     *      表示的是 1970年1月1日 00:00:00
     *
     *
     *      已过时
     */
    public static void main(String[] args) {
        //空参构造创建对象
        Date date1 = new Date();
        System.out.println(date1);

        //有参构造创建对象
        Date date2 = new Date(1000);
        System.out.println(date2);

    }
}

时间原点:1970-01-01 00:00:00 由于中国处于东八区(GMT+08:00),比世界协调时间/格林威治时间(GMT)快8小时,当格林威治标准时间为 0:00 时,东八区的标准时间为 08:00。

2. 常用方法

Date 类的大多数方法都被标记为已过时,不推荐使用,这里我们主要学习两个方法。

image.png

public class DateDemo02 {

    /**
     * 常用方法
     *      public void setTime(long time)      //设置 Date 对象中封装的毫秒值
     *      public long getTime()               //获取 Date 对象中封装的毫秒值
     */
    public static void main(String[] args) {
        //创建封装了当前时间的Date对象
        Date date = new Date();
        System.out.println(date);

        //获取毫秒值
        long time = date.getTime();
        System.out.println(time); //1639103299950

        //修改Date对象中封装的毫秒值
        date.setTime(1000);
        System.out.println(date);
    }
}

(二)DateFormat 类

1. DateFormat 类概述

java.text.DateFormat 类的两个主要功能,分别是格式化和解析。

  • 格式化 :将 Date 对象转换成特定格式的字符串文本,以便于用户阅读。
  • 解析 :将用户输入的字符串日期信息转换成 Date 对象。

DateFormat 是抽象类,不能创建对象,我们可以使用它的子类 java.text.SimpleDateFormat。

//使用指定的模式创建 SimpleDateFormat 对象
public SimpleDateFormat(String pattern) { //... }

模式规则

image.png

2. 格式化和解析

public class DateFormatDemo01 {

    /**
     * DateFormat 类
     *      由于 DateFormat 是抽象类,无法创建对象,我们可以使用它的子类 SimpleDateFormat。
     *
     * SimpleDateFormat
     *      构造方法
     *          public SimpleDateFormat(String pattern)     //按照指定的模式来构建 SimpleDateFormat 对象
     *
     *          2021年12月10日 10:48:00
     *      模式
     *          y   :年
     *          M   :月
     *          d   :日
     *          H   :时  h:12小时制, H:24小时制
     *          m   :分
     *          s   :秒
     *          S   :毫秒
     *
     *      常用方法
     *          public final String format(Date date)   //格式化日期对象
     *          public Date parse(String source)        //将一个字符串转换成Date对象
     */
    public static void main(String[] args) throws ParseException {
//        //创建日期格式化对象
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
//        //创建一个当前时间的Date对象
//        Date date = new Date();
//
//        //使用日期格式化对象去格式化date对象
//        String dateStr = sdf.format(date);
//
//        //打印结果
//        System.out.println(dateStr);


        //让用户在控制台输入他的生日,接收到之后转换成Date对象
        Scanner sc = new Scanner(System.in);
        //提示用户输入
        System.out.println("请输入您的生日(yyyy-mm-dd)");
        //接收数据
        String birStr = sc.nextLine();

        //将字符串转换成Date对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //解析
        Date date = sdf.parse(birStr);
        //打印结果
        System.out.println(date);
    }
}

(三)Calendar 类

1. Calendar 类概述

java.util.Calendar 类表示日历,可以进行日期时间的运算。它是一个抽象类,无法直接使用,但我们可以使用它的子类 java.util.GregorianCalendar 。

创建 Calendar 对象的方法有两种

  • 直接创建 GregorianCalendar 类的对象
  • 调用 Calendar 类的静态方法 getInstance() 获得一个存储了当前时间信息的 GregorianCalendar 对象。

2. 常用方法

image.png

注意

  • 月份值的范围是 0 ~ 11,0 表示 1 月,11 表示12 月。
  • 星期值的范围是 1 ~ 7,1 表示星期日,2 表示星期一 … 7 表示星期六。
public class CalendarDemo01 {

    /**
     * Calendar 类
     *      由于 Calendar 类是抽象类,无法直接对象,我们可以创建它的子类 GregorianCalendar 对象。
     *
     *      我们也可以使用 Calendar 提供的静态方法 getInstance 直接获得子类对象。
     *
     *      常用方法
     *          public static Calendar getInstance()                //获得 Calendar 类的子类对象
     *          public int get(int field)                           //获取日期和时间信息
     *          public void set(int field, int value)               //设置日期和时间信息
     *          public abstract void add(int field, int amount)     //修改日期和时间信息
     */
    public static void main(String[] args) {

        //获取 1999 年 12 月 12 日的星期

        //获取一个 Calendar 对象
        Calendar cal = Calendar.getInstance();

        //修改年月日
        cal.set(Calendar.YEAR, 1999);
        cal.set(Calendar.MONTH, 11); //11表示的是12月,因为月份是从0开始的
        cal.set(Calendar.DAY_OF_MONTH, 12);

        //取出星期
        int week = cal.get(Calendar.DAY_OF_WEEK);

        //打印结果
        System.out.println(getWeek(week));


//        //获取一个 Calendar 对象,默认封装当前的时间
//        Calendar cal = Calendar.getInstance();
//
//        //单独获取年月日时分秒的信息
//        int year = cal.get(Calendar.YEAR);
//        int month = cal.get(Calendar.MONTH);        //月是从0开始的,也就是说0是1月,11是12月
//        int day = cal.get(Calendar.DAY_OF_MONTH);
//        int hour = cal.get(Calendar.HOUR_OF_DAY);
//        int minute = cal.get(Calendar.MINUTE);
//        int second = cal.get(Calendar.SECOND);
//        int week = cal.get(Calendar.DAY_OF_WEEK);   //1表示星期日,2表示星期一....
//
//
//        System.out.println(year);
//        System.out.println(month + 1);
//        System.out.println(day);
//        System.out.println(hour);
//        System.out.println(minute);
//        System.out.println(second);
//        System.out.println(getWeek(week));
    }

    private static String getWeek(int week) {
        //将所有的星期存入数组中
        String[] weeks = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        //取出星期并返回
        return weeks[week - 1];
    }
}

3. 案例

public class CalendarDemo02 {

    /**
     * 计算 200 天后的日期(年、月、日)
     *
     *      public abstract void add(int field, int amount)     //修改日期和时间信息
     */
    public static void main(String[] args) {
        //获得Calendar对象
        Calendar cal = Calendar.getInstance();

        //将日期加上200天
        cal.add(Calendar.DAY_OF_MONTH, 200);

        //获取年月日
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.get(Calendar.DAY_OF_MONTH);

        System.out.println(year + "-" + month + "-" + day);

    }
}

(四)Math 类

1. Math 类概述

java.lang.Math 类包含了数学相关的运算操作。使用该类时无需创建对象,直接调用该类的静态方法即可。
常用方法

image.png

2. 案例

public class MathDemo {

    /**
     * public static int abs(int a)                     //求绝对值
     * public static double ceil(double a)              //向上取整
     * public static double floor(double a)             //向下取整
     * public static double pow(double a, double b)     //求a的b次幂
     * public static long round(double a)               //四舍五入
     */
    public static void main(String[] args) {
        //计算 5 和 -10 的绝对值
        //绝对值:正数的绝对值是它本身,负数的绝对值是它的相反数
        System.out.println(Math.abs(5));
        System.out.println(Math.abs(-10));

        //3.4、3.5、-3.4、-3.5 向上取整
        System.out.println(Math.ceil(3.4));     //4.0
        System.out.println(Math.ceil(3.5));     //4.0
        System.out.println(Math.ceil(-3.4));    //-3.0
        System.out.println(Math.ceil(-3.5));    //-3.0

        //3.4、3.5、-3.4、-3.5 向下取整
        System.out.println(Math.floor(3.4));     //3
        System.out.println(Math.floor(3.5));     //3
        System.out.println(Math.floor(-3.4));    //-4
        System.out.println(Math.floor(-3.5));    //-4


        //byte -128~127 = 256个数  1个字节 = 8位

        //计算 2 的 8 次幂
        System.out.println(Math.pow(2, 32));     //256.0

        //Math.floor(num + 0.5)
        //计算 11.4、11.5、-11.4、-11.5 的四舍五入结果
        System.out.println(Math.round(11.4));   //11
        System.out.println(Math.round(11.5));   //12
        System.out.println(Math.round(-11.4));  //-11
        System.out.println(Math.round(-11.5));  //-11

        //max
        int a = 10;
        int b = 20;
        int max = Math.max(a, b);
        System.out.println(max); //20

        //min
        int min = Math.min(a, b);
        System.out.println(min); //10
    }
}

注意:\color{red}{注意:}对负数进行四舍五入运算. 对负数进行round() 运算:绝对值小于0.5,直接返回0;绝对值大于0.5,先将原值+0.5,然后对其做floor() 运算负数的floor()运算;

(五)Random 类

Random 类是 Java 中用于生成伪随机数的类。它位于 java.util 包中,提供了多种方法来生成不同类型的随机数。以下是 Random 类的构造方法和常用方法的表格:

构造方法/方法描述
Random()创建一个新的随机数生成器。
Random(long seed)使用指定的种子值创建一个新的随机数生成器,以确保生成的序列是可预测的。
nextInt()返回一个随机的 int 值。
nextInt(int bound)返回一个在 [0, bound) 范围内的随机 int 值。
nextLong()返回一个随机的 long 值。
nextDouble()返回一个在 [0.0, 1.0) 范围内的随机 double 值。
nextFloat()返回一个在 [0.0, 1.0) 范围内的随机 float 值。
nextBoolean()返回一个随机的 boolean 值。
nextBytes(byte[] bytes)生成随机字节并将其存储到用户提供的字节数组中。

使用场景和代码案例

  1. 生成随机整数

    场景:生成 0 到 9 的随机整数,用于抽奖或游戏中生成随机位置。

    import java.util.Random;
    
    public class RandomIntegerExample {
        public static void main(String[] args) {
            Random random = new Random();
            int randomInt = random.nextInt(10); // 生成 0 到 9 之间的随机整数
            System.out.println("Random Integer: " + randomInt);
        }
    }
    
  2. 生成随机浮点数

    场景:生成一个随机浮点数,用于模拟概率或创建随机噪声。

    import java.util.Random;
    
    public class RandomFloatExample {
        public static void main(String[] args) {
            Random random = new Random();
            float randomFloat = random.nextFloat(); // 生成 0.0 到 1.0 之间的随机浮点数
            System.out.println("Random Float: " + randomFloat);
        }
    }
    
  3. 生成随机布尔值

    场景:随机决定一个二选一的事件,如抛硬币。

    import java.util.Random;
    
    public class RandomBooleanExample {
        public static void main(String[] args) {
            Random random = new Random();
            boolean randomBoolean = random.nextBoolean(); // 生成随机布尔值
            System.out.println("Random Boolean: " + randomBoolean);
        }
    }
    
  4. 生成指定范围内的随机整数

    场景:生成一个在特定范围内的随机数,用于选择数组中的随机元素。

    import java.util.Random;
    
    public class RandomIntRangeExample {
        public static void main(String[] args) {
            Random random = new Random();
            int min = 50;
            int max = 100;
            int randomInt = random.nextInt(max - min + 1) + min; // 生成 50 到 100 之间的随机整数
            System.out.println("Random Integer between 50 and 100: " + randomInt);
        }
    }
    
  5. 生成随机字节数组

    场景:生成随机字节数组,用于加密或生成随机文件内容。

    import java.util.Random;
    
    public class RandomBytesExample {
        public static void main(String[] args) {
            Random random = new Random();
            byte[] bytes = new byte[16]; // 生成长度为 16 的随机字节数组
            random.nextBytes(bytes);
    
            System.out.println("Random Bytes:");
            for (byte b : bytes) {
                System.out.print(b + " ");
            }
        }
    }
    

这些示例展示了 Random 类在生成各种类型的随机值时的灵活性和多样性,适用于游戏开发、模拟、数据随机化等多个场景。

(六)System 类

1. System 类概述

System 类是 Java 提供的一个包含许多有用的静态方法和系统属性的类,用于获取系统信息、管理系统资源、执行系统级的操作等。由于 System 类的构造方法是私有的,因此无法实例化该类。

常用方法
方法名描述
exit(int status)终止当前正在运行的 Java 虚拟机。参数 status 表示退出状态码,0 通常表示正常退出。
currentTimeMillis()返回当前时间的毫秒值,自 1970-01-01 00:00:00 UTC 开始。
nanoTime()返回最准确的可用系统计时器的当前值,以纳秒为单位。用于精确测量时间间隔。
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)从源数组复制数组元素到目标数组。
gc()提示 JVM 执行垃圾回收。
getProperties()返回系统属性的集合(Properties 对象),表示当前系统配置。
getProperty(String key)返回指定系统属性的值。
setProperty(String key, String value)设置系统属性。
getenv(String name)获取指定环境变量的值。
getSecurityManager()返回当前的安全管理器。如果没有安装安全管理器,则返回 null
lineSeparator()返回当前操作系统的行分隔符。

2. 案例

import java.util.Properties;
import java.util.Enumeration;

public class SystemDemo {

    public static void main(String[] args) {
        // 1. 获取当前时间(纳秒)
        long startTime = System.nanoTime();
        System.out.println("Starting the program...");

        // 2. 获取系统属性
        String osName = System.getProperty("os.name");
        String javaVersion = System.getProperty("java.version");
        System.out.println("Operating System: " + osName);
        System.out.println("Java Version: " + javaVersion);

        // 3. 获取环境变量
        String path = System.getenv("PATH");
        System.out.println("PATH Environment Variable: " + path);

        // 4. 复制数组
        int[] sourceArray = {1, 2, 3, 4, 5};
        int[] destArray = new int[sourceArray.length];
        System.arraycopy(sourceArray, 0, destArray, 0, sourceArray.length);
        System.out.print("Copied Array: ");
        for (int num : destArray) {
            System.out.print(num + " ");
        }
        System.out.println();

        // 5. 测量程序运行时间
        long endTime = System.nanoTime();
        long duration = endTime - startTime; // 计算时间差
        System.out.println("Execution time in nanoseconds: " + duration);

        // 6. 打印所有系统属性
        Properties props = System.getProperties();
        Enumeration<?> propertyNames = props.propertyNames();
        System.out.println("\nSystem Properties:");
        while (propertyNames.hasMoreElements()) {
            String propertyName = (String) propertyNames.nextElement();
            String propertyValue = System.getProperty(propertyName);
            System.out.println(propertyName + ": " + propertyValue);
        }

        // 7. 退出程序
        System.out.println("Exiting the program.");
        System.exit(0); // 正常退出程序
    }
}

(七)BigDecimal 类

1. BigDecimal 类概述

以下程序的运行结果是?

public static void main(String[] args) {    
    System.out.println(0.09 + 0.01);    
    System.out.println(1.0 - 0.32);    
    System.out.println(1.015 * 100);    
    System.out.println(1.301 / 100);
}
public class BigDecimalDemo01 {

    /**
     *
     */
    public static void main(String[] args) {
        System.out.println(0.09 + 0.01);    //0.1       //0.09999999999999999
        System.out.println(1.0 - 0.32);     //0.68      //0.6799999999999999
        System.out.println(1.015 * 100);    //101.5     //101.49999999999999
        System.out.println(1.301 / 100);    //0.01301   //0.013009999999999999
    }
}

java.math.BigDecimal 提供了浮点数的精确计算操作。

构造方法

image.png

推荐使用根据字符串构建的方式,因为根据 double 值构建的 BigDecimal 对象在计算时仍然存在精度问题。

public class BigDecimalDemo02 {

    /**
     * BigDecimal 提供浮点数的精确计算
     *
     *      构造方法
     *          public BigDecimal(double val)       //将一个double值封装到BigDecimal对象中
     *          public BigDecimal(String val)       //将一个字符串类型的浮点数封装到BigDecimal对象中
     */
    public static void main(String[] args) {
        //将一个double值封装到BigDecimal对象中
        //(不推荐)
        BigDecimal bd1 = new BigDecimal(0.09);
        BigDecimal bd2 = new BigDecimal(0.01);
        BigDecimal bdResult1 = bd1.add(bd2);
        System.out.println(bdResult1);

        //将一个字符串类型的浮点数封装到BigDecimal对象中
        //(推荐)
        BigDecimal bd3 = new BigDecimal("0.09");
        BigDecimal bd4 = new BigDecimal("0.01");
        BigDecimal bdResult2 = bd3.add(bd4);
        System.out.println(bdResult2);
    }
}

2. 常用方法

image.png

public class BigDecimalDemo03 {

    /**
     * 常用方法
     *
     *      public static BigDecimal valueOf(double val)        //根据一个double值构建BigDecimal对象
     *
     *      public BigDecimal add(BigDecimal augend)            //加法操作
     *      public BigDecimal subtract(BigDecimal subtrahend)   //减法操作
     *      public BigDecimal multiply(BigDecimal multiplicand) //乘法操作
     *      public BigDecimal divide(BigDecimal divisor)        //除法操作
     *
     *      public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)  //除法操作
     */
    public static void main(String[] args) {
        //加法操作
        BigDecimal bd1 = BigDecimal.valueOf(0.09);
        BigDecimal bd2 = BigDecimal.valueOf(0.01);

        BigDecimal bdResult1 = bd1.add(bd2);
        System.out.println(bdResult1.doubleValue());

        //减法操作
        BigDecimal bd3 = BigDecimal.valueOf(1.0);
        BigDecimal bd4 = BigDecimal.valueOf(0.32);

        BigDecimal bdResult2 = bd3.subtract(bd4);
        System.out.println(bdResult2.doubleValue());

        //乘法操作
        BigDecimal bd5 = BigDecimal.valueOf(1.015);
        BigDecimal bd6 = BigDecimal.valueOf(100.0);

        BigDecimal bdResult3 = bd5.multiply(bd6);
        System.out.println(bdResult3.doubleValue());

        //除法操作
        BigDecimal bd7 = BigDecimal.valueOf(1.301);
        BigDecimal bd8 = BigDecimal.valueOf(100.0);

        BigDecimal bdResult4 = bd7.divide(bd8);
        System.out.println(bdResult4.doubleValue());
    }
}
public class BigDecimalDemo04 {

    /**
     * public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)  //除法操作
     */
    public static void main(String[] args) {

        BigDecimal bd1 = BigDecimal.valueOf(10.0);
        BigDecimal bd2 = BigDecimal.valueOf(3.0);

        /**
         * divisor:         除数
         * scale:           要保留的小数位
         * roundingMode     取舍模式
         */
        BigDecimal bdResult = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
        System.out.println(bdResult); //3.33
    }
}
public class BigDecimalDemo05 {

    /**
     * BigInteger   大数值
     */
    public static void main(String[] args) {
        //求阶乘
        //5!  = 120
        //10! = 3628800
        //15! = 1307674368000
        //16! = 20922789888000
        //1000!
        BigInteger n = BigInteger.ONE;
        for (int i = 1; i <= 1000; i++) {
            n = n.multiply(BigInteger.valueOf(i));
            //n *= i;
        }

        System.out.println(n);
    }
}

五、包装类

(一)包装类概述

Java 语言有两大数据类型,基本数据类型和引用数据类型。使用基本数据类型的效率较高,然而,在某些情况下基本类型的功能过于单一,无法满足实际需求。我们需要一种像操作对象一样的方式去操作基本数据类型。

Java 为每一种基本数据类型都提供了对应的包装类型,允许我们以对象的方式去操作基本类型的数据。

基本数据类型包装类型描述
booleanBoolean表示 truefalse 的布尔值
byteByte表示一个 8 位有符号整数
charCharacter表示一个 16 位 Unicode 字符
shortShort表示一个 16 位有符号整数
intInteger表示一个 32 位有符号整数
longLong表示一个 64 位有符号整数
floatFloat表示一个 32 位 IEEE 754 浮点数
doubleDouble表示一个 64 位 IEEE 754 浮点数
  • 基本数据类型:这些类型是 Java 的基本构建块,它们是语言内建的,效率高但功能有限。

  • 包装类型:这些是基本数据类型的对象表示形式。它们提供了与基本数据类型相关的各种方法,并允许基本数据类型与 Java 的集合框架(如 ListMap)一起使用,因为集合框架只能存储对象而不是基本数据类型。

(二)常用方法

包装类型构造方法和常用方法

包装类型常用构造方法常用方法
BooleanBoolean(boolean value)booleanValue()
Boolean(String s)toString()
ByteByte(byte value)byteValue()
Byte(String s)toString()
CharacterCharacter(char value)charValue()
isDigit(char ch)
isLetter(char ch)
ShortShort(short value)shortValue()
Short(String s)toString()
IntegerInteger(int value)intValue()
Integer(String s)parseInt(String s)
Integer(String s, int radix)toString()
LongLong(long value)longValue()
Long(String s)parseLong(String s)
Long(String s, int radix)toString()
FloatFloat(float value)floatValue()
Float(String s)parseFloat(String s)
toString()
DoubleDouble(double value)doubleValue()
Double(String s)parseDouble(String s)
toString()
public class WrapperExample {

    public static void main(String[] args) {
        // Boolean 示例
        Boolean boolTrue = new Boolean(true);
        Boolean boolFalse = Boolean.valueOf("false");
        System.out.println("Boolean true: " + boolTrue);
        System.out.println("Boolean false: " + boolFalse);
        System.out.println("Boolean true to String: " + boolTrue.toString());

        // Byte 示例
        Byte byteValue = new Byte((byte) 100);
        Byte byteFromString = Byte.valueOf("120");
        System.out.println("Byte value: " + byteValue);
        System.out.println("Byte from string: " + byteFromString);
        System.out.println("Byte value to String: " + byteValue.toString());

        // Character 示例
        Character charValue = new Character('A');
        System.out.println("Character value: " + charValue);
        System.out.println("Character value as char: " + charValue.charValue());
        System.out.println("Is 'A' a letter? " + Character.isLetter('A'));

        // Short 示例
        Short shortValue = new Short((short) 32000);
        Short shortFromString = Short.valueOf("12345");
        System.out.println("Short value: " + shortValue);
        System.out.println("Short from string: " + shortFromString);
        System.out.println("Short value to String: " + shortValue.toString());

        // Integer 示例
        Integer intValue = new Integer(123456);
        Integer intFromString = Integer.valueOf("789");
        System.out.println("Integer value: " + intValue);
        System.out.println("Integer from string: " + intFromString);
        System.out.println("Parsed Integer: " + Integer.parseInt("999"));
        System.out.println("Integer value to String: " + intValue.toString());

        // Long 示例
        Long longValue = new Long(123456789L);
        Long longFromString = Long.valueOf("9876543210");
        System.out.println("Long value: " + longValue);
        System.out.println("Long from string: " + longFromString);
        System.out.println("Parsed Long: " + Long.parseLong("1234567890123456789"));
        System.out.println("Long value to String: " + longValue.toString());

        // Float 示例
        Float floatValue = new Float(3.14f);
        Float floatFromString = Float.valueOf("2.718");
        System.out.println("Float value: " + floatValue);
        System.out.println("Float from string: " + floatFromString);
        System.out.println("Parsed Float: " + Float.parseFloat("1.414"));
        System.out.println("Float value to String: " + floatValue.toString());

        // Double 示例
        Double doubleValue = new Double(3.14159265358979);
        Double doubleFromString = Double.valueOf("2.718281828459");
        System.out.println("Double value: " + doubleValue);
        System.out.println("Double from string: " + doubleFromString);
        System.out.println("Parsed Double: " + Double.parseDouble("1.6180339887"));
        System.out.println("Double value to String: " + doubleValue.toString());
    }
}

(三)装箱与拆箱

基本数据类型与对应的包装类型之间的转换过程称为“装箱”与“拆箱”。

  • 装箱:将基本数据类型赋值给包装类型
  • 拆箱:将包装类型赋值给基本数据类型

装箱和拆箱的底层原理是通过调用 valueOf 和 xxxValue 实现的。

public class Demo04 {

    /**
     * 装箱和拆箱
     *      自动装箱:将int值转换成Integer对象
     *      自动拆箱:将Integer对象转换成int值
     *
     * 语法糖
     */
    public static void main(String[] args) {
        //自动装箱
        Integer i1 = 100; //Integer i1 = Integer.valueOf(100);

        //自动拆箱
        int i2 = i1;      //int i2 = i1.intValue();
    }
}