5、Java常用API


常用 API 概述:

基础知识学完了. 开启了一个新篇章。在前面, 我们几乎把 Java 的基础语法学完了。接下来, 我们要对 JDK 提供给我们的一些工具类进行详细的剖析,为了后面的项目开发继续打基础。
参考官方文档 JDK 中所有的 API:https://docs.oracle.com/javase/8/docs/api/index.html

也可以下载一个中文 jdk 文档(有检索功能)
https://www.jb51.net/books/698419.html
在本章你能学到:

  1. 数学类 Math, 除了加减乘除以外的其他数学运算都在这里了

  2. 包装类, 基本数据类型实际上并不属于对象的范畴, 所以 java 提供给了包装类把非面向对象的基本数据类型包装成 java 中的对象

    基本数据类型:
    byte
    short
    int
    long
    float
    double
    char
    boolean

  3. 时间类 Date 和 Calendar, 时间在程序里怎么表示, 以及时间差怎么计算

  4. 字符串, 前面咱们只是简单认识了一下字符串, 这里来具体的介绍数据类型的霸主, 字符串都有哪些操作

  5. StringBuffer 和 StringBuilder, 另类的两个字符串

  6. DecimailFormat 数字的格式化

一、数学类 Math

数学操作,很多小伙伴会想到 + - * / % . 没错, 我们接触最多的也确实就这几个。但是有些时候啊,这些操作不够用,比如说我想让你帮我计算一下一元二次方程的解. 瞬间石化..
ax2+bx+c = 0 的解是:

来, 你用加减乘除来搞~~ 搞不定了吧. 哈哈.
此时我们就需要数学类的帮助来完成相应的操作了.
数学类提供的一些常用方法:

  • pow(x,y)      计算 x 的 y 次幂
  • abs(x).      计算 x 的绝对值
  • log(x).      计算以 e 为底 x 的对数, e 是啥, 我只能告诉你 e 被称为欧拉数….
  • max(x,y)      返回 x, y 中大的那个数
  • min(x, y)      返回 x,y 中小的那个数
  • round(x)     x 四舍五入
  • sqrt(x)      计算 x 的开平方,根号下 x
  • ceil(7.5)    //返回大于或等于该浮点数的整数
  • floor(3.6)    //返回小于或等于该浮点数的整数
  • random()    //返回 [0.0,1.0)之间的浮点数

咱们就介绍这些 ,当然 Math 肯定不止这么多方法,对我们而言, 这些就足够用的了. 如果你需要看数学类的其他方法, 送你一个传送门:https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html

package com.xyq.math;
public class Test {
    public static void main(String[] args) {
        System.out.println(Math.pow(3, 3)); // 3的3次方
        System.out.println(Math.abs(-12)); // 12
        System.out.println(Math.log(2)); // 以e为底, 2的对数
        System.out.println(Math.max(12, 33)); // 求大数   33
        System.out.println(Math.min(55, 33)); // 求小数  33
        System.out.println(Math.round(3.56789));  // 4 四舍五入
        System.out.println(Math.sqrt(3));  // 根号9  1.732
    }
}

来吧, 解决一下一元二次方程吧

package com.xyq.math;
import java.util.Scanner;
public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入a:");
        double a = sc.nextInt();
        System.out.println("请输入b:");
        double b = sc.nextInt();
        System.out.println("请输入c:");
        double c = sc.nextInt();
        // 先判断b*b-4*a*c是否大于0 . 不大于0无解
        double dt = b*b - 4*a*c;
        if (dt < 0){
            System.out.println("此方程无解");
        } else if(dt == 0){
            System.out.println("此方程有一个解");
            double x = -b/(2*a);
            System.out.println("x = " + x);
        } else {
            System.out.println("此方程有两个解");
            double x1 = (-b+Math.sqrt(dt)) / (2*a);
            double x2 = (-b-Math.sqrt(dt)) / (2*a);
            System.out.println("x1 = "+x1 + ", x2 = "+x2);
        }
    }
}

二、基本数据类型的包装类

说包装类之前, 我们先看这样一段代码.

package com.xyq.pack;
public class Test {
    public static void main(String[] args) {
        int a = 10;
        System.out.println(a.toString()); // 报错
    }
}

