Java笔记_11(常用API)

这篇具有很好参考价值的文章主要介绍了Java笔记_11(常用API)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、常用的API

1.1、Math

  • 是一个帮助我们进行数学计算的工具类
  • 私有化构造方法,所有的方法都是静态的

Math类的常用方法

方法名 说明
public static int abs(int a) 获取参数绝对值
public static doublie ceil(double a) 向上取整
public static doublie floor(double a) 向下取整
public static int round(float a) 四舍五入
public static int max(int a,int b) 获取两个int值中的较大值
public static doublie pow(double a,double b) 返回a的b次幂的值
public static doublie random() 返回为double的随机值,范围[0.0,1.0)
public static doublie sqrt(double a) 返回平方根
public static doublie cbrt(double a) 返回立方根

Math练习

  • 判断是否为质数
public static boolean isProme(int a){

        for (int i = 1; i <Math.sqrt(a) ; i++) {
            if(a%i==0){
                return false;
            }
        }
        return true;
    }
  • 获取四叶玫瑰数
int count = 0;
        for (int i = 1000; i < 9999; i++) {
            int ge = i%10;
            int shi = i/10%10;
            int bai = i/100%10;
            int qian = i/1000%10;

            double sum = Math.pow(ge,4)+Math.pow(shi,4)+Math.pow(bai,4)+Math.pow(qian,4);

            if(sum==i){
                count++;
                System.out.println(i);
            }
        }
        System.out.println(count);

1.2、System

  • System也是工具类,提供一些与系统相关的方法

计算机中的时间原点

1970年1月1日 08:00:00
我国在东八区,有八小时的时差

原因:
1969年8月,贝尔实验室的程序员肯汤普逊利用妻儿离开一个月的机会。开始着手创造一个全新的革命性的操作系统。他使用B编译语言在老旧的PDP-7机器上开发出了Unix的一个版本。随后,汤普逊和同事丹尼斯里奇改进了B语言,开发出了C语言,重写了UNIX。

1970年1月1日 算C语言的生日

  • 1秒 = 1000毫秒
  • 1毫秒 = 1000微秒
  • 1微秒 = 1000纳秒
方法名 说明
public static void exit(int status) 终止当前运行的Java虚拟机
public static long currentTimeMillis() 返回当前系统的时间毫秒值形式
public static void arraycopy(数据源数组,起始索引,目的地索引,起始索引,拷贝个数) 数组拷贝

使用arraycopy时注意事项:

  1. 如果数据源数组和目的地数组两者都是基本数据类型,两者的数据类型必须保持一致,否则会进行报错
  2. 在拷贝的时候需要考虑数组的长度,如果超出范围也会报错
  3. 如果数据源数组和目的地数组都是引用数据类型,那么子类类型可以赋值给父类类型

1.3、Runtime

  • Runtime表示当前虚拟机的运行环境
方法名 说明
public static Runtime getRuntime() 当前系统的运营环境对象
public void exit(int status) 停止虚拟机
public int availableProcessors() 获得CPU的线程数
public long maxMemory() JVM能从系统中获取总内存大小(单位byte)
public long totalMemory() JVM已经从系统中获取总内存大小(单位byte)
public long freeMemory() JVM剩余内存大小(单位byte)
public Process exec(String command) 运行cmd命令

exec命令关机 shutdown(加上参数才能执行)

  1. -s :默认在1分钟之后关机
  2. -s -t 指定时间:指定关机时间
  3. -a :取消关机操作
  4. -r :关机并重启

1.4、Object

  • Object是Java中的顶级父类。所有的类都直接或间接的继承于Object类。
  • Object类中的方法可以被所有子类访问,所以我们要学习Object类和其中的方法
方法名 说明
public String toString() 返回对象的字符串表示形式
public boolean equals(object obj) 比较两个对象是否相等
protected object clone(int a) 对象克隆

println():方法

  • 参数:表示打印的对象
  • 核心逻辑:当我们打印一个对象的时候,底层会调用对象的toString方法,把对象变成字符串。然后再打印在控制台上,打印完毕换行处理。

toString方法结论:

  1. 如果我们打印一个对象,想要看到属性值的话,那么就重写tostring方法就可以了。
  2. 在重写的方法中,把对象的属性值进行拼接。

equals方法结论:

  1. 如果没有重写equals方法,那么默认使用object中的方法进行比较,比较的是地址值是否相等
  2. 一般来讲地址值对于我们意义不大,所以我们会重写,重写之后比较的就是对象内部的属性值了。

String中的equals方法

  • 先判断参数是否为字符串如果是字符串,再比较内部的属性
  • 但是如果参数不是字符串,直接返回false

StringBulider中的equals方法

  • 在StringBuilder当中,没有重写equals方法使用的是object中的在Object当中默认是使用==号比较两个对象的地址值

1.5、浅克隆、深克隆

  • 把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制

细节:

方法在底层会帮我们创建一个对象,并把原对象中的数据拷贝过去

书写细节:

  1. 重写Object中的clone方法
  2. 让javabean类实现Cloneable接口
  3. 创建原对象并调用clone就可以了。

Cloneable

  • 如果一个接口里面没有抽象方法表示当前接口是一个标志性接口,现在Cloneable表示一旦实现了,那么当前类的对象就可以被克隆
  • 浅克隆
    Java笔记_11(常用API)
    Object中的克隆是浅克隆
    重写的代码块
protected Object clone() throws CloneNotSupportedException{
        //调用父类中的clone方法
        //相当于让java帮我们克隆一个对象,并把克隆之后的对象返回
        return super clone();
    }
  • 深克隆

