常用类

一. 字符串相关:

String类

  • final的(该有的功能都有了,不用、不可以再继承了)

  • 位于java.lang包

  • 实现了Serializable接口:表示字符串是支持序列化的;
    实现了Comparable接口:(比较器)表示可以比较大小;
    比较两个字符串:用equals比较;
    直接的“ ”里面的字符串和new出来的字符串比较(地址比较:==)不同:地址不同。

  • 内部定义了final char[] value 用于存储字符串数据(数组不可以重新赋值,数组元素也不可以在被修改了,只可以在新指定的内存区域赋值
    不可变字符序列。(所有的拼接、替换、去空格、截取等相应的操作,都是生成的新字符串,不会影响到原来的字符串)

  • String常用方法:API文档

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

不可以直接强制转换的,父子类才可以强转。

  • String - - >基本数据类型、包装类 :调用包装类的静态方法:parseXxx(str);
 		String str1 = "123";
        int num = Integer.parseInt(str1);
  • 基本数据类型、包装类 – >String类型:调用String重载的valueOf(xxx);
 		String str2 = String.valueOf(num);          //str2为123了

2.String类型与char[ ]之间的转换

  • String–>char[ ]: 调用String的toCharArray()方法:
public static void main(String[] args) {
        String str1 = "abc123";
        char[] charArray = str1.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            System.out.println(charArray[i]);
        }
    }
  • char[ ] -->String类:调用String构造器
 public static void main(String[] args) {
       char[] arr = new char[]{'h','e','l','l','o'};
       String str = new String(arr);
       System.out.println(str);
    }

3.String类型与字节Byte[ ]之间的转换

  • String --> Byte[ ]: 调用String的getBytes();- ->得到相应的ascll码(编码:字符串 转换成 看不懂的 字节
 public static void main(String[] args) {
        String str1 = "abc123中国"; 
        byte[] bytes = str1.getBytes();//使用默认的字符集(UTF-8),进行转换
        System.out.println(Arrays.toString(bytes));
    }
  • Byte[ ] 数组 --> String:调用String的构造器 (解码:看不懂的二进制字节 转换到 看得懂的 字符串
    (出现乱码的时候:很有可能是解码集不同造成的)

4.String对象的创建:

public static void main(String[] args) {
        String str = "hello";

        String str1 = new String();//本质:新建的char[0]

        String str2 = new String("value");//新建一个长度是5的char型数组。

        char[] value1 = {'a', 'b', 'c', 'd'};
        String str3 = new String(value1);  //相当于String str4 = new String("abcd");

        char[] value2 = {'a', 'b', 'c', 'd'};
        String str4 = new String(value2, 1, 2);        //相当于String str5 = new String("bc");

        System.out.println(str+"-"+str1+"-"+str2+"-"+str3+"-"+str4);
    }

Q & A 1:
str:字面量定义的方式 VS str2:通过new+构造器的方式有什么区别?

1. str1数据在方法区中的字符常量池中,而new+构造器保存的地址值是:在堆空间中开辟空间之后,再对应的值。
2. 两个字面上定义的相同字符串是可以相等的(因为常量池中是不可以有相同的内容的),但是两个new+构造器出来的字符串不能相等(两个都是新的)。
3. 加上final之后可能就看为常量了,结果可能为true。
 public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";

        String s3 = new String("hello");
        String s4 = new String("hello");

        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1 == s4);
        System.out.println(s3 == s4);
    }

得出结果:

true
false
false
false

Q & A 2:
new+构造器的方法如:String s = new String(“abc”);创建对象,在内存中创建了几个对象?

两个:一个是堆空间中的new结构创建的,另一个是char[]对应的常量池中的数据”abc”,而常量池中又不会存在两个相同的,所以如果常量池中先声明过了要用的那个,可以直接拿来用。

Q & A 3:
判断是否相等:(地址)

 public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";

        String s3 = "helloworld";  		//简单字面量连接
        String s4 = "hello"+"world";		//简单字面量连接
        String s5 = "hello"+s2;		//变量名出现,在堆中开辟空间(相当于new)
        String s6 = s1 + "world";
        String s7 = s1 + s2;

        System.out.println(s3 == s4);
        System.out.println(s3 == s5);
        System.out.println(s3 == s6);
        System.out.println(s3 == s7);
        System.out.println(s5 == s6);
        System.out.println(s6 == s7);
    }