为什么会报错呢? 想想啊, 前面我们说过, 任何类都要继承 Object, 所以在 java 里认为万事万物皆为对象. 而 toString()方法是 Object 提供的一个方法. 也就意味着, 所有的类都会有一个默认的 toString(). 但是此时我们发现 int 类型不能执行这个 toString(). 为什么呢? 因为!!!! int 是基本数据类型, 根本就没有继承 Object. 换句话说. 所有的基本数据类型都不在面向对象的范畴. 但是这又与 Java 纯面向对象编程语言相违背. 怎么办? Java 很聪明. 既然 int 不是对象的范畴, 那我就想办法把你变成面向对象, 所以, java 提供了基本数据类型的包装类来对基本数据类型进行包装. 包装之后的东西就是面向对象了.

基本数据类型包装类

基本类型 包装类型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Charactor
boolean Boolean

除了 int 和 char 以外都是基本数据类型首字母大写. 很好记.
那这些类有什么用

package com.xyq.pack;
public class Test {
    public static void main(String[] args) {
        Integer t = new Integer(12); // new了个对象. 但是没什么实际意义. 和int i = 12 几乎是一样的.
        System.out.println(t);  //  12
        Integer tt = new Integer(13);
        System.out.println(t+tt); // 数学运算也OK.
    }
}

包装类最大的作用就是把基本数据类型变成了对象,实现不同类型之间转换

你看, 可以执行这么多方法了. 可能懵懂的你还是很不爽. 没用!!!! 好接下来就是重点了.
我们说, int 并没有继承 Object. 那就意味着. int 不可以向上转型成 Object. 对吧. 那如果我写一个方法接收 Object 类型的参数. int 就不能给这个方法传参.

package com.xyq.pack;
public class Test {
    public static void chi(Object obj){
        System.out.println(obj);
    }
    public static void main(String[] args) {
        chi(1); // 没报错
    }
}

我们发现, 这段代码并没有报错. 讲道理应该报错才对啊. 这里就涉及到一个新的知识点, 自动打包和解包. 在 java 里, 基本数据类型是可以和包装类型进行无缝转换的.

Integer i = 1;  // 自动打包成Integer对象
int b = i; //  自动解包成int类型

所以, 在上面的代码里, 程序是自动把 1 转化成了 Integer 对象. 然后传给了 obj. 中间有一个打包的过程.
怎么验证? 简单. 打印的时候打印 obj.getClass()看看

package com.xyq.pack;
public class Test {
    public static void chi(Object obj){
        System.out.println(obj.getClass()); // class java.lang.Integer
    }
    public static void main(String[] args) {
        chi(1); // 没报错
    }
}

OK. 基本数据类型包装类存在的意义:

  1. 让基本数据类型有了面向对象的特征.
  2. 可以把字符串转化成各种基本数据类型
/*1.int转String*/
int a = 100;
String a1 = ""+a;       //方式1

String a2 = String.valueOf(a);      //方式2

/*2.String转int*/
String b = "100";
int b1 = Integer.parseInt(b);//方式1

Integer b2 = Integer.valueOf(b);      //方式2
int b3 = b2.intValue();

规律: 字符串->基本数据类型

基本数据类型包装类.parse 基本数据类型(待转化的内容)

  • Integer.parseInt(“12”); //将字符串转化为整型
  • Double.parseDouble();
  • Long.parseLong();
  • Boolean.parseBoolean();

案例:给定字符串”91 27 46 38 50” 按空格分割后排序输出

String s1 = "91 27 46 38 50";
System.out.println(sortStr(s1));

public static String sortStr(String s1){
    String[] strArr = s1.split(" ");
    StringBuilder sb = new StringBuilder();
    int[] arr = new int[strArr.length];
    for (int i = 0; i < arr.length; i++) {
        arr[i] = Integer.parseInt(strArr[i]);
    }
    Arrays.sort(arr);
    return Arrays.toString(arr);
}

自动装箱和拆箱

  • 装箱:把基本数据类型转换为对应的包装类类型
  • 拆箱:把包装类类型转换为基本数据类型
Integer a1 = Integer.valueOf(100);   //装箱
Integer a2 = 100;   //自动装箱,jdk5之后可以这么写,底层是上句代码

Integer a3 = Integer.valueOf(200);
a3+=100;        //自动拆箱,a3.intValue() +100

注意:在使用包装类的时候,如果做操作,最好先判断是否为 null,推荐只要是对象 在使用前就必须进行部位 null 的判断

三、日期时间

JDK 文档:https://docs.oracle.com/javase/8/docs/api/index.html
java.util.Date, 日期类. 帮我们处理时间的一个类

