一.主要框架
1.框架图
①String
②StringBuffer和StringBuider
③日期API
④比较器
2.总体概述
①String
***/
1.String概念
1.1 String类的代码:
implements Serializable, Comparable实现了序列化和比较器接口,可序列化和比较
public final class String定义为final类,不可继承
private final char value[]定义char[]数组为final,即不可变字符序列
1.2 String两种定义方式:
字面量:引用地址直接赋值给方法区中的常量池中字符串
新建对象:引用地址赋值给堆中new出的char[]数组,value再指向方法区中的常量池中的字符串
1.3 String的拼接操作
即只要涉及变量的拼接,则该String需要new在堆中
只有两者都是常量,才会放在常量池中
注意final定义的为常量而不是变量
1.4 String重新赋值的理解
若定义了一个字面量,重新赋值则只是指向了方法区中另一个字符串
若定义了一个对象,重新赋值只是将指向堆中的引用指向了方法区,并没有改变value
concat方法可以称之为重新赋值,但本质也并未改变value的值,而是返回了一个新建对象
1.5 String例题分析
1.常见方法测试
改:
replace,concat 实际上并不算修改字符串,而只是返回了一个新的字符串对象
查:
charAt
长度:
length
遍历
contains
subString
2.String类与其他类型的数据转换加粗样式
String与基本数据类型转换
String与char[]类型转换(遍历时常用)
②Stringbuffer和Stringbuider
/*
1.StringBuffer和StringBuider对比String
对比String:两者都是可变序列,两者都不可字面量赋值
对比String:三者底层都是char[]类型数组,但是String的value指向方法区,而两者的value指向堆中new的对象即可更改
两者对比:StringBuffer和StringBuider前者是线程不安全,效率高,后者是线程安全,效率低
2.StringBuffer和StringBuider的扩容问题
如果超出数组长度,则会扩容为原来数组长度的二倍加二,并且将原来数组的数据复制过来返回新数组
3.StringBuffer的常用方法:
增:append,insert
删:delete
改:replace
查:subString
遍历:charAt
*/
③日期API
1.JDK8以前的日期API使用及转化
时间戳类:java.util.Date和java.sql.Date
具体时间类:Calender(抽象类)
转化类:SimpleDateFormat
2.转化过程:从string到sql.Date
利用转化类将string转化为util.Date
再利用时间戳为中间变量将util.Date转化为sql.Date
3.JDK8以后的日期API使用及转换(时间和日期都会不变,即提供静态方法来创建实例对象)
时间戳类:Instant
具体时间类:LocalDateTime
转化类:DateTimeFormatter
4.转化过程:从string到LocalDateTime
即利用LocalDateTime的静态方法parse传入第一个形参为String,第二个形参为DateTimeFormatter,即可得到localdatetime的类型
5.常用静态方法
System.currentTimeMills() 直接返回时间戳,一般用于判断程序的执行时间
*/
④JAVA比较器
/*
1.自然排序
自定义类需要在Arrays.sort方法中排序,则需要实现comparable中的compareTo方法,在排序时会自动调用方法
java中的工具类已经提前实现了方法,可以直接排序,比如String
2.定制排序
在进行Arrays.sort时,传入的第一个参数为数组名,传入的第二个参数为比较器,可以直接定制两个对象如何比较
3.两者对比
自然排序时在任何场合都会使用
定制排序只是临时的一个排序
*/
二.代码简介
1.String
public class Test1 {
//String的两种定义方式的理解
@Test
public void stringTest1(){
String str1 = "abc";
String str2 = "abc";
//结果为true,说明常量池中不可能有两个相同字符串
System.out.println(str1 == str2);
String str3 = new String("abc");
//结果为false,说明确实新建对象引用给堆,字面量给常量池
System.out.println(str1 == str3);
str1 = "bcd";
//结果为false,说明当重新赋值时,如若该字符串与原常量池中其他字符串不同,会重新建一个字符串,并且引用执行该字符串
System.out.println(str1 == str2);
}
//String的拼接方法
@Test
public void stringTest2(){
String str = "ab";
String str1 = "a";
String str2 = "b";
String reuslt = str1 + str2;
System.out.println(str == reuslt);//false,变量与变量的拼接结果在堆中
String str3 ="a" + "b";
System.out.println(str == str3);//true,常量与常量的拼接结果在方法区
String str4 = "a" + str2;
System.out.println(str == str4);//false,即变量与常量的拼接结果在堆中
final String str5 = "b";
String result2 = "a" + str5;
System.out.println(str == result2);//true,即final定义的为常量而不是变量
}
//String重新赋值
@Test
public void StringTest3(){
String str = new String("abc");
//由于是给str先new了属性,即此时value指向方法区中的abc,若此时让str指向cdf,那么究竟是value变了还是引用str变了。
String str0 = str;
str = "cdf" ;
String str1 = str;
System.out.println(str0 == str1);//false,则证明此时是str引用变了,而final类型的value不变
//分析,即此时赋值相当于将引用str指向堆换成了指向方法区
String a = "abc";
String b = a.concat("bcd");
System.out.println(a == b);//false,则证明此时concat是返回了一个新new的对象
}
//String例题分析
@Test
public void StringTest4(){
String str = new String("good");
char[] ch = {'b','e','s','t'};
change(str,ch);
System.out.println(str);//good,此时虽然将str地址赋值给形参,但是里面新建的方法区对象会返回另一个地址,而不是让该地址指向另一个字符串
System.out.println(ch);//test,此时对应的直接操作ch数组,则直接会修改数组的内容
}
public void change(String str,char[] ch){
str = "test ok";
ch[0] = 't';
}
}
public class Test2 {
//常见方法测试
@Test
public void Test(){
String str = "I love you";
System.out.println(str.replace('I','M'));
System.out.println(str.concat(" and he"));
System.out.println(str.charAt(0));
System.out.println(str.length());
System.out.println(str.contains("you"));
System.out.println(str.substring(2,6));
}
//数据转换
@Test
public void Test1(){
//基本数据类型 转换为 String
String a = ""+123;
//String 转换为 基本数据类型
int b = Integer.parseInt("132");
float c = Float.parseFloat("12.0f");
//char[] 转换为 String
char[] ch = new char[]{'a'};
String str = new String(ch);
//String 转换为 char[]
char[] ch1 = str.toCharArray();
}
}
2.StringBuffer和StringBuider
public class Test3 {
//StringBuffer和StringBuider与String的对比
@Test
public void Test0(){
String str = "abc";
StringBuffer a = new StringBuffer("abc");
StringBuffer b = a;
a.replace(0,3,"cde");
System.out.println(a);
System.out.println(b == a);//true,即改变了StringBuffer的内容,但是实际的引用并未改变
}
//StringBuffer的方法
@Test
public void test1(){
StringBuffer a = new StringBuffer("abc");
//增
System.out.println(a.append('d'));
System.out.println(a.insert(4,"efg"));
//删
System.out.println(a.delete(5,7));//注意左闭右开
//改
System.out.println(a.replace(0,1,"1"));
//查
System.out.println(a.substring(0,2));//返回子串
//遍历
System.out.println(a.charAt(0));
}
}
③日期API
public class Test4 {
//JDK8以前的日期API使用及转化
@Test
public void test1() throws ParseException {
//时间戳类
Date date = new Date();
System.out.println(date.getTime());//1665039694398
//具体时间类
Calendar date1 = Calendar.getInstance();//注意Calender类为抽象类,只能使用其静态方法返回一个实例
System.out.println( date1.getTime());//Thu Oct 06 15:03:04 CST 2022
//转化类SimpleDateFormat
//具体实现例子:通过字符串传入java.sql.Date对象中
SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd");
String birth = "2020-09-08";
Date date2 = a.parse(birth);//此处先返回一个util下的Date
java.sql.Date result = new java.sql.Date(date2.getTime());//利用中间变量时间戳赋值
}
//JDK8以后的日期API使用及其转化
@Test
public void test2(){
//时间戳类
Instant date = Instant.now();
System.out.println(date.toEpochMilli());//1665040337104
//日期类
LocalDateTime date1 = LocalDateTime.now();
System.out.println(date1.getDayOfMonth());
System.out.println(date1.getDayOfWeek());
//转换类DateTimeFormatter
//具体例子:利用字符串获得localdatetime的对象
String str = "2016-10-25 12:00:00";
DateTimeFormatter a = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date2 = LocalDateTime.parse(str,a);
System.out.println(date2);
}
}
④JAVA比较器
public class Test6 {
//比较器之自然排序
@Test
public void test1(){
String a ="abc";
String b ="abd";
System.out.println(a.compareTo(b));//即String类中实现了接口comparable的compareTo方法
String[] str = new String[]{"abc","abd","p","c"};
Arrays.sort(str);
System.out.println(str[0] + str[1] + str[2] + str[3]);//此时自动调用了String类中的compareTo方法
//自定义类实现排序的比较
Person[] per = new Person[2];
per[0] = new Person(12);
per[1] = new Person(10);
//此时的顺序为 12 10
System.out.println(per[0]);
System.out.println(per[1]);
Arrays.sort(per);
//此时的顺序为 10 12 即arrays.sort自动调用了compareTo方法
System.out.println(per[0]);
System.out.println(per[1]);
}
class Person implements Comparable{
int age;
Person(int age){
this.age = age;
}
@Override
public int compareTo(Object o) {
Person a =(Person) o;
return this.age-a.age;
}
@Override
public String toString() {
return ""+age;
}
}
//比较器之定制排序
@Test
public void test2(){
Person[] per = new Person[2];
per[0] = new Person(12);
per[1] = new Person(10);
Arrays.sort(per, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
Person a = (Person)o1;
Person b = (Person)o2;
return a.age-b.age;
}
});
//实现了定制排序 顺序为10 12
System.out.println(per[0]);
System.out.println(per[1]);
class Person implements Comparable{
int age;
Person(int age){
this.age = age;
}
@Override
public int compareTo(Object o) {
Test6.Person a =(Test6.Person) o;
return this.age-a.age;
}
@Override
public String toString() {
return ""+age;
}
}
}
}