第九章:常用类

2021225

15:24

String:字符串,使用一对""引起来表示。

1.String声明为final的,不可被继承

2.String实现了Serializable接口:表示字符串是支持序列化的。

        实现了Comparable接口:表示String可以比较大小

3.String内部定义了final char[] value用于存储字符串数据

4.String:代表不可变的字符序列。简称:不可变性。

    体现:1.当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值(value是final的)。

         2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

         3. 当调用Stringreplace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。

6.字符串常量池中是不会存储相同内容的字符串的。

String s1 = "abc"; //字面量的定义方式

 

String的实例化方式:

方式一:通过字面量定义的方式

方式二:通过new + 构造器的方式

//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。

String s1 = "javaEE";

String s2 = "javaEE";

//通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值他们的value存储在字符串常量池中

String s3 = new String("javaEE");

String s4 = new String("javaEE");

 

//构造器中用 this.name = name 赋值,采用的字面量定义的方式。都是在字符串常量池中的"Tom",所以p1.name == p2.name

Person p1 = new Person("Tom",12);

Person p2 = new Person("Tom",18);

System.out.println(p1.name.equals(p2.name));//true

System.out.println(p1.name == p2.name);//true

 

面试题:String s = new String("abc");方式创建对象,在内存中创建了几个对象?

        两个:一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"(前提是之前没有用字面量定义的方式定义过"abc")

 

沙 
9 . 1 字 符 串 相 关 的 类 : String 
尚 硅 谷 
"abc"; 与 String str2 = new String("abc"); 的 区 别 ? 
String strl 
0 字 符 串 常 量 存 储 在 
value: 
字 符 串 常 量 池 , 目 
的 是 共 享 
. 字 符 串 非 常 量 对 象 
存 储 在 堆 中 。 
str2 
abc 
strl

 

字符串拼接的存放地址问题:

1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。

2.(两个字符串的拼接)只要其中有一个是变量,结果就在堆中。

3.如果拼接的结果调用intern()方法,返回值就在常量池中

Strings1="javaEE";

Strings2="hadoop";

 

Strings3="javaEEhadoop";

Strings4="javaEE"+"hadoop";

Strings5=s1+"hadoop";

Strings6="javaEE"+s2;

Strings7=s1+s2;

 

System.out.println(s3==s4);//true

System.out.println(s3==s5);//false

System.out.println(s3==s6);//false

System.out.println(s3==s7);//false

System.out.println(s5==s6);//false

System.out.println(s5==s7);//false

System.out.println(s6==s7);//false

 

Strings8=s5.intern();//返回值得到的s8使用的常量池中已经存在的“javaEEhadoop

System.out.println(s3==s8);//true

s1 += "a";  +=操作也是在堆中

 

面试题:

public class StringTest {

    String str = new String("good");

    char[] ch = { 't', 'e', 's', 't' };

 

    public void change(String str, char ch[]) {

        str = "test ok";

        ch[0] = 'b';

    }

 

    public static void main(String[] args) {

        StringTest ex = new StringTest();

        ex.change(ex.str, ex.ch);

        System.out.println(ex.str);//

        System.out.println(ex.ch); //

    }

}

 

ex.str把地址值传给了str,然后str修改了自己的值。因为字符串是不可变的,所以str重新指向了常量池里面的一个新的字符串"test ok",但是此时的ex.str不变,仍然指向new出来的字符串对象。

ex.ch把地址值传给了ch,然后ch修改了该地址的数组里索引为0的字符。此时的ex.ch仍然指向原来的地址,所以ex.ch的值也变了。

正确答案:good best

面试题2

String s1 = "javaEEhadoop";

String s2 = "javaEE";

String s3 = s2 + "hadoop";

System.out.println(s1 == s3); //false

 

final String s4 = "javaEE";

String s5 = s4 + "hadoop";

System.out.println(s1 == s5); //true

 

final String s6 = new String("javaEE");

String s7 = s6 + "hadoop";

System.out.println(s2 == s6); //false

System.out.println(s1 == s7); //false

 

字面量定义的常量,运算时算是常量,运算结果在常量池

new出来的常量,运算时算是变量,结果在堆中

 

字符串相关的类:String常用方法1

int length():返回字符串的长度: return value.length

char charAt(int index) 返回某索引处的字符return value[index]

boolean isEmpty():判断是否是空字符串:return value.length == 0

String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写注意:原字符串不变!

String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写注意:原字符串不变!

String trim():返回字符串的副本,忽略前导空白和尾部空白

boolean equals(Object obj):比较字符串的内容是否相同

boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写

String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”

int compareTo(String anotherString):比较两个字符串的大小 注意:从[0]开始比,如果两个字符串的某个索引值不同就返回两个字符的差值。如果判断到长度最小的字符串的最后都一样,就返回长度的差值。