import java.util.Date;
Date t1 = new Date();
System.out.println(t1);		//Tue Jun 16 09:02:27 CST 2020
System.out.println(t1.getTime());       //时间撮 从1970年1月1日 0点0分0秒开始.
System.out.println(t1.getYear());       //从1900年开始计算,该方法目前已弃用,IDEA会标记删除线
System.out.println(t1.getMonth()+1); // 获取月份. 月份从0开始
System.out.println(t1.getDate()); //  月内的第xxx天.
System.out.println(t1.getHours()); // 小时
System.out.println(t1.getMinutes()); // 分钟
System.out.println(t1.getSeconds()); // 获取到秒

java.util.Calendar日历类:

Calendar rightNow = Calendar.getInstance();
System.out.println(rightNow);
//rightNow对象包含非常丰富的日期信息,比如WEEK_OF_YEAR=25 一年中的第25周,WEEK_OF_MONTH=3 一个月中的第3周;
//java.util.GregorianCalendar[time=1592234532715,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2020,MONTH=5,WEEK_OF_YEAR=25,WEEK_OF_MONTH=3,DAY_OF_MONTH=15,DAY_OF_YEAR=167,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=22,SECOND=12,MILLISECOND=715,ZONE_OFFSET=28800000,DST_OFFSET=0]

日历对象的常用的 get 方法:

System.out.println(rightNow.getTime()); // Calendar转化成Date
System.out.println(rightNow.get(Calendar.YEAR)); // 年
System.out.println(rightNow.get(Calendar.MONTH)+1); // 月  从0开始
System.out.println(rightNow.get(Calendar.DAY_OF_MONTH)); // 日
System.out.println(rightNow.get(Calendar.HOUR_OF_DAY));  // 小时, 24小时
System.out.println(rightNow.get(Calendar.MINUTE)); // 分钟
System.out.println(rightNow.get(Calendar.SECOND));  // 秒

日历对象的 set 方法:

// 在当前系统时间的基础上后延36小时
rightNow.set(Calendar.HOUR_OF_DAY, rightNow.get(Calendar.HOUR_OF_DAY)+36);
System.out.println(rightNow.get(Calendar.HOUR_OF_DAY));  // 小时, 24小时
// 2月22日. 延后18天, 是几号?
rightNow.set(Calendar.DAY_OF_MONTH, rightNow.get(Calendar.DAY_OF_MONTH)+18);
String timefmt = ""+rightNow.get(Calendar.YEAR)+"年"
    +(rightNow.get(Calendar.MONTH)+1)+"月"
    +rightNow.get(Calendar.DAY_OF_MONTH)+"日 "
    +rightNow.get(Calendar.HOUR_OF_DAY)+"时"
    +rightNow.get(Calendar.MINUTE)+"分"
    +rightNow.get(Calendar.SECOND)+"秒";
System.out.println(timefmt);

Date()对象格式化为标准时间:

Date t1 = new Date();
System.out.println(t1);     //Tue Jun 16 08:39:09 CST 2020
// 创建一个格式化对象. 这里必须要通过构造方法传递一个日期格式. 说白了. 你想让日期显示成什么格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//将Date对象格式化为我们需要的日期时间格式
String s = sdf.format(t1);   // 格式化时间
System.out.println(s);  // 2020-06-16 08:39:09

将日期时间字符串格式化为时间对象

Scanner sc = new Scanner(System.in);
System.out.println("请输入一个日期(yyyy-MM-dd): ");
String s = sc.nextLine();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
    Date d = sdf.parse(s);// 转化  // 这里必须要手动处理异常. 原因: 用户输入的那玩意谁也保证不了. 所以很容易出问题. 必须异常处理
    System.out.println(d);
} catch (ParseException e) {
    e.printStackTrace();
}

注意:格式化sdf.parse()容易出错,必须要异常处理
练习:时间差计算

String s1 = "2018-01-01 12:00:00";
String s2 = "2018-01-01 13:44:00";
//首先把这两个字符串转化为Date对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
    Date t1 = sdf.parse(s1);
    Date t2 = sdf.parse(s2);
    //获取毫秒
    long t1_millSec = t1.getTime();
    long t2_millSec = t2.getTime();
    //获取秒
    long t1_sec = t1_millSec/1000;
    long t2_sec = t2_millSec/1000;
    System.out.println(t1_sec);
    System.out.println(t2_sec);
    //获取总分钟
    long t1_min = t1_sec / 60;
    long t2_min = t2_sec / 60;
    //获取小时
    long t1_hour = t1_min/60;
    long t2_hour = t2_min/60;
    //获取分钟
    long t1_minute = t1_min % 60;  //0
    long t2_minute = t2_min % 60;  //44
    System.out.println("您上网的时间差为:"+Math.abs(t1_hour-t2_hour)+"小时"+Math.abs(t1_minute-t2_minute)+"分钟;");
} catch (ParseException e) {
    e.printStackTrace();
}