输出结果:拼接结果是在常量池中操作,常量池中也不会有相同的常量; 只要有变量存在的,都会又多一个堆中的空间,即不相等。

true
false
false
false
false
false

但是,字符串调用intern()方法,返回值会返回到常量池中:

 public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";

        String s3 = "helloworld";
        String s4 = "hello"+"world";
        String s5 = s1+"world";

        String s6 = s5.intern();
        System.out.println(s3 == s6);
    }

返回true。

String类的常用方法

public class StringTest {
    public static void main(String[] args) {
        String s1 = "Hello";
        System.out.println(s1.length());        //1. 数组的返回长度:5

        System.out.println(s1.charAt(2));       //2. 取指定位置上的字符:e;范围满足0~length-1

        System.out.println(s1.isEmpty());       //3. 数组是否为空:false(判断的是数组的长度)

        System.out.println(s1.toLowerCase(Locale.ROOT));        //4. 所有的转换为小写的字母
        System.out.println(s1.toUpperCase(Locale.ROOT));           //大写

        String s2 = s1.toLowerCase(Locale.ROOT);
        System.out.println(s1);     //5. s1没有改变,用new的String类是赋值,是赋给的新的空间给到的s2
        System.out.println(s2);    //s2改变了,新的

        String s3 = "   h el lo wor  ld   ";
        String s4 = s3.trim();      //去除掉首位空格,中间的空格还是有的
        System.out.println(s4);

        String s5 = "helloworld";
        String s6 = "HelloWorld";
        System.out.println(s5.equals(s6));                  //字符串匹配,不忽略大小写的情况
        System.out.println(s5.equalsIgnoreCase(s6));        //字符串忽略大小写的比较(==是地址比较)

        String s7 = "abc";
        String s8 = s7.concat("def");           //连接
        System.out.println(s8);

        String s9 = "abc";
        String s10 = new String("abe");          //ascll码相比较。(字符串排序)
        System.out.println(s9.compareTo(s10));

        String s11 = "好妹妹乐队";
        String s12 = s11.substring(3);              //取子串,下标从0开始
        System.out.println(s11);
        System.out.println(s12);

        String s13 = s11.substring(1, 3);       //左闭右开区间的取子串
        System.out.println(s13);
    }
}

测试结果:

5
l
false
hello
HELLO
Hello
hello
h el lo wor  ld
false
true
abcdef
-2
好妹妹乐队
乐队
妹妹

String常用方法2:

找字符串:

public class StringTest2 {

    public static void main(String[] args) {
        String str1 = "helloworld";

        boolean b1 = str1.endsWith("rld");          //查看是否以指定的字符串后缀结束
        boolean b2 = str1.startsWith("hels");          //前缀是否相同(boolean类型)
        boolean b3 = str1.startsWith("ll",2);   //是不是以“**字符”在某号位置开头

        System.out.println(b1);
        System.out.println(b2);
        System.out.println(b3);

        String str2 = "wo";
        System.out.println(str1.contains(str2));        //str1是否包含str2的字符串(字符串匹配)

        System.out.println(str1.indexOf("o"));         //首次重写的位置,没有的时候返回-1(从a开始的,后面都没有,于是返回了a-1的位置)
        System.out.println(str1.indexOf("o", 5));

        System.out.println(str1.lastIndexOf("o"));    //从后往前的第一个字符串(返回的位置还是从前往后的位置
        System.out.println(str1.lastIndexOf("o", 5));
    }
}

测试结果:

true
false
true
true
4
6
6
4

Q & A:indexOf(str)与lastIndexOf(str)何时找的是一样的?
只存在唯一的str,或者不存在str。

String常用方法3:

public class StringTest3 {
    public static void main(String[] args) {
        String str1 = "少年先锋队少年";
        System.out.println(str1.replace("少", "老")); //返回新的字符串
        System.out.println(str1.replace('少', '老'));

        String str2 = "123he938llo883wo44rl99384d038";
        //第一次replace把所有的数字替换成逗号,第二次replace正则表达式,把首尾的逗号用空格替换。
        System.out.println(str2.replaceAll("\\d+", ",").replaceAll("^,|,$",""));
    }
}

测试结果:

老年先锋队老年
老年先锋队老年
he,llo,wo,rl,d

StringBuffer和StringBuilder

  • 都是String的子类。

String 和StringBuilder 和 StringBuffer三者的异同有哪些?

  1. String :不可变字符序列:自身不可变,都是新生成的,所以产生一堆新的对象。
  2. StringBuffer:可变字符序列 ,是线程安全的,多线程数据量较大,效率低。(多线程 效率低
  3. StringBuilder:(jdk1.5新增)可变字符序列 线程不安全,不做线程同步检查,因此效率高。 单线程数据量较大。
    自身也是可变的,并且返回自身,所以从头到尾就一个变化的对象,最后返回变回自己。
  4. 相同点:他们三个底层使用的都是char[ ]数组存储
    源码分析:
public static void main(String[] args) {
            //new char [0];
        String str = new String();

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

             //Char value = new char[16];相当于创建了一个长度是16的字符数组
        StringBuffer sb1 = new StringBuffer();
        sb1.append('a');        //value[0] = 'a';
        sb1.append('b');        //value[1] = 'b';
             // Char value = new Char ["abc".length() + 16];
        StringBuffer sb2 = new StringBuffer("abc");//(额外空出来16个大小)
        System.out.println(sb2.length());        //length()返回的是:return count;所以结果是3
    }
  • 扩容问题:如果要添加的数据底层数组盛不了,那就需要扩容底层数组。默认情况下,扩容的大小是原来的2倍+2;同时将原有的数组中的元素复制到新的数组中。
  • 指导意义:建议我们在开发过程中,使用StringBuffer(int capacity) 或者 StringBuilder(int capacity),具体用哪个还要考虑安不安全。
  1. 选择的问题:①是不是多线程的?不是多线程一定选StringBuilder;② 由于StringBuilder是新增的,更多的会选择StringBuilder。

StringBuffer用法

  • StringBuilder也通用的。
  • 常用方法列表:返回原来的,不是新的
    1. 重载的public StringBulider append(…)方法
      append附加,添加新的字符序列,但是仍然返回对象自身
      sb.append("aa").append("bb").append(123);可以一直返回下去
    2. public StringBulider delete(int star,int end)
      删除中间那一段,到end-1。返回自身。
    3. public StringBulider insert(…)
      指定位置插入,返回自身。
    4. public StringBulider reverse()
      逆序,返回自身。
    5. public String toString()
      返回自身序列中字符串的表示形式。
    • 具体用法:
      • sb.insert(0,"啊“).insert(0,"邓");在0的位置先插入啊,再在新的0位置处插入邓。
      • 删除子字符串:sb.delete(0,2);删掉了0和1位置的字符。
      • 删除单个字符:sb.deleteCharAt(0).deleteCharAt(0);删掉0号字符,再删掉0号字符。

常见用法测试:

 public static void main(String[] args) {
        StringBuffer sb1 = new StringBuffer("abc");
        sb1.append(1);
        sb1.append('1');
        System.out.println(sb1);  //连接、类似于and

        sb1.delete(2,4);            //左闭右开原则
        System.out.println(sb1);        //可变的,直接修改了

        sb1.replace(2,4,"hello");   //替换
        System.out.println(sb1);

        sb1.insert(2,false);
        System.out.println(sb1);            //插入,不是替换,前面的还在
        System.out.println(sb1.length());

        sb1.reverse();
        System.out.println(sb1);
        System.out.println(sb1.length());       //逆序

        String sb2 = sb1.substring(1, 5);        //返回的sb2,左闭右开原则
        System.out.println(sb1);
        System.out.println(sb2);
    }

测试结果:

abc11
ab1
abhello
abfalsehello
12
olleheslafba
12
olleheslafba
lleh

重点关注:(StringBuffer和StringBuilder用法差不多)

  • 增:append(xxx);
  • 删:delete(int 开始的,int 结束位置);
  • 改:setCharAt(int 数量,char 修改成什么字符);:修改某个字符; / replace(int 开始的位置,int结束的位置,修改的字符串);:替换成新的字符串
  • 查:charAt(int n);
  • 插入:insert(int offset,xxx);
  • 长度:length();
  • 遍历(不多):for+charAt();/ toString();

效率测试:

/*String效率测试*/
public void test{
       String str8 = "";

       long num1 = Runtime.getRuntime().freeMemory();// 获取系统剩余内存空间。
       long time1 = System.currentTimeMillis();//获取系统的当前时间。

       for (int i = 0; i < 5000; i++) {
           str8 = str8 +i;	//产生了5000个对象。
       }

       long num2 = Runtime.getRuntime().freeMemory();// 获取系统剩余内存空间。
       long time2 = System.currentTimeMillis();//获取系统的当前时间。

       System.out.println("String占用的内存空间为:"+(num1-num2));
       System.out.println("String占用的时间为:"+(time2-time1));
}
    /*Stringbuilder效率测试*/
public void test{
	 StringBuilder sb = new StringBuilder("");
	
     long num3 = Runtime.getRuntime().freeMemory();
     long time3 = System.currentTimeMillis();

     for (int i = 0; i < 5000; i++) {
         sb.append(i);	//只有一个对象。
     }
     long num4 = Runtime.getRuntime().freeMemory();
     long time4 = System.currentTimeMillis();

     System.out.println("StringBuilder所占的内存空间为:"+(num3-num4));
     System.out.println("StringBuilder所占用的时间为:"+(time4-time3));
}

测试结果:

String占用的内存空间为:23167328
String占用的时间为:32
StringBuilder所占的内存空间为:0
StringBuilder所占用的时间为:1

三者效率比较:StringBuilder>StringBuffer>String

结论:所以在创建大量字符拼接,用String会产生大量无用对象,被GC掉,系统崩溃。

String和StringBuffer转换

String – >StringBuffer:调用StringBuffer/StringBuilder构造器
StringBuffer --> String:调用String构造器
方法②:调用公用的方法 toString();

一道面试算法题:

import org.junit.Test;

public class deBugTest {
    @Test
    public void testStringBuffer(){
        String str = null;
        StringBuffer sb = new StringBuffer();
        sb.append(str);

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

        System.out.println(sb);// "null"

        StringBuffer sb1 = new StringBuffer(str);//抛异常:NullPointerException
        System.out.println(sb1);
    }
}

返回4的原因如下api:

rivate AbstractStringBuilder appendNull() {
        ensureCapacityInternal(count + 4);
        int count = this.count;
        byte[] val = this.value;
        if (isLatin1()) {
            val[count++] = 'n';
            val[count++] = 'u';
            val[count++] = 'l';
            val[count++] = 'l';
        } else {
            count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
        }
        this.count = count;
        return this;
    }

二、日期、时间相关类:

1. currentTimeMillis();

基准时间:1970年1月1日00:00:00 每个度量单位为1毫秒,0.001s (long类型)大约可以表示到±2.9亿年前后

long now = System.currentTimeMillis();

//返回的是当前时刻的毫秒数(从1970年01月01日00:00:00时刻到现在的毫秒数——时间戳:比如可以用在淘宝订单号的生成)
可以用两个currentTimeMillis()在代码头尾,测试代码效率。

2. Date类:

1.java.util.Date类(平时多用)

import java.util.Date;

public class DateTest {
    public static void main(String[] args) {

  //构造器一:Date():创建一个对应当前时刻的Date对象
        Date d1 = new Date();//需要导入包:alt+enter(因为不知是自动导入哪个类的date,所以要手动选择)
        System.out.println(d1);
        System.out.println(d1.toString());// 显示当前的时刻

        //没有传参,表示当前时刻的时间,距离默认时刻的时间ms数(时间戳)。
        System.out.println(d1.getTime());

  //构造器二:创建指定时间戳的Date对象
        //创建指定的日期: 传参的格式(加L;计算到毫秒)
        Date d2 = new Date(1000L*3600*24*365*250);
        System.out.println(d2);  //返回到基准时间的时刻
    }
}

返回结果:

Sun Mar 07 21:08:22 CST 2021
Sun Mar 07 21:08:22 CST 2021
1615122502935
Tue Nov 02 08:00:00 CST 2219

2. java.sql.Date类(数据库中的日期类型变量)

跟数据库交互的时候会涉及到的:

import java.sql.Date;

public class DateTest2 {
    public static void main(String[] args) {
 //构造器一: 造对象:如何实例化
        Date date = new Date(352255552224L);        //new java.sql.Date();+alt+enter
        System.out.println(date);

//如何让util.Date(父类)对象和sql.Date(子类)对象相互转换?
         //用getTime得到的时间戳进行转换

        java.sql.Date date2 = new java.sql.Date(date.getTime());
    }
}

3. DateFormat 和 SimpleDateFormat (简单)时间格式化类(最常用的):实现日期及时间ms的转换。

父子类:SimpleDateFormat是子类

  • 使用:SimpleDateFormat 对日期Date类的格式化和解析
  • "yyy-MM-dd hh:mm:ss"(年-大月-日 时-分-秒)只有月份M是大写的
    (注意:这里的格式保持一致即可,可以同统一都写上面这个格式)

使用一:

import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;

public class test1 {
    /*
    SimpleDateFormat的使用: SimpleDateFormat 对日期Date类的格式化和解析

    1. 两个操作
    1.1 格式化:日期 --> 字符串
    1.2 解析: 格式化逆过程,字符串 --> 日期

    2. SimpleDateFormat实例化
     */
    @Test
    public void testSimpleDateFormat() throws ParseException {

        //实例化:这里是默认的格式:
        SimpleDateFormat sdf = new SimpleDateFormat();

        //格式化:日期 转字符串
        Date date = new Date();
        System.out.println(date);

        String format = sdf.format(date);
        System.out.println(format);

        //解析的过程:格式转化的逆过程,字符串 -->日期:
        String str = "2021/3/8 下午8:15";
        Date date1 = sdf.parse(str);
        System.out.println(date1);

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

        //默认行为--->指定方式进行格式化解析:调用带参数的构造器
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

        //格式化:
        String format1 = sdf1.format(date);
        System.out.println(format1);

        //解析:
        Date date2 = sdf1.parse("2021-03-08 08:32:04");
        System.out.println(date2);
    }
}

输出结果:

Mon Mar 08 20:55:53 CST 2021
2021/3/8 下午8:55
Mon Mar 08 20:15:00 CST 2021
******************************************
2021-03-08 08:55:53
Mon Mar 08 08:32:04 CST 2021

使用二:

//将字符串转换成date
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date d1 = df.parse("1971-3-10 10:40:52");
        System.out.println(d1.getTime());
 
//将date转换成字符串
         Date d2 = new Date();
         //括号内可以写上具体的时间(ms格式)不写表示当下时刻
        String str = df.format(d2);
        System.out.println(str);

//今年第几周
        DateFormat df2 = new SimpleDateFormat("今年第w周");
        System.out.println(df2.format(d2));//找月份中的w周/年份中的D天

输出结果:

37420852000
2021-02-23 04:18:03
今年第9周
  • 练习:“三天打鱼两天晒网” 给定的某天起开始打鱼,打三天鱼,晒两天网。 到任意一天的时候,是在打鱼还是在晒网?

  • 分析:三天+两天=五天一个周期。
    Date2-Date1为总天数:总天数%5 = 1,2,3时,是打鱼;
    总天数%5 = 4、0(也就是5)是晒网。
    总时间可以用getTime算出毫秒数:
    (date2.getTime()-date1.getTime())/(1000L360024) +1

其他格式需求可以查下表:
在这里插入图片描述

3. Calendar日历类(简单理解即可)

jdk8以前的api:

  • 表示日期和日期计算。
  • 方式一:是一个抽象类,GregorianCalendar公历子类
    (0到11表示12个月)
        GregorianCalendar calendar = new GregorianCalendar(2999,10,9,22,10,50);
        int year = calendar.get(Calendar.YEAR);//打印年
        int month = calendar.get(Calendar.MONTH);//打印月

        //DAY_OF_MONTH 和 DATE输出一样
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int day2 = calendar.get(Calendar.DATE);//打印几号

        int date = calendar.get(Calendar.DAY_OF_WEEK);//打印星期几:1-7:周日到周六

        System.out.println(year);
        System.out.println(month);
        System.out.println(day);
        System.out.println(day2);
        System.out.println(date);

// 设置日期

		GregorianCalendar calendar1 = new GregorianCalendar();

        calendar1.set(Calendar.YEAR,2999);
        calendar1.set(Calendar.MONTH,Calendar.FEBRUARY);
        calendar1.set(Calendar.DATE,3);
        calendar1.set(Calendar.HOUR_OF_DAY,10);
        calendar1.set(Calendar.MINUTE,20);
        calendar1.set(Calendar.SECOND,23);
        printCalendar(calendar1);

// 日期计算

		GregorianCalendar calendar2 = new GregorianCalendar(2999,10,9,22,10,50);
        calendar2.add(Calendar.MONTH,-7);//月份减少7
        calendar2.add(Calendar.DATE,7);//日期增加7
        printCalendar(calendar2);

方式二:Calendar调用棋静态方法getInstance


        //1. 实例化:方法二:调用棋静态方法getInstance
        Calendar calendar = Calendar.getInstance();
        System.out.println(calendar.getClass());

        //2.常用方法:
        //get();操作:获取常用的一些属性信息:大写常量
        int days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);
        System.out.println(Calendar.DAY_OF_YEAR);

        //set();操作:修改:calendar可变的
        calendar.set(Calendar.DAY_OF_MONTH,22);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);

        //add();操作:原有的基础上添加
        calendar.add(Calendar.DAY_OF_MONTH,3);      //可以加负数,就变成了减
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);

        //getTime();操作日历类 -->Date
        Date date = calendar.getTime();
        System.out.println(date);

        //setTime();:Date -->日历类
        Date date1 = new Date();
        calendar.setTime(date1);
        days = calendar.get(Calendar.DAY_OF_MONTH);
        System.out.println(days);
  • 出现新的时间日期API:

修改的原因:

  1. 以前的Calendar是可变的,但是Date这一类应是不可变的。
  2. Date的日期有一个偏移量1990年开始的,month从0月开始。
  3. 格式化:格式化只对Date有用,Calendar则不行。
  4. 他们也不是线程安全的;不能处理润表(地球自转不均匀、变慢)。

jdk8中新的日期时间API

只用到format、temporal两个,少数情况下会用到其他的包。

import org.junit.Test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * jdk8之后的API
 */
public class dateTest {
    /**
     * localDate\LocalTime\LocalDateTime使用
     * 类似jdk8之前的calendar
     */
    @Test
    public void test(){
            //实例化:获取当前时间
        LocalDate localDate = LocalDate.now();
        LocalTime localTime = LocalTime.now();
        LocalDateTime localDateTime = LocalDateTime.now();      //使用频率高些

        System.out.println(localDate);
        System.out.println(localTime);
        System.out.println(localDateTime);

        //实例化:of();设置指定的年月日时分秒是没有偏移量的
        LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 24, 13, 23, 43);
        System.out.println(localDateTime1);

        //getXxx();
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getDayOfYear());
        System.out.println(localDateTime.getDayOfWeek());
        System.out.println(localDateTime.getHour());

        //withXxx();设置当前的特殊值
        LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(22);
        System.out.println(localDateTime2);//2021-03-22T09:20:38.886801400(设置了相关的时间)
        System.out.println(localDateTime); //2021-03-09T09:20:38.886801400(当前的时间)

        //plusXxx();加       minusXxx
        LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
        System.out.println(localDateTime3);//也是不可变性的,从当前的时间开始变
    }
}