String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。注意:substring是全小写的

String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。 注意:substring是全小写的。左闭右开,刚好endIndex - beginIndex就是截取的字符串的长度

 

字符串相关的类:String常用方法2

boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束

boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始

boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始

 

boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true

int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引

int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 注意:找到的话,返回的是从首字母开始计算的索引,而不是从fromIndex计算的索引。比如"helloworld".indexOf("wo",3),返回的是5

int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引 注意:从后往前找,找到的话,返回的是从首字母正着数开始计算的索引,而不是倒着数。

int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 注意:从fromIndex(正着数的)开始从后往前找,找到的话,返回的是从首字母正着数开始计算的索引,而不是倒数。

    String str3 = "hellorworld";

    System.out.println(str3.lastIndexOf("or")); //7

    System.out.println(str3.lastIndexOf("or",6)); //4

 

注:indexOf和lastIndexOf方法如果未找到都是返回-1

 

什么情况下,indexOf(str)和lastIndexOf(str)返回值相同?

    情况一:存在唯一的一个str。情况二:不存在str

 

字符串相关的类:String常用方法3

替换

String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。

String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

匹配:

boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。

切片

String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。

String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。

regex是regular expression,正则表达式的缩写

 

复习:

    String 与基本数据类型、包装类之间的转换。

String --> 基本数据类型、包装类:调用包装类的静态方法:parseXxx(str)

基本数据类型、包装类 --> String:调用String重载的valueOf(xxx)

        String s1 = "123";

//      int num = (int)s1; //错误的写法!只有子父类才可以强转

          int num = Integer.parseInt(s1);

 

String 与 char[]之间的转换

String --> char[]:调用String对象的toCharArray()

char[] --> String:调用String的构造器public String(char value[]){}

字符数组 ---> 字符串

ØString 类的构造器:String(char[]) String(char[]int offsetint

length) 分别用字符数组中的全部字符和部分字符创建字符串对象。

字符串 ---> 字符数组

Øpublic char[] toCharArray()将字符串中的全部字符存放在一个字符数组

中的方法。

Øpublic void getChars(int srcBegin, int srcEnd, char[] dst,

int dstBegin)把字符串中从srcBeginsrcEnd(不含)的字符复制到字符数组dst中,dstBegin是目标数组中的起始偏移量

 

String 与 byte[]之间的转换

    编码:String --> byte[]:调用String的getBytes()

    解码:byte[] --> String:调用String的构造器

 

    编码:字符串 -->字节  (看得懂 --->看不懂的二进制数据)

    解码:编码的逆过程,字节 --> 字符串 (看不懂的二进制数据 ---> 看得懂)

 

    说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。

l 字节数组 ---> 字符串

ØString(byte[])通过使用平台的默认字符集解码指定的 byte 数组,构

造一个新的 String

ØString(byte[]int offsetint length) 用指定的字节数组的一部分,

即从数组起始位置offset开始取length个字节构造一个字符串对象。

l 字符串 ---> 字节数组

Øpublic byte[] getBytes() 使用平台的默认字符集将此 String 编码为

byte 序列,并将结果存储到一个新的 byte 数组中。

Øpublic byte[] getBytes(String charsetName) 使用指定的字符集将

String 编码到 byte 序列,并将结果存储到新的 byte

编码:

byte[] bytes = s1.getBytes(); //使用默认的字符集,进行编码。比如utf-8,汉字占三个字节

System.out.println(Arrays.toString(bytes));

byte[] gbks = s1.getBytes("gbk");//使用gbk字符集进行编码。gbk一个汉字占两个字节。抛异常:UnsupportedEncodingException

解码:

String s2 = new String(bytes);//使用默认的字符集,进行解码。

String s3 = new String(gbks);//出现乱码。原因:编码集和解码集不一致!

String s4 = new String(gbks, "gbk");//没有出现乱码。原因:编码集和解码集一致!

 

StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:

ØStringBuffer():初始容量为16的字符串缓冲区

ØStringBuffer(int size):构造指定容量的字符串缓冲区

ØStringBuffer(String str):将内容初始化为指定字符串内容 

 

String、StringBuffer、StringBuilder三者的异同?

    String:不可变的字符序列;底层使用char[]存储

    StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储

    StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储

 

对比String、StringBuffer、StringBuilder三者的效率:

    从高到低排列:StringBuilder > StringBuffer > String

 

注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder

会改变其值。

 

    源码分析:

    String str = new String();//char[] value = new char[0];

    String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};

 

    StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组

    System.out.println(sb1.length());//0 length()返回的是实际存储值的长度,不是底层数组容量大小

    sb1.append('a');//value[0] = 'a';

    sb1.append('b');//value[1] = 'b';

 

    StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];

 

    //问题1. System.out.println(sb2.length());//3

    //问题2. 扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。

             默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。

 

            指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)

  如果知道该字符串会经常修改,并且长度会超过16,就显式地创建一个长点的初始数组

 

StringBuffer的常用方法:

StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接

StringBuffer delete(int start,int end):删除指定位置的内容

StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str

deletereplace:①左开右闭,开头超出长度报错,结尾超出长度不报错,会操作到末尾

StringBuffer insert(int offset, xxx):在指定位置插入xxx

StringBuffer reverse() :把当前字符序列逆转

public int indexOf(String str)

public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串。注意:substring()不操作本身StringBuffer

public int length()

public char charAt(int n )

public void setCharAt(int n ,char ch)

 

        总结:

        增:append(xxx)

        删:delete(int start,int end)

        改:setCharAt(int n ,char ch) / replace(int start, int end, String str)

        查:charAt(int n )

        插:insert(int offset, xxx)

        长度:length();

        *遍历:for() + charAt() / toString()

 

面试题:

String str = null;

StringBuffer sb = new StringBuffer();

sb.append(str);

System.out.println(sb.length());// 4

System.out.println(sb);// "null" nullappend()的时候,会作为4个字符被追加

 

StringBuffer sb1 = new StringBuffer(null); //null作为StringBuffer的构造器参数的时候会报空指针异常,因为创建初始数组会调用str.length()

StringBuffer sb2 = new StringBuffer(str); //null作为StringBuffer的构造器参数的时候会报空指针异常,因为创建初始数组会调用str.length()

System.out.println(sb1);

nullappend()的时候,有一个专门的appendNull()方法做处理,会作为4个字符被追加

null作为StringBuffer的构造器参数的时候会报空指针异常,因为创建初始数组会调用str.length()

细节:写字符串null的时候,要写 "null" ,和null区分

 

StringStringBufferStringBuilder之间的转换

String ---> StringBufferStringBuilder 调用StringBufferStringBuilder构造器

StringBufferStringBuilder ---> String ①调用String构造器;②StringBufferStringBuildertoString()

 

JVM中字符串常量池存放位置说明:

jdk1.6:字符串常量池存储在方法区(永久区)

jdk1.7:字符串常量池存储在堆空间

jdk1.8:字符串常量池存储在方法区(元空间)

 

1.反转部分字符串的解题思路:

将字符串的部分反转的时候,可以用xy来循环,一个++,一个--。这样逻辑更加清晰一些。

for(int x = start,y = end;x < y;x++,y--){

//xy互换

}

//我写的,算各个数的时候太麻烦,逻辑不够清晰

for (int i = start - 1,j = 1; j <= (end + 1 - start) / 2; i++,j++) {

    char temp = fChar[i];

    fChar[i] = fChar[end - j];

    fChar[end - j] = temp;

}

思路2:用拼接的方式,先获取第一段,从0startIndex,再倒着循环获取第二段,从endIndexstartIndex反转的部分,最后再获取第三段,从endIndex到最后

 

while(true){

    if(s1.indexOf(s2,indexN) >= 0){

        indexN = s1.indexOf(s2,indexN) + s2.length();

        System.out.println(indexN);

        count++;

    }else{

        break;

    }

}

!!写法复杂了,可以直接把if里面的判断作为while里面的条件

 

JDK8之前日期时间API

1.System类中的currentTimeMillis()

long time = System.currentTimeMillis();

//返回当前时间与197011000秒之间以毫秒为单位的时间差。

//称为时间戳

System.out.println(time); //1614439014541

 