四、字符串详解

1.字符串的扩展用法

字符串是程序中使用频率最高的一种数据类型,Java 的 JDK 提供了非常多的使用方法
首先来看看两种创建字符串的方式:

String s1 = "胡辣汤";
String s2 = new String("狗不理");


这两种方式在内存中创建的方式不同,但是在我们使用上, 是没有什么区别和影响的。
接下来, 看看有哪些操作吧:

package com.xyq.str;
public class TestString {
    public static void main(String[] args) {
        String s = "今天特别想吃哈密瓜";
        //charAt(int) 获取到字符串中某个位置的字符.  从0开始数
        System.out.println(s.charAt(0)); // 今
        System.out.println(s.charAt(4)); // 想

        // concat(String) 字符串拼接. 和+是一样的
        System.out.println(s.concat("伊丽莎白")); // 今天特别想吃哈密瓜伊丽莎白
        //今天特别想吃哈密瓜 深坑: 字符串是不可变的. 不论做什么操作, 原来的字符串不会发生改变, 每次操作都是返回一个新字符串
        System.out.println(s);

        // contains(String) 判断字符串中是否包含xxx
        System.out.println(s.contains("明天"));  // false
        System.out.println(s.contains("哈密瓜"));  // true

        // startswith(String) 判断字符串是否以xxxx开头
        // endswith(String) 判断字符串是否以xxxx结尾
        System.out.println(s.startsWith("今天"));  // true
        System.out.println(s.endsWith("哈密瓜"));  // true

        // equals(String)  判断两个字符串内容是否一致
        // equalsIgnoreCase(String)  判断两个字符串内容是否一致(忽略大小写)
        System.out.println("abc".equals("abc")); // true
        System.out.println("abc".equalsIgnoreCase("ABC")); // true

        // indexOf(String) 根据给定的字符串计算该字符串首次出现的位置 ->  从前向后
        // lastIndexOf(String) 根据给定的字符串计算该字符串最后出现的位置-> 从后向前
        System.out.println(s.indexOf("特别")); // 2
        System.out.println(s.lastIndexOf("哈密瓜")); // 6

        // isEmpty() 判断字符串是否是空字符串
        System.out.println("".isEmpty()); // true
        System.out.println("   ".isEmpty()); // false

        // length() 字符串的长度 -> 有多少个字符组成(区别数组长度 arr.length)
        System.out.println(s.length());  // 9

        // replace(String, String)  把xxx替换成xxx
        String s1 = s.replace("今天", "昨天");
        System.out.println(s); // 今天特别想吃哈密瓜          没变~~~~ 字符串不可变哦
        System.out.println(s1);  // 昨天特别想吃哈密瓜        获得的新字符串

        // replaceFirst(String, String); 替换第一个
        String s2 = s.replace("天", "日");
        System.out.println(s2);  // 今日特别想吃哈密瓜

        // split(String regex)  字符串切割,返回字符串数组
        String[] strs = s.split("想吃");  // 使用"想吃"进行字符串切割. 切割的结果放在字符串数组中
        System.out.println(strs[0]);  // 今天特别
        System.out.println(strs[1]);  // 哈密瓜

        //	split(String regex, int limit)  分成3份
        String arr[] = "a_b_c_d_e".split("_",3);
        for (String item:arr) {
            System.out.println(item);       //a  b  c_d_e
        }

        // subString(int beginIndex, int endIndex)  字符串截取. 从xxx截取到xxx
        //如果不给endIndex 就从beginIndex 截取到字符串结尾
        String s3 = s.substring(2, 4);
        System.out.println(s3);  // 特别

        // toUpperCase(); 转化成大写
        // toLowerCase(); 转化成小写
        String s4 = "abcDefGhIJKLMN";
        System.out.println(s4.toUpperCase());
        System.out.println(s4.toLowerCase());

        // trim(); 去掉左右两端的空格
        String s5 = "    哇哈哈哈哈     ";
        System.out.println(s5.trim()); //哇哈哈哈哈

        //hashCode()   返回该字符串的哈希值
        System.out.println("xiong".hashCode()); //114060759
        System.out.println("zhao".hashCode());  //3737564
    }
}

总结:

  • 字符串是不可变的。不论做什么操作, 原来的字符串不会发生改变, 每次操作都是返回一个新字符串;

.compareTo() 方法

A.compareTo(B)  //比较A B