Java笔记_11(常用API)
重写的clone()方法

protected Object clone() throws CloneNotSupportedException{
        //调用父类中的clone方法
        //相当于让java帮我们克隆一个对象,并把克隆之后的对象返回
        int[] data = this.data;
        int[] data2 = new int[data.length];

        for (int i = 0; i < data.length; i++) {
            data2[i] = data[i];
        }
        User u =(User) super.clone();
        u.data = data2;
        return u;
    }

1.6、对象工具类的Objects

方法名 说明
public static boolean equals(Object a,Object b) 先做非空判断,比较两个对象
public static boolean isNull(Object obj) 判断对象是否为null,为null返回true,反之
public static boolean nonNull(Object obj) 判断对象是否为null,跟isNull的结果相反

细节:

  1. 方法的底层会判断 第一个对象 是否为null,如果为null,直接返回false
  2. 如果 第一个对象 不为null,那么就利用 第一个对象 再次调用equals方法
  3. 此时 第一个对象设置的对象 类型,所以最终还是会调用 设置的对象 中的equals方法。
  4. 如果没有重写,比较地址值,如果重写了,就比较属性值。

1.7、BigInteger(大整数)

BigInteger构造方法

方法名 说明
public BigInteger(int num,Random rnd) 获取随机大的整数,范围:[0~2的num次方-1]
public BigInteger(String val) 获取指定的大整数(字符串中必须是整数,否则会报错)
public BigInteger(String val,int radix) 获取指定进制的大整数(字符串中的数字必须与进制吻合)
public static BigInteger valueOf(long val) 静态方法获取BigInteger的对象,内部有优化
  • 对象一旦创建,内部记录的值不能发生改变
  • valueOf(long val)方法中会对 -16~16 之间的值进行优化,会创建好这些数字的对象,当赋值在这个范围内使用==号对比两个对象得到的是true

BigInteger常见成员方法

方法 说明
public BigInteger add(BigInteger val) 加法
public BigInteger subtract(BigInteger val) 减法
public BigInteger multiply(BigInteger val) 乘法
public BigInteger divide(BigInteger val) 除法,获取商
public BigInteger[ ] divideAndRemainder(BigInteger val) 除法,获取商和余数(数组0索引是商,1索引是余数)
public boolean equals(Object x) 比较是否相同
public BigInteger pow(int exponent) 次幂
public BigInteger max/min(BigInteger val) 返回较大值/较小值
public int intValue(BigInteger val) 转为int类型整数,超出范围数据有误

1.8、BigDecimal(大小数)

BigDecimal的作用

  • 用于小数的精确计算
  • 用来表示很大的小数

BigDecimal的构造方法

方法 说明
public BigDecimal( double val) 通过double来获得一个小数 (得到的小数有可能不精确)
public BigDecimal( String val) 通过String获得一个小数
public static BigDecimal valueOf( double val) 静态方法创建一个对象

细节:

  1. 如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
  2. 如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
  3. 如果我们传递的是0~10之间的整数,包含0,包含10,那么方法会返回已经创建好的对象,不会重新new

BigDecimal的使用

方法名 说明
public static BigDecimal valueof(double val) 获取对
public BigDecimal add(BigDecimal val) 加法
public BigDecimal subtract(BigDecimal val) 减法
public BigDecimal multiply(BigDecimal val) 乘法
public BigDecimal divide(BigDecimal val) 除法
public BigDecimal divide(BigDecimal val,精确几位,舍入模式) 除法

舍入模式(举例):

  • UP:远离零方向舍入的舍入模式
  • DOWN:向零方向舍入的舍入模式
  • CEILING:向正无限大方向舍入的舍入模式
  • FLOOR:向负无限大方向舍入的舍入模式
  • HALF_UP:小数距离两个数之间距离相等时向上舍入
  • HALF_DOWN:小数距离两个数之间距离相等时向下舍入

二、正则表达式

2.1、正则表达式基础知识

正则表达式的作用:

  1. 校验字符串是否满足规则
  2. 在一段文本中查找满足要求的内容

字符类(只能匹配一个字符)

字符 作用
[abc] 只能是a, b,或c
[^abc] 除了a, b, c之外的任何字符
[a-zA-Z] a到zA到Z,包括(范围)
[a-d[m-p]] a到d,或m到p
a-z&&[def] a-z和def的交集。为: d, e, f
[a-z&&[^bc]] a-z和非bc的交集。(等同于[ad-z])
[a-z&&[^m-p]] a到z和除了m到p的交集。(等同于[a-lq-z])

细节:
如果要求两个范围的交集,那么需要写符号&&
如果写成了一个&,那么此时&表示就不是交集了,而是一个简简单单的&符号(没有任何含义)

预定义字符(只匹配一个字符)

字符 作用
. 任何字符
\d 一个数字:[0-9]
\D 非数字:[^0-9]
\s 一个空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w [a-zA-Z_0-9]英文、数字、下划线
\W [^\w]一个非单词字符

\在Java中是转义字符
\\表示前面的\是一个转义字符,改变了后面\原本的含义,把他变成了一个普普通通的\

数量词

字符 作用
X? X,一次或0次
X* X,零次或多次
X+ X,一次或多次
x{n} X,正好n次
X{n,} X,至少n次
X{n,m} X,至少n但不超过m次

2.2、正则表达式-练习1

Java笔记_11(常用API)

package API_.RegexDome;