2.java.util.Date

           |---java.sql.Date类(继承于java.util.Date类,用于sql

关于java.util.Date

    1.两个构造器的使用

        >构造器一:Date():空参的构造器,创建一个对应当前时间的Date对象

        >构造器二:Date(long date): 创建指定毫秒数的Date对象

Date date1 = new Date();

System.out.println(date1.toString());//Sat Feb 27 23:53:00 CST 2021

Date date2 = new Date(1514439765108L);

System.out.println(date2.toString());//Thu Dec 28 13:42:45 CST 2017 

    2.两个方法的使用

        >toString(): 显示当前的年、月、日、时、分、秒

        >getTime(): 获取当前Date对象对应的毫秒数。(时间戳)

long time = date1.getTime();

System.out.println(time);//1614441180257

java.sql.Date对应着数据库中的日期类型的变量

        >如何实例化 Date(long date)

        >如何将java.util.Date对象转换为java.sql.Date对象

java.util.DategetTime()的时间戳,作为java.sql.Date对象的构造器参数

//继承于java.util.Date

java.sql.Date date3 = new java.sql.Date(1514439765108L);

System.out.println(date3); //2017-12-28toString()方法重写了

System.out.println(date3.getTime()); //1514439765108

//如何将java.util.Date对象转换为java.sql.Date对象

Date date4 = new Date();

java.sql.Date date5 = new java.sql.Date(date4.getTime());

System.out.println(date5); 

 

3.SimpleDateFormat的使用:SimpleDateFormat对日期Date类的格式化和解析

1.两个操作:

    1.1 格式化:日期 --->字符串 SimpleDateFormat对象的format()方法

    1.2 解析:格式化的逆过程,字符串 ---> 日期 SimpleDateFormat对象的parse()方法

 

    2.SimpleDateFormat的实例化

//实例化SimpleDateFormat:使用默认的构造器

        SimpleDateFormat sdf = new SimpleDateFormat();

//格式化:日期 --->字符串

        Date date = new Date();

        String format = sdf.format(date);

        System.out.println(format);//默认格式21-2-28下午6:17

 

        //解析:格式化的逆过程,字符串 ---> 日期

        String str = "19-12-18 上午11:43";

        Date date1 = sdf.parse(str);

        System.out.println(date1);

 

//*************按照指定的方式格式化和解析:调用带参的构造器*****************

        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        //格式化

        String format1 = sdf1.format(date);

        System.out.println(format1);//2019-02-18 11:48:27

        //解析:要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),

        //否则,抛异常

        Date date2 = sdf1.parse("2020-02-18 11:48:27");

 

y

M

w

一年第几周

W

一月第几周

D

一年第几天

d

一月第几天

E

星期几

u

周几,1-7

a

上午下午

H

小时(24小时制)

h

小时(12小时制)

m

分钟

s

S

毫秒

z

时区 CST 中国标准时间

Z

时区 +0800

 

4.Calendar日历类(抽象类)的使用

实例化的两种方式:

//方式一:创建其子类(GregorianCalendar)的对象

//方式二:调用其静态方法getInstance()

Calendar calendar = Calendar.getInstance();//返回的是GregorianCalendar对象(根据区域判断的)

System.out.println(calendar.getClass()); //classjava.util.GregorianCalendar

常用方法:

一个Calendar的实例是系统时间的抽象表示,通过get(int field)方法来取得想

要的时间信息。比如YEARMONTHDAY_OF_WEEKHOUR_OF_DAY

MINUTESECOND

Ø public void set(int field,int value)

Ø public void add(int field,int amount)

Ø public final Date getTime() 把当前Calendar对象转换为Date对象

Ø public final void setTime(Date date)  Date对象设置当前Calendar对象的时间

l 注意:

Ø 获取月份时:一月是0,二月是1,以此类推,12月是11

Ø 获取星期时:周日是1,周二是2 ,。。。。周六是7

//get() 底层用int[] fields存储的,通过对应常量找到常量对应角标的int

int day = calendar.get(Calendar.DAY_OF_MONTH); //5

int month = calendar.get(Calendar.MONTH) + 1; //2

 

//set()

//calendar可变性,返回值是void,直接修改当前Calendar对象

calendar.set(Calendar.DAY_OF_MONTH,15); //设置为15

day = calendar.get(Calendar.DAY_OF_MONTH);

 

//add() 在原有的属性上增加,比如加5天,加5个月。底层的时间会变动,所以获取的时间是新的,比如时间增加后过了一个月会进入下一个月

//月份是从0开始的,0-11。所以看时间的时候要算好

calendar.add(Calendar.DAY_OF_MONTH,18); //21518天,变成了35

 

//getTime():日历类 ---> Date

Date date = calendar.getTime();

System.out.println(date);

 

//setTime()Date ---> 日历类 设置当前Calendar对象的时间

Date date1 = new Date();

calendar.setTime(date1);

 

JDK8中新日期时间API

JDK8之前的版本可以通过导入Joda-Time的方式使用新的API

 

LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例

不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。

now() I • 
now(ZoneId zone) 
of() 
getDayOfMonth()/getDayOfYear() 
getDayOfWeek() 
getMonth() 
getMonthValue() I getYear() 
withDayOfMonth()/withDayOfYear()/ 
withMonth()/withYear() 
plusDays(), plusWeeks(), 
plusMonths(), plusYears(),plusHours() 
minusMonths() I minusWeeks()/ 
minusDays()/minusYears()/minusHours() 
DayOfWeek 
Month

实例化:

now():获取当前的日期、时间、日期+时间 静态方法

LocalDate localDate = LocalDate.now();

LocalTime localTime = LocalTime.now();

LocalDateTime localDateTime = LocalDateTime.now();

System.out.println(localDate); //2021-02-28

System.out.println(localTime); //22:42:53.468

System.out.println(localDateTime); //2021-02-28T22:42:53.468

of():设置指定的年、月、日、时、分、秒。没有偏移量静态方法

LocalDateTime localDateTime1 = LocalDateTime.of(2025, 10, 25, 21, 13, 35);

System.out.println(localDateTime1); //2025-10-25T21:13:35 

getXxx():获取相关的属性

System.out.println(localDateTime.getDayOfYear()); //59

System.out.println(localDateTime.getYear()); //2021

System.out.println(localDateTime.getMonth()); //FEBRUARY

System.out.println(localDateTime.getMonthValue()); //2

System.out.println(localDateTime.getDayOfWeek()); //SUNDAY

withXxx():设置相关的属性 返回新对象,原来对象不变 体现了不可变性

LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(3);

System.out.println(localDateTime); //2021-02-28T23:01:10.444

System.out.println(localDateTime2); //2021-02-03T23:01:10.444

 

LocalDateTime localDateTime3 = localDateTime.withHour(18);

plusXxx():增加相关的属性 返回新对象,原来对象不变 体现了不可变性

minusXxx():减少相关的属性 返回新对象,原来对象不变 体现了不可变性

LocalDateTime localDateTime4 = localDateTime.plusMonths(5);

System.out.println(localDateTime);

System.out.println(localDateTime4);

//plus的参数可以为负数,减

LocalDateTime localDateTime5 = localDateTime.plusDays(-5);

System.out.println(localDateTime5);

 

LocalDateTime localDateTime6 = localDateTime.minusDays(10);

System.out.println(localDateTime6);

在用withplusminus的时候,都是返回一个新对象,原来的对象不变。体现了LocalDateLocalTimeLocalDateTime对象的不可变性

 

Instant类似于java.util.Date

沙 
9 . 3JDK8 中 新 日 期 时 间 AP 》 
尚 硅 谷 
方 法 
now() 
ofEpochMilli(long epochMilli) 
atOffset(ZoneOffset Offset) 
toEpochMilli() 
描 述 
静 态 方 法 , 返 回 默 认 UTC 时 区 的 丨 nstant 类 的 对 象 
静 态 方 法 , 返 回 在 1970 . 01 . 01 開 ℃ 0 ℃ 0 基 础 上 加 上 指 定 毫 秒 
数 之 后 的 | nstant 类 的 对 象 
结 合 即 时 的 偏 移 来 创 建 一 个 OffsetDateTime 
返 回 1970 . 01 . 01 00 : 00 : 00 到 当 前 时 间 的 亳 秒 数 , 即 为 时 间 戳 
时 间 戳 是 指 格 林 威 治 时 间 1970 年 01 月 01 日 00 时 00 分 00 秒 ( 北 京 时 间 1970 年 01 月 01 
日 08 时 00 分 00 秒 ) 起 至 现 在 的 总 秒 数 。

now():获取本初子午线对应的标准时间静态方法

Instant instant = Instant.now();

System.out.println(instant); 

atOffset(ZoneOffset offset)添加时间的偏移量,结合即时的偏移来创建一个 OffsetDateTime

这个方法是偏移原来的时间点,得到一个新的时间,所以是非静态方法。参数是ZoneOffset对象。返回值是OffsetDateTime对象。

ZoneOffset类只有一个私有的构造器,外部使用的话,只能通过静态的ofXxx方法生成对象

ofHoursofHoursMinutesofHoursMinutesSecondsoffTotalSeconds

OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));