返回值
返回值是整型,它是先比较对应字符的大小(ASCII 码顺序),如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值,如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方结束。

  • 如果参数字符串等于此字符串,则返回值 0;
  • 如果此字符串小于字符串参数,则返回一个小于 0 的值;
  • 如果此字符串大于字符串参数,则返回一个大于 0 的值。
String str1 = "Strings";
String str2 = "Strings";
String str3 = "Strings123";
int result = str1.compareTo( str2 );
System.out.println(result);		//0
result = str2.compareTo( str3 );
System.out.println(result);		//-3
result = str3.compareTo( str1 );
System.out.println(result);		//3

2.StringBuffer 和 StringBuilder

在前面的学习中我们了解到字符串是一个不可变的数据类型。也就是说一旦字符串被创建好, 就不可以被修改。并且每次操作都会返回一个新的字符串,如果反复的对字符串进行操作,此时势必会造成大量的内存浪费。
比如:“我的妈呀”+”你的妈呀”+”谁的妈呀”+”怎么这么卡”,在老的 JDK 中 每次相加都会产生一个新的字符串, 非常的浪费内存资源, 但是在新版本中, JDK 对这里进行了优化。每次 + 都是执行用的 StringBuilder 中的字符串拼接方法。为什么呢? 因为 StringBuilder 是可以改变的字符串,都在原来的基础上进行操作。所以不会产生内存浪费,接下来我们来看看这个叫 StringBuilder 的东西。
StringBuilder: 可变的字符串
用法:

package com.xyq.str;
public class TestStringBuilder {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(); // 空的字符串.
        StringBuilder sb2 = new StringBuilder("王二麻子的麻子特别特别麻"); // 也可以给出具体的字符串. 都OK
        sb2.append(", 李二麻子的麻子就不是特别麻");  // 在后面追加
        System.out.println(sb2);  // 王二麻子的麻子特别特别麻, 李二麻子的麻子就不是特别麻
        //还可以追加整数
        sb2.append(123); //可以追加任何数据类型
        //在指定位置插入
        sb2.insert(3, "插入");// 还可以在中间插入
        System.out.println(sb2);  // 王二麻插入子的麻子特别特别麻, 李二麻子的麻子就不是特别麻123

        String s = sb2.toString(); // 转化回正常的普通字符串
        System.out.println(s);
    }
}

关于 StringBuilder, 咱们就说这么多. 足够大家在平时使用了
StringBuffer 和 StringBuilder 基本上一模一样,区别是StringBuffer 线程安全,StringBuilder 线程不安全
等到后面我们学到线程的时候, 在给大家说他俩的区别,就目前而言. 你可以认为没区别。

五、DecimalFormat 小数格式化

DecimalFormat 顾名思义, 就是用来格式化数字的,这东西有什么用? 想想 10/3.0 得到那种无限循环小数,现实生活中价格都要保留小数点后两位怎么办??? 就可以通过 DecimalFormat 对小数进行格式化处理。

package com.xyq.num;
import java.text.DecimalFormat;
public class TestNumberFormat {
    public static void main(String[] args) {
        double d = 9/2.0;
        System.out.println(d);

        DecimalFormat df = new DecimalFormat(".00"); 	// 保留小数点后两位
        String s = df.format(d);
        System.out.println(s); // 4.50

        DecimalFormat df2 = new DecimalFormat(".##"); 	// 保留小数点后两位
        String s2 = df.format(d);
        System.out.println(s2); // 4.50
    }
}

格式:

这一堆格式中, 我们程序员要用的就三个:
0 : 数字
# : 数字
. : 小数点

.00 和 .## 是一样的,都是保留两位小数

用法案例

  1. 判断某个人是不是姓张
Scanner sc  = new Scanner(System.in);
System.out.println("请输入一个人的名字:");
String name = sc.nextLine();
System.out.println(name.startsWith("张")?"是的":"不是");		//三元表达式
  1. 打印字符串中每一个字符
String s = "I love you";
for(int i = 0; i < s.length(); i++){
   System.out.println(s.charAt(i));
}
//当然还可以用for each方法
  1. 有如下学生信息, 请计算并打印出每个学生的平均分
