Java云同桌学习系列(六)——常用类库

本博客java云同桌学习系列,旨在记录本人学习java的过程,并与大家分享,对于想学习java的同学,我希望这个系列能够鼓励大家一同与我学习java,成为“云同桌”。

每月预计保持更新数量三章起,每章都会从整体框架入手,介绍章节所涉及的重要知识点及相关练习题,并会设置推荐学习时间,每篇博客涉及到的点都会在开篇目录进行总览。(博客中所有高亮部分表示是面试题进阶考点)

学习时间:一周半
学习建议:本章内容较多,所涉及的类都是未来开发常用类,需要以实践为主,最后能够对每个类的常用方法都亲手敲一遍,加深记忆。


1.中文API文档获取

本节所涉及内容,基本都是对java源码的分析和总结,配合官方的源码阅读效果更加,也推荐在java学习过程中,多阅读官方Java源码。对于英文有阅读困难的同学,可以在网上搜索对应JDK版本的API中文文档进行阅读,若网上资源没有找到,可私信(424197379@qq.com)博主单独联系发送中文JDK11API文档。



2.泛型

泛型,即将数据类型也参数化,在编写时不指定数据类型由泛型替代,在调用时传入具体的数据类型

泛型在类中的使用

1.泛型的在类中的定义(泛型字母可以随意定义)

publiic class Example<T>{
//传入一个泛型数据类型
    //声明一个泛型变量data
    private T data;

}

2.泛型的调用类的指定

//传入泛型具体的数据类型
public class Mainexample{
    //传入String类的泛型
   Example<String> example = new Example<>();
}

泛型在接口中的使用

1.泛型在接口的定义

public interface Example<T>{
    T getdata();//返回值为T的抽象方法
}

2.泛型在实现接口时的指定(可以选择是否对泛型进行类型指定,如若不指定,继续使用泛型)

class Test2 implements Example<String> {

    public String getdata(){
        System.out.println("hhh");
        return null;
    }
}

泛型在方法中的使用

泛型定义在方法的声明,且只在此方法范围内有效

public static void main(String[] args) {

    Test2 test2 = new Test2();
    test2.getdata(5.5555);//此处指定泛型为double
}


static class Test2  {

    public <T> String getdata(T a) {//传入泛型形参变量a
        System.out.println(a);  //输出5.5555
        return null;
    }
}

泛型也可以对所接受的数据类型进行限制,

<T extends 类或接口1 & 接口2>

即限制此处的泛型,指定时必须是继承于某某类或实现了某某接口

泛型中也可以使用通配符代替具体的类型实参

1   <? extends Parent> 指定了泛型类型的上届
2   <? super Child> 指定了泛型类型的下届
3   <?> 指定了没有限制的泛型类型

泛型不会进入运行阶段,在编译时便会去泛型化,即指定类型后,会自动将泛型的相关信息擦除



3.package与import关键字

package关键字:

java中,在类的上面会有一条package语句,

package dao;//表示该类存放在此package下

在访问权限中,也有对包的限制,如只有public、protected、default才能访问其他包的内容

import关键字

在访问之前,还需要将包导入进来,即通过import语句

import dao.ExpressDao;//表示导入dao包下的ExpressDao类

由于java.lang包非常常用,编译器会自动导入java.lang,可以直接使用其下的类

import导入包有两种形式:

1.单类型导入,如import java.util.Random;
2.按需类型导入,如import java.util.*

单类型导入可以使编译器一次性查找到需要的类文件

按需类型导入并不是说导入该路径下的所有类,而是到该路径下进行查找所需要用到的类,这样不会影响java代码的执行效率,但会提高java代码的编译速度。



4.对象常用类之objects

ps:都是干货

java.util.objects
介绍:此类所包含的静态方法,常用于操作对象或在操作前检查某些条件使用,直接 类名.方法名 就可以使用

常用方法:

  • isNull(Object o)