System.out.println(offsetDateTime); //2021-03-01T09:10:20.186+08:00

toEpochMilli():获取自197011000秒(UTC)开始的毫秒数  ---> Date类的getTime() 

long milli = instant.toEpochMilli();

System.out.println(milli); //1614561020186

ofEpochMilli():通过给定的毫秒数,获取Instant实例 静态方法  -->Date(long millis) 

Instant instant1 = Instant.ofEpochMilli(1614560684324L);

System.out.println(instant1); //2021-03-01T01:04:44.324Z

 

DateTimeFormatter:格式化或解析日期、时间

    类似于SimpleDateFormat

通过DateTimeFormatter的静态方法(如ofLocalizedDateTime()ofPattern())来实例化一个格式化器(对象),使用的静态方法决定格式化器的格式。

//parse()方法的参数(字符串)必须符合格式化器的格式

//parse()方法返回的是java.time.format.Parsed对象,实现了TemporalAccessor接口

TemporalAccessor parse = formatter.parse("2021-03-01T09:36:02.965");

//方式一:预定义的标准格式。如: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(str1); //2021-03-01T10:05:35.849

System.out.println(localDateTime); //2021-03-01T10:05:35.849

 

//解析:字符串 ---> 日期

//LocalDateTimeLocalDateLocalTime都实现了TemporalAccessor接口

