当前位置: 首页 > news >正文

Java常见问题(二)

11. Java中的 throw 和 throws 有什么区别?

        在Java中,throw 和 throws 都与异常处理相关,但它们的用途和行为有显著区别。

11.1 throw 关键字
  • 作用

    • 用于在代码中显式抛出一个异常。

    • 通常用于在满足某些条件时主动抛出异常。

  • 语法

    throw 异常对象;
  • 示例

    public class Main {
        public static void main(String[] args) {
            int age = -5;
            if (age < 0) {
                throw new IllegalArgumentException("年龄不能为负数"); // 抛出异常
            }
        }
    }
  • 特点

    • throw 用于方法内部。

    • 抛出的异常必须是 Throwable 或其子类的实例。

    • 抛出异常后,程序会立即停止当前方法的执行,并将异常传递给调用者。

11.2 throws 关键字
  • 作用

    • 用于方法签名中,声明该方法可能抛出的异常类型。

    • 调用该方法时,必须处理这些异常(使用 try-catch 或继续向上抛出)。

  • 语法

    返回类型 方法名(参数列表) throws 异常类型1, 异常类型2, ... {
        // 方法体
    }
  • 示例

    public class Main {
        public static void main(String[] args) {
            try {
                readFile("file.txt");
            } catch (IOException e) {
                System.out.println("捕获异常: " + e.getMessage());
            }
        }
    
        static void readFile(String fileName) throws IOException {
            if (!fileName.equals("file.txt")) {
                throw new IOException("文件未找到"); // 抛出异常
            }
        }
    }
  • 特点

    • throws 用于方法签名中。

    • 可以声明多个异常类型,用逗号分隔。

    • 调用者必须处理这些异常,否则程序会编译失败。

11.3 throw 和 throws 的区别
特性throwthrows
用途显式抛出一个异常声明方法可能抛出的异常类型
位置方法内部方法签名中
异常对象必须是一个具体的异常对象只需要指定异常类型
调用者处理不需要在方法签名中声明调用者必须处理或继续抛出
示例throw new Exception("错误");void method() throws Exception;
11.4 使用场景
(1)throw 的使用场景
  • 当方法内部检测到某些条件不满足时,主动抛出异常。

  • 例如,参数校验、业务逻辑检查等。

(2)throws 的使用场景
  • 当方法内部可能抛出受检异常(checked exception),但不想在方法内部处理时,使用 throws 将异常传递给调用者。

  • 例如,文件操作、网络操作等可能抛出 IOException 的场景。

11.5 注意事项
  1. 受检异常 vs 非受检异常

    • 受检异常(checked exception):必须使用 throws 声明或在方法内部处理(如 IOException)。

    • 非受检异常(unchecked exception):不需要使用 throws 声明(如 NullPointerExceptionIllegalArgumentException)。

  2. 方法重写时的 throws

    • 子类重写父类方法时,throws 声明的异常类型不能比父类方法更宽泛。

    • 例如,父类方法声明 throws IOException,子类方法可以声明 throws FileNotFoundExceptionFileNotFoundException 是 IOException 的子类),但不能声明 throws Exception

  3. throw 和 throws 的结合使用

    • 可以在方法内部使用 throw 抛出异常,同时在方法签名中使用 throws 声明异常类型。

总结
  • throw:用于在代码中显式抛出一个异常。

  • throws:用于方法签名中,声明该方法可能抛出的异常类型。

12. Java中的 interface 和 abstract class 有什么区别?

        在Java中,interface 和 abstract class 都是用于实现抽象和多态的重要机制,但它们在设计和使用上有显著的区别。

12.1 定义
  • 接口(Interface)

    • 是一种完全抽象的类,只能包含抽象方法(Java 8 之前)。

    • 从 Java 8 开始,接口可以包含默认方法(default 方法)和静态方法。

    • 从 Java 9 开始,接口可以包含私有方法。

  • 抽象类(Abstract Class)

    • 是一种部分抽象的类,可以包含抽象方法和具体方法。

    • 可以定义成员变量、构造器、普通方法和抽象方法。

