本博客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类,不再赘述)
都学习到这里了,不妨关注点赞一下~