TemporalAccessor parse = formatter.parse("2021-03-01T09:36:02.965");

System.out.println(parse);

//返回的是java.time.format.Parsed对象,实现了TemporalAccessor接口

System.out.println(parse.getClass());

 

//方式二:

//本地化相关的格式。如:ofLocalizedDateTime()

//FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTime

//ofLocalizedDateTime的参数是FormatStyle对象,FormatStyle是枚举类

DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); //不能使用FormatStyle.FULL

//格式化

String str2 = formatter1.format(localDateTime);

System.out.println(str2);

//LONG 202131日 上午094723

//MIDIUM 2021-3-1 9:48:05

//SHORT 21-3-1 上午9:48

 

//本地化相关的格式。如:ofLocalizedDateTime()

//FormatStyle.FULL只适用于ofLocalizedDate(),用在ofLocalizedDateTime()会报错。

//但是生成的DateTimeFormatter对象可以用format()转换LocalDateTime对象。因为format()的参数要求是TemporalAccessor对象就行

//FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDate

DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);

String str3 = formatter2.format(LocalDate.now());

System.out.println(str3); //202131日 星期一

 

//重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”) 

DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");

//格式化

String str4 = formatter3.format(localDateTime);

System.out.println(str4); //2021-03-01 10:05:35

//解析

TemporalAccessor accessor = formatter3.parse("2021-03-01 10:03:39");

System.out.println(accessor); //{SecondOfMinute=39, HourOfAmPm=10, MicroOfSecond=0, NanoOfSecond=0, MinuteOfHour=3, MilliOfSecond=0},ISO resolved to 2021-03-01

System.out.println(accessor.getClass()); //class java.time.format.Parsed

 

其他API

l ZoneId:该类中包含了所有的时区信息,一个时区的ID,如 Europe/Paris

l ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如 2007-12-03T10:15:30+01:00 Europe/Paris。

Ø 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等

l Clock:使用时区提供对当前即时、日期和时间的访问的时钟。

l 持续时间:Duration,用于计算两个“时间”间隔

l 日期间隔:Period,用于计算两个“日期”间隔

l TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。

l TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。

ZoneId:类中包含了所有的时区信息

//ZoneId的静态方法of()返回一个指定时区的ZoneId对象

LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));

//ZonedDateTime:带时区的日期时间

// ZonedDateTimenow():获取本时区的ZonedDateTime对象

ZonedDateTime zonedDateTime = ZonedDateTime.now();

System.out.println(zonedDateTime); //2021-03-01T10:58:18.677+08:00[Asia/Shanghai]

// ZonedDateTimenow(ZoneId id):获取指定时区的ZonedDateTime对象

ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

System.out.println(zonedDateTime1); //2021-03-01T11:58:18.677+09:00[Asia/Tokyo]

Duration:用于计算两个“时间”间隔,以秒和纳秒为基准

between():静态方法,返回Duration对象,表示两个时间的间隔

toDays() toHours() toMinutes() toMillis() 转换单位

LocalTime localTime = LocalTime.now();

LocalTime localTime1 = LocalTime.of(15, 23, 32);

//between():静态方法,返回Duration对象,表示两个时间的间隔

Duration duration = Duration.between(localTime1, localTime);

System.out.println(duration); //PT-4H-21M-1.308S

System.out.println(duration.getSeconds()); //-15662

System.out.println(duration.getNano()); //692000000

LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);

LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);

Duration duration1 = Duration.between(localDateTime1, localDateTime);

System.out.println(duration1.toDays()); //-365

toDays() toHours() toMinutes() toMillis() 转换单位

Period:用于计算两个“日期”间隔,以年、月、日衡量

Period:用于计算两个日期间隔,以年、月、日衡量

between() 静态方法,返回Period对象

getYears() getMonths() getDays()

withYears() withMonths() withDays() 设置对应属性,返回新对象(是设置,不是增加)

LocalDate localDate = LocalDate.now();

LocalDate localDate1 = LocalDate.of(2028, 5, 18);

Period period = Period.between(localDate, localDate1);

System.out.println(period); //P7Y2M17D

System.out.println(period.getYears()); //7

System.out.println(period.getMonths()); //2

System.out.println(period.getDays()); //17

Period period1 = period.withYears(2);

System.out.println(period1); //P2Y2M17D

TemporalAdjuster:时间校正器

// 获取当前日期的下一个周日是哪天?

//next()静态方法,需要DayOfWeek(枚举类,周一到周日)

TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);

LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);

System.out.println(localDateTime); //2021-03-07T11:38:40.565

// 获取下一个工作日是哪天?

LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {

    @Override

    public Temporal adjustInto(Temporal temporal) {

        LocalDate date = (LocalDate) temporal;

        if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {

            return date.plusDays(3);

        } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {

            return date.plusDays(2);

        } else {

            return date.plusDays(1);

        } }

});

System.out.println("下一个工作日是:" + localDate); //下一个工作日是:2021-03-02

 

与传统日期处理的转换:

9.3 
9.3.5 
java.time.lnstant5java.util.Date 
java.time.Instant5java.sqI.Timestamp 
java.time.ZonedDateTime5 
java.utiI.GregorianCaIendar 
java.time.LocalDate5java.sql.Time 
java.time.LocalTime5java.sql.Time 
java.time.LocalDateTime5 
java.sqI.Timestamp 
java.time.Zoneld5java.util.TimeZone 
j ava. time. format.DateTimeFormatter5 
java.text.DateFormat 
Datefrom(instant) 
Timestamp.from(instant) 
GregorianCaIendar.from(zonedDateTime) 
Date.vaIueOf(locaIDate) 
Times tamp.vaIueOf(IocalDateTıme) 
Timezone.getTımeZone(id) 
formatter.toFormat() 
From 
timestamp.tolnstant() 
cal.toZonedDateTime() 
date.toLocaIDate() 
timestamp.toLocaIDateTime() 
timeZone.toZoneId()

 

Java比较器Java实现对象排序的方式有两种:

Ø 自然排序:java.lang.Comparable

Ø 定制排序:java.util.Comparator

 

方式一:自然排序:java.lang.Comparable

lComparable 的典型实现:(默认都是从小到大排列的)

ØString:按照字符串中字符的Unicode值进行比较

ØCharacter:按照字符的Unicode值来进行比较

Ø数值类型对应的包装类以及BigIntegerBigDecimal:按照它们对应的数值大小进行比较

ØBooleantrue 对应的包装类实例大于 false 对应的包装类实例

ØDateTime等:后面的日期时间比前面的日期时间大

 

Comparable接口的使用举例:自然排序

1.String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。

2.String、包装类重写compareTo()方法以后,进行了从小到大的排列

3.重写compareTo(obj)的规则:

如果当前对象this大于形参对象obj,则返回正整数,

如果当前对象this小于形参对象obj,则返回负整数,

如果当前对象this等于形参对象obj,则返回零。

4.对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。

compareTo(obj)方法中指明如何排序

Arrays.sort(arr);  //Arrays.sort()会调用对象的compareTo()方法,结果会直接修改原来的数组

//比较字符串的时候,可以直接用字符串的compareTo()方法

return this.name.compareTo(goods.name);

//比较数值可以直接使用包装类的compare方法

return Double.compare(this.price,goods.price);

 

方式二:定制排序:java.util.Comparator

1.背景:

    当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码,

    或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,

    那么可以考虑使用 Comparator 的对象来排序

2.重写compare(Object o1,Object o2)方法,比较o1o2的大小:

    如果方法返回正整数,则表示o1大于o2

    如果返回0,表示相等;

    返回负整数,表示o1小于o2

Arrays.sort(arr,new Comparator(){

    //指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序

    @Override

    public int compare(Object o1, Object o2) {

        if(o1 instanceof Goods && o2 instanceof Goods){

            Goods g1 = (Goods) o1;

            Goods g2 = (Goods) o2;

            if(g1.getName().equals(g2.getName())){

                return -Double.compare(g1.getPrice(),g2.getPrice());

            }else{

                return g1.getName().compareTo(g2.getName());

            }

        }

        throw new RuntimeException("提供的数据类型有误!");

    }

});

 

Comparable接口与Comparator的使用的对比:

 *    Comparable接口的方式一旦指定,保证Comparable接口实现类的对象在任何位置都可以比较大小。

 *    Comparator接口属于临时性的比较。

 

System代表系统,系统级的很多属性和控制方法都放置在该类的内部。

该类位于java.lang包。

l 成员变量

Ø System类内部包含inouterr三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)

l 成员方法

Ø native long currentTimeMillis()

该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)197011000秒所差的毫秒数。

Ø void exit(int status)

该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等。

Ø void gc()

该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。

Ø String getProperty(String key)

该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:

轾 性 名 
Java.version 
Java. horne 
OS. 
user.home 
User. 
性 说 日 目 
」 艹 运 行 时 环 憤 所 本 
“ 支 装 目 录 
掃 作 系 的 名 称 
掾 作 羊 圻 才 
用 户 的 账 户 名 称 
用 户 的 主 目 录 
用 户 的 当 前 工 作 目 录

    String javaVersion = System.getProperty("java.version");

    System.out.println("javaversion:" + javaVersion); //javaversion:1.8.0_281

    String javaHome = System.getProperty("java.home");

    System.out.println("javahome:" + javaHome); //javahome:D:\Java\jdk1.8.0_281\jre

    String osName = System.getProperty("os.name");

    System.out.println("osname:" + osName); //osname:Windows 10

    String osVersion = System.getProperty("os.version");

    System.out.println("osversion:" + osVersion); //osversion:10.0

    String userName = System.getProperty("user.name");

    System.out.println("username:" + userName); //username:Gumusu

    String userHome = System.getProperty("user.home");

    System.out.println("userhome:" + userHome); //userhome:C:\Users\Gumusu

    String userDir = System.getProperty("user.dir");

    System.out.println("userdir:" + userDir); //userdir:D:\workspace\workspace_idea\JavaSenior\day04 

 

Math

java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回

值类型一般为double型。

abs 绝对值

acos,asin,atan,cos,sin,tan 三角函数

sqrt 平方根

pow(double a,doble b) ab次幂

log 自然对数

exp e为底指数

max(double a,double b)

min(double a,double b)

random() 返回0.01.0的随机数

long round(double a) double型数据a转换为long型(四舍五入)

toDegrees(double angrad) 弧度—>角度

toRadians(double angdeg) 角度—>弧度

 

BigInteger

l java.math包的BigInteger可以表示不可变的任意精度的整数BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供 java.lang.Math 的所有相关方法。

另外,BigInteger 还提供以下运算:模算术、GCD 计算、质数测试、素数生成、位操作以及一些其他操作。

l 构造器

Ø BigInteger(String val):根据字符串构建BigInteger对象

l 常用方法

Ø public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger

Ø BigInteger add(BigInteger val) :返回其值为 (this + val) BigInteger

Ø BigInteger subtract(BigInteger val) :返回其值为 (this - val) BigInteger

Ø BigInteger multiply(BigInteger val) :返回其值为 (this * val) BigInteger

Ø BigInteger divide(BigInteger val) :返回其值为 (this / val) BigInteger。整数

相除只保留整数部分。

Ø BigInteger remainder(BigInteger val) :返回其值为 (this % val) BigInteger

Ø BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟

(this % val) 的两个 BigInteger 的数组。

Ø BigInteger pow(int exponent) :返回其值为 (thisexponent) BigInteger

 

BigDecimal

l 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。

l BigDecimal类支持不可变的、任意精度的有符号十进制定点数。

l 构造器

Ø public BigDecimal(double val)

Ø public BigDecimal(String val)

l 常用方法  加减乘除

Ø public BigDecimal add(BigDecimal augend)

Ø public BigDecimal subtract(BigDecimal subtrahend)

Ø public BigDecimal multiply(BigDecimal multiplicand)

Ø public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

 

练习题:

将字符串"2017-08-16"转换为对应的java.sql.Date类的对象

//JDK8之前的API

String str = "2017-08-16";

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

Date parse = sdf.parse(str);

java.sql.Date date1 = new java.sql.Date(parse.getTime());

System.out.println(date1);

System.out.println("**************");

//JDK8之后的API

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

LocalDate localDate = LocalDate.parse(str, dtf);

java.sql.Date date2 = java.sql.Date.valueOf(localDate);

System.out.println(date2);

System.out.println("**************");

DateTimeFormatter.parse()解码出来的对象是TemporalAccessor对象,不好转换。

所以使用DateTimeFormatter解码的时候,可以用LocalDateLocalTimeLocalDateTime里面的parse(CharSequence text, DateTimeFormatter formatter)方法,直接生成对应的对象。

LocalDateTime里面的parse(CharSequence text, DateTimeFormatter formatter),要求formatter必须是有日期和时间的格式,比如 "yyyy-MM-dd hh:mm:ss a"。不能只有单独的日期,会报错。

java.sql.Date.valueOf(LocalDate date) 静态方法,把LocalDate对象转换为java.sql.Date对象

 

排序,比较字符串时候出现的错误!想要实现书名比较,如果书名<书名返回-1,大于返回1,相等返回0

//错误!不能这样写,字符串的compareTo()方法的返回值不只有三种!!!

//应该用if-else来判断!

//            switch (this.getName().compareTo(b1.getName())){

//                case -1:

//                    return -1;

//                case 1:

//                    return 1;

//                case 0:

//                    return 0;

//            }

 

20213211:50:10 会报错。然后把整句话加粗了。LocalDateTime里面的parse(CharSequence text, DateTimeFormatter formatter),要求formatter必须是有日期和时间的格式,比如 "yyyy-MM-dd hh:mm:ss a"。不能只有单独的日期,会报错。

 

结尾

 

使用 Microsoft OneNote 2016 创建。 版权所有:古木苏