public class Test1 {
    public static void main(String[] args) {
        //验证手机号码  13112345678 17665063261 13112345678
        String regex1 = "1\\d{10}";

        System.out.println("13112345678".matches(regex1));
        System.out.println("17665063261".matches(regex1));
        System.out.println("13112345678".matches(regex1));
        System.out.println("131123456782".matches(regex1));

        System.out.println("-------------------------------------------------");
        //验证座机电话号码 020-2324242 02122442 027-42424 0712-3242434

        String regex2 = "0\\d{2,3}-?[1-9]\\d{4,9}";
        System.out.println("020-2324242".matches(regex2));
        System.out.println("02122442".matches(regex2));
        System.out.println("027-42424".matches(regex2));
        System.out.println("0712-3242434".matches(regex2));

        System.out.println("-------------------------------------------------");
        //验证邮箱号码 3232323@qq.com   zhangsan@itcast.cnn   dlied0009@163.com   dle13121@pci.com.cn

        String regex3 = "\\w+@[\\w&&[^_]]{2,6}(\\.[a-zA-Z]{2,3}){1,2}";
        System.out.println("3232323@qq.com".matches(regex3));
        System.out.println("zhangsan@itcast.cnn".matches(regex3));
        System.out.println("dlied0009@163.com".matches(regex3));
        System.out.println("dle13121@pci.com.cn".matches(regex3));

    }
}

2.3、正则表达式-练习2

Java笔记_11(常用API)

  • (?i)可以忽略后面字母的大小写
  • 编写正则的小心得
    1. 按照正确的数据进行拆分
    2. 找每一部分的规律,并编写正则表达式
    3. 把每一部分的正则拼接在一起,就是最终的结果
    4. 书写的时候:从左到右去书写。
package API_.RegexDome;

public class Test2 {
    public static void main(String[] args) {
        //用户名要求
        String regex1 = "\\w{4,16}";

        System.out.println("zhangsan_123".matches(regex1));
        System.out.println("--------------------------------------------");

        //身份证号码验证
        String regex2 = "[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]";

        System.out.println("411423200006012222".matches(regex2));
    }
}

2.4、爬虫

Pattern类:表示正则表达式
Matcher类:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。

package API_.RegexDome;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test3 {
    public static void main(String[] args) {
        String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11," +
                "因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
        //获取正则表达式对象
        Pattern p = Pattern.compile("Java\\d{0,2}");
        //获取文本匹配器对象
        //m:文本匹配器对象
        //str:大串
        //p:规则
        //m要在str中找到符合p规则的小串
        Matcher m = p.matcher(str);

        //拿着文本匹配器从头开始读取,寻找是否有满足规则的字串
        //如果没有,方法返回false
        //如果有,返回true,在底层记录字串的其实索引和结束索引+1
        boolean b = m.find();
        //方法底层会根据find方法记录的索引进行字符串的截取
        // subString(起始索引,结束索引);包头不包尾
        //(0,4)但是不包含4索引
        String s1 = m.group();
        System.out.println(s1);

    }
}

2.5、带条件爬取、贪婪爬取和识别正则的两个方法

  • 定义正则表达式
    • ?理解为前面的数据
    • =表示在Java后面要跟随的数据
    • :表示获取的是所有的与之类型相关的字符
    • !表示获取去除带有后面跟随数据的相关字符串
    • 获取的数据是括号之前的
package API_.RegexDome;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test4 {
    public static void main(String[] args) {
        /*需求1:爬取版本号为8,11,17的Java文本,但是只要java,不显示版本号。
        需求2:爬取版本号为8,11,17的Java文本。正确爬取结果为: Java8 Java11 Java17 Java17
        需求3:爬取除了版本号为8,11,17的Java文本,

        */

        String s = "java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和JAva11," +
                "因为这两个是长期支持版本,下一个长期支持版本是JAVa17,相信在未来不久JAVA17也会逐渐登上历史舞台";

        //需求一:
        String regex1 = "((?i)java)(?=8|11|17)";//(?i)忽略大小写
        //需求二:
        String regex2 = "((?i)java)(8|11|17)";
        String regex3 = "((?i)java)(?:8|11|17)";

        Pattern p =Pattern.compile(regex3);
        Matcher m = p.matcher(s);

        while (m.find()){
            System.out.println(m.group());
        }

        
    }
}

贪婪爬取:尽可能地多获取数据
非贪婪爬取:尽可能地少获取数据

  • Java中,默认的就是贪婪爬取
  • 在定义的正则中有出现+时在其后面加上?即可使其变为非贪婪爬取

正则表达式在字符串方法中的使用

方法名 说明
public String[ ] matches (String regex) 判断字符串是否满足正则表达式的规则
public String replaceAll(String regex, String newStr) 按照正则表达式的规则进行替换
public String[ ] split(String regex) 按照正则表达式的规则切割字符串
package API_.RegexDome;