见名知意,如果传入的对象为null,则返回true,如果传入的对象不是null,则返回false

String string = "hello world";
System.out.println(Objects.isNull(string));//false
  • nonNull(Object o)

与上一个方法刚好相反,只有传入一个非空对象时,才回返回true

  • equals(Object a,Object b)

检查传入的两个对象是否相等,相等返回true,不相等返回false,相比Object的equals()方法,这里增加了对空对象的考虑(在不确定对象是否为空的请况下比较时比较常用)

String string1 = null;
String string2 = "hello world";
System.out.println(Objects.equals(string1,string2));//false
System.out.println(string1.equals(string2));//空指针异常
  • requireNonNull(T obj)

检查指定对象是否为空,如果是空,则抛出一个空指针异常

String string1 = null;

try {
    Objects.requireNonNull(string1);
}catch (NullPointerException e){
    System.out.println("对象为空");
}
//输出:对象为空
  • checkIndex(int index,int length)

检查传入的int变量index,是否在范围[0,length)内,如在此范围,返回index值,如不在,抛出IndexOutOfBoundsException(下标越界)异常

System.out.println(Objects.checkIndex(3,4));//3
System.out.println(Objects.checkIndex(4,4));//IndexOutOfBoundsException
  • checkFromToIndex(int fromIndex, int toIndex, int length)

检查传入的[fromIndex,toIndex)是否在[0,length)的范围内,如果在,返回fromIndex,如果不在,抛出下标越界异常

System.out.println(Objects.checkFromToIndex(3,4,4));//3
  • checkFromIndexSize(int fromIndex, int size, int length)

检查传入的[fromIndex,fromIndex+size)是否在[0,length)的范围内,如果在,返回fromIndex,如果不在,抛出下标越界异常

System.out.println(Objects.checkFromIndexSize(3,1,4));//3
  • toString( Object o)

将传入的对象转化成字符串输出,相比于Object类的toString(),此方法可以接受对象为空,对象为空时转化的字符串为“null”

String string1 = null;
String string2 = "hh";
System.out.println(Objects.toString(string1));//null
System.out.println(new Object().toString(string1));//Object类的toString无法编译
System.out.println(Objects.toString(string2));//hh
  • toString(Object o, String nullDefault)

将传入的对象转化成字符串输出,相比于Object类的toString(),此方法可以接受对象为空,对象为空时转化的字符串为“nullDefault”,即输入第二个参数,将其作为空对象的默认字符串

String string1 = null;
System.out.println(Objects.toString(string1));//null
System.out.println(Objects.toString(string1,"这是个空对象"));//这是个空对象


5.数学常用类Math

**java.lang.Math(自动导入)

介绍:此类所包含的静态方法,常用于执行基本数字运算的方法使用:直接 类名.方法名 就可以使用

常用方法:

  • abs(double a)

返回所传double值的绝对值,特别地,参数为0,返回0,参数无限大,结果是正无穷大

System.out.println(Math.abs(-5));//5
  • round(double a)

返回所传参数的四舍五入的int值

System.out.println(Math.round(5.5));//6System.out.println(Math.round(5.4));//5
System.out.println(Math.round(-5.6));//-6,相当于-6+0.4,舍去0.4,得-6
System.out.println(Math.round(-5.5));//-5,相当于-6+0.5,入一位,得-5
System.out.println(Math.round(-5.4));//-5,相当于-6+0.6,入一位,得-5
  • floor(double a)

返回所传参数的向下取整double值

System.out.println(Math.floor(5.9));//5.0
System.out.println(Math.floor(-5.1));//-6.0
  • ceil(double a)

返回所传参数的向上取整double值

System.out.println(Math.floor(5.1));//6.0
System.out.println(Math.floor(-5.9));//-5.0
  • pow(double a, double b)

返回a的b次幂的double值

System.out.println(Math.pow(2,3));//8.0
  • max(double a, double b)

返回a,b中的最大值,double类型

