常见API
1.API
1.1API概述
-
什么是API
API (Application Programming Interface) :应用程序编程接口
-
java中的API
指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。
1.2如何使用API帮助文档
- 打开帮助文档
- 找到索引选项卡中的输入框
- 在输入框中输入Random
- 看类在哪个包下
- 看类的描述
- 看构造方法
- 看成员方法
2.String类
2.1String类概述
String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。String 类在 java.lang 包下,所以使用的时候不需要导包!
2.2String类的特点
- 字符串不可变,它们的值在创建后不能被更改
- 虽然 String 的值是不可变的,但是它们可以被共享
- 字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )
2.3String类的构造方法
-
常用的构造方法
方法名 说明 public String() 创建一个空白字符串对象,不含有任何内容 public String(char[] chs) 根据字符数组的内容,来创建字符串对象 public String(byte[] bys) 根据字节数组的内容,来创建字符串对象 String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc -
示例代码
public class StringDemo01 { public static void main(String[] args) { //public String():创建一个空白字符串对象,不含有任何内容 String s1 = new String(); System.out.println("s1:" + s1); //public String(char[] chs):根据字符数组的内容,来创建字符串对象 char[] chs = {'a', 'b', 'c'}; String s2 = new String(chs); System.out.println("s2:" + s2); //public String(byte[] bys):根据字节数组的内容,来创建字符串对象 byte[] bys = {97, 98, 99}; String s3 = new String(bys); System.out.println("s3:" + s3); //String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc String s4 = "abc"; System.out.println("s4:" + s4); } }
2.4创建字符串对象两种方式的区别
-
通过构造方法创建
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
-
直接赋值方式创建
以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护
-
内存
2.5字符串的比较
2.5.1==号的作用
- 比较基本数据类型:比较的是具体的值
- 比较引用数据类型:比较的是对象地址值
2.5.2equals方法的作用
-
方法介绍
public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写
-
示例代码
public class StringDemo02 { public static void main(String[] args) { //构造方法的方式得到对象 char[] chs = {'a', 'b', 'c'}; String s1 = new String(chs); String s2 = new String(chs); //直接赋值的方式得到对象 String s3 = "abc"; String s4 = "abc"; //比较字符串对象地址是否相同 System.out.println(s1 == s2);F System.out.println(s1 == s3);F System.out.println(s3 == s4);T System.out.println("--------"); //比较字符串内容是否相同 System.out.println(s1.equals(s2));T System.out.println(s1.equals(s3));T System.out.println(s3.equals(s4));T } }
2.6用户登录案例
2.6.1案例需求
已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
2.6.2代码实现
public class Test1登录案例 {
public static void main(String[] args) {
//1.定义两个变量用来记录正确的用户名和密码
String rightUsername = "it";
String rightPassword = "1234";
//2.键盘录入用户名和密码
//ctrl + alt + T 选择包裹方式
for (int i = 0; i < 3; i++) {//0 1 2
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.next();
System.out.println("请输入密码");
String password = sc.next();
//3.判断比较
if (username.equals(rightUsername) && password.equals(rightPassword)) {
System.out.println("登录成功");
//如果正确,循环结束
break;
} else {
//最后一次机会
if(i == 2){
System.out.println("账户" + username + "被锁定,请联系官方小姐姐:XXXXXXX");
}else{
//不是最后一次机会
System.out.println("用户名或密码错误,登录失败,还剩下" + (2 - i) + "次机会");//2 1 0
}
}
}
}
}
2.7遍历字符串案例
2.7.1案例需求
键盘录入一个字符串,使用程序实现在控制台遍历该字符串
2.7.2直接遍历字符串
public class Test2字符串直接遍历 {
public static void main(String[] args) {
//两个方法:
//charAt():会根据索引获取对应的字符
//length(): 会返回字符串的长度
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串");
String str = sc.next();
System.out.println(str);
//2.遍历
for (int i = 0; i < str.length(); i++) {
//i 依次表示字符串的每一个索引
//索引的范围:0 ~ 长度-1
//根据索引获取字符串里面的每一个字符
//ctrl + alt + V 自动生成左边的接受变量
char c = str.charAt(i);
System.out.println(c);
}
}
}
2.8统计字符次数案例
2.8.1案例需求
键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
2.8.2代码实现
public class Test4统计个数 {
public static void main(String[] args) {
//键盘录入一个字符串,统计大写,小写,数字出现的次数
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.统计 --- 计数器count
//此时我要统计的有3样东西,所以要定义3个计数器分别进行统计
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
//得到这个字符串里面每一个字符
for (int i = 0; i < str.length(); i++) {
//i 表示字符串中的索引
//c 表示字符串中的每一个字符
char c = str.charAt(i);
//对c进行判断
if (c >= 'a' && c <= 'z') {
smallCount++;
}else if(c >= 'A' && c <= 'Z'){
bigCount++;
}else if(c >= '0' && c <= '9'){
numberCount++;
}
}
//3.当循环结束之后,三个变量记录的就是对应的个数
System.out.println("大写字符有:" + bigCount + "个");
System.out.println("小写字符有:" + smallCount + "个");
System.out.println("数字字符有:" + numberCount + "个");
}
}
2.9字符串拼接案例
2.9.1案例需求
定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,
并在控制台输出结果。例如,数组为 int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
2.9.2代码实现
public class Test5数组拼接成字符串 {
public static void main(String[] args) {
//定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,
//并在控制台输出结果。例如,数组为 int[] arr = {1,2,3};
//执行方法后的输出结果为:[1, 2, 3]
int[] arr = {1, 2, 3, 4, 5};
String str = arrToString(arr);
System.out.println(str);
}
//作用:把一个数组变成字符串
public static String arrToString(int[] arr) {
String s = "";
//拼接左括号
s = s + "["; //此时是拿着长度为0的字符串,跟[进行拼接,产生一个新的字符串。
//把新的字符串再赋值给s,此时变量s记录的就是新的字符串"["的地址值
//下面我想得到数组里面的每一个元素并进行拼接
//那么就需要遍历数组,得到每一个元素才行
for (int i = 0; i < arr.length; i++) {
//假设第一次循环:i = 0 获取的就是0索引上的元素
//在拼接的时候:"[" + 1 + ", " 拼接完毕之后产生一个新的字符串 "[1, "
//第二次循环:i = 1 获取的就是1索引上的元素
//在拼接的时候: 此时s就是第一次循环结束后拼接完毕的结果:"[1, "
//在拼接的时候:"[1, " + 2 + ", " 拼接完毕之后产生一个新的字符串 "[1, 2, "
//...
if(i == arr.length - 1){
//如果是最后一个元素,那么不需要拼接逗号空格
s = s + arr[i];
}else{
//如果不是最后一个元素,需要拼接元素和逗号空格
s = s + arr[i] + ", ";
}
}
//等循环结束之后,再拼接最后一个右括号
s = s + "]";
return s;
}
//用来遍历数组
public static void printArr(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
} else {
System.out.print(arr[i] + ", ");
}
}
System.out.println("]");
//[1, 2, 3, 4, 5]
//我们现在要知道,这个最终结果是怎么来的?
//从到右依次打印得来的。
}
}
2.10字符串反转案例
2.10.1案例需求
定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
例如,键盘录入 abc,输出结果 cba
2.10.2代码实现
public class Test6反转字符串 {
public static void main(String[] args) {
/*定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
例如,键盘录入 abc,输出结果 cba*/
//1.定义一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.定义一个方法,反转字符串
//abc ---> cba
//可以把字符串倒着遍历,再拼接
String result = reverse(str);
System.out.println(result);
}
//注释:方法的作用就是反转字符串
//把传递进来的字符串进行反转
public static String reverse(String str){//abc
//核心思想:倒着遍历并进行拼接就可以了
//fori :正着遍历 forr:倒着遍历
String s = "";
for (int i = str.length() - 1; i >= 0; i--) {
//i 依次表示字符串里面的每一个索引(倒着的)
//我们就可以拿到里面的每一个字符并拼接
s = s + str.charAt(i);
}
//把倒着拼接之后的结果返回即可
return s;
}
}
2.11 金额转换
2.11.1 案例需求
把2135变成:零佰零拾零万贰仟壹佰叁拾伍元
把789变成:零佰零拾零万零仟柒佰捌拾玖元
2.11.2 代码实现
package com.it.stringdemo;
import java.util.Scanner;
public class StringDemo9 {
public static void main(String[] args) {
//1.键盘录入一个金额
Scanner sc = new Scanner(System.in);
int money;
while (true) {
System.out.println("请录入一个金额");
money = sc.nextInt();
if (money >= 0 && money <= 9999999) {
break;
} else {
System.out.println("金额无效");
}
}
//定义一个变量用来表示钱的大写
String moneyStr = "";
//2.得到money里面的每一位数字,再转成中文
while (true) {//2135
//从右往左获取数据,因为右侧是数据的个位
int ge = money % 10;
String capitalNumber = getCapitalNumber(ge);
//把转换之后的大写拼接到moneyStr当中
moneyStr = capitalNumber + moneyStr;
//第一次循环 : "伍" + "" = "伍"
//第二次循环 : "叁" + "伍" = "叁伍"
//去掉刚刚获取的数据
money = money / 10;
//如果数字上的每一位全部获取到了,那么money记录的就是0,此时循环结束
if (money == 0) {
break;
}
}
//3.在前面补0,补齐7位
int count = 7 - moneyStr.length();
for (int i = 0; i < count; i++) {
moneyStr = "零" + moneyStr;
}
System.out.println(moneyStr);//零零零贰壹叁伍
//4.插入单位
//定义一个数组表示单位
String[] arr = {"佰","拾","万","仟","佰","拾","元"};
// 零 零 零 贰 壹 叁 伍
//遍历moneyStr,依次得到 零 零 零 贰 壹 叁 伍
//然后把arr的单位插入进去
String result = "";
for (int i = 0; i < moneyStr.length(); i++) {
char c = moneyStr.charAt(i);
//把大写数字和单位拼接到result当中
result = result + c + arr[i];
}
//5.打印最终结果
System.out.println(result);
}
//定义一个方法把数字变成大写的中文
//1 -- 壹
public static String getCapitalNumber(int number) {
//定义数组,让数字跟大写的中文产生一个对应关系
String[] arr = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
//返回结果
return arr[number];
}
}
2.12 手机号屏蔽
需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
最终效果为:131****9468
代码实现:
public class Test8手机号屏蔽 {
public static void main(String[] args) {
/*以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
最终效果为:131****9468*/
//1.键盘录入一个手机号码
Scanner sc = new Scanner(System.in);
System.out.println("请输入手机号码");
String phoneNumber = sc.next();//13112349408
//2.截取手机号码中的前三位
String star = phoneNumber.substring(0, 3);
//3.截取手机号码中的最后四位
//此时我用substring方法,是用1个参数的,还是两个参数的?1个参数的会更好
//因为现在我要截取到最后,所以建议使用1个参数的。
String end = phoneNumber.substring(7);
//4.拼接
String result = star + "****" + end;
System.out.println(result);
}
}
3.StringBuilder
StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。
当我们在拼接字符串和反转字符串的时候会使用到
3.1 基本使用
public class StringBuilderDemo3 {
public static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder("abc");
//2.添加元素
/*sb.append(1);
sb.append(2.3);
sb.append(true);*/
//反转
sb.reverse();
//获取长度
int len = sb.length();
System.out.println(len);
//打印
//普及:
//因为StringBuilder是Java已经写好的类
//java在底层对他做了一些特殊处理。
//打印对象不是地址值而是属性值。
System.out.println(sb);
}
}
3.2 链式编程
当我们在调用一个方法的时候,不用变量接受他的结果,继续调用其他方法
public class StringBuilderDemo4 {
public static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder();
//2.添加字符串
sb.append("aaa").append("bbb").append("ccc").append("ddd");
System.out.println(sb);//aaabbbcccddd
//3.再把StringBuilder变回字符串
String str = sb.toString();
System.out.println(str);//aaabbbcccddd
}
}
3.3 练习1:对称字符串
需求:
键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
对称字符串:123321、111
非对称字符串:123123
代码示例:
public class StringBuilderDemo6 {
//使用StringBuilder的场景:
//1.字符串的拼接
//2.字符串的反转
public static void main(String[] args) {
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
//2.反转键盘录入的字符串
String result = new StringBuilder().append(str).reverse().toString();
//3.比较
if(str.equals(result)){
System.out.println("当前字符串是对称字符串");
}else{
System.out.println("当前字符串不是对称字符串");
}
}
}
3.4 练习2:拼接字符串
需求:定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回。
调用该方法,并在控制台输出结果。
例如:数组为int[] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]
代码示例:
package com.it.stringbuilderdemo;
public class StringBuilderDemo7 {
public static void main(String[] args) {
//1.定义数组
int[] arr = {1,2,3};
//2.调用方法把数组变成字符串
String str = arrToString(arr);
System.out.println(str);
}
public static String arrToString(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if(i == arr.length - 1){
sb.append(arr[i]);
}else{
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
4. StringJoiner
- StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
- 作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
- JDK8出现的
基本使用:
//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc
//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]
关于字符串的小扩展:
-
字符串存储的内存原理
String s = “abc”;直接赋值
特点:
此时字符串abc是存在字符串常量池中的。
先检查字符串常量池中有没有字符串abc,如果有,不会创建新的,而是直接复用。如果没有abc,才会创建一个新的。
所以,直接赋值的方式,代码简单,而且节约内存。
-
new出来的字符串
看到new关键字,一定是在堆里面开辟了一个小空间。
String s1 = new String(“abc”);
String s2 = “abc”;
s1记录的是new出来的,在堆里面的地址值。
s2是直接赋值的,所以记录的是字符串常量池中的地址值。
-
==号比较的到底是什么?
如果比较的是基本数据类型:比的是具体的数值是否相等。
如果比较的是引用数据类型:比的是地址值是否相等。
结论:==只能用于比较基本数据类型。不能比较引用数据类型。
-
字符串底层拼接原理
ctrl+n
- StringBuilder提高效率图
3 Math类
1.1 概述
tips:了解内容
查看API文档,我们可以看到API文档中关于Math类的定义如下:
Math类所在包为java.lang包,因此在使用的时候不需要进行导包。并且Math类被final修饰了,因此该类是不能被继承的。
Math类包含执行基本数字运算的方法,我们可以使用Math类完成基本的数学运算。
要想使用Math类我们就需要先创建该类的对象,那么创建对象就需要借助于构造方法。因此我们就需要首先查看一下API文档,看看API文档中针对Math类有没有提供对应的构造方法。通过API文档来查看
一下Math类的成员,如下所示:
在API文档中没有体现可用的构造方法(私有化构造方法),因此我们就不能直接通过new关键字去创建Math类的对象。同时我们发现Math类中的方法都是静态的,因此在使用的时候我们可以直接通过类名去调用。在Math类中
定义了很多数学运算的方法,但是我们并不可能将所有的方法学习一遍,我们主要学习的就是一些常见的方法。
1.2 常见方法
tips:重点讲解内容
常见方法介绍
我们要学习的Math的常见方法如下所示:
public static int abs(int a) // 返回参数的绝对值
public static double ceil(double a) // 返回大于或等于参数的最小整数
public static double floor(double a) // 返回小于或等于参数的最大整数
public static int round(float a) // 按照四舍五入返回最接近参数的int类型的值
public static int max(int a,int b) // 获取两个int值中的较大值
public static int min(int a,int b) // 获取两个int值中的较小值
public static double pow (double a,double b) // 计算a的b次幂的值
public static double random() // 返回一个[0.0,1.0)的随机值
补充
案例演示
接下来我们就来演示一些这些方法的执行效果,如下所示:
public class MathDemo01 {
public static void main(String[] args) {
// public static int abs(int a) 返回参数的绝对值
System.out.println("-2的绝对值为:" + Math.abs(-2));
System.out.println("2的绝对值为:" + Math.abs(2));
// public static double ceil(double a) 返回大于或等于参数的最小整数
System.out.println("大于或等于23.45的最小整数位:" + Math.ceil(23.45));
System.out.println("大于或等于-23.45的最小整数位:" + Math.ceil(-23.45));
// public static double floor(double a) 返回小于或等于参数的最大整数
System.out.println("小于或等于23.45的最大整数位:" + Math.floor(23.45));
System.out.println("小于或等于-23.45的最大整数位:" + Math.floor(-23.45));
// public static int round(float a) 按照四舍五入返回最接近参数的int
System.out.println("23.45四舍五入的结果为:" + Math.round(23.45));
System.out.println("23.55四舍五入的结果为:" + Math.round(23.55));
// public static int max(int a,int b) 返回两个int值中的较大值
System.out.println("23和45的最大值为: " + Math.max(23, 45));
// public static int min(int a,int b) 返回两个int值中的较小值
System.out.println("12和34的最小值为: " + Math.min(12 , 34));
// public static double pow (double a,double b)返回a的b次幂的值
System.out.println("2的3次幂计算结果为: " + Math.pow(2,3));
// public static double random()返回值为double的正值,[0.0,1.0)
System.out.println("获取到的0-1之间的随机数为: " + Math.random());
}
}
运行程序进行测试,控制台输出结果如下:
-2的绝对值为:2
2的绝对值为:2
大于或等于23.45的最小整数位:24.0
大于或等于-23.45的最小整数位:-23.0
小于或等于23.45的最大整数位:23.0
小于或等于-23.45的最大整数位:-24.0
23.45四舍五入的结果为:23
23.55四舍五入的结果为:24
23和45的最大值为: 45
12和34的最小值为: 12
2的3次幂计算结果为: 8.0
获取到的0-1之间的随机数为: 0.7322484131745958
4 System类
2.1 概述
tips:了解内容
查看API文档,我们可以看到API文档中关于System类的定义如下:
System类所在包为java.lang包,因此在使用的时候不需要进行导包。并且System类被final修饰了,因此该类是不能被继承的。
System包含了系统操作的一些常用的方法。比如获取当前时间所对应的毫秒值,再比如终止当前JVM等等。
要想使用System类我们就需要先创建该类的对象,那么创建对象就需要借助于构造方法。因此我们就需要首先查看一下API文档,看看API文档中针对System类有没有提供对应的构造方法。通过API文档来
查看一下System类的成员,如下所示:
在API文档中没有体现可用的构造方法,因此我们就不能直接通过new关键字去创建System类的对象。同时我们发现System类中的方法都是静态的,因此在使用的时候我们可以直接通过类名去调用(Nested
Class Summary内部类或者内部接口的描述)。
2.2 常见方法
tips:重点讲解内容
常见方法介绍
我们要学习的System类中的常见方法如下所示:
public static long currentTimeMillis() // 获取当前时间所对应的毫秒值(当前时间为0时区所对应的时间即就是英国格林尼治天文台旧址所在位置)
public static void exit(int status) // 终止当前正在运行的Java虚拟机,0表示正常退出,非零表示异常退出
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); // 进行数值元素copy
案例演示
接下来我们就来通过一些案例演示一下这些方法的特点。
案例1:演示currentTimeMillis方法
public class SystemDemo01 {
public static void main(String[] args) {
// 获取当前时间所对应的毫秒值
long millis = System.currentTimeMillis();
// 输出结果
System.out.println("当前时间所对应的毫秒值为:" + millis);
}
}
运行程序进行测试,控制台的输出结果如下:
当前时间所对应的毫秒值为:1576050298343
获取到当前时间的毫秒值的意义:我们常常来需要统计某一段代码的执行时间。此时我们就可以在执行这段代码之前获取一次时间,在执行完毕以后再次获取一次系统时间,然后计算两个时间的差值,
这个差值就是这段代码执行完毕以后所需要的时间。如下代码所示:
public class SystemDemo2 {
public static void main(String[] args) {
//判断1~100000之间有多少个质数
long start = System.currentTimeMillis();
for (int i = 1; i <= 100000; i++) {
boolean flag = isPrime2(i);
if (flag) {
System.out.println(i);
}
}
long end = System.currentTimeMillis();
//获取程序运行的总时间
System.out.println(end - start); //方式一:1514 毫秒 方式二:71毫秒
}
//以前判断是否为质数的方式
public static boolean isPrime1(int number) {
for (int i = 2; i < number; i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
//改进之后判断是否为质数的方式(效率高)
public static boolean isPrime2(int number) {
for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
}
案例2:演示exit方法
public class SystemDemo01 {
public static void main(String[] args) {
// 输出
System.out.println("程序开始执行了.....");
// 终止JVM
System.exit(0);
// 输出
System.out.println("程序终止了..........");
}
}
运行程序进行测试,控制台输出结果如下:
程序开始执行了.....
此时可以看到在控制台只输出了"程序开始了…",由于JVM终止了,因此输出"程序终止了…"这段代码没有被执行。
5 Runtime
3.1 概述
Runtime表示Java中运行时对象,可以获取到程序运行时设计到的一些信息
3.2 常见方法
常见方法介绍
我们要学习的Object类中的常见方法如下所示:
public static Runtime getRuntime() //当前系统的运行环境对象
public void exit(int status) //停止虚拟机
public int availableProcessors() //获得CPU的线程数
public long maxMemory() //JVM能从系统中获取总内存大小(单位byte)
public long totalMemory() //JVM已经从系统中获取总内存大小(单位byte)
public long freeMemory() //JVM剩余内存大小(单位byte)
public Process exec(String command) //运行cmd命令
代码示例:
public class RunTimeDemo1 {
public static void main(String[] args) throws IOException {
/*
public static Runtime getRuntime() 当前系统的运行环境对象
public void exit(int status) 停止虚拟机
public int availableProcessors() 获得CPU的线程数
public long maxMemory() JVM能从系统中获取总内存大小(单位byte)
public long totalMemory() JVM已经从系统中获取总内存大小(单位byte)
public long freeMemory() JVM剩余内存大小(单位byte)
public Process exec(string command) 运行cmd命令
*/
//1.获取Runtime的对象
//Runtime r1 =Runtime.getRuntime();
//2.exit 停止虚拟机
//Runtime.getRuntime().exit(0);
//System.out.println("看看我执行了吗?");
//3.获得CPU的线程数
System.out.println(Runtime.getRuntime().availableProcessors());//8
//4.总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);//4064
//5.已经获取的总内存大小,单位byte字节
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);//254
//6.剩余内存大小
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);//251
//7.运行cmd命令
//shutdown :关机
//加上参数才能执行
//-s :默认在1分钟之后关机
//-s -t 指定时间 : 指定关机时间
//-a :取消关机操作
//-r: 关机并重启
Runtime.getRuntime().exec("shutdown -s -t 3600");
}
}
6 Object类
4.1 概述
tips:重点讲解内容
查看API文档,我们可以看到API文档中关于Object类的定义如下:
Object类所在包是java.lang包。Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类;换句话说,该类所具备的方法,其他所有类都继承了。
查看API文档我们可以看到,在Object类中提供了一个无参构造方法,如下所示:
但是一般情况下我们很少去主动的创建Object类的对象,调用其对应的方法。更多的是创建Object类的某个子类对象,然后通过子类对象调用Object类中的方法。
4.2 常见方法
tips:重点讲解内容
常见方法介绍
我们要学习的Object类中的常见方法如下所示:
public String toString() //返回该对象的字符串表示形式(可以看做是对象的内存地址值)
public boolean equals(Object obj) //比较两个对象地址值是否相等;true表示相同,false表示不相同
protected Object clone() //对象克隆
案例1:演示equals方法
实现步骤:
- 在测试类(ObjectDemo02)的main方法中,创建两个学生对象,然后比较两个对象是否相同
代码如下所示:
public class ObjectDemo02 {
public static void main(String[] args) {
// 创建两个学生对象
Student s1 = new Student("it" , "14") ;
Student s2 = new Student("it" , "14") ;
// 比较两个对象是否相等
System.out.println(s1 == s2);
}
}
运行程序进行测试,控制台的输出结果如下所示:
false
因为"=="号比较的是对象的地址值,而我们通过new关键字创建了两个对象,它们的地址值是不相同的。因此比较结果就是false。
我们尝试调用Object类中的equals方法进行比较,代码如下所示:
// 调用equals方法比较两个对象是否相等
boolean result = s1.equals(s2);
// 输出结果
System.out.println(result);
运行程序进行测试,控制台的输出结果为:
false
为什么结果还是false呢?我们可以查看一下Object类中equals方法的源码,如下所示:
public boolean equals(Object obj) { // Object类中的equals方法的源码
return (this == obj);
}
通过源码我们可以发现默认情况下equals方法比较的也是对象的地址值。比较内存地址值一般情况下是没有意义的,我们希望比较的是对象的属性,如果两个对象的属性相同,我们认为就是同一个对象;
那么要比较对象的属性,我们就需要在Student类中重写Object类中的equals方法。equals方法的重写,我们也可以使用idea开发工具完成,具体的操作如下所示:
- 在空白处使用快捷键:alt + insert。此时会弹出如下的对话框
- 选择equals() and hashCode()方法,此时会弹出如下的对话框
点击next,会弹出如下对话框:
选择neme和age属性点击next,此时就会弹出如下对话框:
取消name和age属性(因为此时选择的是在生成hashCode方法时所涉及到的属性,关于hashCode方法后期再做重点介绍),点击Finish完成生成操作。生成的equals方法和hashCode方法如下:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(age, student.age); // 比较的是对象的name属性值和age属性值
}
@Override
public int hashCode() {
return 0;
}
hashCode方法我们暂时使用不到,可以将hashCode方法删除。重写完毕以后运行程序进行测试,控制台输出结果如下所示:
true
此时equals方法比较的是对象的成员变量值,而s1和s2两个对象的成员变量值都是相同的。因此比较完毕以后的结果就是true。
小结:
- 默认情况下equals方法比较的是对象的地址值
- 比较对象的地址值是没有意义的,因此一般情况下我们都会重写Object类中的equals方法
案例2:对象克隆
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
对象克隆的分类:
深克隆和浅克隆
浅克隆:
不管对象内部的属性是基本数据类型还是引用数据类型,都完全拷贝过来
基本数据类型拷贝过来的是具体的数据,引用数据类型拷贝过来的是地址值。
Object类默认的是浅克隆
深克隆:
基本数据类型拷贝过来,字符串复用,引用数据类型会重新创建新的
代码实现:
package com.it.a04objectdemo;
public class ObjectDemo4 {
public static void main(String[] args) throws CloneNotSupportedException {
// protected object clone(int a) 对象克隆
//1.先创建一个对象
int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};
User u1 = new User(1, "zhangsan", "1234qwer", "girl11", data);
//2.克隆对象
//细节:
//方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去。
//书写细节:
//1.重写Object中的clone方法
//2.让javabean类实现Cloneable接口
//3.创建原对象并调用clone就可以了
//User u2 =(User)u1.clone();
//验证一件事情:Object中的克隆是浅克隆
//想要进行深克隆,就需要重写clone方法并修改里面的方法体
//int[] arr = u1.getData();
//arr[0] = 100;
//System.out.println(u1);
//System.out.println(u2);
//以后一般会用第三方工具进行克隆
//1.第三方写的代码导入到项目中
//2.编写代码
//Gson gson =new Gson();
//把对象变成一个字符串
//String s=gson.toJson(u1);
//再把字符串变回对象就可以了
//User user =gson.fromJson(s, User.class);
//int[] arr=u1.getData();
//arr[0] = 100;
//打印对象
//System.out.println(user);
}
}
package com.it.a04objectdemo;
import java.util.StringJoiner;
//Cloneable
//如果一个接口里面没有抽象方法
//表示当前的接口是一个标记性接口
//现在Cloneable表示一旦实现了,那么当前类的对象就可以被克降
//如果没有实现,当前类的对象就不能克隆
public class User implements Cloneable {
private int id;
private String username;
private String password;
private String path;
private int[] data;
public User() {
}
public User(int id, String username, String password, String path, int[] data) {
this.id = id;
this.username = username;
this.password = password;
this.path = path;
this.data = data;
}
/**
* 获取
*
* @return id
*/
public int getId() {
return id;
}
/**
* 设置
*
* @param id
*/
public void setId(int id) {
this.id = id;
}
/**
* 获取
*
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
*
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
*
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
*
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取
*
* @return path
*/
public String getPath() {
return path;
}
/**
* 设置
*
* @param path
*/
public void setPath(String path) {
this.path = path;
}
/**
* 获取
*
* @return data
*/
public int[] getData() {
return data;
}
/**
* 设置
*
* @param data
*/
public void setData(int[] data) {
this.data = data;
}
public String toString() {
return "角色编号为:" + id + ",用户名为:" + username + "密码为:" + password + ", 游戏图片为:" + path + ", 进度:" + arrToString();
}
public String arrToString() {
StringJoiner sj = new StringJoiner(", ", "[", "]");
for (int i = 0; i < data.length; i++) {
sj.add(data[i] + "");
}
return sj.toString();
}
@Override
protected Object clone() throws CloneNotSupportedException {
//调用父类中的clone方法
//相当于让Java帮我们克隆一个对象,并把克隆之后的对象返回出去。
//先把被克隆对象中的数组获取出来
int[] data = this.data;
//创建新的数组
int[] newData =new int[data.length];
//拷贝数组中的数据
for (int i = 0; i < data.length; i++) {
newData[i] = data[i];
}
//调用父类中的方法克隆对象
User u=(User)super.clone();
//因为父类中的克隆方法是浅克隆,替换克隆出来对象中的数组地址值
u.data =newData;
return u;
}
}
7 Objects类
5.1 概述
tips:了解内容
查看API文档,我们可以看到API文档中关于Objects类的定义如下:
Objects类所在包是在java.util包下,因此在使用的时候需要进行导包。并且Objects类是被final修饰的,因此该类不能被继承。
Objects类提供了一些对象常见操作的方法。比如判断对象是否相等,判断对象是否为null等等。
接下来我们来查看一下API文档,看一下Objects类中的成员,如下所示:
我们可以发现Objects类中无无参构造方法,因此我们不能使用new关键字去创建Objects的对象。同时我们可以发现Objects类中所提供的方法都是静态的。因此我们可以通过类名直接去调用这些方法。
5.2 常见方法
tips:重点讲解内容
常见方法介绍
我们要重点学习的Objects类中的常见方法如下所示:
public static String toString(Object o) // 获取对象的字符串表现形式
public static boolean equals(Object a, Object b) // 比较两个对象是否相等
public static boolean isNull(Object obj) // 判断对象是否为null
public static boolean nonNull(Object obj) // 判断对象是否不为null
我们要了解的Objects类中的常见方法如下所示:
public static <T> T requireNonNull(T obj) // 检查对象是否不为null,如果为null直接抛出异常;如果不是null返回该对象;
public static <T> T requireNonNullElse(T obj, T defaultObj) // 检查对象是否不为null,如果不为null,返回该对象;如果为null返回defaultObj值
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) // 检查对象是否不为null,如果不为null,返回该对象;如果 // 为null,返回由Supplier所提供的值
8 BigInteger类
6.1 引入
平时在存储整数的时候,Java中默认是int类型,int类型有取值范围:-2147483648 ~ 2147483647。如果数字过大,我们可以使用long类型,但是如果long类型也表示不下怎么办呢?
就需要用到BigInteger,可以理解为:大的整数。
有多大呢?理论上最大到42亿的21亿次方
基本上在内存撑爆之前,都无法达到这个上限。
6.2 概述
查看API文档,我们可以看到API文档中关于BigInteger类的定义如下:
BigInteger所在包是在java.math包下,因此在使用的时候就需要进行导包。我们可以使用BigInteger类进行大整数的计算
6.3 常见方法
构造方法
public BigInteger(int num, Random rnd) //获取随机大整数,范围:[0 ~ 2的num次方-1]
public BigInteger(String val) //获取指定的大整数
public BigInteger(String val, int radix) //获取指定进制的大整数
下面这个不是构造,而是一个静态方法获取BigInteger对象
public static BigInteger valueOf(long val) //静态方法获取BigInteger的对象,内部有优化
构造方法小结:
- 如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取。
- 如果BigInteger表示的超出long的范围,可以用构造方法获取。
- 对象一旦创建,BigInteger内部记录的值不能发生改变。
- 只要进行计算都会产生一个新的BigInteger对象
常见成员方法
BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:
public BigInteger add(BigInteger val) //加法
public BigInteger subtract(BigInteger val) //减法
public BigInteger multiply(BigInteger val) //乘法
public BigInteger divide(BigInteger val) //除法
public BigInteger[] divideAndRemainder(BigInteger val) //除法,获取商和余数
public boolean equals(Object x) //比较是否相同
public BigInteger pow(int exponent) //次幂、次方
public BigInteger max/min(BigInteger val) //返回较大值/较小值
public int intValue(BigInteger val) //转为int类型整数,超出范围数据有误
代码实现:
package com.it.a06bigintegerdemo;
import java.math.BigInteger;
public class BigIntegerDemo1 {
public static void main(String[] args) {
/*
public BigInteger(int num, Random rnd) 获取随机大整数,范围:[0~ 2的num次方-11
public BigInteger(String val) 获取指定的大整数
public BigInteger(String val, int radix) 获取指定进制的大整数
public static BigInteger valueOf(long val) 静态方法获取BigInteger的对象,内部有优化
细节:
对象一旦创建里面的数据不能发生改变。
*/
//1.获取一个随机的大整数
/* Random r=new Random();
for (int i = e; i < 100; i++) {
BigInteger bd1 = new BigInteger(4,r);
System.out.println(bd1);//[@ ~ 15]}
}
*/
//2.获取一个指定的大整数,可以超出long的取值范围
//细节:字符串中必须是整数,否则会报错
/* BigInteger bd2 = new BigInteger("1.1");
System.out.println(bd2);
*/
/*
BigInteger bd3 = new BigInteger("abc");
System.out.println(bd3);
*/
//3.获取指定进制的大整数
//细节:
//1.字符串中的数字必须是整数
//2.字符串中的数字必须要跟进制吻合。
//比如二进制中,那么只能写日和1,写其他的就报错。
BigInteger bd4 = new BigInteger("123", 2);
System.out.println(bd4);
//4.静态方法获取BigInteger的对象,内部有优化
//细节:
//1.能表示范围比较小,只能在long的取值范围之内,如果超出long的范围就不行了。
//2.在内部对常用的数字: -16 ~ 16 进行了优化。
// 提前把-16~16 先创建好BigInteger的对象,如果多次获取不会重新创建新的。
BigInteger bd5 = BigInteger.valueOf(16);
BigInteger bd6 = BigInteger.valueOf(16);
System.out.println(bd5 == bd6);//true
BigInteger bd7 = BigInteger.valueOf(17);
BigInteger bd8 = BigInteger.valueOf(17);
System.out.println(bd7 == bd8);//false
//5.对象一旦创建内部的数据不能发生改变
BigInteger bd9 =BigInteger.valueOf(1);
BigInteger bd10 =BigInteger.valueOf(2);
//此时,不会修改参与计算的BigInteger对象中的借,而是产生了一个新的BigInteger对象记录
BigInteger result=bd9.add(bd10);
System.out.println(result);//3
}
}
package com.it.a06bigintegerdemo;
import java.math.BigInteger;
public class BigIntegerDemo2 {
public static void main(String[] args) {
/*
public BigInteger add(BigInteger val) 加法
public BigInteger subtract(BigInteger val) 减法
public BigInteger multiply(BigInteger val) 乘法
public BigInteger divide(BigInteger val) 除法,获取商
public BigInteger[] divideAndRemainder(BigInteger val) 除法,获取商和余数
public boolean equals(Object x) 比较是否相同
public BigInteger pow(int exponent) 次幂
public BigInteger max/min(BigInteger val) 返回较大值/较小值
public int intValue(BigInteger val) 转为int类型整数,超出范围数据有误
*/
//1.创建两个BigInteger对象
BigInteger bd1 = BigInteger.valueOf(10);
BigInteger bd2 = BigInteger.valueOf(5);
//2.加法
BigInteger bd3 = bd1.add(bd2);
System.out.println(bd3);
//3.除法,获取商和余数
BigInteger[] arr = bd1.divideAndRemainder(bd2);
System.out.println(arr[0]);
System.out.println(arr[1]);
//4.比较是否相同
boolean result = bd1.equals(bd2);
System.out.println(result);
//5.次幂
BigInteger bd4 = bd1.pow(2);
System.out.println(bd4);
//6.max
BigInteger bd5 = bd1.max(bd2);
//7.转为int类型整数,超出范围数据有误
/* BigInteger bd6 = BigInteger.valueOf(2147483647L);
int i = bd6.intValue();
System.out.println(i);
*/
BigInteger bd6 = BigInteger.valueOf(200);
double v = bd6.doubleValue();
System.out.println(v);//200.0
}
}
6.4 底层存储方式:
对于计算机而言,其实是没有数据类型的概念的,都是0101010101,数据类型是编程语言自己规定的,所以在实际存储的时候,先把具体的数字变成二进制,每32个bit为一组,存储在数组中。
数组中最多能存储元素个数:21亿多
数组中每一位能表示的数字:42亿多
理论上,BigInteger能表示的最大数字为:42亿的21亿次方。
但是还没到这个数字,电脑的内存就会撑爆,所以一般认为BigInteger是无限的。
存储方式如图所示:
9 BigDecimal类
7.1 引入
首先我们来分析一下如下程序的执行结果:
public class BigDecimalDemo01 {
public static void main(String[] args) {
System.out.println(0.09 + 0.01);
}
}
这段代码比较简单,就是计算0.09和0.01之和,并且将其结果在控制台进行输出。那么按照我们的想法在控制台输出的结果应该为0.1。那么实际的运行结果是什么呢?我们来运行一下程序,控制台的输出
结果如下所示:
0.09999999999999999
这样的结果其实就是一个丢失精度的结果。为什么会产生精度丢失呢?
在使用float或者double类型的数据在进行数学运算的时候,很有可能会产生精度丢失问题。我们都知道计算机底层在进行运算的时候,使用的都是二进制数据; 当我们在程序中写了一个十进制数据 ,在
进行运算的时候,计算机会将这个十进制数据转换成二进制数据,然后再进行运算,计算完毕以后计算机会把运算的结果再转换成十进制数据给我们展示; 如果我们使用的是整数类型的数据进行计算,那
么在把十进制数据转换成二进制数据的时候不会存在精度问题; 如果我们的数据是一个浮点类型的数据,有的时候计算机并不会将这个数据完全转换成一个二进制数据,而是将这个将其转换成一个无限的
趋近于这个十进数的二进制数据; 这样使用一个不太准确的数据进行运算的时候, 最终就会造成精度丢失;为了提高精度,Java就给我们提供了BigDecimal供我们进行数据运算。
作用:用于小数的精确计算,表示很大的小数。
7.2 概述
查看API文档,我们可以看到API文档中关于BigDecimal类的定义如下:
BigDecimal所在包是在java.math包下,因此在使用的时候就需要进行导包。我们可以使用BigDecimal类进行更加精准的数据计算。
7.3 常见方法
构造方法
要用BigDecimal类,那么就需要首先学习一下如何去创建BigDecimal的对象。通过查看API文档,我们可以发现Jdk中针对BigDecimal类提供了很多的构造方法,但是最常用的构造方法是:
了解完常见的构造方法以后,我们接下来就重点介绍一下常见的成员方法。
常见成员方法
BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:
public BigDecimal add(BigDecimal value) // 加法运算
public BigDecimal subtract(BigDecimal value) // 减法运算
public BigDecimal multiply(BigDecimal value) // 乘法运算
public BigDecimal divide(BigDecimal value) // 触发运算
接下来我们就来通过一些案例演示一下这些成员方法的使用。
案例1:演示基本的四则运算
代码如下所示:
public class BigDecimalDemo01 {
public static void main(String[] args) {
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("0.3") ;
BigDecimal b2 = new BigDecimal("4") ;
// 调用方法进行b1和b2的四则运算,并将其运算结果在控制台进行输出
System.out.println(b1.add(b2)); // 进行加法运算
System.out.println(b1.subtract(b2)); // 进行减法运算
System.out.println(b1.multiply(b2)); // 进行乘法运算
System.out.println(b1.divide(b2)); // 进行除法运算
}
}
运行程序进行测试,控制台输出结果如下:
4.3
-3.7
1.2
0.075
此时我们可以看到使用BigDecimal类来完成浮点数的计算不会存在损失精度的问题。
案例2:演示除法的特殊情况
如果使用BigDecimal类型的数据进行除法运算的时候,得到的结果是一个无限循环小数,那么就会报错:ArithmeticException。 如下代码所示:
public class BigDecimalDemo02 {
public static void main(String[] args) {
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("1") ;
BigDecimal b2 = new BigDecimal("3") ;
// 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
System.out.println(b1.divide(b2));
}
}
运行程序进行测试,控制台输出结果如下所示:
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.base/java.math.BigDecimal.divide(BigDecimal.java:1716)
at com.i.api.bigdecimal.demo02.BigDecimalDemo02.main(BigDecimalDemo02.java:14)
针对这个问题怎么解决,此时我们就需要使用到BigDecimal类中另外一个divide方法,如下所示:
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
上述divide方法参数说明:
divisor: 除数对应的BigDecimal对象;
scale: 精确的位数;
roundingMode: 取舍模式;
取舍模式被封装到了RoundingMode这个枚举类中(关于枚举我们后期再做重点讲解),在这个枚举类中定义了很多种取舍方式。最常见的取舍方式有如下几个:
UP(直接进1) , FLOOR(直接删除) , HALF_UP(4舍五入),我们可以通过如下格式直接访问这些取舍模式:枚举类名.变量名
接下来我们就来演示一下这些取舍模式,代码如下所示:
public class BigDecimalDemo02 {
public static void main(String[] args) {
// 调用方法
method_03() ;
}
// 演示取舍模式HALF_UP
public static void method_03() {
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("0.3") ;
BigDecimal b2 = new BigDecimal("4") ;
// 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
System.out.println(b1.divide(b2 , 2 , RoundingMode.HALF_UP));
}
// 演示取舍模式FLOOR
public static void method_02() {
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("1") ;
BigDecimal b2 = new BigDecimal("3") ;
// 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
System.out.println(b1.divide(b2 , 2 , RoundingMode.FLOOR));
}
// 演示取舍模式UP
public static void method_01() {
// 创建两个BigDecimal对象
BigDecimal b1 = new BigDecimal("1") ;
BigDecimal b2 = new BigDecimal("3") ;
// 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
System.out.println(b1.divide(b2 , 2 , RoundingMode.UP));
}
}
小结:后期在进行两个数的除法运算的时候,我们常常使用的是可以设置取舍模式的divide方法。
7.4 底层存储方式:
把数据看成字符串,遍历得到里面的每一个字符,把这些字符在ASCII码表上的值,都存储到数组中。
总结
10 Date类
[](https://z4a.net/image/jW
1.1 Date概述
java.util.Date`类 表示特定的瞬间,精确到毫秒。
G)
继续查阅Date类的描述,发现Date拥有多个构造函数,只是部分已经过时,我们重点看以下两个构造函数
public Date()
:从运行程序的此时此刻到时间原点经历的毫秒值,转换成Date对象,分配Date对象并初始化此对象,以表示分配它的时间(精确到毫秒)。public Date(long date)
:将指定参数的毫秒值date,转换成Date对象,分配Date对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即1970年1月1日00:00:00 GMT)以来的指定毫秒数。
tips: 由于中国处于东八区(GMT+08:00)是比世界协调时间/格林尼治时间(GMT)快8小时的时区,当格林尼治标准时间为0:00时,东八区的标准时间为08:00。
简单来说:使用无参构造,可以自动设置当前系统时间的毫秒时刻;指定long类型的构造参数,可以自定义毫秒时刻。例如:
import java.util.Date;
public class Demo01Date {
public static void main(String[] args) {
// 创建日期对象,把当前的时间
System.out.println(new Date()); // Tue Jan 16 14:37:35 CST 2020
// 创建日期对象,把当前的毫秒值转成日期对象
System.out.println(new Date(0L)); // Thu Jan 01 08:00:00 CST 1970
}
}
tips:在使用println方法时,会自动调用Date类中的toString方法。Date类对Object类中的toString方法进行了覆盖重写,所以结果为指定格式的字符串。
1.2 Date常用方法
Date类中的多数方法已经过时,常用的方法有:
public long getTime()
把日期对象转换成对应的时间毫秒值。public void setTime(long time)
把方法参数给定的毫秒值设置给日期对象
示例代码
public class DateDemo02 {
public static void main(String[] args) {
//创建日期对象
Date d = new Date();
//public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
//System.out.println(d.getTime());
//System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
//public void setTime(long time):设置时间,给的是毫秒值
//long time = 1000*60*60;
long time = System.currentTimeMillis();
d.setTime(time);
System.out.println(d);
}
}
小结:Date表示特定的时间瞬间,我们可以使用Date对象对时间进行操作。
11 SimpleDateFormat类
java.text.SimpleDateFormat
是日期/时间格式化类,我们通过这个类可以帮我们完成日期和文本之间的转换,也就是可以在Date对象与String对象之间进行来回转换。
- 格式化:按照指定的格式,把Date对象转换为String对象。
- 解析:按照指定的格式,把String对象转换为Date对象。
2.1 构造方法
由于DateFormat为抽象类,不能直接使用,所以需要常用的子类java.text.SimpleDateFormat
。这个类需要一个模式(格式)来指定格式化或解析的标准。构造方法为:
public SimpleDateFormat(String pattern)
:用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。参数pattern是一个字符串,代表日期时间的自定义格式。
2.2 格式规则
常用的格式规则为:
标识字母(区分大小写) | 含义 |
---|---|
y | 年 |
M | 月 |
d | 日 |
H | 时 |
m | 分 |
s | 秒 |
备注:更详细的格式规则,可以参考SimpleDateFormat类的API文档。
2.3 常用方法
DateFormat类的常用方法有:
-
public String format(Date date)
:将Date对象格式化为字符串。 -
public Date parse(String source)
:将字符串解析为Date对象。import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class A03_SimpleDateFormatDemo1 { public static void main(String[] args) throws ParseException { /* public simpleDateFormat() 默认格式 public simpleDateFormat(String pattern) 指定格式 public final string format(Date date) 格式化(日期对象 ->字符串) public Date parse(string source) 解析(字符串 ->日期对象) */ //1.定义一个字符串表示时间 String str = "2023-11-11 11:11:11"; //2.利用空参构造创建simpleDateFormat对象 // 细节: //创建对象的格式要跟字符串的格式完全一致 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(str); //3.打印结果 System.out.println(date.getTime());//1699672271000 } private static void method1() { //1.利用空参构造创建simpleDateFormat对象,默认格式 SimpleDateFormat sdf1 = new SimpleDateFormat(); Date d1 = new Date(0L); String str1 = sdf1.format(d1); System.out.println(str1);//1970/1/1 上午8:00 //2.利用带参构造创建simpleDateFormat对象,指定格式 SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss"); String str2 = sdf2.format(d1); System.out.println(str2);//1970年01月01日 08:00:00 //课堂练习:yyyy年MM月dd日 时:分:秒 星期 } }
小结:DateFormat可以将Date对象和字符串相互转换。
12 Calendar类
3.1 概述
- java.util.Calendar类表示一个“日历类”,可以进行日期运算。它是一个抽象类,不能创建对象,我们可以使用它的子类:java.util.GregorianCalendar类。
- 有两种方式可以获取GregorianCalendar对象:
- 直接创建GregorianCalendar对象;
- 通过Calendar的静态方法getInstance()方法获取GregorianCalendar对象【本次课使用】
3.2 常用方法
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取一个它的子类GregorianCalendar对象。 |
public int get(int field) | 获取某个字段的值。field参数表示获取哪个字段的值, 可以使用Calender中定义的常量来表示: Calendar.YEAR : 年 Calendar.MONTH :月 Calendar.DAY_OF_MONTH:月中的日期 Calendar.HOUR:小时 Calendar.MINUTE:分钟 Calendar.SECOND:秒 Calendar.DAY_OF_WEEK:星期 |
public void set(int field,int value) | 设置某个字段的值 |
public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
3.3 get方法示例
public class Demo {
public static void main(String[] args) {
//1.获取一个GregorianCalendar对象
Calendar instance = Calendar.getInstance();//获取子类对象
//2.打印子类对象
System.out.println(instance);
//3.获取属性
int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH) + 1;//Calendar的月份值是0-11
int day = instance.get(Calendar.DAY_OF_MONTH);
int hour = instance.get(Calendar.HOUR);
int minute = instance.get(Calendar.MINUTE);
int second = instance.get(Calendar.SECOND);
int week = instance.get(Calendar.DAY_OF_WEEK);//返回值范围:1--7,分别表示:"星期日","星期一","星期二",...,"星期六"
System.out.println(year + "年" + month + "月" + day + "日" +
hour + ":" + minute + ":" + second);
System.out.println(getWeek(week));
}
//查表法,查询星期几
public static String getWeek(int w) {//w = 1 --- 7
//做一个表(数组)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
3.4 set方法示例:
public class Demo {
public static void main(String[] args) {
//设置属性——set(int field,int value):
Calendar c1 = Calendar.getInstance();//获取当前日期
//计算班长出生那天是星期几(假如班长出生日期为:1998年3月18日)
c1.set(Calendar.YEAR, 1998);
c1.set(Calendar.MONTH, 3 - 1);//转换为Calendar内部的月份值
c1.set(Calendar.DAY_OF_MONTH, 18);
int w = c1.get(Calendar.DAY_OF_WEEK);
System.out.println("班长出生那天是:" + getWeek(w));
}
//查表法,查询星期几
public static String getWeek(int w) {//w = 1 --- 7
//做一个表(数组)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
3.5 add方法示例:
public class Demo {
public static void main(String[] args) {
//计算200天以后是哪年哪月哪日,星期几?
Calendar c2 = Calendar.getInstance();//获取当前日期
c2.add(Calendar.DAY_OF_MONTH, 200);//日期加200
int y = c2.get(Calendar.YEAR);
int m = c2.get(Calendar.MONTH) + 1;//转换为实际的月份
int d = c2.get(Calendar.DAY_OF_MONTH);
int wk = c2.get(Calendar.DAY_OF_WEEK);
System.out.println("200天后是:" + y + "年" + m + "月" + d + "日" + getWeek(wk));
}
//查表法,查询星期几
public static String getWeek(int w) {//w = 1 --- 7
//做一个表(数组)
String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
// 索引 [0] [1] [2] [3] [4] [5] [6]
//查表
return weekArray[w - 1];
}
}
13 JDK8时间相关类
JDK8时间类类名 | 作用 |
---|---|
ZoneId | 时区 |
Instant | 时间戳 |
ZoneDateTime | 带时区的时间 |
DateTimeFormatter | 用于时间的格式化和解析 |
LocalDate | 年、月、日 |
LocalTime | 时、分、秒 |
LocalDateTime | 年、月、日、时、分、秒 |
Duration | 时间间隔(秒,纳,秒) |
Period | 时间间隔(年,月,日) |
ChronoUnit | 时间间隔(所有单位) |
4.1 ZoneId 时区
/*
static Set<string> getAvailableZoneIds() 获取Java中支持的所有时区
static ZoneId systemDefault() 获取系统默认时区
static Zoneld of(string zoneld) 获取一个指定时区
*/
//1.获取所有的时区名称
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds.size());//600
System.out.println(zoneIds);// Asia/Shanghai
//2.获取当前系统的默认时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId);//Asia/Shanghai
//3.获取指定的时区
ZoneId zoneId1 = ZoneId.of("Asia/Pontianak");
System.out.println(zoneId1);//Asia/Pontianak
4.2 Instant 时间戳
/*
static Instant now() 获取当前时间的Instant对象(标准时间)
static Instant ofXxxx(long epochMilli) 根据(秒/毫秒/纳秒)获取Instant对象
ZonedDateTime atZone(ZoneIdzone) 指定时区
boolean isxxx(Instant otherInstant) 判断系列的方法
Instant minusXxx(long millisToSubtract) 减少时间系列的方法
Instant plusXxx(long millisToSubtract) 增加时间系列的方法
*/
//1.获取当前时间的Instant对象(标准时间)
Instant now = Instant.now();
System.out.println(now);
//2.根据(秒/毫秒/纳秒)获取Instant对象
Instant instant1 = Instant.ofEpochMilli(0L);
System.out.println(instant1);//1970-01-01T00:00:00z
Instant instant2 = Instant.ofEpochSecond(1L);
System.out.println(instant2);//1970-01-01T00:00:01Z
Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
System.out.println(instant3);//1970-01-01T00:00:027
//3. 指定时区
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(time);
//4.isXxx 判断
Instant instant4=Instant.ofEpochMilli(0L);
Instant instant5 =Instant.ofEpochMilli(1000L);
//5.用于时间的判断
//isBefore:判断调用者代表的时间是否在参数表示时间的前面
boolean result1=instant4.isBefore(instant5);
System.out.println(result1);//true
//isAfter:判断调用者代表的时间是否在参数表示时间的后面
boolean result2 = instant4.isAfter(instant5);
System.out.println(result2);//false
//6.Instant minusXxx(long millisToSubtract) 减少时间系列的方法
Instant instant6 =Instant.ofEpochMilli(3000L);
System.out.println(instant6);//1970-01-01T00:00:03Z
Instant instant7 =instant6.minusSeconds(1);
System.out.println(instant7);//1970-01-01T00:00:02Z
4.3 ZoneDateTime 带时区的时间
/*
static ZonedDateTime now() 获取当前时间的ZonedDateTime对象
static ZonedDateTime ofXxxx(。。。) 获取指定时间的ZonedDateTime对象
ZonedDateTime withXxx(时间) 修改时间系列的方法
ZonedDateTime minusXxx(时间) 减少时间系列的方法
ZonedDateTime plusXxx(时间) 增加时间系列的方法
*/
//1.获取当前时间对象(带时区)
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
//2.获取指定的时间对象(带时区)1/年月日时分秒纳秒方式指定
ZonedDateTime time1 = ZonedDateTime.of(2023, 10, 1,
11, 12, 12, 0, ZoneId.of("Asia/Shanghai"));
System.out.println(time1);
//通过Instant + 时区的方式指定获取时间对象
Instant instant = Instant.ofEpochMilli(0L);
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
ZonedDateTime time2 = ZonedDateTime.ofInstant(instant, zoneId);
System.out.println(time2);
//3.withXxx 修改时间系列的方法
ZonedDateTime time3 = time2.withYear(2000);
System.out.println(time3);
//4. 减少时间
ZonedDateTime time4 = time3.minusYears(1);
System.out.println(time4);
//5.增加时间
ZonedDateTime time5 = time4.plusYears(1);
System.out.println(time5);
4.4DateTimeFormatter 用于时间的格式化和解析
/*
static DateTimeFormatter ofPattern(格式) 获取格式对象
String format(时间对象) 按照指定方式格式化
*/
//获取时间对象
ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
// 解析/格式化器
DateTimeFormatter dtf1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm;ss EE a");
// 格式化
System.out.println(dtf1.format(time));
4.5LocalDate 年、月、日
//1.获取当前时间的日历对象(包含 年月日)
LocalDate nowDate = LocalDate.now();
//System.out.println("今天的日期:" + nowDate);
//2.获取指定的时间的日历对象
LocalDate ldDate = LocalDate.of(2023, 1, 1);
System.out.println("指定日期:" + ldDate);
System.out.println("=============================");
//3.get系列方法获取日历中的每一个属性值//获取年
int year = ldDate.getYear();
System.out.println("year: " + year);
//获取月//方式一:
Month m = ldDate.getMonth();
System.out.println(m);
System.out.println(m.getValue());
//方式二:
int month = ldDate.getMonthValue();
System.out.println("month: " + month);
//获取日
int day = ldDate.getDayOfMonth();
System.out.println("day:" + day);
//获取一年的第几天
int dayofYear = ldDate.getDayOfYear();
System.out.println("dayOfYear:" + dayofYear);
//获取星期
DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
System.out.println(dayOfWeek);
System.out.println(dayOfWeek.getValue());
//is开头的方法表示判断
System.out.println(ldDate.isBefore(ldDate));
System.out.println(ldDate.isAfter(ldDate));
//with开头的方法表示修改,只能修改年月日
LocalDate withLocalDate = ldDate.withYear(2000);
System.out.println(withLocalDate);
//minus开头的方法表示减少,只能减少年月日
LocalDate minusLocalDate = ldDate.minusYears(1);
System.out.println(minusLocalDate);
//plus开头的方法表示增加,只能增加年月日
LocalDate plusLocalDate = ldDate.plusDays(1);
System.out.println(plusLocalDate);
//-------------
// 判断今天是否是你的生日
LocalDate birDate = LocalDate.of(2000, 1, 1);
LocalDate nowDate1 = LocalDate.now();
MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
MonthDay nowMd = MonthDay.from(nowDate1);
System.out.println("今天是你的生日吗? " + birMd.equals(nowMd));//今天是你的生日吗?
4.6 LocalTime 时、分、秒
// 获取本地时间的日历对象。(包含 时分秒)
LocalTime nowTime = LocalTime.now();
System.out.println("今天的时间:" + nowTime);
int hour = nowTime.getHour();//时
System.out.println("hour: " + hour);
int minute = nowTime.getMinute();//分
System.out.println("minute: " + minute);
int second = nowTime.getSecond();//秒
System.out.println("second:" + second);
int nano = nowTime.getNano();//纳秒
System.out.println("nano:" + nano);
System.out.println("------------------------------------");
System.out.println(LocalTime.of(8, 20));//时分
System.out.println(LocalTime.of(8, 20, 30));//时分秒
System.out.println(LocalTime.of(8, 20, 30, 150));//时分秒纳秒
LocalTime mTime = LocalTime.of(8, 20, 30, 150);
//is系列的方法
System.out.println(nowTime.isBefore(mTime));
System.out.println(nowTime.isAfter(mTime));
//with系列的方法,只能修改时、分、秒
System.out.println(nowTime.withHour(10));
//plus系列的方法,只能修改时、分、秒
System.out.println(nowTime.plusHours(10));
4.7 LocalDateTime 年、月、日、时、分、秒
// 当前时间的的日历对象(包含年月日时分秒)
LocalDateTime nowDateTime = LocalDateTime.now();
System.out.println("今天是:" + nowDateTime);//今天是:
System.out.println(nowDateTime.getYear());//年
System.out.println(nowDateTime.getMonthValue());//月
System.out.println(nowDateTime.getDayOfMonth());//日
System.out.println(nowDateTime.getHour());//时
System.out.println(nowDateTime.getMinute());//分
System.out.println(nowDateTime.getSecond());//秒
System.out.println(nowDateTime.getNano());//纳秒
// 日:当年的第几天
System.out.println("dayofYear:" + nowDateTime.getDayOfYear());
//星期
System.out.println(nowDateTime.getDayOfWeek());
System.out.println(nowDateTime.getDayOfWeek().getValue());
//月份
System.out.println(nowDateTime.getMonth());
System.out.println(nowDateTime.getMonth().getValue());
LocalDate ld = nowDateTime.toLocalDate();
System.out.println(ld);
LocalTime lt = nowDateTime.toLocalTime();
System.out.println(lt.getHour());
System.out.println(lt.getMinute());
System.out.println(lt.getSecond());
4.8 Duration 时间间隔(秒,纳,秒)
// 本地日期时间对象。
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 出生的日期时间对象
LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
System.out.println(birthDate);
Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数
System.out.println("相差的时间间隔对象:" + duration);
System.out.println("============================================");
System.out.println(duration.toDays());//两个时间差的天数
System.out.println(duration.toHours());//两个时间差的小时数
System.out.println(duration.toMinutes());//两个时间差的分钟数
System.out.println(duration.toMillis());//两个时间差的毫秒数
System.out.println(duration.toNanos());//两个时间差的纳秒数
4.9 Period 时间间隔(年,月,日)
// 当前本地 年月日
LocalDate today = LocalDate.now();
System.out.println(today);
// 生日的 年月日
LocalDate birthDate = LocalDate.of(2000, 1, 1);
System.out.println(birthDate);
Period period = Period.between(birthDate, today);//第二个参数减第一个参数
System.out.println("相差的时间间隔对象:" + period);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
System.out.println(period.toTotalMonths());
4.10 ChronoUnit 时间间隔(所有单位)
// 当前时间
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
// 生日时间
LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1,0, 0, 0);
System.out.println(birthDate);
System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));
14 包装类
)
5.1 概述)
Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类,如下:
基本类型 | 对应的包装类(位于java.lang包中) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
5.2 Integer类
-
Integer类概述
包装一个对象中的原始类型 int 的值
-
Integer类构造方法及静态方法
方法名 | 说明 |
---|---|
public Integer(int value) | 根据 int 值创建 Integer 对象(过时) |
public Integer(String s) | 根据 String 值创建 Integer 对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 |
public static Integer valueOf(String s) | 返回保存指定String值的 Integer 对象 |
static string tobinarystring(int i) | 得到二进制 |
static string tooctalstring(int i) | 得到八进制 |
static string toHexstring(int i) | 得到十六进制 |
static int parseInt(string s) | 将字符串类型的整数转成int类型的整数 |
- 示例代码
//public Integer(int value):根据 int 值创建 Integer 对象(过时)
Integer i1 = new Integer(100);
System.out.println(i1);
//public Integer(String s):根据 String 值创建 Integer 对象(过时)
Integer i2 = new Integer("100");
//Integer i2 = new Integer("abc"); //NumberFormatException
System.out.println(i2);
System.out.println("--------");
//public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 实例
Integer i3 = Integer.valueOf(100);
System.out.println(i3);
//public static Integer valueOf(String s):返回保存指定String值的Integer对象
Integer i4 = Integer.valueOf("100");
System.out.println(i4);
/*
public static string tobinarystring(int i) 得到二进制
public static string tooctalstring(int i) 得到八进制
public static string toHexstring(int i) 得到十六进制
public static int parseInt(string s) 将字符串类型的整数转成int类型的整数
*/
//1.把整数转成二进制,十六进制
String str1 = Integer.toBinaryString(100);
System.out.println(str1);//1100100
//2.把整数转成八进制
String str2 = Integer.toOctalString(100);
System.out.println(str2);//144
//3.把整数转成十六进制
String str3 = Integer.toHexString(100);
System.out.println(str3);//64
//4.将字符串类型的整数转成int类型的整数
//强类型语言:每种数据在java中都有各自的数据类型
//在计算的时候,如果不是同一种数据类型,是无法直接计算的。
int i = Integer.parseInt("123");
System.out.println(i);
System.out.println(i + 1);//124
//细节1:
//在类型转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错
//细节2:
//8种包装类当中,除了Character都有对应的parseXxx的方法,进行类型转换
String str = "true";
boolean b = Boolean.parseBoolean(str);
System.out.println(b);
5.3 装箱与拆箱
基本类型与对应的包装类对象之间,来回转换的过程称为”装箱“与”拆箱“:
- 装箱:从基本类型转换为对应的包装类对象。
- 拆箱:从包装类对象转换为对应的基本类型。
用Integer与 int为例:(看懂代码即可)
基本数值---->包装对象
Integer i = new Integer(4);//使用构造函数函数
Integer iii = Integer.valueOf(4);//使用包装类中的valueOf方法
包装对象---->基本数值
int num = i.intValue();
5.4 自动装箱与自动拆箱
由于我们经常要做基本类型与包装类之间的转换,从Java 5(JDK 1.5)开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:
Integer i = 4;//自动装箱。相当于Integer i = Integer.valueOf(4);
i = i + 5;//等号右边:将i对象转成基本数值(自动拆箱) i.intValue() + 5;
//加法运算完成后,再次装箱,把基本数值转成对象。
5.5 基本类型与字符串之间的转换
基本类型转换为String
- 转换方式
- 方式一:直接在数字后加一个空字符串
- 方式二:通过String类静态方法valueOf()
- 示例代码
public class IntegerDemo {
public static void main(String[] args) {
//int --- String
int number = 100;
//方式1
String s1 = number + "";
System.out.println(s1);
//方式2
//public static String valueOf(int i)
String s2 = String.valueOf(number);
System.out.println(s2);
System.out.println("--------");
}
}
String转换成基本类型
除了Character类之外,其他所有包装类都具有parseXxx静态方法可以将字符串参数转换为对应的基本类型:
public static byte parseByte(String s)
:将字符串参数转换为对应的byte基本类型。public static short parseShort(String s)
:将字符串参数转换为对应的short基本类型。public static int parseInt(String s)
:将字符串参数转换为对应的int基本类型。public static long parseLong(String s)
:将字符串参数转换为对应的long基本类型。public static float parseFloat(String s)
:将字符串参数转换为对应的float基本类型。public static double parseDouble(String s)
:将字符串参数转换为对应的double基本类型。public static boolean parseBoolean(String s)
:将字符串参数转换为对应的boolean基本类型。
代码使用(仅以Integer类的静态方法parseXxx为例)如:
- 转换方式
- 方式一:先将字符串数字转成Integer,再调用valueOf()方法
- 方式二:通过Integer静态方法parseInt()进行转换
- 示例代码
public class IntegerDemo {
public static void main(String[] args) {
//String --- int
String s = "100";
//方式1:String --- Integer --- int
Integer i = Integer.valueOf(s);
//public int intValue()
int x = i.intValue();
System.out.println(x);
//方式2
//public static int parseInt(String s)
int y = Integer.parseInt(s);
System.out.println(y);
}
}
注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出
java.lang.NumberFormatException
异常。
5.6 底层原理
建议:获取Integer对象的时候不要自己new,而是采取直接赋值或者静态方法valueOf的方式
因为在实际开发中,-128~127之间的数据,用的比较多。如果每次使用都是new对象,那么太浪费内存了。
所以,提前把这个范围之内的每一个数据都创建好对象,如果要用到了不会创建新的,而是返回已经创建好的对象。
//1.利用构造方法获取Integer的对象(JDK5以前的方式)
/*Integer i1 = new Integer(1);
Integer i2 = new Integer("1");
System.out.println(i1);
System.out.println(i2);*/
//2.利用静态方法获取Integer的对象(JDK5以前的方式)
Integer i3 = Integer.valueOf(123);
Integer i4 = Integer.valueOf("123");
Integer i5 = Integer.valueOf("123", 8);
System.out.println(i3);
System.out.println(i4);
System.out.println(i5);
//3.这两种方式获取对象的区别(掌握)
//底层原理:
//因为在实际开发中,-128~127之间的数据,用的比较多。
//如果每次使用都是new对象,那么太浪费内存了
//所以,提前把这个范围之内的每一个数据都创建好对象
//如果要用到了不会创建新的,而是返回已经创建好的对象。
Integer i6 = Integer.valueOf(127);
Integer i7 = Integer.valueOf(127);
System.out.println(i6 == i7);//true
Integer i8 = Integer.valueOf(128);
Integer i9 = Integer.valueOf(128);
System.out.println(i8 == i9);//false
//因为看到了new关键字,在Java中,每一次new都是创建了一个新的对象
//所以下面的两个对象都是new出来,地址值不一样。
/*Integer i10 = new Integer(127);
Integer i11 = new Integer(127);
System.out.println(i10 == i11);
Integer i12 = new Integer(128);
Integer i13 = new Integer(128);
System.out.println(i12 == i13);*/