public class Test5 {
    public static void main(String[] args) {
        String s = "例阿斯顿asdasdasda啊实打实的asdadas";

        String result = s.replaceAll("[\\w&&[^_]]+","vs");

        System.out.println(result);

        String[] arr  = s.split("[\\w&&[^_]]+");
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

2.6、捕获分组和非捕获分组

  • 分组就是一个小括号
    • 每一组都是有组号的,也就是序号
    • 规则1:从1开始,连续不间断
    • 规则2:以左括号为基准,最左边的是第一组,其次是第二组,以此类推
    • \\组号将某一组的数据拿出来再用一次
package API_.RegexDome;

public class Test6 {
    public static void main(String[] args) {
        //需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
        // 举例:a123a  b456b  17891  &abc&  a123b(false)
        String regex1 = "(.).+\\1";
        System.out.println("a123a".matches(regex1));
        System.out.println("b456b".matches(regex1));
        System.out.println("17891".matches(regex1));
        System.out.println("&abc&".matches(regex1));
        System.out.println("a123a".matches(regex1));
        System.out.println("a123b".matches(regex1));
        System.out.println("-------------------------------------------------");

        //需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
        //举例:abc123abc  b456b   123789123  &!@abc&!@  abc123abd(false)
        String regex2 = "(.+).+\\1";
        System.out.println("abc123abc".matches(regex2));
        System.out.println("b456b".matches(regex2));
        System.out.println("123789123".matches(regex2));
        System.out.println("&!@abc&!@".matches(regex2));
        System.out.println("abc123abd".matches(regex2));
        System.out.println("-------------------------------------------------");

        //需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
        //举例: aaa123aaa  bbb456bbb  111789111  &&abc&&
        
       	//(.):把首字母看作一组
        // \\2:把首字母拿出来再次使用
        String regex3 = "((.)\\2*)\\w+\\1";
        System.out.println("aaa123aaa".matches(regex3));
        System.out.println("bbb456bbb".matches(regex3));
        System.out.println("111789111".matches(regex3));
        System.out.println("&&abc&&".matches(regex3));
        System.out.println("-------------------------------------------------");
    }
}

  • 捕获分组:
    • \\组号——在正则内部捕获
    • $组号——在正则外部捕获
package API_.RegexDome;

public class Test7 {
    public static void main(String[] args) {
        String s = "我我我我我我我要要要要要要学学学学学学编编编编编编编编程程程程程";

        String result = s.replaceAll("(.)\\1+","$1");
        System.out.println(result);

    }
}

非捕获分组

符号 含义 举例
(?:正则) 获取所有 Java(?:8|11|17)
(?=正则) 获取前面部分 Java(?=8|11|17)
(?!正则) 获取不是指定内容的前面部分 Java(?!8|11|17)
  • 分组之后不需要再用本组数据,仅仅把数据括起来,不占组号

三、JDK7时间

3.1、JDK7时间-Date

世界标准时间

格林尼治时间/格林威治时间(Greenwich Mean Time)简称GMT。
目前世界标准时间((UTC)已经替换为:原子钟

中国标准时间

世界标准时间+8小时

时间换算单位

1秒 = 1000毫秒
1毫秒 = 1000微秒
1微秒 = 1000纳秒

Date时间类
Date类是一个JDK写好的Javabean类,用来描述时间,精确到毫秒。
利用空参构造创建的对象,默认表示系统当前时间。
利用有参构造创建的对象,表示指定的时间。

  1. 如何创建日期对象?

    • Date date = new Date();
    • Date date = new Date(指定毫秒值);
  2. 如何修改时间对象的毫秒值?

    • setTime(毫秒值)
  3. 如何获取时间对象中的毫秒值

    • getTime();
package API_.JDK7DateDome;

import java.util.Date;
import java.util.Random;

public class Dome1 {
    public static void main(String[] args) {
        //创建一个表示时间原点的对象
        Date d1 = new Date(0L);
        //获取d1时间的毫秒值
        long time  = d1.getTime();
        //在这个基础上我们要加一年的毫秒值即可
        time = time + 1000L*60*60*24*365;
        //把这个时间设置到d1里面
        d1.setTime(time);
        //打印出来
        System.out.println(d1);


        Random r = new Random();
        Date d2 = new Date(Math.abs(r.nextInt()));
        Date d3 = new Date(Math.abs(r.nextInt()));

        long date2 = d2.getTime();
        long date3 = d3.getTime();

        if (date3>date2){
            System.out.println("后者大于前者");
        } else if (date3<date2) {
                System.out.println("前者大于后者");
        }else {
            System.out.println("两者一样");
        }

    }
}

3.2、JDK7时间-SimpleDateFormat类

  • 格式化:把时间变成我们喜欢的格式
  • 解析:把字符串表示的时间变成Date对象

构造方法:

构造方法 说明
public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认格式
public simpleDateFormat(string pattern) 构造一个simpleDateFormat,使用指定的格式

常用方法:

常用方法 说明
public final String format(Date date) 格式化(日期对象->字符串)
public Date parse(String source) 解析(字符串->日期对象)

Java笔记_11(常用API)

  • 格式化日期对象
package API_.JDK7DateDome;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Dome2 {
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf1 = new SimpleDateFormat();
        Date d1 = new Date(0L);
        String str1 = sdf1.format(d1);
        System.out.println(str1);

        SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY年MM月dd HH时mm分ss秒 EE");
        Date d2 = new Date(0L);
        String str2 = sdf2.format(d2);
        System.out.println(str2);

        //1.定义一个字符串表示时间
        String s1 = "2022-11-11 18-12-00";
        //细节:
        //创建对象的格式要和字符串的格式完全一致
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        Date date = sdf4.parse(s1);
        System.out.println(date.getTime());
    }
}
  • 时间格式转换练习
package API_.JDK7DateDome;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Dome3 {
    public static void main(String[] args) throws ParseException {
        //2020-08-07 23:00:00
        String s1 = "2020-8-7 23:00:00";
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = sdf1.parse(s1);
        //创建第二个SimpleDateFormat对象
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        String s2 =  sdf2.format(date);
        System.out.println(s2);
    }
}

3.3、JDK7时间-Calendar

  • Calendar代表了系统当前时间的日历对象,可以单独修改、获取时间中的年,月,日
  • 细节Calendar是一个抽象类,不能直接创建对象。

获取Calendar日历类对象方法

方法名 说明
public static calendar getInstance() 获取当前时间的日历对象

Calendar常用方法

方法名 说明
public final Date getTime() 获取日期对象
public final setTime(Date date) 给日历设置日期对象
public long getTimeInMillis() 拿到时间毫秒值
public void setTimeInMillis( long millis) 给日历设置时间毫秒值
public int get(int field) 取日历中的某个字段信息
public void set(int field,int value) 修改日历的某个字段信息
public void add(int field,int amount) 为某个字段增加/减少指定的值
  1. 获取日历对象
    • 细节1: calendar是一个抽象类,不能直接new,而是通过一个静态方法获取到子类对象
    • 细节2:
      • 月份:范围0~11如果获取出来的是1那么实际上是2月。
      • 星期:1(星期日),2(星期一),3(星期二),4(星期三),5(星期四),6(星期五),7(星期六)
    • 底层原理:会根据系统的不同时区来获取不同的日历对象。把会把时间中的纪元,年,月,日,时,分,秒,星期,等等的都放到一个数组当中
    • 数组中的索引代表着不同的数据
    • Java底层通过常量使其替换数组来使可读性提高
      • ERA–0
      • TEAR–1
      • MONTH–2
      • WEEK_OF_YEAR–3
      • WEEK_OF_MONTH–4
      • DATE(DAY_OF_DATE)–5
      • DAY_OF_YEAR–6
      • DAY_OF_WEEK–7
package API_.JDK7DateDome;

import java.util.Calendar;
import java.util.Date;

public class Dome4 {
    public static void main(String[] args) {
        Calendar c = Calendar.getInstance();

        Date d = new Date(0L);
        c.setTime(d);
        //修改时间的值
        //当设置的值超过给类型的上限(比如设置了999个月)组会将多余的月份转化为年
        c.set(Calendar.YEAR,1996);
        c.set(Calendar.MONDAY,11);
        c.set(Calendar.DAY_OF_MONTH,34);
        //增加某个字段的值
        c.add(Calendar.YEAR,2);
        //获取时间的年月日
        int year = c.get(Calendar.YEAR);
        int month = c.get(Calendar.MONTH)+1;
        int month2 = c.get(Calendar.MONDAY)+1;
        int date = c.get(Calendar.DAY_OF_MONTH);
        int day = c.get(Calendar.DAY_OF_WEEK);
        //打印
        System.out.println(year);
        System.out.println(month);
        System.out.println(month2);
        System.out.println(date);
        System.out.println(getDay(day));
    }
    public static String getDay(int index){
        String[] weekDay = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
        return weekDay[index];
    }
}

四、JDK8时间

4.1、JDK8时间类

JDK7与JDK8相比

  1. 代码层面
    • JDK7:代码麻烦
      Java笔记_11(常用API)
    • JDK8:简单 判断的方法,计算时间间隔的方法
  2. 安全层面
    • JDK7:多线程环境下会导致数据安全的问题
    • JDK8:时间日期对象都是不可变的,解决了这个问题

JDK8时间

  1. JDK8时间
    • ZoneId: 时区
    • Instant: 时间戳
    • ZoneDateTime: 带时区的时间
  2. 日期格式化类:
    SimpleDateFormat
    • DateTimeFormatter用于时间的格式化和解析
  3. 日历类:
    calendar
    • LocalDate:年、月、日
    • LocalTime:时、分、秒
    • LocalDateTime :年、月、日、时、分、秒
  4. 工具类
    • Duration:时间间隔(秒,纳秒)
    • Period:时间间隔(年,月,日)
    • ChronoUnit:时间间隔(所有单位)

4.2、Date类

ZoneId时区

方法名 说明
static Set<String> getAvailableZoneIds() 获取Java中支持的所有时区
static ZoneId systemDefault() 获取系统默认时区
static ZoneId of(String zoneId) 获取一个指定时区
package API_.JDK8DateDome;

import java.time.ZoneId;
import java.util.Set;

public class Dome1 {
    public static void main(String[] args) {
        //获取所有的地区时间ID
        Set<String> ZoneId1 = ZoneId.getAvailableZoneIds();
        System.out.println(ZoneId1.size());//602
        //System.out.println(ZoneId1);
        //获取默认地区的时间ID
        ZoneId zoneId2 = ZoneId.systemDefault();
        System.out.println(zoneId2);
        //获取指定的时区
        ZoneId zoneId3 = ZoneId.of("Asia/Chongqing");
        System.out.println(zoneId3);
    }
}

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) 增加时间系列的方法
package API_.JDK8DateDome;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Dome2 {
    public static void main(String[] args) {
        //获取当前时间的Instant对象(标准时间)
        Instant instant = Instant.now();
        System.out.println(instant);

        //根据(秒/毫秒/纳秒)获取Instant对象
        Instant instant2 = Instant.ofEpochMilli(0L);
        System.out.println(instant2);
        Instant instant3 = Instant.ofEpochSecond(1);
        System.out.println(instant3);
        Instant instant4 = Instant.ofEpochSecond(1,1000000000);
        System.out.println(instant4);

        //指定时区
        ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
        System.out.println(time);

        //isXxx判断
        Instant instant5 = Instant.ofEpochMilli(2L);
        Instant instant6 = Instant.ofEpochMilli(3L);
        boolean b1 =  instant5.isBefore(instant6);
        boolean b2 =  instant5.isAfter(instant6);
        System.out.println(b1);
        System.out.println(b2);

        //减少时间系列的方法
        Instant instant7 = Instant.ofEpochMilli(3000L);
        Instant instant8 = instant7.minusSeconds(1);
        System.out.println(instant8);
        Instant instant9 = instant7.plusSeconds(1);
        System.out.println(instant9);
    }
}

ZoneDateTime带时区的时间

方法名 说明
static ZonedDateTime now() 获取当前时间的ZonedDateTime对象
static ZonedDateTime ofXxxx(。。。) 获取指定时间的ZonedDateTime对象
ZonedDateTime withXxx(时间) 修改时间系列的方法
ZonedDateTime minusXxx(时间) 减少时间系列的方法
ZonedDateTime plusxxx(时间) 增加时间系列的方法
package API_.JDK8DateDome;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Dome3 {
    public static void main(String[] args) {
        //创建一个ZonedDateTime时间对象
        ZonedDateTime time1 = ZonedDateTime.now();
        System.out.println(time1);//2023-04-22T19:46:37.067646400+08:00[Asia/Shanghai]

        //创建一个指定时间对象
        ZonedDateTime time2 = ZonedDateTime.of(2023,4,22,19,50,
                30,0, ZoneId.of("Asia/Shanghai"));
        System.out.println(time2);
        //通过Instant+时区的方式指定获取的时间对象
        Instant instant = Instant.ofEpochMilli(0L);
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        ZonedDateTime time = ZonedDateTime.ofInstant(instant,zoneId);
        System.out.println(time);
        //修改时间
        ZonedDateTime time3 = time.withYear(2000);
        //增加时间
        ZonedDateTime time4 = time3.minusYears(1);
        //减少时间
        ZonedDateTime time5 = time3.plusYears(1);
        System.out.println(time3);
        System.out.println(time4);
        System.out.println(time5);

    }
}

细节:
JDK8新增的时间对象都是不可变的如果我们修改了,减少了,增加了时间那么调用者是不会发生改变的,产生一个新的时间。

4.3、日期格式化类

DateTimeFormatter 用于时间的格式化和解析

方法名 说明
static DateTimeFormatter ofPattern(格式) 获取格式对象
String format(时间对象) 按照指定方式格式化
package API_.JDK8DateDome;

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class Dome4 {
    public static void main(String[] args) {
        ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss EE a");

        System.out.println(dtf.format(time));
    }
}

4.4、日历类

LocalDate、LocalTime、LocalDateTime

方法名 说明
static xxx now() 获取当前时间的对象
static xxx of(。。。) 获取指定时间的对象
get开头的方法 获取日历中的年、月、日、时、分、秒等信息
isBefore,isAfter 比较两个LocalDate
with开头的 修改时间系列的方法
minus开头的 减少时间系列的方法
plus开头的 增加时间系列的方法
  • get方法中,LocalDate只能获取年月日,LocalTime只能获取时分秒
  • LocalDateTime可以转化为LocalDate、LocalTime
方法名 说明
public LocalDate toLocalDate() LocalDateTime转换成一个LocalDate对象
public LocalTime toLocalTime() LocalDateTime转换成一个LocalTime对象
package API_.JDK8DateDome;

import javax.xml.stream.Location;
import java.time.*;

public class Dome5 {
    public static void main(String[] args) {
        //获取日期
        LocalDate localDate = LocalDate.now();
        LocalDate localDate2 = LocalDate.of(2000,10,1);
        System.out.println(localDate);
        //获取年份
        int y = localDate.getYear();
        System.out.println(y);
        //获取月份
        Month m = localDate.getMonth();
        System.out.println(m);
        int m1 = m.getValue();
        System.out.println(m1);
        int date = localDate.getDayOfYear();
        int date2 = localDate.getDayOfMonth();
        System.out.println(date);
        System.out.println(date2);
        //获取星期数
        DayOfWeek dayOfWeek = localDate.getDayOfWeek();
        System.out.println(dayOfWeek);
        //比较日期
        System.out.println(localDate.isAfter(localDate2));
        System.out.println(localDate.isBefore(localDate2));
        //修改日期
        LocalDate localDate1 = localDate2.withYear(2021);
        System.out.println(localDate1);
        //增减日期
        LocalDate localDate3 = localDate2.minusYears(1);
        LocalDate localDate4 = localDate2.plusYears(1);
        System.out.println(localDate3);
        System.out.println(localDate4);

        LocalDate birthday = LocalDate.of(2000,4,23);
        LocalDate newDay = LocalDate.now();

        MonthDay bir = MonthDay.of(birthday.getMonth(),birthday.getDayOfMonth());
        MonthDay new1 = MonthDay.of(newDay.getMonth(),newDay.getDayOfMonth());
        System.out.println(bir.equals(new1));

    }
}

4.5、工具类

Period——用于计算两个“日期”间隔(年、月、日)
Duration——用于计算两个“时间”间隔(秒,纳秒)
ChronoUnit——用于计算两个“日期”间隔

Period

package API_.JDK8DateDome;

import java.time.LocalDate;
import java.time.Period;

public class Dome6 {
    public static void main(String[] args) {
        LocalDate toDay = LocalDate.now();
        System.out.println(toDay);

        LocalDate birthday = LocalDate.of(2000, 1, 1);

        Period period = Period.between(birthday,toDay);
        System.out.println(period);
        System.out.println(period.getYears());
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
        //相距的月份
        System.out.println(period.toTotalMonths());
    }
}

Duration

package API_.JDK8DateDome;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;

public class Dome7 {
    public static void main(String[] args) {
        LocalDateTime toDay = LocalDateTime.now();

        System.out.println(toDay);

        LocalDateTime birthday = LocalDateTime.of(2000, 1, 1,1,0,00,00);

        Duration Duration1 = Duration.between(birthday,toDay);
        System.out.println(Duration1);
        System.out.println(Duration1.getSeconds());
        System.out.println(Duration1.getNano());
        //相距
        System.out.println(Duration1.toDays());
        System.out.println(Duration1.toHours());
        System.out.println(Duration1.toMillis());
        System.out.println(Duration1.toDaysPart());
        System.out.println(Duration1.toNanos());
    }
}

ChronoUnit

package API_.JDK8DateDome;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Dome8 {
    public static void main(String[] args) {
        LocalDateTime today = LocalDateTime.now( );
        System.out.println(today ) ;
        //生日时间
        LocalDateTime birthDate = LocalDateTime.of( 2000,1, 1,0,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));

    }
}