System.out.println(Math.max(2.0,3.0));//3.0
  • min(double a, double b)

返回a,b中的较小值,double类型

System.out.println(Math.min(2.0,3.0));//2.0
  • random()

返回一个[0.0,1.0)范围内的double类型伪随机数,可以通过额外的加减和乘除获得其他范围的随机数

System.out.println(Math.random());//0.8504752206028524
System.out.println(Math.random());//0.6191899065874201
System.out.println(Math.random());//0.5293749508235337
  • sin(double a)

返回所传参数的sin值,即三角正弦值

  • cos(double a)

返回所传参数的cos值,即三角余弦值

  • tan(double a)

返回所传参数的tan值,即三角正切值



6.数组常用类Arrays

java.util.Arrays

介绍:

  • 此类所包含的静态方法,常用于操作数组的各种方法(例如排序和搜索)。
  • 此类还包含一个静态工厂,允许将数组视为列表。
  • 如果指定的数组引用为null,则此类中的方法都抛出NullPointerException ,除非另有说明。

使用: 类名.方法名 就可以使用

常用方法:

  • sort(int[] a)

将指定的数组按升序排序(采用双枢轴快速算法)

int[] arr = new int[]{3,2,1};
Arrays.sort(arr);
for(int i=0;i<arr.length;i++){    
	System.out.print(arr[i]);    
	System.out.print(" ");
}
//输出:1 2 3
  • sort(int[] a, int fromIndex, int toIndex)

将数组a中下标在 [fromIndex,toIndex)范围的值,进行升序排序

int[] arr = new int[]{3,2,1,7,4,9,1};

Arrays.sort(arr,0,6);

for(int i=0;i<arr.length;i++){
    System.out.print(arr[i]);
    System.out.print(" ");
}
//输出:1 2 3 4 7 9 1
  • asList(T… a)

返回有指定数组支持的固定大小的List集,此方法与Collection.toArray()结合使用,作为基于数组和基于集合的API之间的桥梁。

int[] arr = new int[]{3,2,1,7,4,9,1};

List<int[]> a = Arrays.asList(arr);

但是需要注意的是,这里转换后的ArrayList并不是java.util.ArrayList,而是Arrays的内部类,并且转换后的list,并且转换后的Arraylist是final修饰的,不可以进行add添加等等的操作,Arrays该部分的源码如下:

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
        ..........
}
  • compare(int[] a, int[] b)

从下标为0开始,依次按顺序比较两个数组的每个数据,直到遇到第一个不相同的数据

若该不相同的下标处:

a[i]>b[i],则返回    1
a[i]<b[i],则返回    -1

若没有数据不相同的位置,即两个数组数据顺序和值完全相等返回0

若数组a == null,返回    -1
若数组b == null,返回     1
int[] arr1 = new int[]{3,2,1,7,4,9,1};
int[] arr2 = new int[]{3,2,1,9,4,9,1};//下标为3的数据不同
System.out.println(Arrays.compare(arr1,arr2));//输出-1


int[] arr3= new int[]{3,2,1,9,4,9,1};
int[] arr4 = new int[]{3,2,1,7,4,9,1};//下标为3的数据不同
System.out.println(Arrays.compare(arr3,arr4));//输出1


int[] arr5= new int[]{3,2,1,7,4,9,1};
int[] arr6 = new int[]{3,2,1,7,4,9,1};//两个数组数据相同
System.out.println(Arrays.compare(arr5,arr6));//输出0
  • copyOf(int[] original, int newLength)

返回一个新数组,该数组的长度是min(newLength,original.length),新数组的数据为原数组下标范围在[0,新数组长度)的数据

int[] arr1 = new int[]{3,2,1,7,4,9,1};

int[] arr2 = Arrays.copyOf(arr1,3);

for(int i=0;i<arr2.length;i++){
    System.out.print(arr2[i]);
    System.out.print(" ");
}
//输出:3 2 1
  • copyOfRange(int[] original, int from, int to)