12.2 主要区别
特性接口(Interface)抽象类(Abstract Class)
方法实现Java 8 之前只能包含抽象方法;Java 8 开始可以包含默认方法和静态方法可以包含抽象方法和具体方法
成员变量只能包含常量(默认是 public static final可以包含普通成员变量和常量
构造器不能定义构造器可以定义构造器
多继承支持多继承(一个类可以实现多个接口)不支持多继承(一个类只能继承一个抽象类)
默认访问修饰符方法默认是 public abstract方法可以是 publicprotected 或默认访问修饰符
设计目的定义行为规范(“能做什么”)定义类的部分实现(“是什么”和“能做什么”)
12.3 使用场景
(1)接口的使用场景
  • 定义一组行为规范,强调“能做什么”。

  • 需要多继承时(一个类可以实现多个接口)。

  • 适用于定义通用的功能,例如:

    • Runnable 接口定义线程任务。

    • Comparable 接口定义对象的比较规则。

(2)抽象类的使用场景
  • 定义部分实现,强调“是什么”和“能做什么”。

  • 需要共享代码或状态时(抽象类可以包含成员变量和具体方法)。

  • 适用于定义具有共同特征的类,例如:

    • 动物类(Animal)可以定义抽象方法 sound(),子类(如 DogCat)实现具体的叫声。

12.4 示例代码

接口示例

interface Flyable {
    void fly(); // 抽象方法
    default void land() { // 默认方法
        System.out.println("正在降落");
    }
    static void altitude() { // 静态方法
        System.out.println("飞行高度");
    }
}

class Bird implements Flyable {
    public void fly() {
        System.out.println("鸟在飞翔");
    }
}

public class Main {
    public static void main(String[] args) {
        Bird bird = new Bird();
        bird.fly(); // 输出: 鸟在飞翔
        bird.land(); // 输出: 正在降落
        Flyable.altitude(); // 输出: 飞行高度
    }
}

抽象类示例

abstract class Animal {
    String name;
    Animal(String name) {
        this.name = name;
    }
    abstract void sound(); // 抽象方法
    void sleep() { // 具体方法
        System.out.println(name + " 正在睡觉");
    }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);
    }
    void sound() {
        System.out.println(name + " 汪汪叫");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("小黑");
        dog.sound(); // 输出: 小黑 汪汪叫
        dog.sleep(); // 输出: 小黑 正在睡觉
    }
}
12.6 如何选择接口还是抽象类?
  • 使用接口

    • 需要定义一组行为规范。

    • 需要多继承。

    • 不关心具体实现细节。

  • 使用抽象类

    • 需要共享代码或状态。

    • 需要定义部分实现。

    • 需要构造器或非静态成员变量。

13. Java中的 volatile 关键字有什么作用?

        在 Java 中,volatile 关键字用于修饰变量,主要作用是确保变量的可见性和禁止指令重排序。

13.1 可见性
  • 作用:当一个线程修改了 volatile 变量的值,其他线程能立即看到最新的值。

  • 机制volatile 变量不会被线程缓存,所有读写操作都直接在主内存中进行,保证了多线程环境下的可见性。

13.2 禁止指令重排序
  • 作用:防止 JVM 和处理器对指令进行重排序,确保代码执行顺序与编写顺序一致。

  • 机制volatile 变量的读写操作前后会插入内存屏障,防止重排序。

使用场景

  • 状态标志:用于标记线程是否继续运行。

    volatile boolean running = true;
    
    public void run() {
        while (running) {
            // 执行任务
        }
    }
    
    public void stop() {
        running = false;
    }
  • 双重检查锁定(Double-Checked Locking):用于单例模式中,确保实例的唯一性。

    class Singleton {
        private volatile static Singleton instance;
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }

注意事项

  • 不保证原子性volatile 不能保证复合操作的原子性,如 i++

  • 性能影响:频繁读写 volatile 变量可能影响性能,因为每次操作都直接访问主内存。

总结

  volatile 关键字主要用于确保变量的可见性和防止指令重排序,适用于状态标志和双重检查锁定等场景,但不适用于需要原子性操作的场合。

14. Java中的 synchronized 关键字有什么作用?

        在 Java 中,synchronized 关键字用于实现线程同步,确保多个线程在访问共享资源时的线程安全。

14.1 互斥性(Mutual Exclusion)
  • 作用synchronized 修饰的代码块或方法在同一时间只能被一个线程执行。

  • 机制:通过获取对象的锁(monitor lock)来实现互斥。当一个线程进入 synchronized 代码块时,其他线程必须等待锁释放后才能进入。

14.2 可见性(Visibility)
  • 作用:确保线程对共享变量的修改对其他线程可见。

  • 机制:在 synchronized 代码块或方法执行完成后,会将线程本地内存中的变量值刷新到主内存中;在进入 synchronized 代码块或方法时,会从主内存中读取最新的变量值。

使用方式

synchronized 可以修饰以下两种形式:

1. 修饰实例方法

  • 锁对象是当前实例(this)。

  • 示例:

    public synchronized void method() {
        // 线程安全的代码
    }

