目录
1.String next()和String nextLine()
3.public String(String original)
2.将此类String与另一个String比较,不考虑大小写
2.根据传入的开始和结束索引,对字符串做截取(包含头,不包含尾)
②public StringBuilder(String str)
①public StringBuilder append(任意类型)
②public StringBuilder reverse()
public Boolean equals(Object o)
(一)数据结构
一、基本数据类型
数据类型 | 关键字 | 内存占用/字节 |
---|---|---|
整数 | byte(-128~127) | 1 |
short | 2 | |
int(默认) | 4 | |
long | 8 | |
浮点数 | float | 4 |
double(默认) | 8 | |
字符 | char | 2 |
布尔 | boolean | 1 |
-
整数类型:首选int,如果发现int装不下了,将类型换为long,定义long类型变量需要加入L/l标识
-
小数类型:首选double,非要用float类型,需要加入F标识
public class shujuleixing { public static void main(String[] args) { //姓名 String name ="小严"; //年龄 int age = 18; //性别 char gender ='男'; //身高 double height = 181.5: //是否单身 boolean flag = true; System.out.printin(name); System.out.println(age); System.out.println(gender); System.out.println(height);System.out.printin(flag); } }
}
运行结果
二、自动装箱、自动拆箱
1.包装类
①介绍
将基本数据类型,包装成类(变成引用数据类型)
变成类,就可以创建对象了,对象就可以调用方法方便地解决问题了
②基本数据类型对应的包装类
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
③Integer类
-
将基本数据类型手动包装为类
手动装箱与手动拆箱
-
手动装箱: 调用方法,手动将基本数据类型,包装成类
-
public Integer(int value) : 通过构造方法(不推荐)
-
public static Integer valueof(int i) : 通过静态方法
-
package integer; public class IntegerDemo { public static void main(String[] args) { int num =10; Integer i1 = Integer.valueOf(num); System.out.println(i1); } }
-
手动拆箱:调用方法,手动将包装类,拆成(转换)基本数据类型
1.public int intValue() : 以 int 类型返回该 Integer 的值
package integer; public class IntegerDemo { public static void main(String[] args) { int num =10; Integer i1 = Integer.valueOf(num); int i = i1.intValue(); System.out.println(i); } }
JDK5版本开始,出现了自动拆装箱:
-
自动装箱 : 可以将基本数据类型直接赋值给包装类的变量
-
自动拆箱 : 可以将包装类的数据,直接赋值给基本数据类型变量
-
基本数据类型和对应的包装类,可以直接做运算了,不需要操心转换的问题了
package integer; public class IntegerDemo { public static void main(String[] args) { int num =10; Integer i1 = num;//Integer i1 = Integer.valueOf(num); int i = i1;//int i = i1.intValue(); System.out.println(i); } }
Integer 常用方法
public static String toBinaryString (int i) : 转二进制 public static String toOctalString (int i) : 转八进制 public static String toHexString (int i) : 转十六进制 public static int parseInt (String s) : 将数字字符串, 转换为数字
package integer; public class IntegerMethodDemo { public static void main(String[] args) { int num = 100; System.out.println(Integer.toBinaryString(num)); System.out.println(Integer.toOctalString(num)); System.out.println(Integer.toHexString(num)); String s = "123"; System.out.println(Integer.parseInt(s) + 100); } }
运行结果:
1100100 144 64 223
包装类练习
要求:已知字符串 String s="10,50,30,20,40" 请将该字符串转换为整数并存入数组 随后求出最大值打印在控制台
package integer; public class IntegerTest { public static void main(String[] args) { String s = "10,50,30,20,40"; //1.根据逗号做切割 String[] sArr = s.split(","); //2.准备一个整数数组,准备存储转换后的数字 int[] nums = new int[sArr.length]; //3.遍历字符串数组 for (int i = 0; i < sArr.length; i++) { //sArr[i]:每一个数字字符串 //4.将数字字符串转换为整数,并存入数组 nums[i] = Integer.parseInt(sArr[i]); } //5.求最大值 int max = nums[0]; for (int i = 1; i < nums.length; i++) { if(nums[i] > max) { max = nums[i]; } } System.out.println("最大值为:" + max); } }
运行结果:
最大值为:50
④面试题
package integer; public class InterView { /* 看程序说结果 */ public static void main(String[] args) { Integer i1 = 127; Integer i2 = 127; System.out.println(i1 == i2);//true Integer i3 = 129; Integer i4 = 129; System.out.println(i3 == i4);//false System.out.println(i4.equals(i3));//true }package integer; public class InterView { /* 看程序说结果 原码: public static Integer valueOf(int i) { if (i >= -128 && i <= 127) { return IntegerCache.cache[255]; } return new Integer(i); } */ public static void main(String[] args) { Integer i1 = 127; Integer i2 = 127; System.out.println(i1 == i2);//true Integer i3 = 129; Integer i4 = 129; System.out.println(i3 == i4);//false System.out.println(i4.equals(i3));//true } }
注意
自动装箱的时候,如果装箱的数据范围是-128~127,==号比较的结果就是true,反之为false
如果装箱的数据不在-128~127之间,会重新创建新的对象
如果装箱的数据, 在 -128 ~ 127 之间, 不会创建新的对象, 而是从底层的数组中, 取出一个提前创建好的Integer对象, 返回
Integer类中, 底层存在一个长度为256个大小的数组,Integer[] cache,在数组中, 存储了256个Integer对象, 分别是 -128 ~ 127
自动装箱的原理
自动帮我们调用了Integer.valueof(127);
(二)常用API
一、介绍
API(Application Programming Interface):应用程序编程接口
就是别人写好的一些类,给咱们程序员直接拿去调用即可解决问题的
二、API帮助文档的使用流程
-
在索引位置搜索自己要查看的类
-
看包:如果是java.lang包(核心包), 不需要编写导包代码(import)。如果不是java.lang包, 都需要编写导包代码
-
看这个类的介绍:搞清楚这个类的作用
-
看这个类的构造方法:为了将该类的对象, 创建出来
-
看这个类的成员方法(方法摘要):方法名、参数、返回值、介绍
三、Scanner键盘录入字符串
1.String next()和String nextLine()
String next() : 遇到了空格, 或者是tab键就不再录入了 String nextLine() : 以回车作为录入的结束标记
2.弊端
-
next() : 数据可能录入不完整
-
nextLine() : 如果之前调用过nextInt(), nextDouble(), nextFloat()... 那么nextLine()方法, 就不干活了
3.解决方案
-
不用解决
Scanner : 采集用户信息 (只在学习过程用的到)
目前的使用方案:
需求如果要键盘录入字符串:
如果所有的数据, 全部都是字符串, 直接nextLine();
举例:键盘录入用户名, 键盘录入用户密码
如果数据除了字符串, 还有其他类型, 需要调用next()方法
举例:键盘录入用户名, 键盘录入用户年龄, 用户身高
package com.itheima.scanner; import java.util.Scanner; public class ScannerDemo1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入用户年龄:"); int age = sc.nextInt(); System.out.println(age); System.out.println("请输入用户名:"); String password = sc.next(); System.out.println(password); } }
(三)String类
一、特点
1.java程序中所有的双引号字符串,都是String这个类的对象
package string; public class StringDemo1 { public static void main(String[] args) { String s = "abc"; //小写变大写 System.out.println(s.toUpperCase()); System.out.println("helloworld".toUpperCase()); } } //运行结果: //ABC //HELLOWORLD
2.字符串一旦被创建,就不可更改(字符串内容不可更改,若果想要更改,只能用新的对象做替换)
package string; public class StringDemo1 { public static void main(String[] args) { String s = "abc"; s = "def"; System.out.println(s); } } //运行结果: //def
3.String字符串虽然不可更改,但是可以被共享(字符串常量池String Table:当我们使用双引号创建字符串对象时,会检查常量池中是否存在该数据,如果不存在:创建;如果存在,复用)
package string; public class StringDemo1 { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; // ==号比较的是地址 System.out.println(s1 == s2); } } //运行结果: //true
二、String类常见构造方法
1.public String()
创建一个空白字符串,里面不含任何内容
package string; public class StringDemo2 { public static void main(String[] args) { String s1 = new String(); System.out.println(s1); } }
运行结果:
2.public String(char[] chs)
根据传入的字符数组,创建字符串对象
package string; public class StringDemo2 { public static void main(String[] args) { char[] chs = {'a','b','c'}; String s2 = new String(chs); System.out.println(s2); } }
运行结果:
3.public String(String original)
根据传入的字符串,来创建字符串对象
package string; public class StringDemo2 { public static void main(String[] args) { String s3 = new String("abc"); System.out.println(s3); } }
运行结果:
4.总结
这三个构造方法,创建字符串对象,都没有双引号直接创建来的
String s = "abc";
三、常见面试题
-
String字符串虽然不可更改,但是可以被共享
-
String s1 = "abc":创建的字符串对象放入常量池中,s1记录常量池中的地址
-
String s2 = new String("abc"):新创建的字符串是该参数 字符串的副本,拷贝的是地址,在堆内存中有自己独立的内存空间
字符串底层其实是一个字节类型的数组
-
变量与字符串常量拼接
-
有"+"拼接时,系统会自动创建StringBuilder对象,再自动调用方法拼成,再调用toString方法转换成String类型
运行结果:true
-
三个字符串常量拼接(java有常量优化机制:编译时直接把三个拼接的字符串转化成了"abc")
四、字符串比较内容-String类中用于比较的方法
1.将此字符串与指定的对象比较
public boolean equals(Object anObject)
package string.method; public class StringMethodDemo1 { public static void main(String[] args) { String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); System.out.println(s1.equals(s2)); } } //运行结果: //false //true
2.将此类String与另一个String比较,不考虑大小写
public boolean equalsIgnoreCase(String anotherString)
package string.method; public class StringMethodDemo1 { public static void main(String[] args) { String s1 = "abc"; String s2 = "ABC"; System.out.println(s1.equals(s2)); System.out.println(s1.equalsIgnoreCase(s2)); } } //运行结果: //false //true
应用:输入验证码
3.案例-用户登录
需求:已知正确的用户名和密码,请用程序实现模拟用户登录总共给三次机会,登录之后,给出相应的提示
package test; import java.util.Scanner; public class StringTest1 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); //1.定义两个字符串类型变量,模拟已经存在的用户名和密码 String username = "admin"; String password = "123456"; for(int i = 1; i <= 3; i++) { //2.键盘录入用户输入的用户名,密码 System.out.println("请输入用户名:"); String inputUsername = sc.nextLine(); System.out.println("请输入密码:"); String inputPassword = sc.nextLine(); //3.比对 if(inputUsername.equals(username) && inputPassword.equals(password)) { System.out.println("登录成功!"); break; }else { if(i == 3) { System.out.println("明儿再来吧~"); }else { System.out.println("登录失败,您还剩" + (3-i) +"次机会!"); } } } } }
五、String字符串的遍历
1.将此字符串转换为一个新的字符数组(效率更高)
public char[] toCharArray()
package method; public class StringMethodDemo2 { public static void main(String[] args) { String s = "foryou"; char[] chars = s.toCharArray(); for (int i = 0; i < chars.length; i++) { System.out.println(chars[i]); } } }
运行结果:
2.返回指定索引处的char值
public char charAt(int index)
返回此字符串的长度
public int length()
package method; public class StringMethodDemo2 { public static void main(String[] args) { String s = "foryou"; //与数组中的length不一样,这里是一种方法 for(int i = 0; i < s.length(); i++) { char c = s.charAt(i); System.out.println(c); } } }
运行结果:
3.案例-统计字符次数
package test; import java.util.Scanner; public class StringTest2 { public static void main(String[] args) { //1.键盘录入一个字符串 Scanner sc = new Scanner(System.in); System.out.println("请输入:"); String content = sc.nextLine(); //2.定义三个计数器变量,用于统计操作 int smallCount = 0; int bigCount = 0; int numCount = 0; //3.遍历字符串,获取到每一个字符 char[] chars = content.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; //4.在遍历的过程中,加入if判断,看字符属于哪一种类别 //5.对应的计数器变量自增 if(c >= 'a' && c <= 'z') { smallCount++; } else if (c >= 'A' && c <= 'Z') { bigCount++; } else if (c >= '0' && c <= '9') { numCount++; } } //6.在遍历结束后,将统计好的计数器变量,打印在控制台 System.out.println("小写字母:" + smallCount + "个"); System.out.println("大写字母:" + bigCount + "个"); System.out.println("数字字符:" + numCount + "个"); } }
运行结果:
六、String字符串的截取方法
1.根据传入的索引开始截取,截取到字符串的末尾
public String substring(int beginIndex);
package method; public class StringMethodDemo3 { public static void main(String[] args) { String s = "foryou"; String result = s.substring(3); System.out.println(result); } }
运行结果:
2.根据传入的开始和结束索引,对字符串做截取(包含头,不包含尾)
public String substring(int beginIndex, int endIndex);
package method; public class StringMethodDemo3 { public static void main(String[] args) { String s = "foryou"; String result = s.substring(0, 3); System.out.println(result); } }
运行结果:
注意: 截取出来的内容,是作为新的字符串返回,别忘记找变量接收
3.案例-手机号屏蔽
需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽,最终效果为:1561234
package test; import java.util.Scanner; public class StringTest3 { public static void main(String[] args) { //1.键盘录入字符串 Scanner sc = new Scanner(System.in); System.out.println("请输入手机号:"); String tel = sc.nextLine(); //2.截取前三位 //18803102512 String start = tel.substring(0, 3); //3.截取后四位 String end = tel.substring(7); //4.拼接 System.out.println(start + "****" + end); } }
运行结果:
七、String字符串的替换方法
1.新值替换旧值
public String replace(CharSequence target,CharSequence replacement);
参数1:旧值 参数2:新值
2.案例-敏感词替换
需求:键盘录入一个字符串,如果字符串中包含 (TMD),则使用*** 替换
package test; import java.util.Scanner; public class StringTest4 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入:"); String content = sc.nextLine(); content = content.replace("TMD","***"); System.out.println(content); } }
运行结果:
八、String字符串的切割方法
根据传入的字符串作为规则,切割当前字符串
public String[] split(String regex);
"."代表任意字符,若想以"."切割,可以写成"\ \ ."
建议: 先正常指定切割规则,后来发现没有得到自己要的效果,就可以尝试在规则前面,加入"\"
package method; public class StringMethodDemo5 { public static void main(String[] args) { String s = "192,168,1,1"; String[] sArr = s.split(","); for (int i = 0; i < sArr.length; i++) { System.out.println(sArr[i]); } } }
(四)StringBuilder类
1.好处
提高字符串操作效率
package stringbuilder; public class StringBuilderDemo1 { public static void main(String[] args) { //高效率 long start = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); for(int i = 1; i <= 100000; i++) { sb.append(i); } System.out.println(sb); long end = System.currentTimeMillis(); System.out.println(end - start); } //低效率 private static void method() { //获取1970年1月1日0时0分0秒到现在所经历过的毫秒值(1秒 = 1000毫秒) long start = System.currentTimeMillis(); String s = ""; for(int i = 1; i <= 100000; i++) { s += i; } System.out.println(s); long end = System.currentTimeMillis(); //计算上面的代码执行了多久 System.out.println(end - start); } }
2.介绍
-
一个可变的字符序列
package stringbuilder; public class StringBuilderDemo2 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); System.out.println(sb); sb.append("红色"); System.out.println(sb); sb.append("绿色"); System.out.println(sb); sb.append("蓝色"); System.out.println(sb); } }
运行结果:
-
StringBuilder是字符串缓冲区,将其理解是容器,这个容器可以存储任意数据类型,但是只要进入到这个容器,全部变成字符串
package stringbuilder; public class StringBuilderDemo2 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append(100); sb.append(45.6); sb.append(false); sb.append('严'); sb.append("小熊"); System.out.println(sb); } }
运行结果:
3.构造方法
①public StringBuilder()
创建一个空白的字符串缓冲区(容器),其初始容量为16个字符,超过16会自动扩容
package stringbuilder; public class StringBuilderDemo2 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("123456789123456789"); System.out.println(sb); } } //运行结果: //123456789123456789
②public StringBuilder(String str)
创建一个字符串缓冲区(容器),容器在创建好之后,就会带有参数的内容
package stringbuilder; public class StringBuilderDemo2 { public static void main(String[] args) { StringBuilder sb = new StringBuilder("abc"); System.out.println(sb); } } //运行结果: //abc
4.常用成员方法
①public StringBuilder append(任意类型)
添加数据,并返回自己
package stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); StringBuilder sb2 = sb.append("红色"); StringBuilder sb3 = sb.append("绿色"); StringBuilder sb4 = sb.append("蓝色"); System.out.println(sb == sb2); System.out.println(sb2 == sb3); System.out.println(sb3 == sb4); System.out.println(sb4 == sb); } }
运行结果:
-
链式编程: 调用的方法,返回的结果是对象,就可以继续向下调用方法
package stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); //StringBuilder sb2 = sb.append("红色"); //链式编程: 调用的方法,返回的结果是对象,就可以继续向下调用方法 sb.append("红色").append("绿色").append("蓝色"); System.out.println(sb); } }
运行结果:
②public StringBuilder reverse()
将缓冲区中的内容,进行反转
package stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("红色").append("绿色").append("蓝色"); System.out.println(sb); sb.reverse().append("你好"); System.out.println(sb); } }
运行结果:
③public int length()
返回长度
package stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("红色").append("绿色").append("蓝色"); System.out.println(sb); sb.reverse().append("你好"); System.out.println(sb); System.out.println(sb.length()); } }
运行结果:
④public String toString()
将缓冲区的内容,以String字符串类型返回
package stringbuilder; public class StringBuilderDemo3 { public static void main(String[] args) { StringBuilder sb = new StringBuilder(); sb.append("红色").append("绿色").append("蓝色"); System.out.println(sb); //情况: 数据在 StringBuilder当中,而要调用的方法,StringBuilder没有,但是String有 //解决: 转换为String,再调用 //String result = sb.toString(); String[] sArr = sb.toString().split("色"); for (int i = 0; i < sArr.length; i++) { System.out.println(sArr[i]); } } }
运行结果:
5.案例
①String和StringBuilder的转换
String --> StringBuilder:
String s = "abc"; StringBuilder sb = new StringBuilder(s);
StringBuilder --> String
String s = sb.toString;
package test; import java.util.Scanner; public class StringBuilderTest1 { /* 需求:键盘接受一个字符串,程序判断出该字符串是否是对称字符串(回文字符串),并在控制台打印是或不是 对称字符串: 123321、111 非对称字符串: 123123 思路: 对拿到的宇符串进行反转,反转后的内容,跟原数据相同,判定为回文字符串 */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入一个对称字符串:"); String content = sc.nextLine(); //为了调用内部反转方法,将String转换为 StringBuilder StringBuilder sb = new StringBuilder(content); sb.reverse(); //判断反转后的内容和原数据是否相同 //content是String类型,sb是StringBuilder类型,肯定不相等 //用toString将sb以String字符串类型返回 if(content.equals(sb.toString())) { System.out.println("是对称字符串"); } else { System.out.println("不是对称字符串"); } } } //运行结果: //请输入一个对称字符串: //123321 //是对称字符串 //请输入一个对称字符串: //123456 //不是对称字符串
②字符串拼接
package test; public class StringBuilderTest2 { /* 需求: 定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回 调用该方法,并在控制台输出结果。 例如:数组为int[] arr = {1, 2, 3}执行方法后的输出结果为: [1,2,3] */ public static void main(String[] args) { int[] arr = {1,2,3}; String result = arrayToString(arr); System.out.println(result); } public static String arrayToString(int[] arr) { //1.创建一个StringBuilder,准备进行拼接 StringBuilder sb = new StringBuilder("["); //2.遍历数组,获取内部的元素 for (int i = 0; i < arr.length - 1; i++) { //3.将获取到元素,拼接到字符串缓冲区 sb.append(arr[i]).append(", "); } //4.特殊处理最后一个元素 sb.append(arr[arr.length - 1]).append("]"); System.out.println(sb); return sb.toString(); } }
6.String和StringBuilder效率对比
String:每创建+就有两个对象被创建
StringBuilder:只有一个对象,只开辟了一块空间
StringBuilder的实例用于多个线程是不安全的
StringBuffer是线程安全的可变字符序列
两者类名和构造方法都是一样的
(五)Object类
所有的类,都直接或者间接的继承了Object类(祖宗类)
Object类的方法是一切子类都可以直接使用的,所以我们要学习Object类的方法。
一、toString方法
public String toString()
①介绍
返回该对象的字符串表示
默认是返回当前对象在堆内存中的地址信息:类的全限名@十六进制哈希值
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
细节: 使用打印语句, 打印对象名的时候, println方法, 源码层面, 会自动调用该对象的toString方法.
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
-
getClass().getName() : 类名称, 全类名(包名 + 类名)
-
Integer.toHexString() : 转十六进制
-
hashCode() : 返回的是对象内存地址 + 哈希算法, 算出来的整数 (哈希值)--> 哈希值不是真的地址,而是地址通过哈希算法得到的对应的值
package object.tostring; public class ToStringDemo { public static void main(String[] args) { A a = new A(); System.out.println(a); System.out.println(a.toString()); } }
②重写toString方法
package object.tostring; public class ToStringDemo { public static void main(String[] args) { A a = new A(); System.out.println(a); System.out.println(a.toString()); } } class A { @Override public String toString() { return "重写了toString方法"; } }
示例:
package com.itheima.object; import java.util.Objects; public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } //重写 public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } }
package object.tostring; public class ToStringDemo { public static void main(String[] args) { A a = new A(); System.out.println(a); System.out.println(a.toString(); Student stu = new Student("张三",23); System.out.println(stu); } }
创建对象再调用对象名的时候,看到的就不是对象的内存地址了,而是对象的属性信息
开发中直接输出对象,默认输出对象的地址其实是毫无意义的
开发中输出对象变量,更多的时候是希望看到对象的内容数据而不是对象的地址信息
③toString存在的意义
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息!
二、equals方法
public Boolean equals(Object o)
①介绍
对象之间进行比较,返回true或者false
public boolean equals(Object obj) { this : stu1 obj : stu2 return (this == obj); }
结论: object类中的equals方法,默认比较的是对象内存地址,通常会重写equals方法,让对象之间比较内容
示例:
package object.tostring; import java.util.Objects; public class Student { private String name; private int age; @Override public boolean equals(Object obj) { //防止类型不匹配 if(obj instanceof Student) { //this:stu1 //obj: stu2 //父类不能调用子类,需要向下转型,才能调用子类特有的成员 //this.age == obj.age; Student stu = (Student) obj; return this.age == stu.age && this.name.equals(stu.name); } else { return false; } } public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } }
package object.equals; import object.tostring.Student; import java.util.ArrayList; public class EqualsDemo { public static void main(String[] args) { Student stu1 = new Student("张三",23); Student stu2 = new Student("张三",23); ArrayList<String> list = new ArrayList<>(); System.out.println(stu1.equals(stu2)); System.out.println(stu1.equals(stu2)); } }
②重写equals方法
-
Objects类与Object还是继承关系,Objects类是从JDK 1.7开始之后才有的
(1)public static boolean equals(Object a, Object b)
package object.tostring; import java.util.Objects; public class Student { private String name; private int age; @Override public boolean equals(Object o) { //this : stu1 //o : stu2 if (this == o) { //两个对象做地址值的比较,如果地址相同,里面的内容肯定相同,直接返回为true return true; } //代码要是能够走到这里,代表地址肯定不相同 //代码要是能够走到这里,代表stu1,背定不是null //stu1不是null,stu2是null,就直接返回false //getClass() != o.getClass():两个对象的字节码是否相同 //如果字节码不相同,就意味着类型不相同,直接返回false if (o == null || getClass() != o.getClass()) { return false; } //代码要是能够走到这里,代表字节码相同,类型肯定相同。 //向下转型 Student student = (Student) o; //比较 //Objects类与Object还是继承关系,Objects类是从JDK 1.7开始之后才有的。 return age == student.age && Objects.equals(name, student.name); } public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } }
package object.equals; import object.tostring.Student; import java.util.ArrayList; import java.util.Objects; public class EqualsDemo { public static void main(String[] args) { Student stu1 = null; Student stu2 = new Student("张三",23); System.out.println(Objects.equals(stu1,stu2)); System.out.println("看看我执行了吗?"); } }
问题: objects.equals方法和stu1.equals方法,有什么区别?
细节:objects.equals方法,内部依赖于我们自己所编写的equals
好处: 0bjects.equals方法,内部带有非null判断,避免空指针异常
(2)public static boolean isNull(Object obj)
package object.equals; import object.tostring.Student; import java.util.ArrayList; import java.util.Objects; public class EqualsDemo { public static void main(String[] args) { Student stu1 = null; Student stu2 = new Student("张三",23); System.out.println(Objects.isNull(stu1)); System.out.println(Objects.isNull(stu2)); System.out.println("看看我执行了吗?"); } }
③equals存在的意义
父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则
(六)Math类
一、介绍
包含执行基本数字运算的方法,都是静态的,直接用类名调用即可
二、方法演示
package math; public class MathDemo { public static void main(String[] args) { //获取参数绝对值 System.out.println(Math.abs(-123)); //123 System.out.println(Math.abs(-12.3)); //12.3 System.out.println("---------------------------"); //向上取整 System.out.println(Math.ceil(12.0)); //12.0 System.out.println(Math.ceil(12.2)); //13.0 System.out.println(Math.ceil(12.5)); //13.0 System.out.println(Math.ceil(12.9)); //13.0 System.out.println("---------------------------"); //向下取整 System.out.println(Math.floor(12.0)); //12.0 System.out.println(Math.floor(12.2)); //12.0 System.out.println(Math.floor(12.5)); //12.0 System.out.println(Math.floor(12.9)); //12.0 System.out.println("---------------------------"); //四舍五入 System.out.println(Math.round(3.4)); //3 System.out.println(Math.round(3.6)); //4 System.out.println("---------------------------"); //获取两个int值中的较大值 System.out.println(Math.max(10, 20)); //20 System.out.println("---------------------------"); //获取两个int值中的较小值 System.out.println(Math.min(10, 20)); //10 System.out.println("---------------------------"); //返回a的b次幂的值 System.out.println(Math.pow(2, 3)); //8.0 System.out.println("---------------------------"); //返回值为double的随机值,范围[0.0,1.0) System.out.println(Math.random()); } }
(七)System类
一、介绍
System的功能是静态的,都是直接用类名调用即可
二、方法演示
package system; public class SystemDemo { public static void main(String[] args) { //数组拷贝 //public static void arraycopy( 数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) //public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) int[] arr = {11,22,33,44,55}; int[] destArr = new int[3]; System.arraycopy(arr,2,destArr,0,3); for (int i = 0; i < destArr.length; i++) { System.out.println(destArr[i]); } } private static void method() { //返回当前系统的时间(毫秒值形式)-->返回1970年1月1日0时0分0秒,到现在所经历过的毫秒值 //应用:测试程序执行了多长时间 long start = System.currentTimeMillis(); String s = ""; for(int i = 1; i <= 100000; i++) { s += i; } System.out.println(s); long end = System.currentTimeMillis(); System.out.println(end - start); } }
(八)BigDecimal类
一、介绍
用于解决小数运算中,出现的不精确问题
二、使用
1.创建对象
-
public BigDecimal(double val) (不推荐,无法保证小数运算的精确)
-
public BigDecimal(String val) (以字符串形式传入数据)
-
public static BigDecimal valueOf(double val)
2.常用成员方法
-
public BigDecimal add(BigDecimal b) : 加法
-
public BigDecimal subtract(BigDecimal b) : 减法
-
public BigDecimal multiply(BigDecimal b) : 乘法
-
public BigDecimal divide(BigDecimal b) : 除法
-
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) : 除法
注意: 如果使用BigDecimal运算,出现了除不尽的情况,就会出现异常
package com.itheima.bigdecimal; import java.math.BigDecimal; import java.math.RoundingMode; public class BigDecimalDemo { public static void main(String[] args) { BigDecimal bd1 = BigDecimal.valueOf(10.0); BigDecimal bd2 = BigDecimal.valueOf(3.0); System.out.println(bd1.divide(bd2, 2, RoundingMode.HALF_UP)); // 四舍五入 3.33 System.out.println(bd1.divide(bd2, 2, RoundingMode.UP)); // 进一法 3.34 System.out.println(bd1.divide(bd2, 2, RoundingMode.DOWN)); // 直接忽略精确位之后的 3.33 BigDecimal result = bd1.divide(bd2, 2, RoundingMode.HALF_UP); double v = result.doubleValue(); //Math.abs()不接收BigDecimal类型的,因此要先转换为double类型 Math.abs(v); } //常用成员方法 private static void method() { BigDecimal bd1 = BigDecimal.valueOf(0.1); BigDecimal bd2 = BigDecimal.valueOf(0.2); System.out.println(bd1.add(bd2)); System.out.println(bd1.subtract(bd2)); System.out.println(bd1.multiply(bd2)); System.out.println(bd1.divide(bd2)); } }
(九)正则表达式
一、介绍
本质来说就是一个字符串,可以指定一些规则,来校验其他字符串
二、格式
规则:
[ ]:表示单个字符
1.字符类
package regex; public class RegexDemo { public static void main(String[] args) { //[abc] String regex = "[abc]"; System.out.println("a".matches(regex));//true String regex2 = "abc"; System.out.println("a".matches(regex2));//false String regex3 = "[a][b][c]"; //[^abc] System.out.println("abc".matches(regex3));//true String regex4 = "[^abc]"; System.out.println("d".matches(regex4));//true //[a-zA-Z] String regex5 = "[a-zA-Z]"; System.out.println("1".matches(regex5));//false String regex6 = "[a-zA-z0-9]"; System.out.println("1".matches(regex6));//true } }
2.预定义字符类
package regex; public class RegexDemo { public static void main(String[] args) { //"." String regex = "."; System.out.println("1".matches(regex));//true System.out.println("11".matches(regex));//false(数量不匹配) String regex2 = ".."; System.out.println("11".matches(regex2));//true //"\d" \:转义字符 String regex3 = "\\d";//第一个\是转义的意思,第二个\和d一起组成转义字符 System.out.println("1".matches(regex3));//true //"\D" String regex4 = "\\D"; System.out.println("1".matches(regex4));//false System.out.println("a".matches(regex4));//true //"\s" String regex5 = "\\s"; System.out.println(" ".matches(regex5));//true //"\S" String regex6 = "\\S"; System.out.println("1".matches(regex6));//true //"\w" String regex7 = "\\w"; System.out.println("!".matches(regex7));//false //"\W" String regex8 = "\\W"; System.out.println("!".matches(regex8));//true } }
3.贪婪的量词
package regex; public class RegexDemo { public static void main(String[] args) { //"X?" 一次或0次 String regex = "\\d?"; System.out.println("1".matches(regex));//true System.out.println("".matches(regex));//true System.out.println("12".matches(regex));//false //"X*" 零次或多次(任意次数) String regex2 = "\\d*"; System.out.println("1".matches(regex2));//true System.out.println("".matches(regex2));//true System.out.println("12".matches(regex2));//true //"X+" 一次或多次(除0次) String regex3 = "\\d+"; System.out.println("1".matches(regex3));//true System.out.println("".matches(regex3));//false System.out.println("12".matches(regex3));//true //"X{n}" 正好n次 String regex4 = "\\d{3}"; System.out.println("123".matches(regex4));//true System.out.println("1".matches(regex4));//false //"X{n,}" 至少n次 String regex5 = "\\d{3,}"; System.out.println("1".matches(regex5));//false System.out.println("123".matches(regex5));//true System.out.println("1234".matches(regex5));//true //"X{n,m}" 至少n次但不超过m次 String regex6 = "\\d{3,5}"; System.out.println("1".matches(regex6));//false System.out.println("1234".matches(regex6));//true System.out.println("123456".matches(regex6));//false } }
三、案例
QQ号正则: 不能以0开头 全部都是数字 5~12位
手机号正则: 必须是1开头 第二位: 3 4 5 6 7 8 9 全都是数字, 必须是11位
邮箱正则: zhangSan@itcast.cn zhangsan@163.com 123456@qq.com zhangsan@sina.com zhangsan@itcast.qq.com zhangsan@xxx.edu zhangsan@xxx.org
package test; public class RegexTest { public static void main(String[] args) { /* QQ号正则: 不能以0开头 全部都是数字 5~12位 */ String qqRegex = "[1-9]\\d{4,11}"; System.out.println("123456".matches(qqRegex));//true System.out.println("123a456".matches(qqRegex));//false System.out.println("0123456".matches(qqRegex));//false /* 手机号正则: 必须是1开头 第二位: 3 4 5 6 7 8 9 全都是数字, 必须是11位 */ String telRegex = "[1][3-9]\\d{9}"; System.out.println("18803102512".matches(telRegex));//true System.out.println("188a0310251".matches(telRegex));//false System.out.println("12803102512".matches(telRegex));//false System.out.println("08803102512".matches(telRegex));//false /* 邮箱正则: zhang_San@itcast.cn zhangsan@163.com 123456@qq.com zhangsan@sina.com zhangsan@itcast.qq.com zhangsan@xxx.edu zhangsan@xxx.org */ String emailRegex = "\\w+[@][\\w&&[^_]]+(\\.[a-z]{2,3})+"; System.out.println("zhangsan@itcast.qq.com".matches(emailRegex));//true } }
四、String类中与正则有关的常见方法
package regex; public class StringRegexMethod { /* public String replaceAll(String regex,String newStr):按照正则表达式匹配的内容进行替换 */ public static void main(String[] args) { String s = "先帝1创业2未半而中道3崩殂4,今5天下三分6,益州疲弊7,此8诚危急存亡之秋也。然9侍卫之臣不懈于内,忠志之士忘身10于外者,盖追先帝之殊遇11,欲报之于陛下也。诚宜12开张圣听13,以光14先帝遗德,恢弘15志士之气,不宜妄自菲薄16,引喻失义17,以塞忠谏之路也18。\n" + "宫中府中,俱为一体19;陟罚臧否20,不宜异同:若有作奸犯科21及为忠善者22,宜付有司23论其刑赏24,以昭陛下平明之理25;不宜偏私26,使内外异法也27。\n" + "侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯28,是以先帝简拔以遗陛下29:愚以为宫中之事,事无大小,悉以咨之30,然后施行,必能裨补阙漏31,有所广益32。"; //把数字替换为空白字符 s = s.replaceAll("\\d",""); System.out.println(s); } }
五、使用正则表达式爬取信息
package test; import java.util.regex.Matcher; import java.util.regex.Pattern; public class PatternTest { /* 需求:请把下面文本中的电话、邮箱、座机号码、热线都爬取出来 */ public static void main(String[] args) { String data = "来黑马程序员学习Java," + "电话:18666668888,18699997777或者联系" + "邮箱:boniu@itcast.cn 邮箱:bozai@itcast.cn 邮箱2:dlei0009@163.com" + "座机电话:01036517895,010-98951256 " +//"010"是区号,可能是3或4位 "热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090"; //定义爬取正则 String regex = "[1][3-9]\\d{9}|\\w+[@][\\w&&[^_]]+(\\.[a-z]{2,3})+|[0]\\d{2,3}-?\\d{7,8}|400-?\\d{3}-?\\d{4}"; //1.将正则表达式封装为 Pattern 对象 Pattern pattern = Pattern.compile(regex); //2.获取匹配器对象 Matcher matcher = pattern.matcher(data); //3.通过匹配器,从内容中爬取信息 // System.out.println(matcher.find());//返回boolean类型(只能看是否存在) // System.out.println(matcher.group());//调用几次爬取几次,但每次爬取的是一样的,所以不能单独使用,必须先调用find查找,再调用group获取 // // System.out.println(matcher.find()); // System.out.println(matcher.group());//缺点:不明确爬取次数时不好用 while (matcher.find()) { System.out.println(matcher.group()); } } }
运行结果:
(十)时间API
一、Date类
-
代表的是日期和时间
1.常用构造方法
package date; import java.util.Date; public class DateDemo1 { public static void main(String[] args) { //将当前时间,封装为Date日期对象 Date d1 =new Date(); System.out.println(d1); //把时间毫秒值转换成Date日期对象 Date d2 = new Date(1000L); System.out.println(d2); } }
2.常用成员方法
package date; import java.util.Date; public class DateDemo1 { public static void main(String[] args) { //将当前时间,封装为Date日期对象 Date d1 =new Date(); System.out.println(d1); //把时间毫秒值转换成Date日期对象 Date d2 = new Date(1000L); System.out.println(d2); //返回从1970年1月1日00:00:00走到此刻的总的毫秒数 System.out.println(d1.getTime()); //返回从1970年1月1日00:00:00走到d2的总的毫秒数 System.out.println(d2.getTime()); //设置日期对象的时间为当前时间毫秒值对应的时间 //等价于 Date d3 = new Date(0L); Date d3 = new Date(); d3.setTime(0L); System.out.println(d3); } }
二、SimpleDateFormat类
-
用于日期格式化
1.常用构造方法
package format; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo { public static void main(String[] args) { //public SimpleDateFormat() 创建一个日期格式化对象,使用[默认模式] SimpleDateFormat simpleDateFormat = new SimpleDateFormat(); //创建Date对象,封装此刻的时间 Date date = new Date(); //将日期对象,转换为字符串 String result = simpleDateFormat.format(date); System.out.println(result); } }
package format; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo { public static void main(String[] args) { //public SimpleDateFormat(String pattern) 创建一个日期格式化对象[手动指定模式] SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss E a"); //创建Date对象,封装此刻的时间 Date date = new Date(); //将日期对象,转换为字符串 String result = simpleDateFormat.format(date); System.out.println(result); } }
2.常用成员方法
package format; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDateFormatDemo { public static void main(String[] args) throws ParseException { //public final Date parse(String source) 将日期字符串解析为日期对象 String today = "2023年4月8日"; //日期字符串与模式要匹配 SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); Date date = simpleDateFormat.parse(today); System.out.println(date); } }
3.案例
-
需求: 计算你来到了这个世界多少天
package test; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanner; public class DateTest1 { public static void main(String[] args) throws ParseException { //1.键盘录入用户的生日 (日期字符串) Scanner sc = new Scanner(System.in); System.out.println("请输入您的生日:xxxx年x月x日"); String birthday = sc.nextLine(); //2.创建SimpleDateFormat对象,指定模式,用于将日期字符串解析为Date日期对象 (birthdayDate) SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日"); //birthdayDate是生日那一天的日期对象 Date birthdayDate = simpleDateFormat.parse(birthday); //3.创建Date日期对象,封装此刻的时间 (todayDate) Date todayDate = new Date(); //4.long time = todayDate.getTime() - birthdayDate.getTime(); long time = todayDate.getTime() - birthdayDate.getTime(); //5.将毫秒值,转换为天的单位 time / 1000 / 60 / 60 / 24; System.out.println("您已经活了" + time / 1000 / 60 / 60 / 24 + "天"); } }
三、Calendar类
-
代表的是系统此刻时间对应的日历,通过它可以单独获取、修改时间中的年、月、日、时、分、秒等。
-
创建对象:Calendar是一个抽象类,不能直接创建对象
1.常用构造方法
public static Calendar getInstance():获取当前时间的日历对象
package calendar; import java.util.Calendar; public class CalendarDemo { public static void main(String[] args) { //Calendar c:抽象类 //Calendar.getInstance():获取的是子类对象 Calendar c = Calendar.getInstance(); System.out.println(c); } } //运行结果: //java.util.GregorianCalendar[time=1680937964008,areFieldsSet=true,areAllFieldsSet=true, // lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0, // useDaylight=false,transitions=31,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1, // YEAR=2023,MONTH=3,WEEK_OF_YEAR=14,WEEK_OF_MONTH=2,DAY_OF_MONTH=8,DAY_OF_YEAR=98,DAY_OF_WEEK=7, // DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=3,HOUR_OF_DAY=15,MINUTE=12,SECOND=44,MILLISECOND=8, // ZONE_OFFSET=28800000,DST_OFFSET=0]
2.常用成员方法
-
Calendar.YEAR:获取年份信息
-
Calendar.MONTH:月份是0~11,记得做+1操作
-
Calendar.DAY_OF_MONTH:获取日
-
Calendar.DAY_OF_WEEK:获取星期,需要提前设计一个数组
-
Calendar.DAY_OF_YEAR:获取一年中的第几天
①get方法
public int get(int field)取日历中的某个字段信息
package calendar; import java.util.Calendar; public class CalendarDemo { public static void main(String[] args) { //Calendar c:抽象类 //Calendar.getInstance():获取的是子类对象 //1.public int get(int field):获取当前时间的日历对象 Calendar c = Calendar.getInstance(); //2.调用get方法,获取指定字段的信息(get方法的参数:Calendar类中的静态常量) int year = c.get(Calendar.YEAR); System.out.println(year); //注意:Calendar类的月份是 0~11,想要获取常规的月份,需要对结果进行 + 1操作 int month = c.get(Calendar.MONTH); System.out.println(month + 1); int day = c.get(Calendar.DAY_OF_MONTH); System.out.println(day); char[] weeks = {' ','日','一','二','三','四','五','六'}; // 0 1 2 3 4 5 6 7 //注意:英语中Sunday是一周中的第一天 int weekIndex = c.get(Calendar.DAY_OF_WEEK); System.out.println(weeks[weekIndex]); int dayOfYear = c.get(Calendar.DAY_OF_YEAR); System.out.println(dayOfYear); } }
②set方法
public void set(int field,int value):修改日历的某个字段信息
package calendar; import java.util.Calendar; public class CalendarDemo { public static void main(String[] args) { Calendar c = Calendar.getInstance(); c.set(Calendar.YEAR,2022); c.set(2004,8,16); System.out.println(c.get(Calendar.YEAR)); } }
③add方法
public void add(int field,int amount):为某个字段增加/减少指定的值
package calendar; import java.util.Calendar; public class CalendarDemo { public static void main(String[] args) { Calendar c = Calendar.getInstance(); c.add(Calendar.YEAR,-1); System.out.println(c.get(Calendar.YEAR)); } }
3.案例
①疯狂星期四
package test; import java.util.Calendar; public class CalendarTest1 { /* 需求 : 使用程序判断出 2050年3月1日 是否是疯狂星期四 */ public static void main(String[] args) { // 1. 获取日期对象 (此刻的时间) Calendar c = Calendar.getInstance(); // 2. 调用set方法, 将时间设置为 2050年3月1日 c.set(2050, 2, 1); char[] weeks = {' ', '日', '一', '二', '三', '四', '五', '六'}; // 3. 获取星期 int weekIndex = c.get(Calendar.DAY_OF_WEEK); if(weeks[weekIndex] == '四'){ System.out.println("今天是疯狂星期四, 我要奢侈一把~"); } else { System.out.println("今天不是疯狂星期四, 吃不起KFC"); } } }
②一年中的第多少天
package test; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Scanner; public class CalendarTest2 { /* 需求 : 键盘录入一个日期字符串, 程序输出这个日期是一年中的第多少天 1. 使用SimpleDateFormat, 将日期字符串转换为日期对象 2. 将日期对象, 转换为Calendar对象 3. 调用get方法, 获取一年中的第几天 */ public static void main(String[] args) throws ParseException { Scanner sc = new Scanner(System.in); System.out.println("请输入:"); String dateContent = sc.nextLine(); // 1. 使用SimpleDateFormat, 将日期字符串转换为日期对象 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日"); Date date = dateFormat.parse(dateContent); // 2. 将日期对象, 转换为Calendar对象 Calendar c = Calendar.getInstance(); c.setTime(date); // 3. 调用get方法, 获取一年中的第几天 int dayOfYear = c.get(Calendar.DAY_OF_YEAR); System.out.println("是这一年中的第:" + dayOfYear + "天"); } }
四、JDK 8+ 时间类
1.区别
package distinction; import java.time.LocalDateTime; import java.util.Date; public class Test { public static void main(String[] args) { // JDK8版本之前 : // 都是可变对象, 修改后会丢失最开始的时间信息 Date time = new Date(); System.out.println("修改前获取时间: " + time); // 修改 time.setTime(1000); System.out.println("修改后获取时间:" + time); System.out.println("--------------------"); // JDK8版本之后 : // 都是不可变对象, 修改后会返回新的时间对象, 不会丢失最开始的时间 LocalDateTime now = LocalDateTime.now(); System.out.println("修改前获取时间:" + now); LocalDateTime afterTime = now.withYear(2008); System.out.println("修改后获取时间: " + afterTime); System.out.println("修改后获取时间: " + now); } }
2.日历类
①获取对象
package jdk8; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; public class Demo { /* ------------------------------------------ LocalDate、LocalTime、LocalDateTime 对象的创建方式: 1. now() : 当前时间 2. of(...) : 设置时间 ------------------------------------------ LocalDateTime转换LocalDate, LocalTime 1. toLocalDate(); 2. toLocalTime() LocalDate localDate = now.toLocalDate(); */ public static void main(String[] args) { //获取此刻的时间对象 LocalDate localDateTime now = LocalDateTime.now(); System.out.println(now); System.out.println(now.getYear() + "年"); System.out.println(now.getMonth() + "月"); System.out.println(now.getMonthValue() + "月"); System.out.println(now.getDayOfMonth() + "日"); System.out.println(now.getHour() + "时"); System.out.println(now.getMinute() + "分"); System.out.println(now.getSecond() + "秒"); System.out.println(now.getNano() + "纳秒"); // 获取指定的时间对象 LocalDateTime of = LocalDateTime.of(2008,8,8,8,8); System.out.println(of); } }
localDateTime:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)-->重点
package com.itheima.jdk8.p1_local_date_time; import java.time.LocalDateTime; public class LocalDateTimeDemo { public static void main(String[] args) { // 日期 时间 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()); } }
localTime:代表本地时间(时、分、秒、纳秒)
package com.itheima.jdk8.p2_local_time; import java.time.LocalTime; public class LocalTimeDemo { public static void main(String[] args) { // 1、获取本地时间对象 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); } }
localDate:代表本地日期(年、月、日、星期)
package com.itheima.jdk8.p3_local_date; import java.time.LocalDate; public class LocalDateDemo { public static void main(String[] args) { // 1、获取本地日期对象。 LocalDate nowDate = LocalDate.now(); System.out.println("今天的日期:" + nowDate); int year = nowDate.getYear(); System.out.println("year:" + year); int month = nowDate.getMonthValue(); System.out.println("month:" + month); int day = nowDate.getDayOfMonth(); System.out.println("day:" + day); // 当年的第几天 int dayOfYear = nowDate.getDayOfYear(); System.out.println("dayOfYear:" + dayOfYear); // 星期 System.out.println("星期:" + nowDate.getDayOfWeek()); System.out.println("星期:" + nowDate.getDayOfWeek().getValue()); // 月份 System.out.println("月份:" +nowDate.getMonth()); System.out.println("月份:" + nowDate.getMonth().getValue()); } }
②修改年月日时分秒相关的方法
-
注意:LocalDateTime、LocalDate、LocalTime都是不可变的,下列方法返回的是一个新的对象
package com.itheima.jdk8.p4_update; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.MonthDay; public class UpdateTimeDemo { public static void main(String[] args) { LocalDateTime nowTime = LocalDateTime.now(); // 当前时间 System.out.println(nowTime); // minus : 减去 // minusYears(年), minusMonths(月), minusDays(日), minusWeeks(周), minusHours(时), minusMinutes(分), minusSeconds(秒), minusNanos(纳秒) System.out.println("减一小时:" + nowTime.minusHours(1)); System.out.println("减一分钟:" +nowTime.minusMinutes(1)); System.out.println("减一秒钟:" +nowTime.minusSeconds(1)); System.out.println("减一纳秒:" +nowTime.minusNanos(1)); System.out.println("对比时间, 确定方法返回的都是新的实例 >>>>>> " +nowTime); System.out.println("----------------"); // plus : 加 // plusYears(年), plusMonths(月), plusDays(日), plusWeeks(周), plusHours(时), plusMinutes(分), plusSeconds(秒), plusNanos(纳秒) System.out.println("加一小时:" + nowTime.plusHours(1)); System.out.println("加一分钟:" + nowTime.plusMinutes(1)); System.out.println("加一秒钟:" + nowTime.plusSeconds(1)); System.out.println("加一纳秒:" + nowTime.plusNanos(1)); System.out.println("---------------"); // with : 这里体现出的是,设置效果 System.out.println("修改的效果:"); //withYear(年), withMonth(月), withDayOfMonth(日), withHour(时), withMinute(分), withSecond(秒), withNano(纳秒) System.out.println(nowTime.withYear(2008)); System.out.println(nowTime.withMonth(8)); System.out.println(nowTime.withDayOfMonth(8)); System.out.println(nowTime.withHour(8)); System.out.println(nowTime.withMinute(8)); System.out.println(nowTime.withSecond(8)); System.out.println(nowTime.withNano(8)); System.out.println("---------------"); LocalDate myDate = LocalDate.of(2008, 8, 8); LocalDate nowDate = LocalDate.now(); //2008-08-08是否在nowDate之前? System.out.println(myDate + "是否在" + nowDate + "之前? " + myDate.isBefore(nowDate)); //2008-08-08是否在nowDate之后? System.out.println(myDate + "是否在" + nowDate + "之后? " + myDate.isAfter(nowDate)); System.out.println("---------------------------"); // 判断两个时间是否相同 System.out.println(myDate.equals(nowDate)); } }
运行结果:
3.日期格式化类
-
DateTimeFormatter:用于时间的格式化和解析
获取对象
package com.itheima.jdk8.p5_date_time_formatter; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class DateTimeFormatterDemo { /* 用于时间的格式化和解析: 1. 对象的获取 : static DateTimeFormatter ofPattern(格式) : 获取格式对象 2. 格式化 : String format(时间对象) : 按照指定方式格式化 3. 解析 : LocalDateTime.parse("解析字符串", 格式化对象); LocalDate.parse("解析字符串", 格式化对象); LocalTime.parse("解析字符串", 格式化对象); */ public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); System.out.println("格式化之前:" + now); // 获取格式化对象 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年M月d日"); // 格式化 String result = formatter.format(now); System.out.println("格式化之后:" + result); // 解析 String time = "2008年08月08日"; LocalDate parse = LocalDate.parse(time, formatter); System.out.println(parse); } }
4.时间类
-
用于表示时间的对象,类似之前所学习的Date
package com.itheima.jdk8.p6_instant; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; public class InstantDemo1 { /* Instant类 : 用于表示时间的对象, 类似之前所学习的Date */ public static void main(String[] args) { Instant now = Instant.now(); System.out.println("当前的时间戳是:" + now);//有时差 ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.of("Asia/Shanghai")); System.out.println(zonedDateTime); } }
①ZoneId:时区类
常见方法:
package com.itheima.jdk8.p7_Zone; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Set; public class ZoneIdDemo { /* ZoneId类 : 时区类 常见方法 : 1. static Set<String> getAvailableZoneIds() : 获取Java中支持的所有时区 2. static ZoneId systemDefault() : 获取系统默认时区 3. static ZoneId of(String zoneId) : 获取一个指定时区 */ public static void main(String[] args) { // 获取Java中支持的所有时区 Set<String> set = ZoneId.getAvailableZoneIds(); System.out.println(set); System.out.println(set.size()); System.out.println("-----------------------"); // 获取系统默认时区 ZoneId zoneId = ZoneId.systemDefault(); System.out.println(zoneId); System.out.println("-----------------------"); // 获取一个指定时区 ZoneId of = ZoneId.of("Africa/Nairobi"); System.out.println(of); ZonedDateTime zonedDateTime = Instant.now().atZone(of); System.out.println(zonedDateTime); } }
②Instant:时间戳
package com.itheima.jdk8.p6_instant; import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; public class InstantDemo2 { /* Instant类常见方法 : static Instant now() : 获取当前时间的Instant对象(标准时间) static Instant ofXxxx(long epochMilli) : 根据(秒/毫秒/纳秒)获取Instant对象 ZonedDateTime atZone(ZoneId zone) : 指定时区 boolean isXxx(Instant otherInstant) : 判断系列的方法 Instant minusXxx(long millisToSubtract) : 减少时间系列的方法 Instant plusXxx(long millisToSubtract) : 增加时间系列的方法 */ public static void main(String[] args) { // 获取当前时间的Instant对象(标准时间) Instant now = Instant.now(); System.out.println("当前时间为(世界标准时间):" + now); System.out.println("------------------"); // 根据(秒/毫秒/纳秒)获取Instant对象 Instant instant1 = Instant.ofEpochMilli(1000); Instant instant2 = Instant.ofEpochSecond(5); System.out.println(instant1); System.out.println(instant2); System.out.println("------------------"); // 指定时区 ZonedDateTime zonedDateTime = Instant.now().atZone(ZoneId.systemDefault()); System.out.println("带时区的时间:" + zonedDateTime); System.out.println("------------------"); // 判断系列的方法 System.out.println(now.isBefore(instant1)); System.out.println(now.isAfter(instant1)); System.out.println("------------------"); // 减少时间系列的方法 System.out.println("减1000毫秒:" + now.minusMillis(1000)); System.out.println("减5秒钟:" + now.minusSeconds(5)); System.out.println("------------------"); // 增加时间系列的方法 System.out.println("加1000毫秒:" + now.plusMillis(1000)); System.out.println("加5秒钟:" + now.plusSeconds(5)); System.out.println("------------------"); } }
③ZoneDataTime:带时区的时间对象
package com.itheima.jdk8.p7_Zone; import java.time.ZoneId; import java.time.ZonedDateTime; public class ZoneDateTimeDemo { /* ZoneDataTime 带时区的时间对象 : static ZonedDateTime now() : 获取当前时间的ZonedDateTime对象 static ZonedDateTime ofXxxx(...) : 获取指定时间的ZonedDateTime对象 ZonedDateTime withXxx(时间) : 修改时间系列的方法 ZonedDateTime minusXxx(时间) : 减少时间系列的方法 ZonedDateTime plusXxx(时间) : 增加时间系列的方法 */ public static void main(String[] args) { // 获取当前时间的ZonedDateTime对象 ZonedDateTime now = ZonedDateTime.now(); System.out.println(now); System.out.println("--------------------------"); // 获取指定时间的ZonedDateTime对象 ZonedDateTime of = ZonedDateTime.of (2008, 8, 8, 8, 8, 8, 8, ZoneId.systemDefault()); System.out.println(of); System.out.println("--------------------------"); // 修改时间系列的方法 System.out.println(now.withYear(2008)); System.out.println(now.withMonth(8)); System.out.println(now.withDayOfMonth(8)); System.out.println("--------------------------"); // 减少时间系列的方法 System.out.println(now.minusYears(1)); System.out.println(now.minusMonths(1)); System.out.println(now.minusDays(1)); System.out.println("--------------------------"); // 增加时间系列的方法 System.out.println(now.plusYears(1)); System.out.println(now.plusMonths(1)); System.out.println(now.plusDays(1)); } }
5.工具类
①Period:用于计算两个“日期”间隔(年、月、日)
package com.itheima.jdk8.p8_interval; import java.time.LocalDate; import java.time.Period; /** * Period计算日期间隔 (年月日) */ public class PeriodDemo { public static void main(String[] args) { // 此刻年月日 LocalDate today = LocalDate.now(); System.out.println(today); // 昨天年月日 LocalDate otherDate = LocalDate.of(2023, 4, 7); System.out.println(otherDate); //Period对象表示时间的间隔对象 Period period = Period.between(today, otherDate); // 第二个参数减第一个参数 System.out.println(period.getYears()); // 间隔多少年 System.out.println(period.getMonths()); // 间隔的月份 System.out.println(period.getDays()); // 间隔的天数 System.out.println(period.toTotalMonths()); // 总间隔月份 } }
②Duration:用于计算两个“时间”间隔(秒,纳秒)
package com.itheima.jdk8.p8_interval; import java.time.Duration; import java.time.LocalDateTime; /** * Duration计算日期间隔 (时分秒) */ public class DurationDemo { public static void main(String[] args) { // 此刻日期时间对象 LocalDateTime today = LocalDateTime.now(); System.out.println(today); // 昨天的日期时间对象 LocalDateTime otherDate = LocalDateTime.of(2023, 4 , 7, 0, 0, 0); System.out.println(otherDate); Duration duration = Duration.between(otherDate, today); // 第二个参数减第一个参数 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()); // 两个时间差的纳秒数 } }
③ChronoUnit:用于计算两个“日期”间隔(重点)
package com.itheima.jdk8.p8_interval; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; /** * ChronoUnit可用于在单个时间单位内测量一段时间,这个工具类是最全的了,可以用于比较所有的时间单位 */ public class ChronoUnitDemo { public static void main(String[] args) { // 本地日期时间对象:此刻的 LocalDateTime today = LocalDateTime.now(); System.out.println(today); // 生日时间 LocalDateTime birthDate = LocalDateTime.of(2023, 4, 7, 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)); } }
6.案例
package com.itheima.test; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.Scanner; public class CalculateAgeTest { /* 需求 : 键盘录入用户生日, 计算出用户的实际年龄. */ public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入您的生日: "); String birthday = sc.nextLine(); // 1. 将键盘录入的日期字符串, 转换为日期对象 (生日那一天的) LocalDate birthdayDate = LocalDate.parse(birthday, DateTimeFormatter.ofPattern("yyyy年M月d日")); // 2. 获取今天的日期对象 LocalDate now = LocalDate.now(); // 3. 计算时间间隔 long result = ChronoUnit.YEARS.between(birthdayDate, now); System.out.println(result); } }