返回一个新数组,该数组的长度是to-from(负数则产生异常),新数组的数据为原数组下标范围在[from,to)的数据

int[] arr1 = new int[]{3,2,1,7,4,9,1};

int[] arr2 = Arrays.copyOfRange(arr1,3,5);

for(int i=0;i<arr2.length;i++){
    System.out.print(arr2[i]);
    System.out.print(" ");
}
//输出:7 4
  • equals(int[] a, int[] a2)

    如果传入的两个数组的包含相同元素数量

     元素顺序相同且元素数据也相同,返回true,否则,返回false
     两个数组如果都是null,也返回true
    
int[] arr1 = new int[]{3,2,1,7,4,9,1};
int[] arr2 = new int[]{3,2,1,7,4,9,1};
int[] arr3 = new int[]{3,2,1,8,4,9,1};//下标3数据不同

int[] arr4 = null;
int[] arr5 = null;

System.out.println(Arrays.equals(arr1,arr2));//true
System.out.println(Arrays.equals(arr2,arr3));//false
System.out.println(Arrays.equals(arr1,arr4));//false
System.out.println(Arrays.equals(arr4,arr5));//true
  • fill(int[] a, int val)

将指定的int值分配给指定的int数组的每个元素。

int[] arr = new int[]{3,2,1,7,4,9,1};

Arrays.fill(arr,0);

for(int i=0;i<arr.length;i++){
    System.out.print(arr[i]);
    System.out.print(" ");
}
//输出:0 0 0 0 0 0 0
  • mismatch(int[] a, int[] b)

查找并返回两个int数组之间第一个不匹配数据的索引,否则如果未找到不匹配则返回-1。
索引将在0(包括)范围内,直到较小数组的长度(包括)。

int[] arr1 = new int[]{3,2,1,7,4,9,1};
int[] arr2 = new int[]{3,2,1,7,4,9,1};
int[] arr3 = new int[]{3,2,1,7,4,8,1};//下标为5的数据不同

System.out.println(Arrays.mismatch(arr1,arr2));//-1
System.out.println(Arrays.mismatch(arr2,arr3));//5


7.精确数值常用类BigDecimal

介绍:此类所包含的静态方法,常用于精准计算

System.out.println(0.1+0.2);//输出:0.30000000000000004,直接计算不够精确

故在追求高精度精准计算的情况下使用此类

构造方法举例:

BigDecimal(double val)
BigDecimal bigDecimal = new BigDecimal(0.1);

常用方法:

1.add(BigDecimal augend)                        //加
2.subtract(BigDecimal subtrahend)               //减
3.multiply(BigDecimal multiplicand)             //乘
4.divide(BigDecimal divisor)                    //除

//都是将计算结果返回至一个新的BigDeciaml对象

转化相关的方法:

  • valueOf(double val)

静态方法,通过类名.方法名使用

作用:将 double转换为 BigDecimal

BigDecimal bigDecimal2 = BigDecimal.valueOf(a);
  • doubleValue()

将 BigDecimal转换为 double

double b = bigDecimal1.doubleValue();


8.时间常用类类Date,DateFormat,SimpleDateFormat


java.util.Data

介绍: 表示特定的时刻,精度为毫秒,在JDK 1.1之前, Date类还有两个附加功能。 它允许将日期解释为年,月,日,小时,分钟和秒值。 它还允许格式化和解析日期字符串。 不幸的是,这些功能的API不适合国际化。 从JDK 1.1开始, Calendar类应该用于在日期和时间字段之间进行转换,而DateFormat类应该用于格式化和解析日期字符串。

构造方法:

//Date(),获得当前时间
Date date = new Date();
System.out.println(date);
//输出:Fri Sep 18 20:46:29 CST 2020
// 当前时间2020.9.18 20:46

常用方法:

  • getTime()

返回自格林威治时间(1970年1月1日00:00:00 GMT)至今的毫秒数,返回值为long