4.瞬时:Instant:时间戳

起始点:1970年1月1日00:00:00,ms为单位
Instant使用:

 @Test
    public void test2(){
        //实例化:now()获取的是本初子午线的时间
        Instant instant = Instant.now();
        System.out.println(instant);//2021-03-09T02:03:06.713429500Z

        //添加时间偏移量,获取当地时间
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        System.out.println(offsetDateTime);//2021-03-09T10:03:06.713429500+08:00

        //获取自1970年1月1日 00:00:00(UTC)开始的毫秒数
        long milli = instant.toEpochMilli();
        System.out.println(milli);

        //ofEpochMilli():通过给定的毫秒数,获取I你Stance实例 -->Date(long millis)
        Instant instant1 = Instant.ofEpochMilli(1615255716319L);
        System.out.println(instant1);
    }

5.SimpleDateFormatter使用

类似于SimpleDateFormat
自定义使用(最常用的):

  @Test
    public void test(){
        //自定义的格式:如ofPattern("yyyy-MM-dd hh:mm:ss E")
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");

        //格式化:
        String format = dateTimeFormatter.format(LocalDateTime.now());
        System.out.println(format);
        //解析
        TemporalAccessor accessor = dateTimeFormatter.parse("2021-03-09 10:30:47");
        System.out.println(accessor);
    }