五、包装类

包装类:用一个对象,把基本数据类型给包起来

Integer.valueOf()创建int型数据与new Integer()创建int型数据的区别

当用Integer.valueOf()创建的数据大于127时就会出现两个相同数值的变量不相同
底层原理:
因为在实际开发中,-128~127之间的数据,用的比较多。如果每次使用都是new对象,那么太浪费内存了
所以,提前把这个范围之内的每一个数据都创建好对象如果要用到了不会创建新的,而是返回已经创建好的对象。

在JDK5的时候提出了一个机制:

  • 自动装箱和自动拆箱
  • 自动装箱:把基本数据类型会自动的变成其对应的包装类
  • 自动拆箱:把包装类自动的变成其对象的基本数据类型
  • 在JDK5之后,int和integer可以看作是一个东西,因为在其内部可以自动转化

Integer成员方法

方法名 说明
public static String toBinaryString(int i) 得到二进制
public static String toOctalString(int i) 得到八进制
public static String toHexString(int i) 得到十六进制
public static int parselnt(String s) 将字符串类型的整数转成int类型的整数
package API_.Integer;

public class Dome2 {
    public static void main(String[] args) {
        String str1 = Integer.toBinaryString(123);
        String str2 = Integer.toOctalString(123);
        String str3 = Integer.toHexString(123);

        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);

