一、Math
Java中的Math类是一个包含基本数学函数的工具类。这个类不能被实例化,因为它的构造方法是私有的。所有方法都是静态方法,所以可以直接使用Math类名调用它们。Math类提供了许多在实际应用中常用的数学函数,如求幂、平方根、三角函数、取整等。
以下是一些Math类中的常用方法:
abs(double a)
:返回给定值的绝对值。ceil(double a)
:返回大于或等于给定值的最小整数(以double表示)。floor(double a)
:返回小于或等于给定值的最大整数(以double表示)。round(double a)
:将给定的浮点数四舍五入为最接近的整数(以long表示)。max(double a, double b)
:返回两个给定值中的较大值。min(double a, double b)
:返回两个给定值中的较小值。pow(double a, double b)
:返回a
的b
次幂。sqrt(double a)
:返回给定值的平方根。cbrt(double a)
:返回给定值的立方根。random()
:返回一个大于等于0且小于1的随机浮点数。sin(double a)
:返回给定角度(以弧度表示)的正弦值。cos(double a)
:返回给定角度(以弧度表示)的余弦值。tan(double a)
:返回给定角度(以弧度表示)的正切值。asin(double a)
:返回给定值的反正弦值(以弧度表示)。acos(double a)
:返回给定值的反余弦值(以弧度表示)。atan(double a)
:返回给定值的反正切值(以弧度表示)。toDegrees(double angrad)
:将角度从弧度转换为度。toRadians(double angdeg)
:将角度从度转换为弧度。
这些方法在许多实际应用中都非常有用,如科学计算、工程设计、游戏开发等。
Math类的使用场景:
- 几何计算:计算两点之间的距离。例如,根据两个平面上点的坐标计算它们之间的欧几里得距离。
public class DistanceCalculator {
public static void main(String[] args) {
double x1 = 3, y1 = 4;
double x2 = 7, y2 = 9;
double distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
System.out.println("Distance between the two points: " + distance);
}
}
- 随机数生成:生成一个指定范围内的随机整数。例如,在1到6之间生成一个随机整数,模拟掷骰子的过程。
public class DiceRoll {
public static void main(String[] args) {
int min = 1;
int max = 6;
int randomNum = (int) (Math.random() * (max - min + 1) + min);
System.out.println("You rolled a: " + randomNum);
}
}
二、System
Java中的System类提供了访问系统资源的方法,如标准输入、输出和错误流,以及与当前系统环境有关的实用方法。它是一个不能被实例化的工具类,因为它的构造方法是私有的。所有方法都是静态方法,因此可以直接使用System类名调用它们。
以下是System
类中的一些常用方法和属性:
-
out
:System.out
是一个PrintStream
类型的对象,用于访问标准输出流(通常指控制台)。您可以使用System.out.print()
和System.out.println()
方法将文本输出到标准输出流。 -
in
:System.in
是一个InputStream
类型的对象,用于访问标准输入流(通常指从键盘或控制台输入)。您可以使用System.in.read()
方法从标准输入流读取数据。 -
err
:System.err
是一个PrintStream
类型的对象,用于访问标准错误流。您可以使用System.err.print()
和System.err.println()
方法将错误信息输出到标准错误流。 -
currentTimeMillis()
:此方法返回当前时间(以毫秒为单位),从1970年1月1日00:00:00 UTC开始。这个方法常用于测量代码执行时间或任务调度。 -
nanoTime()
:此方法返回当前时间(以纳秒为单位),其值与任何固定点无关。此方法通常用于测量代码段的执行时间,特别是当需要较高精度时。 -
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
:此方法用于将一个数组的一部分复制到另一个数组。它可以高效地复制数组,因为它是使用本地代码实现的。 -
exit(int status)
:此方法终止当前运行的Java虚拟机,status
参数表示退出状态。非零值通常表示异常终止。 -
gc()
:此方法建议Java虚拟机运行垃圾收集器。但是,这只是一个建议,具体的垃圾收集行为取决于Java虚拟机的实现。 -
getenv(String name)
:此方法返回指定环境变量的值。如果未找到该环境变量,则返回null
。 -
getProperty(String key)
:此方法返回指定系统属性的值。系统属性包括关于操作系统、文件编码、用户语言等的信息。
这些方法和属性在许多实际应用中都非常有用,例如日志记录、性能分析、系统调试等。
System类的使用场景:
- 控制台输入/输出:从控制台读取用户输入并向其打印结果。例如,一个简单的加法程序,从用户处获取两个数并显示它们的和。
import java.util.Scanner;
public class ConsoleInputOutput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the first number: ");
int a = scanner.nextInt();
System.out.println("Enter the second number: ");
int b = scanner.nextInt();
int sum = a + b;
System.out.println("The sum is: " + sum);
}
}
- 性能测试和计时:测量代码执行时间。例如,测量一个排序算法的执行时间。
public class PerformanceTest {
public static void main(String[] args) {
int[] array = new int[100000];
// ... Fill the array with random numbers ...
long startTime = System.nanoTime();
// ... Call the sorting algorithm ...
long endTime = System.nanoTime();
long elapsedTime = endTime - startTime;
System.out.println("Execution time: " + elapsedTime + " nanoseconds");
}
}
三、Runtime
Java中的Runtime
类代表了Java应用程序运行时环境。通过调用Runtime
类的方法,可以与底层操作系统进行交互,执行系统命令,获取系统资源信息等。Runtime
类是一个单例类,因此您不能使用构造方法创建新的Runtime
实例。要获取Runtime
实例,请调用Runtime.getRuntime()
方法。
以下是Runtime
类中的一些常用方法:
-
exec(String command)
:此方法允许您执行操作系统命令。command
参数是要执行的系统命令。方法返回一个Process
对象,代表正在执行的命令进程。 -
addShutdownHook(Thread hook)
:此方法允许您在Java虚拟机(JVM)关闭时执行指定的线程。这在需要在应用程序结束时执行清理工作时非常有用,例如关闭数据库连接、释放系统资源等。 -
availableProcessors()
:此方法返回可用于Java虚拟机的处理器数量。这对于编写并行处理代码时了解可用处理能力很有帮助。 -
freeMemory()
:此方法返回Java虚拟机中的空闲内存量。这对于监控应用程序的内存使用和性能分析很有用。 -
totalMemory()
:此方法返回Java虚拟机的总内存量。这同样可以用于监控应用程序的内存使用和性能分析。 -
maxMemory()
:此方法返回Java虚拟机试图使用的最大内存量。这有助于了解应用程序可以使用的最大内存资源。 -
gc()
:此方法建议Java虚拟机运行垃圾收集器。然而,这只是一个建议,具体的垃圾收集行为取决于Java虚拟机的实现。
这些方法在实际应用中有很多用途,例如执行系统命令、资源管理、性能监控和调优等。
以下是Runtime
类的一些使用场景示例:
- 执行操作系统命令:使用
exec()
方法执行系统命令,例如在Windows系统中打开记事本。
public class ExecuteSystemCommand {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("notepad.exe");
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 注册JVM关闭时的钩子(Shutdown Hook):在JVM关闭时执行特定的任务,例如关闭资源或进行清理工作。
public class ShutdownHookExample {
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Performing cleanup before shutting down...");
// ... Close resources, perform cleanup tasks ...
}
});
System.out.println("Application is running...");
// ... Run the main part of the application ...
}
}
- 获取处理器数量:根据可用处理器数量调整并行任务数量。
public class ProcessorInfo {
public static void main(String[] args) {
int processors = Runtime.getRuntime().availableProcessors();
System.out.println("Available processors: " + processors);
// ... Use the processor count to adjust parallel tasks ...
}
}
- 监控内存使用情况:获取JVM的内存信息,以评估应用程序的性能。
public class MemoryUsage {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
System.out.println("Max memory: " + maxMemory);
System.out.println("Total memory: " + totalMemory);
System.out.println("Free memory: " + freeMemory);
System.out.println("Used memory: " + (totalMemory - freeMemory));
}
}
四、Object
Java中的Object
类是所有类的基类(也称为超类或父类)。这意味着所有其他类都隐式地继承了Object
类。由于每个类都继承自Object
类,所以它们都具有Object
类中定义的方法。这使得Object
类的方法在编写Java程序时非常通用且有用。
以下是Object
类中的一些常用方法:
-
toString()
:此方法返回一个表示对象的字符串。默认实现返回一个由类名、"@"字符和对象的哈希码的无符号十六进制表示组成的字符串。在实际应用中,通常会覆盖此方法,以便为类的实例提供更有意义的字符串表示。 -
equals(Object obj)
:此方法检查对象是否等于另一个对象。默认实现比较对象的内存地址。在实际应用中,通常会覆盖此方法,以便根据类的属性比较对象是否相等。 -
hashCode()
:此方法返回对象的哈希码。默认实现返回一个基于对象的内存地址的整数。当覆盖equals()
方法时,通常也需要覆盖hashCode()
方法,以便根据类的属性生成哈希码。 -
getClass()
:此方法返回对象的运行时类。返回的Class
对象包含有关类的元数据,如类名、父类、实现的接口等。 -
clone()
:此方法创建并返回对象的副本。默认实现是浅拷贝,意味着对象的字段仅被复制,而不是对象引用的实际对象。为了使用此方法,类必须实现Cloneable
接口,并可能需要覆盖clone()
方法以实现深拷贝。 -
notify()
、notifyAll()
和wait()
:这些方法用于线程同步和通信。notify()
和notifyAll()
方法用于唤醒在对象上等待的线程,而wait()
方法使当前线程等待直到另一个线程调用notify()
或notifyAll()
方法。
这些方法在实际编程中经常被用到。例如,当需要自定义类的字符串表示形式、比较类的实例是否相等、实现线程同步等场景时,会使用到Object
类的方法。
以下是Object
类的一些使用场景示例:
- 自定义
toString()
方法:提供一个有意义的字符串表示形式,以便更容易地理解和调试对象。
public class Person {
private String name;
private int age;
// ... Constructor, getters, and setters ...
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
Person person = new Person("Alice", 30);
System.out.println(person); // 输出: Person{name='Alice', age=30}
- 覆盖
equals()
和hashCode()
方法:基于类的属性比较对象是否相等。
import java.util.Objects;
public class Person {
private String name;
private int age;
// ... Constructor, getters, and setters ...
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
Person person = (Person) obj;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
Person person1 = new Person("Alice", 30);
Person person2 = new Person("Alice", 30);
System.out.println(person1.equals(person2)); // 输出: true
- 使用
getClass()
方法:动态获取对象的类信息,例如获取类名。
public class ClassInfo {
public static void main(String[] args) {
Person person = new Person("Bob", 25);
Class<?> personClass = person.getClass();
System.out.println("Class name: " + personClass.getName());
}
}
- 线程同步:使用
wait()
和notify()
方法实现生产者-消费者模式。
import java.util.LinkedList;
import java.util.Queue;
public class ProducerConsumer {
public static void main(String[] args) {
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 5;
Thread producer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (buffer) {
while (buffer.size() == maxSize) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer.add(i);
System.out.println("Produced: " + i);
buffer.notifyAll();
}
}
});
Thread consumer = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (buffer) {
while (buffer.isEmpty()) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int value = buffer.remove();
System.out.println("Consumed: " + value);
buffer.notifyAll();
}
}
});
producer.start();
consumer.start();
}
}
五、浅克隆和深克隆
浅克隆(Shallow Cloning)和深克隆(Deep Cloning)是创建对象副本的两种方法。
-
浅克隆:创建对象的一个新实例,并将原始对象的非静态字段复制到新对象中。如果字段是值类型,则复制字段的值;如果字段是引用类型,则复制引用,而不是引用的对象。这意味着原始对象和克隆对象共享相同的引用对象。在Java中,通过实现
Cloneable
接口并使用Object
类的clone()
方法可以实现浅克隆。 -
深克隆:创建对象的一个新实例,并递归地复制原始对象及其引用对象。这意味着原始对象和克隆对象的所有引用对象也是各自独立的副本。深克隆通常需要自定义实现,例如通过重写
clone()
方法,或使用序列化和反序列化技术。
以下是浅克隆和深克隆的示例:
import java.util.ArrayList;
class Person implements Cloneable {
String name;
ArrayList<String> friends;
public Person(String name) {
this.name = name;
this.friends = new ArrayList<>();
}
// Shallow cloning
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
// Deep cloning
protected Person deepClone() throws CloneNotSupportedException {
Person clonedPerson = (Person) super.clone();
clonedPerson.friends = new ArrayList<>(this.friends);
return clonedPerson;
}
}
public class CloningExample {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("Alice");
person1.friends.add("Bob");
person1.friends.add("Charlie");
Person person2 = person1.clone(); // Shallow cloning
Person person3 = person1.deepClone(); // Deep cloning
person1.friends.remove("Bob");
System.out.println("person1 friends: " + person1.friends);
System.out.println("person2 friends: " + person2.friends); // Shallow clone shares the same friends list
System.out.println("person3 friends: " + person3.friends); // Deep clone has its own independent friends list
}
}
输出结果:
person1 friends: [Charlie]
person2 friends: [Charlie]
person3 friends: [Bob, Charlie]
使用场景:
-
浅克隆适用于对象的引用对象不需要独立复制的情况。例如,如果对象包含对不可变对象的引用,或者对象之间共享相同的引用对象没有副作用。
-
深克隆适用于对象的引用对象需要独立复制的情况。例如,在多线程环境中,各线程需要独立操作对象及其引用对象,或者在处理具有嵌套引用对象的复杂数据结构时
六、Objects
Java中的Objects
类是一个实用类,包含了一些用于操作对象的静态方法。它在实际应用中提供了很多方便的方法,以简化对对象的操作,例如比较、生成哈希码、检查空值等。
以下是Objects
类中的一些常用方法:
-
equals(Object a, Object b)
:比较两个对象是否相等,处理了空值的情况。如果两个对象都为null
,则认为它们相等;如果其中一个对象为null
,则认为它们不相等;否则,使用a.equals(b)
进行比较。 -
hashCode(Object o)
:返回对象的哈希码,处理了空值的情况。如果对象为null
,则返回0;否则,返回o.hashCode()
。 -
hash(Object... values)
:根据传入的多个对象,计算一个组合哈希码。这对于覆盖一个类的hashCode()
方法非常有用,可以轻松地根据多个字段生成哈希码。 -
requireNonNull(T obj)
:检查对象是否为null
。如果对象为null
,则抛出NullPointerException
。这在检查方法参数或类属性是否为null
时非常有用。 -
toString(Object o)
:返回对象的字符串表示形式,处理了空值的情况。如果对象为null
,则返回字符串"null"
;否则,返回o.toString()
。 -
compare(T a, T b, Comparator<? super T> c)
:使用给定的Comparator
比较两个对象。处理了空值的情况。如果两个对象都为null
,则认为它们相等;如果其中一个对象为null
,则认为它们不相等;否则,使用c.compare(a, b)
进行比较。 -
isNull(Object obj)
和nonNull(Object obj)
:这两个方法用于检查对象是否为null
。isNull(Object obj)
在对象为null
时返回true
,否则返回false
。nonNull(Object obj)
在对象为null
时返回false
,否则返回true
。
Objects类提供了许多实用方法,可用于处理各种对象操作的使用场景。以下是一些使用场景的示例:
-
检查方法参数或类属性是否为null:
在构造函数或方法中,可以使用Objects.requireNonNull()
来检查参数是否为null,确保在创建对象或执行方法时不会使用null值。public class Employee { private String name; public Employee(String name) { this.name = Objects.requireNonNull(name, "Name must not be null"); } }
-
实现equals方法:
在实现自定义类的equals()
方法时,可以使用Objects.equals()
比较两个对象,避免空指针异常。@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } Employee employee = (Employee) obj; return Objects.equals(name, employee.name); }
-
实现hashCode方法:
在实现自定义类的hashCode()
方法时,可以使用Objects.hash()
基于多个字段生成哈希码。@Override public int hashCode() { return Objects.hash(name, age); }
-
实现toString方法:
在实现自定义类的toString()
方法时,可以使用Objects.toString()
生成字符串表示,处理null值。@Override public String toString() { return "Employee{name=" + Objects.toString(name) + "}"; }
-
使用Objects类的静态方法处理null值:
当在方法中处理可能为null的对象时,可以使用Objects.isNull()
或Objects.nonNull()
避免空指针异常。public void doSomething(Employee employee) { if (Objects.nonNull(employee)) { // Perform some action with the employee object } else { // Handle the case when the employee object is null } }
这些示例展示了Objects类在实际使用中的一些常见场景。通过使用这些实用方法,可以简化代码并减少错误,例如空指针异常。
七、Objects类和Object类的区别
Object类和Objects类在Java中扮演着不同的角色,它们之间有一些重要的区别。
-
Object类:Object类是Java中所有类的根类,位于java.lang包中。换句话说,Java中的所有类都直接或间接地继承自Object类。Object类提供了一些基本的方法,这些方法在所有Java类中都可用。这些方法包括:
equals(Object obj):用于比较两个对象是否相等。 hashCode():返回对象的哈希码。 toString():返回对象的字符串表示。 getClass():返回对象的运行时类。 clone():创建并返回对象的一个副本。 finalize():在对象被垃圾收集器回收之前调用。 notify(), notifyAll(), wait():与对象监视器和线程同步相关的方法。
-
Objects类:Objects类是一个工具类,位于java.util包中。它提供了一系列静态方法,这些方法主要用于操作对象、处理null值以及辅助实现Object类中的方法(例如equals()和hashCode())。Objects类的部分方法包括:
equals(Object a, Object b):用于比较两个对象是否相等,同时处理null值的情况。 hashCode(Object o):返回对象的哈希码,如果对象为null,则返回0。 toString(Object o):返回对象的字符串表示,如果对象为null,则返回字符串"null"。 requireNonNull(T obj):检查对象是否为null,如果为null则抛出NullPointerException。 compare(T a, T b, Comparator<? super T> c):使用给定的Comparator比较两个对象。 isNull(Object obj):检查对象是否为null。 nonNull(Object obj):检查对象是否非null。
总之,Object类是Java中所有类的根类,它提供了一些基本的方法。Objects类是一个工具类,提供了一系列静态方法用于操作对象、处理null值以及辅助实现Object类中的方法。这两个类在Java中有着不同的用途和功能。