测试结果:

2021-03-09 10:31:51
{MinuteOfHour=30, MicroOfSecond=0, MilliOfSecond=0, SecondOfMinute=47, NanoOfSecond=0, HourOfAmPm=10},ISO resolved to 2021-03-09

总结:java.util.Date 和 java.sql.Date → Instant
SimpleDateFormat → DateTimeFormatter
Calendar(get、set) → LocalDate、LocalTime、LocalDateTime(with)

三、※java比较器:(涉及到对象比较)(490)

说明:
java中的对象,一般只能进行比较:== 或者 !=。不能使用大小比较,但是在Java开发的场景中,我们需要对多个对象进行比较,言外之意,就需要比较对象的大小。通过Comparable或Comparator接口实现。

Comparable接口(自然排序)使用举例

  1. 像String、包装类等实现了 Comparable接口,重写了compareTo()方法,给出了比较两个对象大小的方式
  2. 重写compareTo()的规则:进行的是从小到大的排序
    如果当前对象this大于形参对象obj,则返回正整数;小于,返回负整数;相等返回0。
  3. 对于自定义类,需要排序时,我们可以让自定义类实现comparable接口,重写compareTo接口。在compareTo(obj)方法中指明排序规则。(实现接口+重写方法+排序规则)
  4. 相同的名次,会默认按照二级排序来进行
    @Override//指明商品比较大小的规则:这里按照价格从低到高排序,排序有重复会默认一个二级排序
    public int compareTo(Object o) {
        if(o instanceof Goods){
          Goods goods =  (Goods) o;
          if(this.price > goods.price){
              return 1;
          }else if(this.price < goods.price){
              return -1;
          }else{
              return 0;
          }
    // 方法二:return Double.compare(this.price,goods.price);
        }
        throw new RuntimeException("传入的数据类型不一致!");
    }