2. 修饰静态方法

  • 锁对象是当前类的 Class 对象。

  • 示例:

    public static synchronized void staticMethod() {
        // 线程安全的代码
    }

3. 修饰代码块

  • 需要显式指定锁对象。

  • 示例:

    public void method() {
        synchronized (this) { // 锁对象是当前实例
            // 线程安全的代码
        }
    }
    使用场景
  • 保护共享资源

    • 当多个线程需要访问或修改共享资源时,使用 synchronized 可以避免数据不一致问题。

    • 示例:

      public class Counter {
          private int count = 0;
      
          public synchronized void increment() {
              count++;
          }
      
          public synchronized int getCount() {
              return count;
          }
      }
  • 实现线程安全的单例模式

    • 使用 synchronized 确保单例对象的唯一性。

    • 示例:

      public class Singleton {
          private static Singleton instance;
      
          private Singleton() {}
      
          public static synchronized Singleton getInstance() {
              if (instance == null) {
                  instance = new Singleton();
              }
              return instance;
          }
      }
  • 线程间通信

    • 结合 wait() 和 notify() 方法,实现线程间的协作。

    • 示例:

      public class SharedResource {
          private boolean isReady = false;
      
          public synchronized void waitUntilReady() throws InterruptedException {
              while (!isReady) {
                  wait(); // 释放锁并等待
              }
          }
      
          public synchronized void setReady() {
              isReady = true;
              notifyAll(); // 唤醒等待的线程
          }
      }
      注意事项
    • 性能开销:

      • synchronized 会引入锁竞争,可能导致线程阻塞,影响性能。

      • 在高并发场景下,可以考虑使用更高效的并发工具(如 ReentrantLock 或 java.util.concurrent 包中的类)。

    • 死锁风险

      • 如果多个线程互相持有对方需要的锁,可能导致死锁。

      • 示例:

        // 线程1
        synchronized (lockA) {
            synchronized (lockB) {
                // 操作
            }
        }
        
        // 线程2
        synchronized (lockB) {
            synchronized (lockA) {
                // 操作
            }
        }
    • 锁的范围

      • 尽量缩小同步代码块的范围,避免不必要的性能损耗。

总结

  synchronized 关键字是 Java 中最基本的线程同步机制,用于实现互斥性和可见性。它适用于保护共享资源、实现线程安全的单例模式以及线程间通信等场景。但在高并发场景下,需要注意性能开销和死锁风险,必要时可以使用更高级的并发工具。

15. Java中的 transient 关键字有什么作用?

        在 Java 中,transient 关键字用于修饰类的成员变量,其主要作用是阻止该变量被序列化。具体来说,当一个对象被序列化时,transient 修饰的变量不会被包含在序列化的数据中。

15.1 作用
  • 阻止序列化transient 修饰的变量在对象序列化时会被忽略,不会被保存到文件或通过网络传输。

  • 默认值:在反序列化时,transient 变量的值会被设置为默认值(如 int 类型为 0,对象类型为 null)。

15.2 使用场景
  1. 敏感信息

    • 如果某些变量包含敏感信息(如密码、密钥等),可以使用 transient 修饰,避免序列化时泄露。

    • 示例:

      public class User implements Serializable {
          private String username;
          private transient String password; // 不会被序列化
      
          // 构造方法、getter 和 setter
      }
  2. 临时数据

    • 如果某些变量是临时数据或可以通过其他数据计算得出,可以使用 transient 修饰,避免不必要的序列化。

    • 示例:

      public class Data implements Serializable {
          private int value;
          private transient int cachedResult; // 临时缓存,不需要序列化
      
          public int computeResult() {
              if (cachedResult == 0) {
                  cachedResult = value * 2; // 假设这是一个计算过程
              }
              return cachedResult;
          }
      }
  3. 不可序列化的对象

    • 如果某个成员变量是不可序列化的对象(如 Thread 或 InputStream),可以使用 transient 修饰,避免序列化时抛出 NotSerializableException

    • 示例:

      public class AppState implements Serializable {
          private String appName;
          private transient Thread workerThread; // 不可序列化的对象
      }
15.3 注意事项
  1. 反序列化时的初始化

    • 反序列化时,transient 变量的值会被设置为默认值。如果需要恢复这些变量的值,可以自定义 readObject 方法。

    • 示例:

      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
          in.defaultReadObject(); // 默认反序列化
          this.password = "defaultPassword"; // 手动初始化 transient 变量
      }
  2. 与静态变量的区别

    • transient 修饰的是实例变量,而静态变量(static)本身就不会被序列化,因此不需要使用 transient 修饰。