        int i = Integer.parseInt("123");
        System.out.println(i+1);
    }
}

  • 细节1:
    在类型转换的时候,括号中的参数只能是数字不能是其他,否则代码会报错
  • 细节2:
    8种包装类当中,除了character都有对应的parsexxx的方法,进行类型转换

键盘录入改进
在键盘录入时使用nextLine方法

  • 这种方法的特点是只有遇到回车才会停止

六、综合练习

6.1、键盘录入

Java笔记_11(常用API)

package API_;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test1 {
    public static void main(String[] args) {
        //创建一个集合
        ArrayList<Integer> arr  = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        while (true){
            System.out.println("请输入一个整数(1~200)");
            String num0 = sc.nextLine();
            int num = Integer.parseInt(num0);
            if(num<1||num>200){
                System.out.println("输入的数字不符合要求");
            }
            //将符合要求的数字存到集合中
            arr.add(num);
            int sum = getSum( arr , num);
            if(sum>200){
                break;
            }
        }
        //遍历集合
        for (int i = 0; i < arr.size(); i++) {
            System.out.print(arr.get(i)+" ");
        }
    }
    //对集合里面的数字进行相加求和
    private static int getSum(ArrayList<Integer> arr, int num) {
        int sum = 0;
        for (int i = 0; i < arr.size(); i++) {

            sum = sum + num;
        }
        return sum;
    }
}