测试:

    @Test
    public void test1(){
        Goods[] arr = new Goods[5];
        arr[0] = new Goods("lenovoMouse",34);
        arr[1] = new Goods("dellMouse",43);
        arr[2] = new Goods("xiaomiMouse",12);
        arr[3] = new Goods("huaweiMouse",65);
        arr[4] = new Goods("microsoftMouse",43);

        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }

测试结果:

[Goods{name='xiaomiMouse', price=12.0}, Goods{name='lenovoMouse', price=34.0}, Goods{name='dellMouse', price=43.0}, Goods{name='microsoftMouse', price=43.0}, Goods{name='huaweiMouse', price=65.0}]

Comparator接口(定制排序)的使用:

当元素类型没有实现Comparable接口又不方便修改代码,或是不合适当前的操作,这时考虑使用comparator接口:

   @Test    //(匿名类实现)
    public void test(){
        String[] strings = {"AA", "BB", "CC", "DD", "FF", "GG"};
        Arrays.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                if(o1 instanceof String && o2 instanceof String){
                    String s1 = (String) o1;
                    String s2 = (String) o2;
                    return -s1.compareTo(s2);
                }
                throw new RuntimeException("输入的数据类型不一致!");
            }
        });
        System.out.println(Arrays.toString(strings));
    }