总结

  transient 关键字用于阻止变量被序列化,适用于保护敏感信息、避免序列化临时数据或不可序列化的对象。反序列化时,transient 变量的值会被设置为默认值,如果需要恢复其值,可以自定义 readObject 方法。

16. Java中的 Comparable 和 Comparator 有什么区别?

        在 Java 中,Comparable 和 Comparator 都是用于对象排序的接口,但它们的用途和实现方式有所不同。

16.1 Comparable
  • 定义Comparable 是一个接口,定义在 java.lang 包中。

  • 作用:用于实现对象的自然排序(即默认排序规则)。

  • 方法:需要实现 compareTo(T o) 方法。

  • 使用场景:当一个类有明确的自然排序规则时,可以实现 Comparable 接口。

  • 示例

public class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public int compareTo(Person other) {
        return this.age - other.age; // 按年龄排序
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }

    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        Collections.sort(people); // 使用自然排序
        System.out.println(people); // 输出:[Bob (25), Alice (30), Charlie (35)]
    }
}
16.2 Comparator
  • 定义Comparator 是一个接口,定义在 java.util 包中。

  • 作用:用于实现对象的定制排序(即灵活的排序规则)。

  • 方法:需要实现 compare(T o1, T o2) 方法。

  • 使用场景

    • 当一个类没有实现 Comparable 接口时,可以通过 Comparator 进行排序。

    • 当需要多种排序规则时,可以使用 Comparator

  • 示例

import java.util.*;

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

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }

    public static void main(String[] args) {
        List<Person> people = new ArrayList<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        // 使用 Comparator 按姓名排序
        Comparator<Person> nameComparator = new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p1.name.compareTo(p2.name);
            }
        };
        Collections.sort(people, nameComparator);
        System.out.println(people); // 输出:[Alice (30), Bob (25), Charlie (35)]
    }
}
16.3 区别对比
特性ComparableComparator
包名java.langjava.util
方法compareTo(To)compare(To1, To2)
排序规则自然排序(默认排序规则)定制排序(灵活排序规则)
实现位置在类内部实现在类外部实现
使用场景单一排序规则多种排序规则
修改排序规则需要修改类的代码不需要修改类的代码
示例Collections.sort(list)Collections.sort(list, comparator)
16.4 使用建议
  • 使用 Comparable

    • 当类有明确的自然排序规则时。

    • 例如,String 和 Integer 类都实现了 Comparable,因为它们有明确的排序规则。

  • 使用 Comparator

    • 当需要多种排序规则时。

    • 当无法修改类的源代码时(例如,使用第三方库的类)。

    • 当需要临时定义排序规则时。

总结
  • Comparable 用于定义对象的自然排序规则,适合单一排序场景。

  • Comparator 用于定义灵活的排序规则,适合多种排序场景。

17. Java中的 instanceof 关键字有什么作用?

        在 Java 中,instanceof 是一个二元操作符,用于检查一个对象是否是指定类型(类、接口或子类)的实例

17.1 作用
  • 类型检查:判断一个对象是否属于某个类或其子类、接口的实现类。

  • 避免类型转换异常:在类型转换之前使用 instanceof 进行检查,可以避免 ClassCastException

17.2 语法
object instanceof Type
  • object:需要检查的对象。

  • Type:目标类型(类、接口或子类)。

  • 返回值true 或 false

17.3 使用场景

1. 类型检查

  • 在需要判断对象的实际类型时使用。

  • 示例:

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        System.out.println(myDog instanceof Dog); // true
        System.out.println(myDog instanceof Animal); // true
        System.out.println(myCat instanceof Dog); // false
    }
}

2. 避免类型转换异常

  • 在类型转换之前使用 instanceof 进行检查,确保转换的安全性。

  • 示例:

Animal animal = new Dog();

if (animal instanceof Dog) {
    Dog dog = (Dog) animal; // 安全转换
    System.out.println("This is a Dog.");
} else {
    System.out.println("This is not a Dog.");
}

3. 多态场景下的类型判断

  • 在处理多态对象时,instanceof 可以帮助确定对象的实际类型。

  • 示例:

public void checkAnimal(Animal animal) {
    if (animal instanceof Dog) {
        System.out.println("This is a Dog.");
    } else if (animal instanceof Cat) {
        System.out.println("This is a Cat.");
    } else {
        System.out.println("This is an unknown Animal.");
    }
}

4. 接口实现检查

  • 检查对象是否实现了某个接口。

  • 示例:

interface Swimmable {}
class Fish implements Swimmable {}
class Bird {}

