文章目录
- 前言
- 一、Math(工具类)
- 二、Random:生成随机数
- 三、Runtime(和当前虚拟机运行环境相关的一个类)
- 四、System(工具类,和系统相关的)
- 五、System.out :输出对象和System.in:输入对象
- 六、Scanner类: 输入(键盘录入)
- 七、Object(重要!!!)和Objects类
- 八、浅克隆和深克隆(重要!!)
- 九、BigInteger(大整数)和BigDecimal(大小数)
- 十、Java中的时间类(用到了再来查,太多了,根本记不住)
前言
需要注意,这些常用API的方法属性千万不要背,背是背不完的,用到再去查阅帮助文档就是了。我在这里写这个系列博客也是为了形成一个私人的文档查询库。
该部分还将之前已经学过的部分 Random、System.out、Scanner这些零零散散的也汇总到这里方便查阅。
一、Math(工具类)
Math是java.lang.Math包下的一个静态工具类,由于是静态的,我们只需要类名调用即可。
1 属性
该类下面有两个字段属性
2 常见方法
主要介绍几个常见的方法,需要其他具体的方法,查阅帮助文档即可。
方法名 | 说明 | |
---|---|---|
piblic static int | abs(int a) | 获取参数的绝对值 |
piblic static double | ceil(double a) | 向上取整 |
piblic static double | floor(double a) | 向下取整 |
piblic static int | round(float a) | 四舍五入 |
piblic static int | max(int a, int b) | 获取两个int值中的较大值 |
piblic static double | pow(double a,double b) | 返回 a b a^b ab的值 |
piblic static double | random() | 返回值为double的随机值,范围为[0.0, 1.0) |
piblic static double | sqrt(double a) | 返回 double 值的正确四舍五入的正平方根 |
其实上述方法都还有各自的重载方法,所以你记肯定是不好记的,我们要学会查阅帮助文档。
double pi = Math.PI;
System.out.println("PI = " + pi); // PI = 3.141592653589793
int a = 4;
System.out.println(Math.sqrt(a)); // 2.0 ,自动隐藏转换为double类型
二、Random:生成随机数
和Scanner类一样,java.util 包里面还有一个生成随机数的Random类也较为常用。
下面给出其的一些基本方法
- 创建Random对象
Random random = new Random();
(1)nextInt(int bound): 生成一个范围在0(包括)到指定bound(不包括)之间的随机int值。不指定bound就是随机生成一个int值
int rnum = random.nextInt(100); // 生成0到99之间的随机整数
(2)nextDouble(): 生成一个范围在0.0(包括)到1.0(不包括)之间的随机double值。不能指定范围
double randomDouble = random.nextDouble();
【注】:还有一些其他的例如 nextFloat()等等,但似乎没有Python里面的好用,这里我们简单介绍一下就可以了。实际虽然有用到,但不是很多,用到再查阅资料就可以了。
麻烦就麻烦再如果要生成指定范围的随机数,就需要数学技巧了,例如要生成2-99的随机数需要 nextInt(97)+2才能实现,如果是生成指定范围的浮点数更加复杂,要像下面那样
double min = 10.0;
double max = 20.0;
double randomValue = min + (max - min) * random.nextDouble();
System.out.println("Random Double within Range: " + randomValue);
和Python一比这就显得过于繁琐了,但在java中如果不想用第三方库就必须用这个技巧了。
三、Runtime(和当前虚拟机运行环境相关的一个类)
1 基本方法
这个类,有一点特别,不是工具类。但是也不能够通过new创建对象,而是在内部就已经帮我们创建好了一个对象,我们调用一个get方法拿到这个对象就行。为什么这么设计,因为一台电脑就一个环境,当然就只有一个对象,所以干脆给你创建好了这个对象,直接get用就行。
方法名 | 说明 |
---|---|
public static Runtime getRuntime() | 返回与当前 Java 应用程序关联的运行时环境对象。 |
public void exit(int status) | 停止运行 Java 虚拟机。 |
public int availableProcessors() | 返回 Java 虚拟机可用的处理器数量(获得CPU线程数)。 |
public long maxMemory() | 返回 Java 虚拟机将尝试使用的最大内存量(单位byte)。 |
public long totalMemory() | 返回 Java 虚拟机中的内存总量(单位byte)。 |
public long freeMemory() | 返回 Java 虚拟机中的可用内存量(单位byte)。 |
public Process exec(String command) | 执行括号内的cmd命令 |
package cn.hjblogs.demo;
import java.io.IOException;
public class Test {
public static void main(String[] args) {
// 1 获取Runtime对象
Runtime runtime = Runtime.getRuntime();
// 2 停止虚拟机(和System类中停止虚拟机运行那个方法一模一样的效果)
//runtime.exit(0);
// 3 获取CPU的线程数
System.out.println("当前虚拟机的可用处理器数量:" + runtime.availableProcessors()); // 32
// 4 总内存大小,单位byte字节,转换成MB
System.out.println("当前虚拟机的总内存大小:" + runtime.maxMemory() / 1024 / 1024 + "MB"); // 4026MB
// 5 已经获取的总内存大小,单位byte字节,转换成MB
System.out.println("当前虚拟机已经获取的总内存大小:" + runtime.totalMemory() / 1024 / 1024 + "MB"); // 252MB
// 6 剩余内存大小,单位byte字节,转换成MB
System.out.println("当前虚拟机的剩余内存大小:" + runtime.freeMemory() / 1024 / 1024 + "MB"); // 248MB
// 7 运行cmd命令
try {
runtime.exec("notepad.exe"); // 打开记事本
} catch (Exception e) {
e.printStackTrace();
}
// cmd 命令
// shutdown 关机 加上参数才能执行
// shutdown -s : 默认在一分钟后关机
// shutdown -s -t 3600 :3600s后关机
// shutdown -a : 取消关机
// shutdown -r : 关机并重启
try {
Runtime.getRuntime().exec("shutdown -s -t 3600"); // 一小时后关机
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
Runtime.getRuntime().exec("shutdown -a"); // 取消关机
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2 public Process exec(String command)— 执行括号内的cmd命令 方法开发恶搞基友软件练习
要有前面的Java Swing GUI框架编程基础
四、System(工具类,和系统相关的)
System也是一个工具类,提供了一些与系统相关的方法,这里我们主要介绍三个
1 public static void exit(int status) — 终止当前运行的 Java 虚拟机。
- int status:状态码
(1)0 : 表示当前虚拟机正常停止
(2)非0(一般1即可):表示当前虚拟机异常停止
public class Test {
public static void main(String[] args) {
System.exit(0);
System.out.println("hello"); // 这行代码不会被执行
}
}
2 public static long currentTimeMillis() — 以毫秒为单位返回当前unix时间。
-
问题:什么叫做unix时间?
(1)由1970年1月1日 00:00:00 到当前时间一共经过了多少毫秒,这就是unix时间。
(2)由于北京时间与国际时间晚8小时,因此国内是从1970年1月1日 08:00:00开始算 -
毫秒又是什么,为什么是 1970年1月1日 00:00:00 这个时间?
这个时间称为计算机中的时间原点,这里有一个小故事。
没错,就是C语言诞生的时间,C语言可是一门伟大的语言。 -
应用:通常可以用来统计程序的运行时间
public class Test {
public static void main(String[] args) {
long start = System.currentTimeMillis();
System.out.println(start); // 1723818371814
int sum = 0;
for(int i = 0; i < 10000000; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println(end); // 1723818371819
System.out.println(end-start); // 5毫秒 ,这个时间是不固定的
}
}
3 public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) — 拷贝数组(对引用数据类型是浅拷贝(拷贝引用))
- public static void arraycopy(数据源数组, 源数组起始索引, 目标数组, 目标数组起始索引, 拷贝个数)
将指定源数组中的数组从指定位置开始复制到目标数组的指定位置。
【注】:
- 对于基本数据类型:拷贝的是值,互不影响
- 对于引用数据类型:浅拷贝,拷贝的是引用
package cn.hjblogs.demo;
public class Test {
public static void main(String[] args) {
int[] arr1 = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] arr2 = new int[10];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
// 验证
for (int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i]+" "); // 1 2 3 4 5 6 7 8 9 10
}
System.out.println(); // 换行
int[] arr3 = new int[10];
System.arraycopy(arr1, 3, arr3, 0, 5);
// 验证
for (int i = 0; i < arr3.length; i++) {
System.out.print(arr3[i]+" "); // 4 5 6 7 8 6 7 8 9 10
}
}
}
关于这个方法还有几个注意事项:
- 1 如果数据源数组和目的地数组都是基本数据类型,那么两者的类型必须保持一致,否则会报错
- 2 在拷贝的时候需要考虑数组的长度,如果超出范围也会报错
- 2 如果数据源数组和目的地数组都是引用数据类型,那么子类型可以可以拷贝到父类型(隐式转换),不过拿出来的时候需要进行一步强转就可以了。---- 多态哪里的父类(大范围)与子类(小范围)的隐式转换和强转
// 减少展示长度,Student,Person类就不展示了
public class Test {
public static void main(String[] args) {
Student s1 = new Student("张三", 18);
Student s2 = new Student("李四", 20);
Student s3 = new Student("王五", 22);
Student[] arr1 = {
s1, s2, s3};
Person[] arr2 = new Person[3];
System.arraycopy(arr1, 0, arr2, 0, 3);
// 遍历arr2数组
for (Person p : arr2) {
Student s = (Student) p; // 强制类型转换 父类转子类
System.out.println(p.getName()); // 张三 李四 王五
}
}
}
五、System.out :输出对象和System.in:输入对象
由于System.in:输入对象里面的方法我们暂时还没有接触到,这里暂时只记录System.out
【注】:关于打印函数有一点需要注意,打印函数都是先调用Object 下的toString()方法,这个方法有没有被重写打印结果有区别,主要是:
- 如果我们之间打印一个对象,打印的是 对象包名@地址值
- 如果我们不想要这种地址值,想要看到属性值的话,那么重写toString() 方法就可以了。在重写的方法中,将对象的属性值进行拼接
1 System.out.println(“hello world!”);
【注】:该语法过后自动换行
System.out.println(“hello world!”);是 Java 中用于向控制台输出字符串的语句。以下是对这条语句的详细解释和用法说明:
语句结构
- System: 是属于 java.lang 包下的工具类。System 类不能被实例化。
- out: 是System这个工具类下面的一个属性对象,这个对象就是控制台的输出对象。
- println:是System.out这个控制台输出对象里面的一个方法 。
- “hello world!”: 这是要输出的字符串。
为什么我们用这种简单的打印最多在java里面,因为java里面有一个神奇的特性,字符串可以通过 + 和任意数据类型(如整数、浮点数这些还有其他),这就方便了,直接用 + 就可以实现Python中的 f’ ’ 这种作用了,看下面示例
示例1:
public class DataManager {
// Main method
public static void main(String[] args) {
String name = "HJ";
int age = 18;
System.out.println("我的名字是:" + name + ",今年" + age + "岁了。"); // 我的名字是:HJ,今年18岁了。
}
}
示例2:
package cn.hjblogs.demo;
public class Test {
public static void main(String[] args) {
Student s = new Student(12,"张三");
// 细节
// System: 类名
// out: 静态成员变量
// System.out: 获取打印的对象
// println: 打印方法
// 参数:表示打印的内容
// 结合后面的 Object的toString方法会更加深入理解这行代码
System.out.println(s); // cn.hjblogs.demo.Student@1b6d3586 包名.类名@哈希值(地址经过映射)
}
}
class Student{
String name;
int age;
public Student() {
}
public Student(int age, String name) {
this.age = age;
this.name = name;
}
}
2 System.out.printf(formatString, arg1, arg2, …); — 格式化打印输出
(1)参数解释
System.out.printf(formatString, arg1, arg2, ...);
- formatString 是一个包含文本和格式说明符的字符串。
- arg1, arg2, … 是格式说明符所对应的参数,依次按照格式化%来
最后能实现的效果是Python里面print(f’ ') 类似的功能。
下面我们就要介绍C中经典的 % 格式化语法了
(2)格式化语法
格式说明符的基本结构如下:
%[flags][width][.precision]conversion
- %:格式说明符的起始标志。
- flags:可选标志,用于控制输出格式(简单来说就是用什么填充,对齐方式哪些东西)。
- width:最小宽度,可选。
- .precision:精度(通常浮点数用的多),可选。
- conversion:转换字符,决定了如何格式化参数。
常用转换字符:
转换字符 | 含义 |
---|---|
%d | 十进制整数。 |
%x | 十六进制整数。 |
%o | 八进制整数。 |
%f | 十进制浮点数。 |
%e | 科学计数法表示的浮点数。 |
%g | 根据值的大小自动选择 %f 或 %e。 |
%c | 字符。 |
%s | 字符串。 |
%b | 布尔值。 |
%% | 输出一个 % 字符。 |
常用标志(对齐方式等等)
常用标志 | 含义 |
---|---|
- | 左对齐(默认是右对齐)。 |
+ | 显示正号。 |
0 | 数字前面补零。 |
, | 添加千位分隔符。 |
( | 用括号表示负数。 |
需要一些格式化示例来演示一下:
示例 1:基本浮点数格式化
double pi = 3.141592653589793;
System.out.printf("%f\n", pi); // 默认浮点数格式,输出:3.141593
System.out.printf("%.2f\n", pi); // 保留两位小数,输出:3.14
System.out.printf("%8.2f\n", pi); // 宽度为8,保留两位小数,输出: 3.14
System.out.printf("%-8.2f\n", pi); // 左对齐,宽度为8,保留两位小数,输出:3.14
System.out.printf("%08.2f\n", pi); // 用零填充,宽度为8,保留两位小数,输出:00003.14
示例 2:整数格式化
int number = 12345;
System.out.printf("%d\n", number); // 默认整数格式,输出:12345
System.out.printf("%10d\n", number); // 宽度为10,右对齐,输出: 12345
System.out.printf("%-10d\n", number); // 宽度为10,左对齐,输出:12345
System.out.printf("%010d\n", number); // 宽度为10,用零填充,输出:0000012345
System.out.printf("%+10d\n", number); // 宽度为10,显示正号,输出: +12345
System.out.printf("%,10d\n", number); // 宽度为10,添加千位分隔符,输出: 12,345
示例 3:字符串格式化
String str = "Hello";
System.out.printf("%s\n", str); // 默认字符串格式,输出:Hello
System.out.printf("%20s\n", str); // 宽度为20,右对齐,输出: Hello
System.out.printf("%-20s\n", str); // 宽度为20,左对齐,输出:Hello
System.out.printf("%.3s\n", str); // 最多显示3个字符,输出:Hel
System.out.printf("%20.3s\n", str); // 宽度为20,最多显示3个字符,右对齐,输出: Hel
综合示例
public class Main {
public static void main(String[] args) {
int num = 12345;
double price = 45.678;
String name = "Alice";
System.out.printf("Name: %-10s | Number: %+010d | Price: %,.2f\n", name, num, price);
}
}
输出:
Name: Alice | Number: +000012345 | Price: 45.68
%-10s
:字符串name
,左对齐,占10个字符宽度。%+010d
:整数num
,显示正号,占10个字符宽度,用零填充。%,.2f
:浮点数price
,保留两位小数,添加千位分隔符。
通过这些示例,可以更好地理解Java中的printf
格式化输出语法。
3 System.out.print(“abc”) — 不换行打印
- System.out.println(); // 不打印任何数据,只做换行处理。
- System.out.println(“abc”); // 先打印abc,在换行
- System.out.print(“abc”); // 只打印abc,不换行
public class Business {
public static void main(String[] args) {
System.out.print("Hello World!");
System.out.print("Hello World!\n"); // \n 是换行符
System.out.print("Hello World!");
System.out.print("Hello World!");
}
}
/* 输出:
Hello World!Hello World!
Hello World!Hello World!
*/
六、Scanner类: 输入(键盘录入)
键盘录入就没那么方便了,Python里面只要input()就能够结束,但在java中可不行。
输入的方法 放在 java.unit 这个包下面的Scanner(扫描)类里面,前面说过这个包里面的类都是要我们手动导包和实例化的,因此java这里面它分了三部要,哭死:
- 导包
- 实例化(创建Scanner对象):这里实例化要传入 System.in这个类 。联想一下Python就知道这是在干什么了
- 调用输入方法
import java.util.Scanner; // 导入Scanner类
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // 实例化对象
// 读取一个字符串
System.out.print("Enter a string: ");
String str = sc.nextLine();
// 读取一个整数
System.out.print("Enter an integer: ");
int num = sc.nextInt();
// 读取一个浮点数
System.out.print("Enter a float: ");
float fnum = sc.nextFloat();
System.out.println("You entered: " + str + ", " + num + ", " + fnum);
}
}
可以看到和Python的input()输入的全部都是字符串,java这里提供了三个分别对应整数、浮点数、字符串的输入三个函数:
- sc.nextLine(): 读取一个字符串(碰到换行才会结束)
一般无论是录入字符串、整数、浮点数都是结合包装类用这个(最常用) - sc.nextInt():读取一个整数(空格就会结束录入)
- sc.nextFloat():读取一个浮点数(空格就会结束录入)
如果学了包装类,里面有一个数据类型间的转换函数,结合这个我们今后碰到键盘录入,统一规定使用sc.nextLine():
包装类参考博客
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String str = sc.nextLine();
System.out.println("输入的字符串是:" + str);
System.out.println("请输入整数:");
int num = Integer.parseInt(sc