String类和时间类

目录

(一)数据结构

一、基本数据类型

二、自动装箱、自动拆箱

1.包装类

(二)常用API

一、介绍

二、API帮助文档的使用流程

三、Scanner键盘录入字符串

1.String next()和String nextLine()

2.弊端

3.解决方案

(三)String类

一、特点

二、String类常见构造方法

1.public String()

2.public String(char[] chs)

3.public String(String original)

4.总结

三、常见面试题

四、字符串比较内容-String类中用于比较的方法

1.将此字符串与指定的对象比较

2.将此类String与另一个String比较,不考虑大小写

3.案例-用户登录

五、String字符串的遍历

1.将此字符串转换为一个新的字符数组(效率更高)

2.返回指定索引处的char值

3.案例-统计字符次数

六、String字符串的截取方法

1.根据传入的索引开始截取,截取到字符串的末尾

2.根据传入的开始和结束索引,对字符串做截取(包含头,不包含尾)

3.案例-手机号屏蔽

七、String字符串的替换方法

1.新值替换旧值

2.案例-敏感词替换

八、String字符串的切割方法

根据传入的字符串作为规则,切割当前字符串

(四)StringBuilder类

1.好处

2.介绍

3.构造方法

①public StringBuilder()

②public StringBuilder(String str)

4.常用成员方法

①public StringBuilder append(任意类型)

②public StringBuilder reverse()

③public int length()

④public String toString()

5.案例

①String和StringBuilder的转换

②字符串拼接

6.String和StringBuilder效率对比

(五)Object类

一、toString方法

public String toString()

二、equals方法

public Boolean equals(Object o)

(六)Math类

一、介绍

二、方法演示

(七)System类

一、介绍

二、方法演示

(八)BigDecimal类

一、介绍

二、使用

1.创建对象

2.常用成员方法

(九)正则表达式

一、介绍

二、格式

1.字符类

2.预定义字符类

3.贪婪的量词

三、案例

四、String类中与正则有关的常见方法

五、使用正则表达式爬取信息

(十)时间API

一、Date类

1.常用构造方法

2.常用成员方法

二、SimpleDateFormat类

1.常用构造方法

2.常用成员方法

3.案例

三、Calendar类

1.常用构造方法

2.常用成员方法

3.案例

四、JDK 8+ 时间类

1.区别

2.日历类

3.日期格式化类

4.时间类

5.工具类

6.案例


(一)数据结构

一、基本数据类型

数据类型关键字内存占用/字节
整数byte(-128~127)1
short2
int(默认)4
long8
浮点数float4
double(默认)8
字符char2
布尔boolean1
  1. 整数类型:首选int,如果发现int装不下了,将类型换为long,定义long类型变量需要加入L/l标识

  2. 小数类型:首选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.包装类

①介绍

基本数据类型,包装成(变成引用数据类型)

变成类,就可以创建对象了,对象就可以调用方法方便地解决问题了

②基本数据类型对应的包装类

基本数据类型引用数据类型
byteByte
shortShort
intInteger
longLong
charCharacter
floatFloat
doubleDouble
booleanBoolean

③Integer类

  • 将基本数据类型手动包装为类

手动装箱与手动拆箱

  • 手动装箱: 调用方法,手动将基本数据类型,包装成类

    1. public Integer(int value) : 通过构造方法(不推荐)

    2. 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
    }
}

三、案例

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);
 
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值