String[] stus = {"小绿_数学_12_语文_33_英语_42", "钢管男_数学_25_语文_56_英语_27","泰斯波尔_数学_99_语文_88_英语_120"};
for(int i =0; i < stus.length; i++){
    String stu = stus[i]; // 获取到每个学生的信息
    // 把学生信息进行切割得到数组  {"小绿","数学","12","语文","33","英语","42"}
    String[] stuInfo = stu.split("_");
    String name = stuInfo[0];
    String math = stuInfo[2];
    String chinese = stuInfo[4];
    String english = stuInfo[6];
    // 字符串转化成数字 Integer.parseInt()
    int total = Integer.parseInt(math)+Integer.parseInt(chinese)+Integer.parseInt(english);
    double avg = total / 3.0;
    System.out.println(name+"平均分: "+avg);
}
  1. 让用户输入一个数学表达式: 3+6+9+18 , 编程完成数学表达式的计算
package com.xyq.homework;
import java.util.Scanner;
public class Test1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个加法表达式:");
        String content = sc.nextLine(); // 3+6+9+12
        // 去除字符串中所有空格," xiong  ".trim() 去除字符串左右两端空格
        content = content.replace(" ", "");
        // 切割
        // + 是正则表达式的一个元字符. 此时想要用+切割. 这里必须要写\\+, 关于正则, 后面会专门找一章来给大家讲解.
        String[] strs = content.split("\\+");
        for(int i = 0; i < strs.length; i++){
            System.out.println(strs[i]);
        }
    }
}
  1. 计算手速

效果:

准备测试. 请狂按enter
你按了
你按了
你按了
你按了
你按了
你按了
你按了
你按了
你按了
你按了
// 20秒后
// 您的手速是: 30.28次/秒

编程实现:

package com.xyq.homework;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class Test2 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("游戏随时可以开始, 按enter开始");
        sc.nextLine(); // 程序停在这里,直到用户按下Enter键

        int count  = 0;
        //计算出结束游戏的时间
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.SECOND, cal.get(Calendar.SECOND)+20); // 向后算20秒
        Date end = cal.getTime();
        long endlong = end.getTime();  //时间撮
        while(endlong - new Date().getTime()>=0){ // 时间差是0. 结束游戏
            sc.nextLine();
            System.out.println(count);
            count++; // 按了一次
        }
        double rate = count / 20.0;  // 计算频率
        DecimalFormat df = new DecimalFormat(".00"); // 格式化数字
        System.out.println("一共按了"+count+"次, 您的手速是:" + df.format(rate)+"/秒");
    }
}

六、Object 类