对比:Comparable接口永久的,在任何实现类的对象在任何位置都可以比较;Comparator接口:一次性的,临时使用,何时需要就创建。

四.System类

系统类:java.lang包;静态的;私有的
标准输入流、标准输出流、
成员方法:

  1. native long currentTimeMillis();当前时间毫秒数。
  2. void exit(int status);退出程序
  3. void gc():请求系统进行垃圾回收。但是会不会立刻回收看系统情况。
  4. String getProperty(String key);获取某个属性,对应系统某个属性值
public class SystemTest {
    @Test
   public void test1(){
        String javaVersion = System.getProperty("java.version");
        System.out.println("java的version" + javaVersion);
    }
}

五.Math类

java.lang.Math:静态的方法,直接调用方法即可,不需要创造类。

  • 初等数学里面那些常见的数学方法。
    常见的常数:
	System.out.println(Math.PI);
	System.out.println(Math.E);
	
01之间随机数:[0,1)
	System.out.println(Math.random());
	....

Random类

生成随机数 UUID
System.out.println(Math.random());[0,1)

	    Random rand = new Random();
	    
        System.out.println(rand.nextInt());//随机整数
        
        System.out.println(rand.nextDouble());
        System.out.println(rand.nextFloat());//随机浮点数float和double
        
        System.out.println(rand.nextBoolean());//随机正误
        System.out.println(rand.nextInt(10));//随机生成1~10的整数

BigInteger类(整型)

  • Integer类作为int的包装类,能存储的最大整型值为2^31 -1 Long型 2^ 63 -1 。 更大的数字表示不出来,于是有了BigInteger。提供不可变的任意精度的整数。
  • BigInteger除了包括那些Math操作,还有模算数、GCD计算、质数测试、素数生成、位操作等。

BigDecimal类(浮点型)

  • 支持科学计算、工程计算等。
  • 支持不可变的、任意精度的有符号十进制定点数。

六、File类

java.io.File
创建文件:.createNewFile(); 查看读写文件、修改文件、删除文件:.delete();
创建是否成功:Boolean类型的定义一个:
Boolean flag = f.mkdir();
创建目录:.mkdirs();中间缺失,可以自动补起来目录;.mkdir();少一个s,中间有缺失的部分,就不可以建起该目录。
可以代表一个文件或者一个目录。

  • file类常见的构造类型:
项目路径:System.out.println(System.getProperty("user.dir"));

常见file的一些操作:

 public static void main(String[] args) throws Exception{

        File f = new File("d:/b.txt");
        System.out.println("file是否存在:"+f.exists());
        System.out.println("file是否存在目录:"+f.isDirectory());
        System.out.println("file是否存在文件:"+f.isFile());
        System.out.println("file最后修改时间:"+new Date(f.lastModified()));
        System.out.println("file的大小:"+f.length());
        System.out.println("file的文件名:"+f.getName());
        System.out.println("file的目录路径:"+f.getPath());
        
    }

递+归应用:打印目录、菜单:
自己调用自己:递归头 + 结束的条件:递归体

一般可以用递归实现的,循环都能实现。

七.java内部类:

  1. 类中的类
  2. 一个java类中可以有多个class类,但是只能有一个public class类
  3. 当外部类和内部类重名,可以用outer.this.成员名 来调用外部类。
  4. 局部内部类:方法内部定义的类。极其少用。作用域也就是只能在这个方法范围内。
  5. 非静态内部类:必须继承在一个outer外部对象里面。(现有外面才有里面);内部可以直接访问外部的,外部的不能直接访问内部的;非静态不能定义static的变量、方法、初始化块。
  6. 静态内部类:有static的类:可以访问外部类的静态成员,不能普通成员。
  7. 匿名内部类:只需要用一次。没有名字的初始化类,不用讲实例保存到变量中,直接new。(重点)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值