public class Main {
    public static void main(String[] args) {
        Swimmable fish = new Fish();
        Bird bird = new Bird();

        System.out.println(fish instanceof Swimmable); // true
        System.out.println(bird instanceof Swimmable); // false
    }
}
17.4 注意事项
  1. null 检查

    • 如果对象为 nullinstanceof 会返回 false

    • 示例:

      Animal animal = null;
      System.out.println(animal instanceof Animal); // false
  2. 泛型类型擦除

    • 由于 Java 泛型的类型擦除机制,instanceof 不能直接用于泛型类型。

    • 示例:

      List<String> list = new ArrayList<>();
      // 以下代码无法通过编译
      // System.out.println(list instanceof List<String>);
  3. 性能影响

    • instanceof 的性能通常较好,但在高频调用时可能会影响性能。

总结

  instanceof 关键字用于检查对象是否属于某个类型,常用于类型检查、避免类型转换异常以及多态场景下的类型判断。它是 Java 中实现类型安全的重要工具,但在使用时需要注意 null 值和泛型类型擦除的限制。

18. Java中的 break 和 continue 有什么区别?

        在 Java 中,break 和 continue 都是用于控制循环流程的关键字,但它们的作用和行为有所不同。

18.1 break
  • 作用:立即终止当前循环(forwhiledo-while 或 switch 语句),并跳出循环体。

  • 使用场景

    • 当满足某个条件时,提前结束循环。

    • 在 switch 语句中,用于跳出 case 分支。

  • 示例

    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break; // 当 i 等于 5 时,终止循环
        }
        System.out.println(i);
    }
    // 输出:1 2 3 4
18.2 continue
  • 作用:跳过当前循环的剩余代码,直接进入下一次循环迭代。

  • 使用场景

    • 当满足某个条件时,跳过当前迭代,继续执行下一次循环。

  • 示例

for (int i = 1; i <= 5; i++) {
    if (i == 3) {
        continue; // 当 i 等于 3 时,跳过本次循环
    }
    System.out.println(i);
}
// 输出:1 2 4 5
18.3 区别对比
特性breakcontinue
作用终止整个循环跳过当前迭代,继续下一次循环
使用场景提前结束循环跳过某些特定条件的迭代
循环行为循环完全结束循环继续执行,但跳过当前迭代
适用语句forwhiledo-whileswitchforwhiledo-while
18.4 嵌套循环中的使用
  • break:默认只跳出当前所在的循环。如果需要跳出外层循环,可以使用带标签的 break

  • continue:默认只跳过当前循环的当前迭代。如果需要跳过外层循环的当前迭代,可以使用带标签的 continue

带标签的 break 示例:

outerLoop:
for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (i == 2 && j == 2) {
            break outerLoop; // 跳出外层循环
        }
        System.out.println("i=" + i + ", j=" + j);
    }
}
// 输出:
// i=1, j=1
// i=1, j=2
// i=1, j=3
// i=2, j=1

带标签的 continue 示例:

outerLoop:
for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
        if (i == 2 && j == 2) {
            continue outerLoop; // 跳过外层循环的当前迭代
        }
        System.out.println("i=" + i + ", j=" + j);
    }
}
// 输出:
// i=1, j=1
// i=1, j=2
// i=1, j=3
// i=2, j=1
// i=3, j=1
// i=3, j=2
// i=3, j=3
总结
  • break:用于完全终止循环,适用于提前结束循环或跳出 switch 语句。

  • continue:用于跳过当前迭代,继续执行下一次循环,适用于跳过某些特定条件的迭代。

  • 在嵌套循环中,可以使用带标签的 break 和 continue 来控制外层循环的行为。

19. Java中的 Math 类有哪些常用方法?

        Java 中的 Math 类提供了许多用于数学运算的静态方法。

19.1 基本运算
  • abs(int a)abs(long a)abs(float a)abs(double a)
    返回参数的绝对值。

  • max(int a, int b)max(long a, long b)max(float a, float b)max(double a, double b)
    返回两个参数中的较大值。

  • min(int a, int b)min(long a, long b)min(float a, float b)min(double a, double b)
    返回两个参数中的较小值。

19.2 指数和对数
  • pow(double a, double b)
    返回 a 的 b 次方。

  • sqrt(double a)
    返回 a 的平方根。

  • exp(double a)
    返回自然对数底数 e 的 a 次方。

  • log(double a)
    返回 a 的自然对数(以 e 为底)。

  • log10(double a)
    返回 a 的以 10 为底的对数。