Date date = new Date();
long l = date.getTime();
System.out.println(l);
//输出:1600433477720
//电脑当前时间2020.9.18 20:51 

java.text.DateFormat

介绍: 是日期/时间格式化子类的抽象类,可以对日期/时间进行格式化控制显示

类:抽象类

构造方法:DateFormat(),创造新的日期格式(抽象类的构造方法只能通过子类创建时调用)

常用方法:
在SimpleDateFormat里进行了描述,通常是由SimpleDateFormat对象进行调用


java.text.SimpleDateFormat

介绍: 是DateFormat的直接子类,允许为日期/时间自定义格式模板

构造方法:

  • SimpleDateFormat()

构造一个SimpleDateFormat使用默认模式和日期格式符号默认的格式模板

  • SimpleDateFormat(String pattern)

允许用户自定义一个日期/时间格式模板,定义方式为:

y-年,M-月,d-日,H-时,m-分,s-秒字母的数量代表显示的对应时间的格式位数,
如:yyyy 代表 4位显示年的数字
如:yyyy.MM.dd  HH:mm:ss 代表 2001.07.04 12:08:56中间可以插入任意字符,
如:yyyy年MM月dd日 HH:mm:ss  代表 2001年07月04日 12:08:56

常用方法:

  • 继承自父类的 format(Date date)

将一个Date对象添加该DateFormat对象时间/日期格式,返回一个String字符串

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//设置格式
String string = simpleDateFormat.format(new Date());
System.out.println(string);//输出:2020年09月18日 21:10:20
//1.通过SimpleDateFormat设置格式
//2.Date对象获取时间,然后添加格式
//3.输出:2020年09月18日 21:10:20
  • 继承至父类的 parse(String source)

从给定字符串解析格式,得到无格式的date对象时间,相当于format的反作用

Date date = simpleDateFormat.parse("2020年09月18日 21:10:20");//会产生受检异常
System.out.println(date.getTime());//输出:1600434620000

java.util.Calendar

介绍: 解决了Date类日期国际化的问题,里面提供了操作日历的相关方法

有一个数组field[],存放了获取到的日历的相关字段属性,如年,月,日,每个月的天数,每年的天数,分别以不同的下标存放在该日历数组中,在查看时,可通过相关方法指定要查看的字段名查看

类:抽象类

构造方法:

Calendar(),使用默认的时区和语言构造日历(抽象类的构造方法只能通过子类创建时调用)

通常更多的是,直接调用类的static方法getInstance()方法取得Calendar对象

常用方法:

  • getInstance()

使用默认时区和区域设置获取日历,返回一个Calendar对象,较为常用的获取该对象的方式

Calendar calendar = Calendar.getInstance();
  • get(int field)

获取该Calendar对象中某个字段的值(可通过常量名指定,或直接输入常量对应的数组下标),返回一个获取到的int值,常用的字段有:

YEAR = 1 //年
MONTH = 2//月
DATE = 5//日
DAY_OF_MONTH = 5//该月的第几天
DAY_OF_YEAR = 6//该年的第几天
DAY_OF_WEEK = 7//该周第几天
HOUR = 10//小时
MINUTE = 12//分
SECOND = 13//秒

以DAY_OF_WEEK为例:

Calendar calendar = Calendar.getInstance();
int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(day_of_week);//7
  • set(int field, int value)

更改该Calendar对象的某个字段的值

Calendar calendar = Calendar.getInstance();//获取当前默认时间
int date = calendar.get(Calendar.DATE);//获取日期字段值
System.out.println(date);//输出:19,显示当前日期
calendar.set(Calendar.DATE,20);//将此对象的日期设为20
date = calendar.get(Calendar.DATE);//获取日期字段值
System.out.println(date);//输出:20,显示新的日期
  • add(int field, int amount)

更改该Calendar对象的某个字段的值,将该字段值+amount

注意,计算机中:1-7分别对应星期日-星期六,0-11分别对应小时0点(中12点)-11点

