Java 常用类
记录一些Java 学习使用, 经常使用类进行总结.. 这个文章感觉还是很有必要的
后面会常总结扩展...
String字符串相关的类
String Java.lang包
Java中字符串被称作为 String 类型对象来处理 String类是Java设计人员预先提供一个非常有用的类
Java.lang包中!
- String是一个final类,代表不可变的字符序列
- 字符串是常量,用双引号引起来表示。它们的值:
在创建之后不能更改
- String对象的字符内容是存储在一个字符数组value[]中的
- 实现了
序列化
Comparable比较器
CharSequence
接口
String对象的创建:
子面量定义方式;
String s = "Hello World"; 就是我们常用的方式...
String代表不可变的字符序列,简称不可变性:
在不new String(""); 情况直接赋值相同值String类型对象,==比较是相同的;
String a = "abc";
String b = "abc";
boolean isok = (a==b); 结果为true;(==比对象比地址)
原因:
Java首次通过字面量方式声明给一个字符串赋值时,会将字符串值声明在: "Jvm方法区中常量池里,并把地址赋值给,栈空间中的String对象上;"
当又一个String对象以字面量的方式赋同样的值,它会直接引用相同的地址值;
所以: "字面量赋值相同的String对象值 == 比较值相同结果为: true" (其实就是地址相同;
String不可变性:
当对字符串的值,重新赋值/拼接时,常量池中会出现你新赋值的一个空间字符串,需要重新指定常量池的地址值;而不是在改变原先空间的值;
String s = new String();
new创建一个空字符串,相当于底层new char[0];
在堆空间创建出,空间存储值,并把地址复制给,栈空间的对象引用;
所以:
String s = new String("s");
String s1 = new String("s");
boolean isok = (s==s1); 结果为 false
对象指向的是堆空间的地址,new一个就产生一个...所以两个new对象的地址永远不会true;
但因为String值是存放在 常量池中的...所以其实真实情况是: "对象栈———指向> 堆地址 ——指向> 方法区"
String的内存解析:
首先我们要知道:Java创建对象
- JVM 里面有两个用于存储对象的空间
堆
栈
堆:存放所有new出来的对象
栈:存放基本类型的变量数据和对象的引用
对象本身不存放在栈中,而是存放在:堆 或 常量池;引用类型栈对象只指向堆的地址~
所以: new a 和 new b 程序在堆空间开启了两个地址,a b指向的堆地址不同
a==b==比较地址返回 false
首先对于对象引用类型,程序每
new
一次的操作, 都会在JVM的堆空间中开辟一个内存空间...String类的常用方法();
这里就不一一举例了,使用多了自然就会用了...
int .length(); //返回字符串长度;
char[] .toCharArray(); //String 与 char[]数组转换;
//char[]数组转换成String String str = new String(char[]);
byte[] .getBytes(); //String 与 byte[]数组转换; byte类型值是数值类型的哦; a对应97...
注意中文: 分为一个/多个字节,注意编码格式; .getBytes();使用编辑器默认编码格式,可以通过.getBytes("utf-8");指定编码格式;
一个中文utf-8是3个字节; GBK是2个字节;
boolean .isEmpty(); //判断字符串是否是否是空字符;
str.length()==0; 空true 则false
boolean .startWith(str); //判断当前字符串是否以 str开头是true则false 区分大小写;
boolean .endsWith(str); //判断当前字符串是否以 str结尾是true则false 区分大小写;
boolean .contains(); //该方法判断字符串中是否有指定字符内容,
有true 无则false;
eg: ABCD.conntains("ABC"); true;
int .compareTo(String); //比较字符串大小;可进行字符串排序;
str.compareTo(str1); 一个给比较内部值 负数str小,正数str大 0str一样大等于str1;
char .charAt(int); //获取指定位置的字符;
注意数组越界 "String归根结底是一个 char[] 字符数组!"
String .replace("1","2"); //替换将字符串
指定位置1字符/字符串,替换为2字符/字符串;
boolean .equals(String); //比较字符串值是否一致 String
"String重写了Object类的equals(Objetc o)方法;"
String .toLowerCase(); //转换 字符串 中英文字母 为小写;
返回字符串小写形式,不影响堆/常量池
String .toUpperCase(); //转换 字符串 中英文字母 为大写;
返回字符串大写形式,不影响堆/常量池
String .concat(); //字符串1 .concat(字符串2);
将2内容追加在 1后面返回字符串; 也可以用'+' 拼接但效率低下;
String .trim(); 返回一个不含空格的字符串;将字符串中所有空格取消;
int .indexof(''); 从头开始搜索 获取字符在字符串中的位置:
下标 0开始 如果没有 该字符返回 -1; //如果参数是字符串以第一个字符为准
int .lastIndexof(''); 从后搜索第一个符合指定字符的位置 0开始没有返回 -1; //如果参数 是 字符串 以第一个 字符为准
String .Substring(int); //提取从索引位置开始到后面所有的 字符串 返回;
String .Substring(int1,int2); //提取范围内字符串;
String[] .spilt(String,int); //拆分:
根据 String 字符为拆分 字符进行拆分 返回 拆分后字符串数组[] 如果不指定 String 则 按 每个单字符 返回 数组;
int 用来限制返回数组中元素个数; "可选,默认即不限制返回String[] 数组!";
还可以是 正则表达式: |表示,或: str.spilt(",|."); 根据 逗号 或 句号 拆分!
StringBuffer
StringBuffer:
- 我们都知道,String类,并不适合频繁的拼接,
每次拼接,其实是在JVM 方法区中有重复创建一个
字符常量数组! - Java.lang.StringBuffer代表
可变的字符序列
即,可以动态的拼接String 而不会开辟新的空间消耗内存! - 很多方法与String相同,作为参数传递时,方法内部可以改变值。
创建:
StringBuffer类不同于String,其对象必须使用构造器生成 有三个构造器
- StringBuffer()
初始容量为16的字符串缓冲区
本质上StringBuffer 底层也是一个字符数组,但不是常量数组长度可以动态改变的
默认长度16 - StringBuffer(int size) 构造指定容量的字符串缓冲区
- StringBuffer(String str) 将内容初始化为指定字符串内容 String s = new String("我喜欢学习");
StringBuffer类的常用方法:
StringBuffer s = new StringBuffer(); //声明一个空 StringBuffer对象;底层相当于 new char[16];
StringBuffer s = new StringBuffer("ABC"); //声明一个字符串 "ABC", 底层相当于 new char["abc".length()+16];
总而言之:
就是会,预存多几个位置,供添加,如果还是超过了16,放心不会越界,反而它还会变大.自动扩容原长度*2...哈哈.
注意的是 s.length(); 长度还是你本身的字符长度....
StringBuffer .toString(); //将StringBuffer 类型字符串 转换为String 类型对象返回; Object类方法 一些写类重写了其方法(自定义类也可以重其方法);
StringBuffer .append(String); //拼接指定字符串效率高..在char[]数组后添加..
StringBuffer .insert(int位置,参数); //在字符串指定位置 int 中插入参数; 参数可以实 String 任何类型....;
StringBuffer .delete(int start,int end); //删除指定位置的内容
StringBuffer .replace(int start, int end, String str); //把[start,end)位置替换为str
StringBuffer .reverse(); //把当前字符串逆转!
StringBuilder
StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且 提供相关功能的方法也一样
总结:
String、StringBuffer、StringBuilder
- 三者都是操作字符串的一种类:
- String(JDK1.0):不可变字符序列
- StringBuffer(JDK1.0):可变字符序列、效率低、
线程安全
- StringBuilder(JDK 5.0):可变字符序列、效率高、
线程不安全
三者执行效率:
- String < StringBuffer < StringBuilder
注意:
作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder 会改变其值
String 是一种特殊的 引用类型
, StringBuffer 和 StringBuilder 相当于还是一种 引用类型的对字符串操作的一种类!
JDK8 之前的日期时间 API
世界时间:
时间是一个非常抽象的概念,多少年来,吸引着无数科学家、物理学家、甚至哲学家花费毕生精力去解释时间的本质是什么
- 这里我们不探讨高深莫测的学术知识,只把目光放聚焦在计算机这个很小的范畴内。
- 具体可以了解这里(大佬~)
计算世界时间的主要标准:
UTC Coordinated Universal Time
- 世界标准时间:
- 协调世界时是以原子时秒长为基础,国际原子时的准确度为每日数纳秒,原子钟
现在我们使用的互联网就采用该计时标准
- 经严谨计算得到的时间,精确到秒,误差在0.9s以内, 是比GMT更为精确的世界时间
GMT Greenwich Mean Time
- 格林威治时间
- 英国伦敦格林威治定为0°经线开始的地方,地球每15°经度 被分为一个时区,共分为24个时区,相邻时区相差一小时
中国北京位于东八区,GMT时间比北京时间慢8小时
- 格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时, 时间
CST Central Standard Time
- 中亚时间
中国: 北京时间~
- 四个不同时区的缩写:
Central Standard Time (USA) UTC-6:00 美国标准时间
Central Standard Time (Australia) UTC+9:30 澳大利亚标准时间
China Standard Time UTC+8:00 中国标准时间
Cuba Standard Time UTC-4:00 古巴标准时间
在Java8之前时间API:
- java.util.Date:表示Java中的日期,但是能够操作到时间级别,
如今这个类中的很多方法都已经被废弃,不建议使用;
Date主要负责存储一个绝对时间并对两边提供操作接口
- java.sql.Date:表示数据库时间,只能操作到日期,不能读取和修改时间;
- java.sql.Time:表示数据库时间;
- java.sql.Timestamp:时间戳;
- Calendar:工具类,提供时间的加减等复杂操作,支持时区;
Calendar负责对Date中特定信息,比如这个时间是该年的第几个星期
此外,还可以通过set,add,roll接口来进行日期时间的增减 - TimeZone:表示时区;
- SimpleDateFormat:日期格式化类,非常常用
SimpleDateFormat主要作为一些格式化的输入输出
Date java.util包
构造器:
java.util 包提供了 Date 类来封装当前的日期和时间 Date 类提供两个构造函数来实例化 Date 对象
第一个构造函数使用当前日期和时间来初始化对象
new Date();
第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
new Date(long l);
第三个还有很多构造器被 @Deprecated 被Java过时注解标记为,以过期了... "并不是不能使用,而是不建议使用...已经过期了."
@Deprecated
public Date(int year, int month, int date){ ... } "该构造器输入的 年月日 创建日期对象, year month 并不准确存在偏移量!"
应该是这个被淘汰了吧, JDK8出现LocalDate "和他功能类似!"
...
常用方法:
long getTime( ) 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
String toString( ) 把此 Date 对象转换为以下形式的 String
dow mon dd hh:mm:ss zzz yyyy 其中:dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)
boolean after(Date date) 若当调用此方法的Date对象在指定日期之后返回true,否则返回false
boolean before(Date date) 若当调用此方法的Date对象在指定日期之前返回true,否则返回false
int compareTo(Date date) 比较当调用此方法的Date对象和指定日期。两者相等时候返回0,
调用对象在指定日期之前则返回负数
调用对象在指定日期之后则返回正数
boolean equals(Object date) Date 重写的Object类的方法! 使其比较的不在是地址!
Demo:
package com.wsm.date;
import java.util.Date;
/**
* Java.util.Date 时间类的使用:
*/
public class DateDemo {
public static void main(String[] args) {
//Java.util 包提供了 Date类来封装当前的日期和时间
//Date类提供两个构造函数来实例化 Date 对象
//new Date(); 构造器;
Date d1 = new Date(); //默认获取当前日期;
System.out.println("new Date():\t"+d1); //Date类默认重写的 toString(); 不直接打印地址!但,因为Java是老外开发的,日期格式并不符号中国~
//new Date(Long l); 构造器;
long l = System.currentTimeMillis(); //获取当前日期时间戳..毫秒数~
Date d2 = new Date(l); //根据: 给定的时间戳,获取指定日期...
System.out.println("new Date(Long):\t"+d2);
//还有很多其它的构造器,但是都过期了..
//Java注解: @Deprecated 注释的方法类,表示JDK以过期不在维护的类,但并不影响使用...!
/**
* Date常用方法:
*/
System.out.println("getTime():\t"+d1.getTime()); //getTime(): 返回自1970 年 1 月 1 日 00:00:00 GMT 以来此Date对象,表示的毫秒数;
System.out.println("toString():\t"+d1.toString()); //toString(): 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 格式;
// dow 是一周中的某一天 (Sun, Mon, Tue, Wed, Thu, Fri, Sat)
// zzz是时间标准,
/** 其它很多方法都过时了 */
}
}
Java.sql.Date
实例化 和 sql.Date 和 util.Date 相互转换;
package com.wsm.date;
import java.util.Date;
/**
* java.sql.Date对应着数据库中的日期类型的变量
* java.sql.Date extends java.util.Date 继承Util.Date
*/
public class SqlDateDemo {
public static void main(String[] args) {
//创建java.sql.Date对象:
//对应数据中的日期变量!`虽然如此但是好像还是很少使用,一般也直接使用 util.Date`
java.sql.Date date = new java.sql.Date(35235325345L); //它只包含日期而没有时间部分,输出时候只显示年月日!
System.out.println(date); //1971-02-13
/** 如何将java.util.Date对象转换为java.sql.Date对象 */
//情况一:
//sql.Date 本质上继承了 util.Date
Date date1 = new java.sql.Date(2343243242323L); //子类赋值父类
java.sql.Date dateS = (java.sql.Date) date1; //然后在强转回, 因为date1 本来就是 sql.Date类型 可以强转回 sql.Date;
System.out.println(dateS);
/** 运行报错! 父类前置转换成子类... */
//情况二:
// java.sql.Date date2 = (java.sql.Date)new Date(); //父类直接强转子类,编译不报错运行报错
//因为:
// 子类直接向上转换成父类, 并可以强转回子类:
// 子类本身继承父类拥有父类的属性方法,本身属于 父类/子类可以来回转换!
// 但:
// 子类继承父类,可以声明自己特有的方法属性... 父类直接转换子类,可能回不存在特有的属性方法(); 故程序报错!
/** java.util.Date对象转换为java.sql.Date对象 */
//情况三:
// util.Date 存在一个方法 getTime(); 返回,当前对象时间戳。
//而: sql.Date 刚好构造函数, 可以通过..时间戳声明!
Date date3 = new Date();
java.sql.Date date4 = new java.sql.Date(date3.getTime());
System.out.println("Java.util.Date:"+date3);
System.out.println("Java.sql.Date:"+date4);
}
}
总结:
sql.Date 本身继承于 util.Date
: 拥有 util.Date 的属性方法..
- sql.Date 是为了,和数据库的日期类型进行匹配赋值使用,
但实际开发中更多还是
util.Date - sql.Date 格式只能是:年月日
- util.Date 格式可以是:年月日时分秒...
Java.text.SimpleDateFormat
Date类的API不易于国际化,大部分被废弃了
SimpleDateFormat 是对日期类Date的格式化 和 解析;
Date类型的toString 输出的是英文格式的时间,而不同国家有自己的日期格式...- SimpleDateFormat 就可以以特定的规则进行日期的 格式化Format
SimpleDateFormatDemo
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* SimpleDateFormat类:
* Date类的格式化 —— 解析
* 格式化:日期 --->字符串
* 解析:格式化的逆过程,字符串 ---> 日期
*
*/
public class SimpleDateFormatDemo {
public static void main(String[] args) throws ParseException {
//实例化SimpleDateFormat:使用默认的构造器
SimpleDateFormat sdf = new SimpleDateFormat(); /** 默认的解析规则就是:(两位)年 月 日 ... */
//格式化:日期 --->字符串
Date date = new Date();
System.out.println(date);
//格式化~
String format = sdf.format(date);
System.out.println(format);
//解析:格式化的逆过程,字符串 ---> 日期
Date date1 = sdf.parse(format); /** 需要处理异常: 这里就throws 抛出了~ */
System.out.println(date1);
/** 使用最多... */
//*************按照指定的方式格式化和解析:调用带参的构造器*****************
// SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//格式化
String format1 = sdf1.format(date);
System.out.println(format1);
//解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),
//否则,抛异常~
Date date2 = sdf1.parse("2020-02-18 11:48:27");
System.out.println(date2);
}
}
日期和时间的格式化编码
字母 | 描述 | 示例 |
---|---|---|
G | 纪元标记 | AD |
y | 四位年份 | 2001 |
M | 月份 | July or 07 |
d | 一个月的日期 | 10 |
h | A.M./P.M. (1~12)格式小时 | 12 |
H | 一天中的小时 (0~23) | 22 |
m | 分钟数 | 30 |
s | 秒数 | 55 |
S | 毫秒数 | 234 |
E | 星期几 | Tuesday |
D | 一年中的日子 | 360 |
F | 一个月中第几周的周几 | 2 (second Wed. in July) |
w | 一年中第几周 | 40 |
W | 一个月中第几周 | 1 |
a | A.M./P.M. 标记 | PM |
k | 一天中的小时(1~24) | 24 |
K | A.M./P.M. (0~11)格式小时 | 10 |
z | 时区 | Eastern Standard Time |
' | 文字定界符 | Delimiter |
" | 单引号 | ` |
java.util.Calendar 日历类
Calendar是一个抽象类,主用用于完成日期字段之间相互操作的功能
- Calendar实例的方法
1.使用Calendar.getInstance()方法
2.调用它的子类GregorianCalendar的构造器 - 一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想要的时间信息
常量: YEAR年
、MONTH月
、DAY_OF_WEEK这一周第几天
、HOUR_OF_DAY这一月第几天
MINUTE分钟
、SECOND秒
通过get(常量);
获取指定的~ - 常用方法
public final Date getTime()
public void set(int field,int value)
public void add(int field,int amount)
public final void setTime(Date date)
注意:
- 获取月份时:一月是0,二月是1,以此类推,12月是11
获取星期时:周日是1,周二是2 , 。。。。周六是7
CalendarDemo.Java
import java.util.Calendar;
import java.util.Date;
/** 日历类对象Calendar 使用; */
public class CalendarDemo {
public static void main(String[] args) {
//1.实例化
//方式一:创建其子类(GregorianCalendar)的对象
// Calendar gregoriancalendar = new GregorianCalendar();
//方式二:调用其静态方法getInstance()
Calendar calendar = Calendar.getInstance(); //获取当前日期的: Calendar日历对象!
// System.out.println(calendar.getClass());
//2.常用方法
//get():
// 根据常量参数,获取对应的日期值~
int days = calendar.get(Calendar.DAY_OF_MONTH); //获取当月的第几天~
System.out.println("当月的第"+days+"天"); //打印!
System.out.println("当年的第"+calendar.get(Calendar.DAY_OF_YEAR)+"天"); //获取当年的第几天~
//set()
//calendar可变性
// 给当前日历对象 进行年月赋值 返回值void: 直接返回给当前对象赋值~
calendar.set(Calendar.DAY_OF_MONTH,22); //给当前日历对象设置为: 当月第22天
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println("修改日历为当月,第"+days+"天"); //打印: 22
//add(): 给当前日历对象进行 + - 操作
calendar.add(Calendar.DAY_OF_MONTH,-3);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days); //打印: 22-3
//getTime():日历类---> Date
// 根据当前日历对象的时间,返回一个Date类型数据~
Date date = calendar.getTime();
System.out.println(date);
//setTime():Date ---> 日历类
// 将一个Date类型数据,转换为: 日历对象!
Date date1 = new Date();
calendar.setTime(date1);
days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
}
}
JDK8 新增的日期时间 API
前言:
Java8 之前的日期,Date JDK1.0 时引入
基本可以满足基本的需求。
但,我们希望时间可以与昼夜 季节 四季有关,JDK1.1 引入了
Calendar类
- 而Calendar类并不比Date类好多少,它们面临的问题
可变性:
calendar.set(Calendar.DAY_OF_MONTH,22); //给当前日历对象设置为: 当月第22天 Calendar类的: Set(); 方法,赋值会直接改变当前的类对象,这在Java 被成为 "可变性"
偏移性:
JDK8 之前时间的类Date 类其实是存在一个构造器: "可以直接年月日返回 Date对象..." 但 Date中的年份是从1900开始的,而月份都从0开始, "直接赋值年月日,实际上返回的日期并不准确,Date是存在偏移量的!" //JDK8之前日期问题...Date存在便宜量~ @Test public void offsetDate(){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //Date(year, month, date); Date d1 = new Date(2000, 9, 9); //创建一个2020 9月9日的日期对象; System.out.println("Date类存在偏移量:"); System.out.println("未设置偏移量输出:"+sdf.format(d1)); //设置便宜量: //Date 正因为存在偏移量,而被淘汰! 而年便宜了 1900年 月默认从0开始~所以 2020 09 09 应该这个样写! Date d2 = new Date(2000-1900, 9-1, 9); System.out.println("设置偏移量输出: "+sdf.format(d2)); //正常输出 20200909 } //控制台输出: Date类存在偏移量: 未设置偏移量输出:3900-10-09 设置偏移量输出: 2000-09-09
- 格式化:
格式化只对Date有用,Calendar则不行。 此外,它们也不是线程安全的;不能处理闰秒等。
Java8 新增API
对日期和时间的操作一直是Java程序员最痛苦的地方之一
因此:
- Java8 之前出现了,
Joda-Time.Jar包
周大-泰~ 来更方便的操作,日期API - 而后,JDK8之后,为了方便用户操作,直接集成了该Jar包的功能!
不在需要用户,每次都要引入Joda-Time.Jar
依赖~
当然如果,你现在公司是Java7 你还想用这些时间ApI 还需要引入Joda-Time.Jar包
- 本地日期(LocalDate)
本地时间 (LocalTime)
本地日期时间(LocalDateTime)
时区(ZonedDateTime)
.... - 为了方便操作,
古老的
Data类 Java8之后,也新增了toInstant() 方法;
用于将,Date 转换成新的表示形式,这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。
LocalDate / Time / DateTime
LocalDate、LocalTime、LocalDateTime
- LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类
它们的实例 是不可变的对象
- 分别表示使用 ISO-8601日历系统的日期、时间、日期和时间
它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息 - LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期
- LocalTime表示一个时间,而不是日期
- LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一
ISO
ISO 国际标准化组织(International Organization for Standardization
常用方法
方法 描述 now()
now(ZoneId zone)静态方法,根据当前时间创建对象/指定时区的对象 of() 静态方法,根据指定日期/时间创建对象 getDayOfMonth()
getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366) getMonthValue()
getYear()获得月份(1-12) /获得年份 getHour() getMinute() getSecond() 获得当前对象对应的小时、分钟、秒 withDayOfMonth() withDayOfYear() withMonth() withYear() 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 plusDays() plusWeeks() plusMonths() plusYears() plusHours() 向当前对象添加几天、几周、几个月、几年、几小时 minusMonths() minusWeeks() minusDays() minusYears() minusHours() 从当前对象减去几月、几周、几天、几年、几小时
Demo
LocalDateTimeDemo.Java
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
/**
* JDK8之后的日期API
* LocalDate 年月日~
* LocalTime 时分秒~
* LocalDateTime 年月日时分秒~
* 三者,方法类似,都是JDK8 之后新增的日期类,分别用于表示不同的时间 日期 时间日期 描述的Java对象!
*/
public class LocalDateTimeDemo {
/** LocalDate LocalTime LocalDateTime 使用/常用方法();
* LocalDateTime相较于LocalDate、LocalTime,使用频率要高
* 类似于Calendar
* */
public static void main(String[] args) {
//now():获取当前的日期、时间、日期+时间
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("localDate:\t"+localDate);
System.out.println("localTime:\t"+localTime);
System.out.println("localDateTime:\t"+localDateTime);
/** 三个类重写了toString(); 直接输入的就是中国的日期格式~ */
//of():设置指定的年、月、日、时、分、秒。没有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);
System.out.println(localDateTime1);
//getXxx():获取相关的属性
System.out.println(localDateTime.getDayOfMonth()); //获取当前日是这个月的第几天
System.out.println(localDateTime.getDayOfWeek()); //获取当前时间是一周中的哪一天
System.out.println(localDateTime.getMonth()); //获取当前月份
System.out.println(localDateTime.getMonthValue()); //获取月份信息
System.out.println(localDateTime.getMinute()); //获取分钟
/** 三个类均可调用类似的方法~ 注意要存在符合的条件~ */
/** 体现不可变性 */
//withXxx():设置相关的属性
// LocalDate 对象通过withxx(); 给日期对象设置日期属性,但是,并不会改变当前对象,而是会返回一个对象,是更高后的日期~ 本类并不会收受到影响~
LocalDate localDate1 = localDate.withDayOfMonth(22);
System.out.println("更新前对象:"+localDate);
System.out.println("更新后对象:"+localDate1);
//plusxxx(); 向当前对象添加几天、几周、几个月、几年、几小时
LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
System.out.println(localDateTime);
System.out.println(localDateTime3);
//minusxxx(); 向当前对象添加几天、几周、几个月、几年、几小时
LocalDateTime localDateTime4 = localDateTime.minusDays(6);
System.out.println(localDateTime);
System.out.println(localDateTime4);
}
//JDK8之前日期问题...Date存在便宜量~
@Test
public void offsetDate(){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//Date(year, month, date);
Date d1 = new Date(2000, 9, 9); //创建一个2020 9月9日的日期对象;
System.out.println("Date类存在偏移量:");
System.out.println("未设置偏移量输出:"+sdf.format(d1));
//设置便宜量:
//Date 正因为存在偏移量,而被淘汰! 而年便宜了 1900年 月默认从0开始~所以 2020 09 09 应该这个样写!
Date d2 = new Date(2000-1900, 9-1, 9);
System.out.println("设置偏移量输出: "+sdf.format(d2)); //正常输出 20200909
}
}
Instant
Instant
时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳
常用方法
方法 描述 now() 静态方法,返回默认UTC时区的Instant类的对象 UTC即本初子午线的时间...
与北京时间, 存在偏差~ofEpochMilli(long epochMilli) 静态方法,返回在1970-01-01 00:00:00基础上加上指定毫秒 数之后的Instant类的对象 atOffset(ZoneOffset offset) 结合即时的偏移来创建一个 可以通过它来, 向东偏移8 表示东八区北京时间!
OffsetDateTime toEpochMilli() 返回1970-01-01 00:00:00到当前时间的毫秒数,即为时间戳 Demo
InsantDemo.Java
import java.time.Instant; import java.time.OffsetDateTime; import java.time.ZoneOffset; /*** * Instant 类的Demo学习 * */ public class InsantDemo { public static void main(String[] args) { //now():获取本初子午线对应的标准时间 Instant instant = Instant.now(); System.out.println(instant);//2019-02-18T07:29:41.719Z // //北京世界东八区! 1949年起的逾半世纪,在中国大陆、台湾、香港、澳门所使用的标准时间皆为东八区(UTC+8)时间 //中国,占五个时区.分别是东5区 东6区 东7区 东8区 东9区 据北京较远的地区也有不使用北京时间的 比如乌鲁木齐时间就是东九区时间,比北京时间早一个小时 世界分24个时区 //添加时间的偏移量 OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime);//2019-02-18T15:32:50.611+08:00 //toEpochMilli(): 获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数 ---> Date类的getTime() long milli = instant.toEpochMilli(); System.out.println(milli); //ofEpochMilli():通过给定的毫秒数,获取Instant实例 -->Date(long millis) Instant instant1 = Instant.ofEpochMilli(1550475314878L); System.out.println(instant1); } }
DateTimeFormatter
DateTimeFormatter
该类提供了三种格式化方法:
- 预定义的标准格式
就是默认的日期格式化~ 不需要任何指定~ - 本地化相关的格式
提供了几种定义好的枚举,格式化类型~年月日时分秒
yyyy-MM-DD HH:mm:ss
- 自定义的格式
通过:ofPattern(yyyymm); 来指定日期的格式~
常用方法:
方法 | 描述 |
---|---|
ofPattern(String pattern) | 静态方法 , 返 回一个指定字 符串格式 |
DateTimeFormatter format(TemporalAccessor t) | 格式化一个日期、时间,返回字符串 |
parse(CharSequence text) | 将指定格式的字符序列解析为一个日期、时间 |
- 格式化:
将日期(对象) 转换为字符串~
- 解析:
将字符串日期转换为~ 日期对象
转换的字符 和 日期对象的格式要一致, 不然转换失败!
Demo
DateTimeFormatterDemo.Java
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;
/** DateTimeFormatter */
public class DateTimeFormatterDemo {
public static void main(String[] args) {
// 方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME; ISO_LOCAL_DATE; ISO_LOCAL_TIME 分布对应三个对象!
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化:日期-->字符串
LocalDateTime localDateTime = LocalDateTime.now();
String str1 = formatter.format(localDateTime);
System.out.println(localDateTime);
System.out.println(str1);//2019-02-18T15:42:18.797
//解析:字符串 -->日期
TemporalAccessor parse = formatter.parse("2019-02-18T15:42:18.797");
System.out.println(parse);
// 方式二:
// 本地化相关的格式。如:ofLocalizedDateTime()
// FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
//格式化
String str2 = formatter1.format(localDateTime);
System.out.println(str2);//2019年2月18日 下午03时47分16秒
// 本地化相关的格式。如:ofLocalizedDate()
// FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate
DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
//格式化
String str3 = formatter2.format(LocalDate.now());
System.out.println(str3);//2019-2-18
// 重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化
String str4 = formatter3.format(LocalDateTime.now());
System.out.println(str4);//2019-02-18 03:52:09
//解析
TemporalAccessor accessor = formatter3.parse("2019-02-18 03:52:09");
System.out.println(accessor);
}
}
总结:
Java8 新增了很多的日期API 其实常用的也就以上...
- Java8之前的其实还有很多人使用,
JDK是向下兼容的,所以不必担心
- 但,8听说效率还挺高,而且确实挺方便的...
JDK8其它API
System Java系统类:
java.lang 包下
的一个 系统类,可以通过该类获取的当前计算机的:属性~
- 该类的构造器是private的 所以无法创建该类的对象,也就是无法实例化该类.
其内部的成员变量和成员方法都是static
的,所以也可以很方便的进行调用
成员变量
- System类内部包含in、out和err三个成员变量
分别代表标准输入流 (键盘输入)
标准输出流(显示器)
标准错误输出流(显示器)
成员方法
方法 | 描述 |
---|---|
native long currentTimeMillis() | 返回当前的计算机时间,时间格式,当前计算机时间和 格林威治时间所差的毫秒数 |
void exit(int status) | 作用是退出程序。其中status 的值为0代表正常退出,非零代表异常退出 在图形界面编程中实现程序的退出功能等 |
void gc() | 作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。 |
String getProperty(String key) | 该方法的作用是获得系统中属性名为key的属性对应的值: 如下 |
Sacnner 扫描器:
java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的控制台输入
需要搭配 System.in
的输入流~ Scanner s = new Scanner(System.in);
常用方法:
方法 | 描述 |
---|---|
hasNext() 与 hasNextLine() |
判断是否还有输入的数据 建议Next之前判断一下... 这些方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认 |
next() 与 nextLine() |
方法获取输入的字符串 nextLine() 会输出一行信息... |
如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持
next.Byte() nextDouble() nextFloat,nextInt() nextLin() nextLong() nextShot()
但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取,不然输入int 的输入了一个 String会报错~
/** 成员属性: in out err */
//in: 配合Scanner 扫描器,可以实现控制台的输入流...
//out: 这个,最常用: System.out.print(); 返回一个输出流,输出信息
//err: 和out 类似,但是它输出的信息一般表示错误,比较显眼的 红色信息!
//创建一个扫描仪
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一段话s1:");
String s1 = scanner.next();
System.out.println("请输入一段话s2:");
String s2 = scanner.next();
System.err.println("s1:"+s1);
System.err.println("s2:"+s2);
//注意: 不要同时两个
// scanner.nextxxx() 写在一起,这些方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认.
// 写在一起,输入了一个回车,则所有的 nextxxx() 都结束了!
scanner.close(); /** 要注意关闭流o 不然占用程序资源... */
SystemDemo
SysDemo.Java
import java.util.Scanner;
/**
* System 系统类的学习...
*/
public class SysDemo {
//main 主方法...
public static void main(String[] args) {
/** 成员属性: in out err */
//in: 配合Scanner 扫描器,可以实现控制台的输入流...
//out: 这个,最常用: System.out.print(); 返回一个输出流,输出信息
//err: 和out 类似,但是它输出的信息一般表示错误,比较显眼的 红色信息!
//创建一个扫描仪
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一段话s1:");
String s1 = scanner.next();
System.out.println("请输入一段话s2:");
String s2 = scanner.next();
System.err.println("s1:"+s1);
System.err.println("s2:"+s2);
//注意: 不要同时两个
// scanner.nextxxx() 写在一起,这些方法执行时都会造成堵塞,等待用户在命令行输入数据回车确认.
// 写在一起,输入了一个回车,则所有的 nextxxx() 都结束了!
scanner.close(); /** 要注意关闭流o 不然占用程序资源... */
/** currentTimeMillis */
long timeStamp = System.currentTimeMillis(); //返回当前时间,时间戳;
//时间戳: 值当前日期距离,格林威治时间(GMT)1970-01-01 的毫秒数~
//使用:
// 通常可以,用于生产一个时间戳, 时间唯一的一个ID, 用作在数据库/文件名...表示数据唯一~
System.out.println(timeStamp);
/** getProperty(): 获取系统的参数信息!*/
String javaVersion = System.getProperty("java.version");
System.out.println("java的环境版本:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的安装路径:" + javaHome);
String osName = System.getProperty("os.name");
System.out.println("操作系统的名称:" + osName);
String osVersion = System.getProperty("os.version");
System.out.println("操作系统的版本:" + osVersion);
String userName = System.getProperty("user.name");
System.out.println("计算机用户账户名:" + userName);
String userHome = System.getProperty("user.home");
System.out.println("用户的主目录:" + userHome);
String userDir = System.getProperty("user.dir");
System.out.println("用户当前工作目录:" + userDir);
}
}
Math Java数学类:
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用 不用new 可以直接调用!
常用方法:
方法 | 描述 |
---|---|
算术计算 | |
Math.sqrt() | 计算平方根 |
Math.cbrt() | 计算立方根 |
Math.pow(a, b) | 计算a的b次方 |
Math.max( , ) | 计算最大值 |
Math.min( , ) | 计算最小值 |
Math.abs() | 取绝对值 就是正数!1 -1 绝对值都是 1 |
进位 | |
Math.ceil() | 逢余进一 有小数就+1 |
Math.floor() | 逢余舍一 舍去小数! |
Math.rint() | 四舍五入,返回double值。注意.5的时候会取偶数 |
Math.round() | 四舍五入,float时返回int值,double时返回long值 |
随机数 | |
Math.random() | 取得一个 [0~1] 范围内的随机数 通常可以用该 方法+算法 获取:1-10 1-100.. 随机数! |
更多待扩展... |
MathDemo
MathDemo.Java
public static void main(String[] args) {
/** 算术计算 */
System.out.println("--------算术计算-----------");
System.out.println(Math.sqrt(16)); // 4.0 4^2 4的二次方=16
System.out.println(Math.cbrt(8)); // 2.0 2^3 2的三次方= 8
System.out.println(Math.pow(3, 2)); // 9.0 3^2 3的二次方=16 几次方就是, x乘x次! 3x3=9
System.out.println(Math.max(2.3, 4.5)); // 4.5 判断最大值!
System.out.println(Math.min(2.3, 4.5)); // 2.3 判断最小值!
/**
* abs求绝对值: 就是把一个数变成 + 正数!
*/
System.out.println(Math.abs(-10.4)); // 10.4
System.out.println(Math.abs(10.1)); // 10.1
/** 进位 */
System.out.println("--------进位-----------");
/**
* ceil天花板的意思,就是逢余进一
* 正数+1
* 小数+1, 小数+1~
*/
System.out.println("--------ceil-----------");
System.out.println(Math.ceil(-10.1)); // -10.0
System.out.println(Math.ceil(10.7)); // 11.0
System.out.println(Math.ceil(-0.7)); // -0.0
System.out.println(Math.ceil(0.0)); // 0.0
System.out.println(Math.ceil(-0.0)); // -0.0
System.out.println(Math.ceil(-1.7)); // -1.0
/**
* floor地板的意思,就是逢余舍一
*/
System.out.println("--------floor-----------");
System.out.println(Math.floor(-10.1)); // -11.0
System.out.println(Math.floor(10.7)); // 10.0
System.out.println(Math.floor(-0.7)); // -1.0
System.out.println(Math.floor(0.0)); // 0.0
System.out.println(Math.floor(-0.0)); // -0.0
/**
* rint 四舍五入,返回double值 注意.5的时候会取偶数 异常的尴尬=。=
*/
System.out.println("--------rint-----------");
System.out.println(Math.rint(10.1)); // 10.0
System.out.println(Math.rint(10.7)); // 11.0
System.out.println(Math.rint(11.5)); // 12.0
System.out.println(Math.rint(10.5)); // 10.0
System.out.println(Math.rint(10.51)); // 11.0
System.out.println(Math.rint(-10.5)); // -10.0
/**
* round 四舍五入,float时返回int值,double时返回long值
*/
System.out.println("--------round-----------");
System.out.println(Math.round(10)); // 10
System.out.println(Math.round(10.1)); // 10
System.out.println(Math.round(10.7)); // 11
System.out.println(Math.round(10.5)); // 11
System.out.println(Math.round(10.51)); // 11
System.out.println(Math.round(-10.5)); // -10
}
获取100以内的随机数!
@Test
/** 获取100以内的随机数! */
public void randomHundred(){
// Math.random() 获取0-1 的随机数! 包含0!
System.out.println("随机0-1");
System.out.println(Math.random());
System.out.println("随机0-100");
System.out.println((int)(Math.random()*100)+1);
/**
* (int)(Math.random()*100)+1
* 因为: Math.random() 获取0-1 的随机数! 包含0!
* *100 获取随机数进两位小数,强制转换(int) 会截取小数点..
* 因为包含0 所以+1 就不会出现呢0 的情况了!!!
*/
}
BigInteger 与 BigDecimal 类:
BigInteger
Java.math包
Interger类作为int的包装类,能存储的最大整型值为2^{31-1}
Long类也是有限的, 最大为2^{63-1}
- 如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了
- BigInteger 提供所有 Java 的基本整数操作符的对应物
并提供 Java.lang.Math 的所有相关方法 - BigInteger 还提供以下运算:
模算术、GCD 计算、质数测试、素数生成、 位操作以及一些其他操作
构造器
- BigInteger(String val):根据字符串构建BigInteger对象
常用方法:
BigInteger abs() 返回大整数的绝对值
BigInteger add(BigInteger val) 返回两个大整数的和
BigInteger and(BigInteger val) 返回两个大整数的按位与的结果
BigInteger andNot(BigInteger val) 返回两个大整数与非的结果
BigInteger divide(BigInteger val) 返回两个大整数的商
double doubleValue() 返回大整数的double类型的值
float floatValue() 返回大整数的float类型的值
BigInteger gcd(BigInteger val) 返回大整数的最大公约数
int intValue() 返回大整数的整型值
long longValue() 返回大整数的long型值
BigInteger max(BigInteger val) 返回两个大整数的最大者
BigInteger min(BigInteger val) 返回两个大整数的最小者
BigInteger mod(BigInteger val) 用当前大整数对val求模
BigInteger multiply(BigInteger val) 返回两个大整数的积
BigInteger negate() 返回当前大整数的相反数
BigInteger not() 返回当前大整数的非
BigInteger or(BigInteger val) 返回两个大整数的按位或
BigInteger pow(int exponent) 返回当前大整数的exponent次方
BigInteger remainder(BigInteger val)返回当前大整数除以val的余数
BigInteger leftShift(int n) 将当前大整数左移n位后返回
BigInteger rightShift(int n) 将当前大整数右移n位后返回
BigInteger subtract(BigInteger val) 返回两个大整数相减的结果
byte[] toByteArray(BigInteger val) 将大整数转换成二进制反码保存在byte数组中
String toString() 将当前大整数转换成十进制的字符串形式
BigInteger xor(BigInteger val) 返回两个大整数的异或
BigDecimal
Decimal:[中:小数]
一般的Float类和Double类可以用来做科学计算或工程计算
但在商业计算中, 要求数字精度比较高,故用到 Java.math.BigDecimal
类
BigDecimal类支持不可变的、任意精度的有符号十进制定点数
构造器
- public BigDecimal(double val)
- public BigDecimal(String val)
常用方法
add(BigDecimal) BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal) BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal) BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal) BigDecimal对象中的值相除,然后返回这个对象。
toString() 将BigDecimal对象的数值转换成字符串。
doubleValue() 将BigDecimal对象中的值以双精度数返回。
floatValue() 将BigDecimal对象中的值以单精度数返回。
longValue() 将BigDecimal对象中的值以长整数返回。
intValue() 将BigDecimal对象中的值以整数返回
Java的 flot double 计算有问题:
查看下面的代码:
@Test
public void bigDecimal(){
System.out.println(0.1+0.2);
System.out.println(0.3-0.1);
System.out.println(0.2*0.1);
System.out.println(0.3/0.1);
}
因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度
- 根本原因是:十进制值通常没有完全相同的二进制表示形式
- 十进制数的二进制表示形式可能不精确。只能无限接近于那个值
但:
- 在项目中,我们不可能让这种情况出现,特别是金融项目
如果你的支付宝账户余额显示193.99999999999998,那是一种怎么样的体验?