19.3 三角函数
  • sin(double a)
    返回角度的正弦值(角度以弧度表示)。

  • cos(double a)
    返回角度的余弦值(角度以弧度表示)。

  • tan(double a)
    返回角度的正切值(角度以弧度表示)。

  • asin(double a)
    返回 a 的反正弦值(结果以弧度表示)。

  • acos(double a)
    返回 a 的反余弦值(结果以弧度表示)。

  • atan(double a)
    返回 a 的反正切值(结果以弧度表示)。

  • atan2(double y, double x)
    返回从直角坐标 (x, y) 到极坐标 (r, theta) 的转换角度 theta

19.4 舍入运算
  • ceil(double a)
    返回大于或等于 a 的最小整数(向上取整)。

  • floor(double a)
    返回小于或等于 a 的最大整数(向下取整)。

  • round(float a)round(double a)
    返回最接近 a 的整数(四舍五入)。

19.5 随机数
  • random()
    返回一个 [0.0, 1.0) 范围内的伪随机 double 值。

19.6 其他
  • toRadians(double angdeg)
    将角度转换为弧度。

  • toDegrees(double angrad)
    将弧度转换为角度。

  • hypot(double x, double y)
    返回 sqrt(x² + y²),即直角三角形的斜边长度。

  • copySign(double magnitude, double sign)
    返回一个与 sign 同符号的 magnitude 值。

  • nextAfter(double start, double direction)
    返回与 start 相邻的、朝向 direction 的浮点数。

  • nextUp(double d)
    返回比 d 大的最小浮点数。

  • nextDown(double d)
    返回比 d 小的最大浮点数。

20. Java中的 Arrays 类有哪些常用方法?

  java.util.Arrays 类是 Java 中用于操作数组的工具类,提供了许多静态方法来处理数组。

20.1 排序
  • sort(array): 对数组进行升序排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.sort(arr);
    // arr 现在是 [1, 2, 3, 4, 5]
  • sort(array, fromIndex, toIndex): 对数组的指定范围进行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.sort(arr, 1, 4);
    // arr 现在是 [5, 1, 3, 4, 2]
20.2 二分查找
  • binarySearch(array, key): 在已排序的数组中使用二分查找法查找指定元素,返回索引。如果未找到,返回负数。

    int[] arr = {1, 2, 3, 4, 5};
    int index = Arrays.binarySearch(arr, 3);
    // index 是 2
  • binarySearch(array, fromIndex, toIndex, key): 在数组的指定范围内进行二分查找。

    int[] arr = {1, 2, 3, 4, 5};
    int index = Arrays.binarySearch(arr, 1, 4, 3);
    // index 是 2
20.3 比较
  • equals(array1, array2): 比较两个数组是否相等(元素顺序和值相同)。

    int[] arr1 = {1, 2, 3};
    int[] arr2 = {1, 2, 3};
    boolean isEqual = Arrays.equals(arr1, arr2);
    // isEqual 是 true
20.4 填充
  • fill(array, value): 将数组的所有元素填充为指定值。

    int[] arr = new int[5];
    Arrays.fill(arr, 10);
    // arr 现在是 [10, 10, 10, 10, 10]
  • fill(array, fromIndex, toIndex, value): 将数组的指定范围填充为指定值。

    int[] arr = new int[5];
    Arrays.fill(arr, 1, 4, 10);
    // arr 现在是 [0, 10, 10, 10, 0]
20.5 复制
  • copyOf(original, newLength): 复制数组,指定新数组的长度。

    int[] arr = {1, 2, 3};
    int[] newArr = Arrays.copyOf(arr, 5);
    // newArr 现在是 [1, 2, 3, 0, 0]
  • copyOfRange(original, from, to): 复制数组的指定范围。

    int[] arr = {1, 2, 3, 4, 5};
    int[] newArr = Arrays.copyOfRange(arr, 1, 4);
    // newArr 现在是 [2, 3, 4]
20.6 转换为字符串
  • toString(array): 将数组转换为字符串表示形式。

    int[] arr = {1, 2, 3};
    String str = Arrays.toString(arr);
    // str 是 "[1, 2, 3]"
20.7 哈希码
  • hashCode(array): 返回数组的哈希码。

    int[] arr = {1, 2, 3};
    int hashCode = Arrays.hashCode(arr);
20.8 流操作
  • stream(array): 将数组转换为流。

    int[] arr = {1, 2, 3};
    IntStream stream = Arrays.stream(arr);
20.9 并行排序
  • parallelSort(array): 对数组进行并行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.parallelSort(arr);
    // arr 现在是 [1, 2, 3, 4, 5]
  • parallelSort(array, fromIndex, toIndex): 对数组的指定范围进行并行排序。

    int[] arr = {5, 3, 1, 4, 2};
    Arrays.parallelSort(arr, 1, 4);
    // arr 现在是 [5, 1, 3, 4, 2]