Calendar calendar = Calendar.getInstance();//获取当前默认时间
int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(day_of_week);//输出:7,当前编写代码时是星期六
calendar.add(Calendar.DAY_OF_WEEK,1);
day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(day_of_week);//输出:1,星期日存储为1


Calendar calendar2 = Calendar.getInstance();//获取当前默认时间
int h = calendar2.get(Calendar.HOUR);
System.out.println(h);//输出:10,当前编写代码时是上午10点
calendar2.add(Calendar.HOUR,2);
h = calendar2.get(Calendar.HOUR);
System.out.println(h);//输出:0,中午12点
  • getTime()

获取此Calendar对象的Date对象

Date date = calendar.getTime();


相关练习题

某公司软件开发工程师孙工,作息规律为上三天班,休息一天,经常不确定休
息日是否周末,为此,请你开发一个程序,当孙工输入年及月,以日历方式显示对
应月份的休息日,用中括号进行标记.同时,统计出本月有几天休息,轮到周末休
息有几天.(注:首次休息日是 2020 年 2 月 2 日)

参考源代码:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;

/**
 * @description: 找到休息日(常用类库)
 * @author: southwindow
 * @create: 2020-09-19 11:22
 **/

/*
某公司软件开发工程师孙工,作息规律为上三天班,休息一天,经常不确定休
息日是否周末,为此,请你开发一个程序,当孙工输入年及月,以日历方式显示对
应月份的休息日,用中括号进行标记.同时,统计出本月有几天休息,轮到周末休
息有几天.(注:首次休息日是 2020 年 2 月 2 日)
 */
public class Task10301001 {

    static Scanner scanner = new Scanner(System.in);
    static Calendar calendar = Calendar.getInstance();

    static int dayOffNum = 0;
    static int dayOffWeekendNum = 0;
    public static void main(String[] args){


        /*
        用户输入模块
         */
        System.out.println("请输入年:");
        int yearInput = inputRight(2020,2060);//假如孙工还能再干40年
        System.out.println("请输入月:");
        int monthInput = inputRight(1,12);

        //录入用户输入的年和月份
        calendar.set(Calendar.YEAR,yearInput);
        //0-11对应1-12月
        calendar.set(Calendar.MONTH,monthInput-1);

        /*
        用户输出模块
         */


        try {
            //显示日历
            showWeekend();
            //本月休息天数
            dayOff_Of_Month();
            //本月周末休息天数
            dayOffWeekend_Of_Month();

        }catch (ParseException e){
            System.out.println("哦,不好意思,程序出了一些问题,请重启一下程序。");
        }


    }

    public static int inputRight(int min,int max) {

        String s = scanner.nextLine();
        int num = -1;
        try {
            num = Integer.parseInt(s);
        }catch (NumberFormatException e){
            System.out.println("输入内容的格式不正确,请重新输入");
            return inputRight(min,max);
        }

        if(num<min || num>max){
            System.out.println("输入的数字不在范围内,请重新输入");
            return inputRight(min,max);
        }
        return num;

    }

    public static void showWeekend() throws ParseException {

        int[] weekArray = new int[37];

        System.out.println("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六\t");

        //从每月的第一天开始输出
        calendar.set(Calendar.DATE,1);

        //确定该月的第一天是周几,1-7分别对应周日-周六
        int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
        //System.out.println("***********" +day_of_week);//调试

        //确定该月共多少天
        int maxDay_of_month = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        //将天数编号放入数组
        for(int i = 1;i<maxDay_of_month+1;i++){
            weekArray[day_of_week-1+(i-1)] = i;
        }

        //显示日历
        for(int i = 0;i<weekArray.length;i++){
            //0占位不显示
            if(weekArray[i] == 0){
                System.out.print(" \t\t");
            }else{
                //休息日
                if(isDayOff(weekArray[i])){
                    System.out.print("[" +weekArray[i]+ "]" + " \t");//细节,\t前加个空格,\t就指代下一个TAB了
                    dayOffNum++;
                    //在周末的休息日
                    if(isWeekend(weekArray[i])){
                        dayOffWeekendNum++;
                    }
                }else{
                    //正常日子
                    System.out.print(weekArray[i]+ "\t\t");
                }
                //如果这天是周六,则换行
                if(isSaturday(weekArray[i])){
                    System.out.println();
                }
            }
        }
        //全部显示完毕后换行
        System.out.println();



    }