6.2、算法水题

Java笔记_11(常用API)

package API_;

import java.util.Scanner;

public class Test2 {
    public static void main(String[] args) {
        System.out.println("请输入整数");
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        //利用正则表达式验证该字符串是否符合要求
        if(!str.matches("[1-9]\\d{0,9}")){
            System.out.println("输入的整数不符合规则");
        }else {
            int number = 0;
            for (int i = 0; i < str.length(); i++) {
                //将字符转化成数字
                int num = str.charAt(i) - '0' ;
                number = number*10 + num;
            }
            System.out.println(number);
        }
    }
}

6.3、算法水题

Java笔记_11(常用API)

package API_;

public class Test3 {
    public static void main(String[] args) {

        System.out.println(toBinaryString(3));
    }
    public static String toBinaryString(int num){
        //创建一个字符空间
        StringBuilder sb = new StringBuilder();

        while (true){
            //判断传入的数字是不是0
            if(num ==0){
                break;
            }
            int number = num%2;
            //将每次循环的到的新的数字放置这个字符空间的首位
            sb.insert(0,number);
            num = num/2;
        }
        return sb.toString();
    }
}

6.4、算法水题

Java笔记_11(常用API)

package API_;

import javax.lang.model.element.NestingKind;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.regex.Pattern;

public class Test4 {
    public static void main(String[] args) throws ParseException {
        //JDK7计算出生时间差
        String birthday = "2000-01-01";
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
        Date date = sdf.parse(birthday);
        long birthdaytime = date.getTime();
        long today = System.currentTimeMillis();

        long time = today-birthdaytime;
        System.out.println(time/1000/60/60/24);

        //JDK8计算出生时间差
        LocalDate localDate = LocalDate.of(2000,1,1);
        LocalDate localDate1 = LocalDate.now();

        System.out.println(ChronoUnit.DAYS.between(localDate, localDate1));

    }
}

6.5、算法水题

Java笔记_11(常用API)文章来源地址https://www.toymoban.com/news/detail-412755.html

package API_;

import java.time.LocalDate;
import java.util.Calendar;