20.10 比较器排序
  • sort(array, comparator): 使用自定义比较器对数组进行排序。

    String[] arr = {"apple", "banana", "cherry"};
    Arrays.sort(arr, (a, b) -> b.compareTo(a));
    // arr 现在是 ["cherry", "banana", "apple"]
20.11 并行前缀计算
  • parallelPrefix(array, op): 对数组进行并行前缀计算。

    int[] arr = {1, 2, 3, 4};
    Arrays.parallelPrefix(arr, (a, b) -> a + b);
    // arr 现在是 [1, 3, 6, 10]
20.12 集合转换
  • asList(array): 将数组转换为固定大小的列表。

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
// list 是 ["a", "b", "c"]

    21. Java中的 Collections 类有哪些常用方法?

      java.util.Collections 类是 Java 中用于操作集合(如 ListSetMap 等)的工具类,提供了许多静态方法来处理集合。

    21.1 排序
    • sort(list): 对列表进行升序排序。

      List<Integer> list = Arrays.asList(5, 3, 1, 4, 2);
      Collections.sort(list);
      // list 现在是 [1, 2, 3, 4, 5]
    • sort(list, comparator): 使用自定义比较器对列表进行排序。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, (a, b) -> b.compareTo(a));
      // list 现在是 ["cherry", "banana", "apple"]
    21.2 二分查找
    • binarySearch(list, key): 在已排序的列表中使用二分查找法查找指定元素,返回索引。如果未找到,返回负数。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int index = Collections.binarySearch(list, 3);
      // index 是 2
    • binarySearch(list, key, comparator): 使用自定义比较器在已排序的列表中进行二分查找。

      List<String> list = Arrays.asList("cherry", "banana", "apple");
      int index = Collections.binarySearch(list, "banana", (a, b) -> b.compareTo(a));
      // index 是 1
    21.3 反转
    • reverse(list): 反转列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.reverse(list);
      // list 现在是 [5, 4, 3, 2, 1]
    21.4 随机打乱
    • shuffle(list): 随机打乱列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.shuffle(list);
      // list 现在是随机顺序,例如 [3, 1, 5, 2, 4]
    • shuffle(list, random): 使用指定的随机源打乱列表中的元素顺序。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.shuffle(list, new Random());
      // list 现在是随机顺序,例如 [4, 2, 1, 5, 3]
    21.5 填充
    • fill(list, value): 将列表的所有元素填充为指定值。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      Collections.fill(list, 10);
      // list 现在是 [10, 10, 10, 10, 10]
    21.6 复制
    • copy(dest, src): 将源列表中的元素复制到目标列表中。

      List<Integer> src = Arrays.asList(1, 2, 3);
      List<Integer> dest = Arrays.asList(4, 5, 6, 7, 8);
      Collections.copy(dest, src);
      // dest 现在是 [1, 2, 3, 7, 8]
    21.7 最小值和最大值
    • min(collection): 返回集合中的最小元素。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int min = Collections.min(list);
      // min 是 1
    • max(collection): 返回集合中的最大元素。

      List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
      int max = Collections.max(list);
      // max 是 5
    • min(collection, comparator): 使用自定义比较器返回集合中的最小元素。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      String min = Collections.min(list, (a, b) -> b.compareTo(a));
      // min 是 "cherry"
    • max(collection, comparator): 使用自定义比较器返回集合中的最大元素。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      String max = Collections.max(list, (a, b) -> b.compareTo(a));
      // max 是 "apple"
    21.8 替换
    • replaceAll(list, oldVal, newVal): 将列表中的所有旧值替换为新值。

      List<String> list = Arrays.asList("apple", "banana", "apple");
      Collections.replaceAll(list, "apple", "orange");
      // list 现在是 ["orange", "banana", "orange"]
    21.9 频率
    • frequency(collection, obj): 返回集合中指定元素的出现次数。

      List<String> list = Arrays.asList("apple", "banana", "apple");
      int freq = Collections.frequency(list, "apple");
      // freq 是 2
    21.10 不可变集合
    • unmodifiableCollection(collection): 返回一个不可修改的集合视图。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collection<String> unmodifiableList = Collections.unmodifiableCollection(list);
      // unmodifiableList 是不可修改的
    • unmodifiableList(list): 返回一个不可修改的列表视图。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      List<String> unmodifiableList = Collections.unmodifiableList(list);
      // unmodifiableList 是不可修改的
    • unmodifiableSet(set): 返回一个不可修改的集合视图。

      Set<String> set = new HashSet<>(Arrays.asList("apple", "banana", "cherry"));
      Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
      // unmodifiableSet 是不可修改的
    • unmodifiableMap(map): 返回一个不可修改的映射视图。

      Map<String, Integer> map = new HashMap<>();
      map.put("apple", 1);
      map.put("banana", 2);
      Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(map);
      // unmodifiableMap 是不可修改的
    21.11 同步集合
    • synchronizedCollection(collection): 返回一个线程安全的集合。

      Collection<String> collection = new ArrayList<>();
      Collection<String> syncCollection = Collections.synchronizedCollection(collection);
      // syncCollection 是线程安全的
    • synchronizedList(list): 返回一个线程安全的列表。

      List<String> list = new ArrayList<>();
      List<String> syncList = Collections.synchronizedList(list);
      // syncList 是线程安全的
    • synchronizedSet(set): 返回一个线程安全的集合。

      Set<String> set = new HashSet<>();
      Set<String> syncSet = Collections.synchronizedSet(set);
      // syncSet 是线程安全的
    • synchronizedMap(map): 返回一个线程安全的映射。

      Map<String, Integer> map = new HashMap<>();
      Map<String, Integer> syncMap = Collections.synchronizedMap(map);
      // syncMap 是线程安全的
    21.12 单元素集合
    • singletonList(obj): 返回一个只包含指定对象的不可变列表。

      List<String> list = Collections.singletonList("apple");
      // list 是 ["apple"]
    • singletonSet(obj): 返回一个只包含指定对象的不可变集合。

      Set<String> set = Collections.singletonSet("apple");
      // set 是 ["apple"]
    • singletonMap(key, value): 返回一个只包含指定键值对的不可变映射。

      Map<String, Integer> map = Collections.singletonMap("apple", 1);
      // map 是 {"apple": 1}
    21.13 空集合
    • emptyList(): 返回一个空的不可变列表。

      List<String> list = Collections.emptyList();
      // list 是 []
    • emptySet(): 返回一个空的不可变集合。

      Set<String> set = Collections.emptySet();
      // set 是 []
    • emptyMap(): 返回一个空的不可变映射。

      Map<String, Integer> map = Collections.emptyMap();
      // map 是 {}
    21.14 检查集合是否为空
    • isEmpty(collection): 检查集合是否为空。

      List<String> list = new ArrayList<>();
      boolean isEmpty = Collections.isEmpty(list);
      // isEmpty 是 true
    21.15 反转比较器
    • reverseOrder(): 返回一个反转自然顺序的比较器。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, Collections.reverseOrder());
      // list 现在是 ["cherry", "banana", "apple"]
    • reverseOrder(comparator): 返回一个反转指定比较器顺序的比较器。

      List<String> list = Arrays.asList("apple", "banana", "cherry");
      Collections.sort(list, Collections.reverseOrder(String.CASE_INSENSITIVE_ORDER));
      // list 现在是 ["cherry", "banana", "apple"]

    相关文章:

  • Jetpack Architecture系列教程之(三)——ViewModel控制器
  • 框架--Mybatis3
  • Git安装
  • 掌握 Zabbix 监控系统配置:从零到精通
  • 用Nginx打造防盗链护盾
  • 怎么学习调试ISP的参数
  • 【分布式系统】幂等性
  • Redis字符串常见命令(String)
  • Llama 3.1 本地电脑部署 Linux系统 【轻松简易】
  • 庖丁解java(一篇文章学java)
  • spring配置文件默认类型与进制转换的坑
  • petalinux-build ERROR
  • MyBatis Plus扩展功能
  • 2024 山东小学组 CSP-X T2 消灭怪兽
  • UEFI Spec 学习笔记---6 - Block Translation Table (BTT) Layout
  • preprocessing.scale函数介绍
  • 区块链研究(一):Windows下搭建以太坊私有链,部署智能合约实现数据上链功能(完整跑通版!好累!)
  • Ubuntu cgroups v2切换cgroups v1
  • 《深入理解JVM》实战笔记(一):内存区域、对象布局与OOM排查指南
  • uni-app开发app时 使用uni.chooseLocation遇到的问题
  • 天元建设集团有限公司楼盘/seo营销论文
  • 网站建设的资源整合与系统设计/万网域名管理入口
  • wordpress后台切换中文/windows优化大师有必要安装吗
  • 怎么查网站有没有做404/全球搜索引擎排行榜
  • 安庆网站建设哪家好/百度官方网址
  • 鲜花网站的网络营销与策划书/如何做好网络营销推广