    public static boolean isSaturday(int day){
        //如果这一天是这一周的第7天,则这天是周六

        //0占位符不检测
        if(day == 0){
            return false;
        }
        //先弄一个临时操作的日历对象
        Calendar calendarTemp = (Calendar) calendar.clone();
        //将其改为传过来的那天
        calendarTemp.set(Calendar.DATE,day);
        //如果这一天是这一周的第7天,则这天是周六
        if(calendarTemp.get(Calendar.DAY_OF_WEEK) == 7){
            return true;
        }else{
            return false;
        }
    }

    public static boolean isWeekend(int day){
        //如果这一天是这一周的第7天或第6天,则这天是周末

        //0占位符不检测
        if(day == 0){
            return false;
        }
        //先弄一个临时操作的日历对象
        Calendar calendarTemp = (Calendar) calendar.clone();
        //将其改为传过来的那天
        calendarTemp.set(Calendar.DATE,day);
        //如果这一天是这一周的第7天或第6天,则这天是周末
        if(calendarTemp.get(Calendar.DAY_OF_WEEK) == 7 ||
                calendarTemp.get(Calendar.DAY_OF_WEEK) == 1 ){
            return true;
        }else{
            return false;
        }
    }

    public static boolean isDayOff(int day) throws ParseException {
        //上三休一,4天一个周期,如果传过来的这一天距离2020年2月2日的天数是4的倍数,则是休息日

        /*
           获得该天的格林威治毫秒数
         */
        Calendar calendarTemp = (Calendar)calendar.clone();
        calendarTemp.set(Calendar.DATE,day);
        //获得Date对象,然后再获得毫秒数
        long day_milliseconds = calendarTemp.getTime().getTime();


        /*
            获得初始日期2020.2.2的格林威治毫秒数
         */

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parse = simpleDateFormat.parse("2020-02-02");
        //获得毫秒数
        long initDay_milliseconds = parse.getTime();


        //问题,秒数零头干扰计算
        //如果传过来的日期在2020.2.2之前,则必定工作日,因为2020.2.2是第一个休息日
        if(day_milliseconds < initDay_milliseconds){
            return false;
        }

        //毫秒数之差,毫秒/1000=秒,秒/60=分钟,分钟/60=小时,小时/24=天数,天数%4==0就知道是不是休息日
        if((int)((initDay_milliseconds - day_milliseconds) / (1000*60*60*24)) %4 == 0 ){
            return true;
        }else {
            return false;
        }
    }

    public static void dayOff_Of_Month(){
        System.out.println("本月的休息天数有:" +dayOffNum+ "天");
    }

    public static void dayOffWeekend_Of_Month(){
        System.out.println("本月轮到周末的休息天数是:" +dayOffWeekendNum+ "天");
    }
}

运行结果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



9.字符串相关类String、StringBuffer、StringBuilder

java.lang.String

介绍:字串符控制的主要常用类

特点:

内部采用字符数组存储字符串,长度不可变

类被关键字final修饰,不可被继承

一个String对象被创建,包含在这个对象中的字符序列是不可改变的(该类的一些方法看似改变了字符串,其实内部都是创建一个新的字符串)

使用:String类比较特殊,有两种比较常用的声明字符串对象的形式:

(1)通过“字面量”的形式直接赋值
String s =123;
(2)通过“new”关键字调用构造函
数创建对象String s = new String("123");

创建对象方式的区别:

(1)通过“字面量”的形式直接赋值创建对象,会在“常量池”中直接创建该字符串常量,然后指向该常量
(2)通过“new”关键字调用构造函数创建对象,需要先在堆中创建字符串变量,然后对象指向该变量的地址这样导致的结果就是,每次new出的String无论内容是否相同,必定是“! = =”的;通过“字面量”赋值创建对象,如果内容相同,那么两个对象就会指向同一个常量,内容相同,则对象“= =”。

常用方法:(非静态类,通过 对象.方法 调用)

  • charAt(int index)

传入一个下标,返回该下标索引指定的单个字符

  • compareTo(String anotherString)

按字母顺序比较两个字符串(基于每个字符的Unicode值)

当两个字符串某个位置的字符不同时,返回的是这一位置Unicode值的差
当两个字符串相同时,则返回两个字符串长度之差

System.out.println("abc".compareTo("abc"));//0
System.out.println("abc".compareTo("aBc"));//32,大写字母Unicode值比小写字母小32
System.out.println("abcd".compareTo("abc"));//1
  • concat(String str)

将指定的字符串连接到此字符串的末尾

`System.out.println("abc".concat("cde"));//abccde`
  • indexOf(int ch)

返回指定字符(ch是该指定字符的Unicode值,此处可直接赋字符,因为int类型会自动转为Unicode值)第一次出现的下标索引

System.out.println("abc".indexOf('c'));//2
  • indexOf(int ch, int fromIndex)

从起始下标索引fromIndex开始,返回指定字符第一次出现的下标索引

  • split(String regex)

将原字符串依据字符串regex进行拆分,拆分成若干String按顺序存放到String[]数组中

String s = "a,b,c";String[] str = s.split(",");
System.out.println(Arrays.toString(str));//[a, b, c],以逗号为边界,进行了拆分
  • replace(char oldChar, char newChar)

将原字符串中所有的oldChar字符都替换成newChar字符,返回一个新的字符串

System.out.println("aabbcc".replace('c','d'));//aabbdd
  • replace(String target,String replacement)

将原字符串中所有的“target”字符串替换成“replacement”字符串,返回一个新的字符串

System.out.println("aabccabc".replace("abc","123"));//a123c123
  • substring(int beginIndex)

返回一个从索引beginIndex开始,一直到结尾的字符串

System.out.println("abc".substring(1));//bc
  • substring(int beginIndex, int endIndex)

返回一个从索引beginIndex(包括)开始,一直到endIndex(不包括)的字符串


不推荐在String类直接进行大量的字符串连接操作,会极大的占用内存空间,String的另外两个兄弟类可以解决这个问题


java.lang.StringBuffer

介绍:线程安全,可变字符串类

特点:

线程安全,字符串缓冲区可供多个线程使用

可以对原字符串进行修改

长度默认是16字符,可自动动态扩容

主要操作是append和insert方法,它们被重载以接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符追加或插入字符串缓冲区

常用方法:

  • append(String str)

将指定的字符串追加到此字符序列后

StringBuffer stringBuffer = new StringBuffer("123");
stringBuffer.append("456");
System.out.println(stringBuffer);//123456
  • insert(int offset, String str)

将指定的字符串str追加到,指定下标位置offset

StringBuffer stringBuffer = new StringBuffer("123");
stringBuffer.insert(0,"456");
System.out.println(stringBuffer);//456123

java.lang.StringBuilder

介绍:线程不安全,可变字符串类

特点:

线程不安全,通常用于单个线程使用字符串缓冲区,在可能的情况下,建议使用此类优先于StringBuffer因为在大多数实现中它会更快。

可以对原字符串进行修改

长度默认是16字符,可自动动态扩容

主要操作是append和insert方法,它们被重载以接受任何类型的数据。 每个都有效地将给定的数据转换为字符串,然后将该字符串的字符追加或插入字符串缓冲区

常用方法:(等同于StringBuffer类,不再赘述)




都学习到这里了,不妨关注点赞一下~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南窗木心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值