变量和类型 方法 描述
protected [Object](Object.html) [clone](#clone())() 创建并返回此对象的副本。
boolean [equals](#equals(java.lang.Object))([Object](Object.html) obj) 指示某个其他对象是否“等于”此对象。
[类](Class.html)<?> [getClass](#getClass())() 返回此 Object的运行时类。
实际上就是当前运行的.java 程序的包名+类名 如com.xjt.duo_tai.Dog
int [hashCode](#hashCode())() 返回对象的哈希码值。
void [notify](#notify())() 唤醒正在此对象监视器上等待的单个线程。
void [notifyAll](#notifyAll())() 唤醒等待此对象监视器的所有线程。
[String](String.html) [toString](#toString())() 返回对象的字符串表示形式。
void [wait](#wait())() 导致当前线程等待它被唤醒,通常是 通知中断
void [wait](#wait(long))(long timeoutMillis) 导致当前线程等待它被唤醒,通常是 通知中断 ,或者直到经过一定量的实时。
void [wait](#wait(long,int))(long timeoutMillis, int nanos) 导致当前线程等待它被唤醒,通常是 通知中断 ,或者直到经过一定量的实时。

toString()

读源码,光标选中该方法按下 Ctrl+B

Animal a1 = new Dog();
System.out.println(a1);    //com.xjt.duo_tai.Dog@2f4d3709

//查看System.out.println(a1);源码流程
/*1.
public void println(String x) {
    if (getClass() == PrintStream.class) {
        writeln(String.valueOf(x));
    } else {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
}*/

/*2.
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}*/

/*3.getClass().getName() 返回com.xjt.duo_tai.Dog 包名全路径
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}*/

通过 IDEA 编辑器重写 Animal 类的 toString 方法

@Override
public String toString() {
    return "Animal{" +
        "name='" + name + '\'' +
        ", age=" + age +
        '}';
}

equals()

Animal a1 = new Dog("汪汪叫","小白");
Animal a2 = new Dog("汪汪叫","小白");
System.out.println(a1 == a2);		//false
System.out.println(a1.equals(a2));	//false

//源码中equals() 比较的是两个对象的地址
public boolean equals(Object obj) {
    return (this == obj);
}

通过 IDEA 方式生成重写 Animal 类的 equals 方法
image.png

七、Arrays

首先自己手写一个冒泡排序

public static String bubble(int[] arr){
    for (int i = 0; i < arr.length-1; i++) {
        for (int j = 0; j < arr.length-1-i; j++) {
            if(arr[j]>arr[j+1]){
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    StringBuilder sb = new StringBuilder("[");
    for (int item:arr
        ) {
        sb.append(item).append(",");
    }
    sb.deleteCharAt(sb.length()-1).append("]");
    return sb.toString();
}

因为排序算法非常常用,因此 Arrays 类给我们提供了,请看下面 Arrays 类的常用方法:

方法名 描述
public static void sort(int[] arr) 将指定的数组按升序排序。
public static String toString(int[] arr) 返回指定数组内容的字符串表示形式
int[] arr = {12, 56, 3, 41, 68, 20, 6, 8, 5, 10};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));	//[3, 5, 6, 8, 10, 12, 20, 41, 56, 68]

import java.util.Arrays    
@工具类的设计思想:

  • 构造方法用 private 修饰(外界无法实例化,通过类名调用方法)
  • 成员用 public static 修饰,可直接用 类名.方法 调用

八、日期时间类

Date 类

java.util.Date

构造方法

构造器 描述
[Date](#%3Cinit%3E())() 分配 Date对象并对其进行初始化,使其表示分配时间,测量 Date到毫秒。
[Date](#%3Cinit%3E(long))(long date) 分配 Date对象并初始化它以表示自标准基准时间(称为“纪元”)以来的指定毫秒数,即 1970 年 1 月 1 日 00:00:00 GMT。

方法

方法 描述
public long getTime() 返回自此 Date对象表示的 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数。

| public void setTime(long time)

| 将此 Date对象设置为表示格林威治标准时间 1970 年 1 月 1 日 00:00:00 之后的 time毫秒的时间点。 |

示例:

Date dt = new Date();
long time = dt.getTime();
System.out.println(time);   //1604413154803 毫秒

long tm = 1*1000*60*60;
Date dt2 = new Date();
dt2.setTime(tm);
System.out.println(dt2);    //Thu Jan 01 09:00:00 CST 1970
//CST中国标准时间,东八区与格林尼治时间相差8小时

SimpleDateFormat

java.text.SimpleDateFormat

构造方法

构造器 描述
[SimpleDateFormat](#%3Cinit%3E())() 构造一个 SimpleDateFormat使用默认模式和日期格式符号默认 FORMAT区域设置。
[SimpleDateFormat](#%3Cinit%3E(java.lang.String))([String](../lang/String.html) pattern) 构造一个 SimpleDateFormat使用给定的模式和默认的默认日期格式符号 FORMAT区域设置。
[SimpleDateFormat](#%3Cinit%3E(java.lang.String,java.text.DateFormatSymbols))([String](../lang/String.html) pattern, [DateFormatSymbols](DateFormatSymbols.html) formatSymbols) 使用给定的模式和日期格式符号构造 SimpleDateFormat
[SimpleDateFormat](#%3Cinit%3E(java.lang.String,java.util.Locale))([String](../lang/String.html) pattern, [Locale](../util/Locale.html) locale) 使用给定模式和给定语言环境的默认日期格式符号构造 SimpleDateFormat

方法

方法 描述
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) 将给定的 Date为日期/时间字符串,并将结果附加到给定的 StringBuffer
@Deprecated public static long parse(String s) 尝试将字符串s解释为日期和时间的表示

示例:

Date d1 = new Date();
SimpleDateFormat sdf = new SimpleDateFormat();
String t1 = sdf.format(d1);
System.out.println(t1);     //2020/11/3 下午10:42

SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String t2 = sdf2.format(d1);
System.out.println(t2);     //2020-11-03 22:42:42

Date dt = sdf2.parse("2020-11-03 22:42:42");
System.out.println(dt);     //Tue Nov 03 22:42:42 CST 2020

案例:日期工具类
说明:类名.stringToDate(Date,format) 将日期 Date 对象转化为格式化时间字符串
类名.dateToString(String,format) 将格式化时间字符串转化为日期 Date 对象
注意:工具类的设计思想,可参考上文

public class DateUtils {
    private DateUtils() {
    }

    public static String dateToString(Date dt, String format){
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        String fmt = sdf.format(dt);
        return fmt;
    }

    public static Date stringToDate(String time,String format) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date tt = sdf.parse(time);
        return tt;
    }
}

//测试
Date date = new Date();

String s1 = DateUtils.dateToString(date, "yyyy-MM-dd HH:mm:ss");
System.out.println(s1);     //2020-11-04 09:41:21

String s2 = DateUtils.dateToString(date, "yyyy年MM月dd日");
System.out.println(s2);     //2020年11月04日

String s3 = DateUtils.dateToString(date, "HH:mm:ss");
System.out.println(s3);     //09:41:21

String tm = "2020-11-11 12:10:52";
Date date1 = DateUtils.stringToDate(tm, "yyyy-MM-dd HH:mm:ss");
System.out.println(date1);      //Wed Nov 11 12:10:52 CST 2020

Calendar 日历类

静态字段

字段声明 字段 描述
public static final int YEAR YEAR 年份
public static final int MONTH MONTH 月份

| public static final int DATE
public static final int DAY_OF_MONTH | DATE
DAY_OF_MONTH | 日 |
| public static final int WEEK_OF_YEAR | WEEK_OF_YEAR | 当年的第几周 |
| public static final int WEEK_OF_MONTH | WEEK_OF_MONTH | 当年的第几个月 |
| public static final int DAY_OF_YEAR | DAY_OF_YEAR | 当年的第几天 |
| public static final int DAY_OF_WEEK | DAY_OF_WEEK | 一周中的第几天 |
| public static final int DAY_OF_WEEK_IN_MONTH | DAY_OF_WEEK_IN_MONTH | 一个月中第几周 |
| public static final int HOUR
public static final int HOUR_OF_DAY | HOUR
HOUR_OF_DAY | 小时(12 小时制)
小时(24 小时制) |
| public static final int MINUTE | MINUTE | 分钟 |
| public static final int SECOND | SECOND | 秒 |

构造方法

Calendar instance = Calendar.getInstance();

方法

方法声明 描述 示例
public int get(int field) 返回给定日历字段的值 Calendar instance = Calendar.getInstance();

int year = instance.get(Calendar.YEAR);
int month = instance.get(Calendar.MONTH)+1;
int day_of_month = instance.get(Calendar.DAY_OF_MONTH);
int date = instance.get(Calendar.DATE);
int hour = instance.get(Calendar.HOUR);
int minute = instance.get(Calendar.MINUTE);
int second = instance.get(Calendar.SECOND); |
| public abstract void add(int field, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 | //需求 1:5 年前的今天 instance.add(Calendar.YEAR,-5);//需求 2:3 年后的 10 天前//        instance.add(Calendar.YEAR,3); |
| public final void set(int year, int month, int date) | 设置日历字段的值(年月日) | instance.set(2020,11,11); |

示例:

Calendar instance = Calendar.getInstance();
//        Date time = instance.getTime();
//        System.out.println(time);   //Wed Nov 04 10:13:48 CST 2020
//
//        int year = instance.get(Calendar.YEAR);
//        int month = instance.get(Calendar.MONTH)+1;
//        int day_of_month = instance.get(Calendar.DAY_OF_MONTH);
//        int date = instance.get(Calendar.DATE);
//        System.out.println(year+"年"+month+"月"+day_of_month+"日");
//        System.out.println(date);

//需求1:3年前的今天
//        instance.add(Calendar.YEAR,-3);
//        int year = instance.get(Calendar.YEAR);
//        int month = instance.get(Calendar.MONTH)+1;
//        int day_of_month = instance.get(Calendar.DAY_OF_MONTH);
//        System.out.println(year+"年"+month+"月"+day_of_month+"日");

//需求2:2年后的10天前
//        instance.add(Calendar.YEAR,2);
//        instance.add(Calendar.DATE,-10);
//        int year = instance.get(Calendar.YEAR);
//        int month = instance.get(Calendar.MONTH)+1;
//        int day_of_month = instance.get(Calendar.DAY_OF_MONTH);
//        System.out.println(year+"年"+month+"月"+day_of_month+"日");

//        int hour = instance.get(Calendar.HOUR);
//        int minute = instance.get(Calendar.MINUTE);
//        int second = instance.get(Calendar.SECOND);
//        System.out.println(hour+","+minute+","+second);

案例:
image.png

instance.set(2020,2,1);
instance.add(Calendar.DATE,-1);
System.out.println(instance);
/*
* java.util.GregorianCalendar[time=1582944375527,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=2020,MONTH=1,WEEK_OF_YEAR=9,
* WEEK_OF_MONTH=5,DAY_OF_MONTH=29,DAY_OF_YEAR=60,DAY_OF_WEEK=7,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=46,SECOND=15,MILLISECOND=527,ZONE_OFFSET=28800000,DST_OFFSET=0]
* */
int day = instance.get(Calendar.DATE);
System.out.println(day);        //29

文章作者: CoderXiong
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 CoderXiong !
  目录