public class Test5 {
    public static void main(String[] args) {
        //用JDK7判断闰年平年
        Calendar calendar = Calendar.getInstance();
        calendar.set(2000,2,1);
        //将日期往前减一天
        calendar.add(Calendar.DAY_OF_MONTH,-1);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(day);

        Calendar calendar1 = Calendar.getInstance();
        calendar1.set(2001,0,1);
        //日期往前减一天
        calendar1.add(Calendar.DAY_OF_YEAR,-1);
        int day1 = calendar1.get(Calendar.DAY_OF_YEAR);
        System.out.println(day1);

        //JDK8
        LocalDate d1 = LocalDate.of(2000,3,1);
        LocalDate d2 = d1.minusDays(1);
        int dayOfMonth = d2.getDayOfMonth();
        System.out.println(dayOfMonth);

        //JDK8中有专门的方法判断是否为闰年
        //true:闰年
        //false:平年
        System.out.println(d1.isLeapYear());

    }
}

到了这里,关于Java笔记_11(常用API)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【系统】【winget】从零开始配置一个开发用的 Windows 11 系统的电脑 - winget 代码终端安装软件

    我有强迫症,需要干净、简单且省心的安装。 我喜欢苹果系统的沙盒机制,在 Win上难以实现或者损耗性能。 我发现可以使用 winget 现在已经可以安装和组织许多软件了,很好用。 微软官方文档:使用 winget 工具安装和管理应用程序 索性电脑一块硬盘只有一个C盘分区,安装软

    2024年02月09日
    浏览(74)
  • 【自学笔记】01Java基础-08Java常用API:05正则表达式与Lambda表达式

    记录Java基础-常用API-正则表达式与Lambda表达式的内容。 正则表达式在线练习网站 正则表达式是一种强大的文本处理工具,它使用特殊的字符和模式来匹配、查找、替换或提取字符串中的特定内容。 在Java中,正则表达式的功能主要通过 java.util.regex 包中的 Pattern 和 Matcher 类实

    2024年01月19日
    浏览(67)
  • 【Java】一个简单的接口例子(帮助理解接口+多态)

    要求: 请实现笔记本电脑使用USB 鼠标、 USB 键盘的例子 1. USB 接口:包含打开设备、关闭设备功能 2. 笔记本类:包含开机功能、关机功能、使用 USB 设备功能 3. 鼠标类:实现 USB 接口,并具备点击功能 4. 键盘类:实现 USB 接口,并具备输入功能 (不需要具体实现,给出框架即

    2024年02月16日
    浏览(42)
  • 掌握Java JDK 1.8 API帮助文档中文版,事半功倍编程

    引言: Java是一门强大且广泛应用的编程语言,在开发过程中,准确地了解和使用Java标准库的API是非常重要的。JDK(Java Development Kit)是Java开发工具包,提供了丰富的API文档,其中包含了Java标准库中各种类和方法的详细说明。本文将为您介绍如何使用JDK 1.8 API帮助文档的中文

    2024年02月07日
    浏览(44)
  • 帮助中心管理系统,人人都能用的知识管理平台

    帮助中心管理系统是一种知识管理平台,旨在帮助企业有效组织和管理知识资源,使其能够为客户和员工提供快速、准确的帮助和支持。 知识库管理: 帮助中心管理系统允许企业将知识组织和分类,建立一个完整的知识库。这包括常见问题解答(FAQs)、操作指南、故障排除

    2024年02月09日
    浏览(38)
  • ChatGPT能帮助我们人类做什么

    一、ChatGPT可以在多个方面帮助人类: 回答问题: ChatGPT可以回答各种问题,提供信息和解释概念。 创造性写作: 它可以生成文章、故事、诗歌等创意性文本。 学术辅助: ChatGPT可以辅助学术研究,提供解释、背景信息和学科知识。 编程辅助: 在编写代码时,它可以提供建

    2024年01月17日
    浏览(35)
  • 【Elasticsearch学习笔记五】es常用的JAVA API、es整合SpringBoot项目中使用、利用JAVA代码操作es、RestHighLevelClient客户端对象

    目录 一、Maven项目集成Easticsearch 1)客户端对象 2)索引操作 3)文档操作 4)高级查询 二、springboot项目集成Spring Data操作Elasticsearch 1)pom文件 2)yaml 3)数据实体类 4)配置类 5)Dao数据访问对象 6)索引操作 7)文档操作 8)文档搜索 三、springboot项目集成bboss操作elasticsearch

    2023年04月09日
    浏览(48)
  • 使用ChatGPT帮助我们编码的10种场景

    ChatGPT 的出现,彻底改变的很多代码开发的方式,特别是通用型的代码,使用它来帮助我们,很大程度上可以提升我们写代码的效率和质量。 本博主工作中主要进行前端方向的项目开发,本文将直接聚焦在代码编写相关的具体场景上。通过日常工作实践中发现的能够使用 Ch

    2023年04月20日
    浏览(46)
  • 在Python中使用Kafka帮助我们处理数据

    Kafka是一个分布式的流数据平台,它可以快速地处理大量的实时数据。Python是一种广泛使用的编程语言,它具有易学易用、高效、灵活等特点。在Python中使用Kafka可以帮助我们更好地处理大量的数据。本文将介绍如何在Python中使用Kafka简单案例。 在Python中使用Kafka,需要安装

    2024年02月12日
    浏览(42)
  • 第11章_常用类和基础API

    1.1 String的特性 java.lang.String 类代表字符串。Java程序中所有的字符串文字(例如 \\\"hello\\\" )都可以看作是实现此类的实例。 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。 字符串String类型本身是final声明的,意味着我们不能继承String。 String对象的字符内容

    2023年04月17日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包