Java常用类

Java 常用类

 

1. String 类

  • String类是final 类, 代表不可变字符序列,无法被继承 , 不可变性

  • String类对象是常量,创建后不能修改

  • String类实现了 Serializable接口, 支持 序列化

  • String类实现了 Comparable 接口, 支持 比较大小

  • String类定义了 final char[] value 数组, 存储 字符串数据

 

 

 

  •  字符串常量池不会存储相同内容(使用String 类的 equal() 方法返回true) 

1.1 不可变性

String的不可变性

  • 通过字面量方式,给字符串赋值,此时此字符串值 声明在常量池中

  • 字符串常量池中,不会存储相同内容的常量

  • 当对字符串重新赋值时,需要重新指定存储区域赋值不能使用原有value进行赋值

  • 当对字符串改变值时 ,需要 重新指定存储区域赋值不能在原有value进行改变

  • 只要对字符串内容进行任何的修改,都要重新建一个对象,不能直接改变

 

 

 

1.2 String对象创建

 //1. 方式1 字面量
 String str = "Hello";
 
 //2. 方式2 new 对象
 
  //2.1 this.value = new char[0];
 String s1 = new String();
 
  //2.2 this.value = original.value;
 String  s2 = new String(String original);
 
  //2.3 this.value = Arrays.copyOf(value,value.length)
 String s3 = new String(char[] a);
 String s4 = new String(char[] , int startIndex,int count)

创建String对象的两种方式解读:

  • String str = "abc"; 声明在方法区的字符串常量池中

  • String str = new String("abc"); str中保存的地址值,是字符串在堆空间中开辟的空间 的 对应的地址值

 public void test(){
  String s1 = "abc";
  String s2 = "abc";
 
  String s3 = new String("abc");
  String s4 = new String("abc");
 
  System.out.println(s1 == s2); //true
  System.out.println(s1 == s3);//false
  System.out.println(s1 == s4);//false
  System.out.println(s3 == s4);//false
 }

🔴面试题

  • String s = new String("abc"); 方式创建对象,在内存中会创建几个对象

    • 一个或者两个

    • 如果 常量池中没有字面量存在, 就要现在常量池中创建一个常量对象,之后在堆中new创建一个字符串对象。

    • 如果 常量池中 有 字面量存在, 就只要在堆中开辟一个空间,创建一个字符串对象,然后将 值 赋值进去。

 

 

注意: 此处是 new Person("字符串",) 和直接 new String("字符串") 不一样

直接 new String("字符串") 如上图, 两个地址是不一样的

但是下图是直接使用的常量池中的字符串, 地址是一样的, 所有使用 == 比较 ,两个地址是相同的

 

 

1.3 拼接字符串

 public void test(){
  String s1 = "javaEE";
     String s2 = "hadoop";
     
     String s3 = "javaEEhadoop";//字面量 常量池中的
     String s4 = "javaEE" + "hadoop";//字面量连接 在常量池中的 是同一个
     String s5 = s1 + "hadoop";//堆中创建的对象
     String s6 = "javaEE" + s2;//堆中创建的对象
     String s7 = s1+s2;//堆中创建的对象
     
     System.out.println(s3==s4);//true
     
     System.out.println(s3==s5);//false
     System.out.println(s3==s6);//false
     System.out.println(s5==s6);//false
     System.out.println(s3==s7);//false
  System.out.println(s5==s7);//false
     System.out.println(s6==s7);//false
     
     String s8 = s5.intern();//s8 使用的是,常量池中已经存在的字符串
     //intern() 方式是直接去常量池中找 与 s5内容相同的字符串字面量了
     
     System.out.println(s3 == s8);//true 最终返回的是字面量和字面量比较结果
 }
 

 

 

 

 

结论

  • 常量与常量拼接结果在常量池中,且常量池中不会存在相同内容的常量

  • 只要其中有一个是变量,结果就在堆中

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

🔴 面试题

 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.print(ex.str);// good String 不可变
  System.out.print(ex.ch);//best
  }
 }

 

1.4常用方法

 

image-20220323193247144

 

字符串与char[] 数组的转换

stringname.toCharArray : 将字符串转换为char数组

String(char[]) : string构造器 将字符数组转换为 字符串

 

字符串与字节数组转换

String.getBytes([charsetName]): 字符串转为字节数组 编码

new String(byte[] bytes,[charsetName]): 字节数组 转为字符串 解码

编码 : 字符串 ---> 字节

节码: 字节 ---> 字符串

编码与解码时 使用的字符集都要一样, 不然会出现乱码

 

 

🔴 面试题: StringBufferStringBuilderString三者的异同

  • String :

    • 不可变的字符序列

    • 使用 char[] 存储

  • StringBuffer: 存在多线程操作 ,涉及线程安全问题使用

    • 可变的字符序列

    • 使用 char[]存储

    • 线程安全

    • 效率偏低

  • StringBuilder: JDK 5.0 新增

    • 可变的字符序列

    • 线程不安全

    • 效率较高

  • 问题1: 长度问题

    • sb.length() StringBuffer长度还是原来的字符的数量,不会把后面的16算进去的

  • 问题2: 扩容问题

    • 默认情况下 扩充后长度: 2*len + 2 ,原有数组元素复制到新的数组 (len是原来长度)

  • 开发建议 : 使用 StringBuffer(int capacity) / StringBuilder(int capacity) 指定容量 避免扩容

 可变与不可变底层存储结构线程安全效率
String 不可变 char[] 安全(不可变)
StringBuffer(jdk 1.0) 可变 char[] 安全 (同步方法)
StringBuilder(jdk5.0新增) 可变 char[] 不安全

源码分析

 String str = new String();//new char[0]
 String str1 = new String("abc");//new char[]{'a','b','c'};
 
 //char[] value = super(capacity:16); new char[16] 底层创建了一个长度16的数组
 StringBuffer sb1 = new StringBuffer();
 sb1.append('a');//value[0] = 'a';
 sb1.apppend('b');//value[1] = 'b';
 
 //char[] value = new char["abc".length() + 16] 每次造完都会额外的空出16个位置
 StringBuffer sb2 = new StringBuffer("abc");
 
 //问题1: 长度问题
 sb2.length();// StringBuffer长度还是原来的字符的数量,不会把后面的16算进去的
 
 //问题2: 扩容问题
 //默认情况下 扩充后长度: 2*len + 2 ,原有数组元素复制到新的数组 (len是原来长度)
 
 //开发建议 : 使用 StringBuffer(int capacity) / StringBuilder(int capacity) 指定容量 避免扩容
 

StringBuffer类的常用方法

 

1.5 String StringBuffer StringBuilder 转换

String ---> StringBuffer,StringBuilder

转换方法: 调用 两者的构造器

 StringBuffer/StringBuilder sb = StringBuffer/StringBuilder(String str);//调用构造器

StringBuffer,StringBuilder ---> String

 String str = String(StringBuffer buffer)//还是调用构造器
 toString(); 方法

image-20220324195212578

字符串常量池存放位置

jdk 1.6 :方法区(永久区

jdk 1.7: 堆空间

jdk 1.8 方法区(元空间)

2. 日期时间类

JDK8 之前的日期时间类

  1. System 类中的 currentTimeMillis()

  2. java.util.Date 和子类 java.sql.Date

  3. SimpleDateFormat : 对日期Date类的格式化与解析

  4. Calendar

2.1 Date类

 

 

JDK8之前的日期和时间API

  • System.currentTimeMillis() 毫秒数 时间戳

  • java.util.Date

    • 两个构造器

      • Date() 创建当前时间的date对象

      • Date(long date) 创建指定毫秒时间的date对象

    • 两个方法

      • toString() : 显示 当前年, 月, 日 , 时 分 秒

      • getTime() : 得到毫秒数 和 时间戳一样

    • java.sql.Date类 (子类)

      • 构造器 java.sql.Date date3 = new java.sql.Date(毫秒时间戳);

      • util.Date --> sql.Date image-20220324161845875

image-20220324162309553

2.2 SimpleDateFormat类

java.text.SimpleDateFormat

image-20220324195852280

两个操作

  1. 格式化: 日期 ---> 字符串

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

 

 
 //1. 使用默认构造器 默认的模式 和语言环境 创建对象
 SimpleDateFormat sdf = new SimpleDateFormat();
 Date date = new Date();
 //将日期格式化为字符串
 String format = sdf.format(date);
 System.out.println(format);
 //将字符串解析为日期
 Strint str = "22-3-24 晚上20:08";//默认只能解析这个字符串
 Date date = sdf.parse(str);
 System.out.println(date);
 
 // 使用指定方式格式化和解析
 //2.使用指定格式构造器
 SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
 
 //格式化
 String format1 = sdf1.format(date);
 System.out.println(format1);
 
 //解析 从字符串到日期
 Date date2 = sdf1.parse("2022-03-24 20:14:00");

2.3 Calendar 日历类使用

抽象类

 

  1. 实例化

    • 方式1: 创建 Calendar 的子类 GregorianCalendar的对象

    • 方式2: 调用静态方法 getInstance()

 Calendar calendar = Calendar.getInstance();

 

  1. 常用方法

    • get() : 获取常用信息

    • set() : 设置天数/年数/月数

    • add() :增加天数/年数/月数

    • getTime() : 从日历对象获取 Date类对象

    • setTime(): 将Date类对象 转换成 日历类对象

 //get() 方法
 int days = calendar.get(Calendar.DAY_OF_MONTH);//获取一些常用信息
 
 //set() 方法
 calendar.set(Calendar.DAY_OF_MONTH,22);//设置信息
 //add() 方法
 calendar.add(Calendar.DAY_OF_MONTH,3);//在当前属性上增加信息
 
 //getTime() 从日历对象 获取 Date
 Date date = calendar.getTime();
 
 //setTime() 将 Date 改变为 日历类
 Date date1 = new Date();
 Calendar.setTime(date1);
 

 

3. 日期时间类 JDK8

  • 可变性: 日期时间应该是不可变的,但是 Calendar可变

  • 偏移量Date 从1900年0月开始, 日期出现了 偏移量, 需要减去偏移量

  • 格式化: 格式化只对 Date有关

  • 线程安全: Date 不是线程安全的

  • 不支持闰秒

java.time API 纠正了过去缺陷:

  • 本地日期 LocalDate

  • 本地时间 LocalTime

  • 本地日期时间 LocalDateTime

  • 时区 ZonedDateTime

  • 持续时间 Duration

  • 计算机记录时间,通过距离 1970 开始以毫秒为单位 Instant

     

 

1. 新时间日期API

  • java.time 包含值对象的基础包

  • java.time.chrono 提供不同的日历系统的访问

  • java.time.format 格式化和解析时间和日期

  • java.time.temporal 包括底层框架和扩展特性

  • java.time.zone 包含时区支持的类

image-20220325134127933

 package datetimetest;
 
 import org.junit.jupiter.api.Test;
 
 import java.time.*;
 
 /**
  * @author ZhongweiLeex
  * @Date 2022-03-25 13:43
  */
 public class JDK8DateTimeTest {
     @Test
     public void test1(){
         //now() : 获取当前 时间 日期 日期时间
         LocalDate localDate = LocalDate.now();
         LocalTime localTime = LocalTime.now();
         LocalDateTime localDateTime = LocalDateTime.now();
         System.out.println(localDateTime);
         System.out.println(localDate);
         System.out.println(localTime);
 
         //of() : 无偏移量 的设置年月日时分秒
         LocalDateTime localDateTime1 = LocalDateTime.of(2022, 3, 25, 13, 46);
         System.out.println(localDateTime1);
 
         System.out.println();
         //getxxx() : 获取相关属性
         System.out.println(localDateTime.getDayOfMonth());
         System.out.println(localDateTime.getDayOfWeek());
         System.out.println(localDateTime.getDayOfYear());
         System.out.println(localDateTime.getMonth());
         System.out.println(localDateTime.getMonthValue());
         System.out.println(localDateTime.getMinute());
 
         System.out.println();
         //withxxx : 设置相关属性
         //体现了不可变性
         LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(22);
         System.out.println(localDateTime2);
         System.out.println(localDateTime);
 
         System.out.println();
         //plusxxx() : 修改相关属性 / minsxxx()
         //体现了不可变性
         LocalDateTime localDateTime3 = localDateTime.plusDays(12);
         System.out.println(localDateTime3);
         System.out.println(localDateTime);
 
         System.out.println();
 
         //java机器时间 以本初子五线的时间为主
         Instant instant = Instant.now();
         System.out.println(instant);//以本初子五线的时间为主
 
         //添加时间偏移量 (根据时区添加偏移量)
         System.out.println(instant.atOffset(ZoneOffset.ofHours(8)));
 
         System.out.println();
         //获取瞬时点的毫秒数
         System.out.println(instant.toEpochMilli());
 
         
         System.out.println();
         //通过毫秒数创建对象
         Instant instant1 = Instant.ofEpochMilli(instant.toEpochMilli());//通过毫秒数创建对象
         System.out.println(instant1);
    }
 }
 
 

 

2. Instant

java中,计算机记录时间,通过距离 1970 开始以毫秒为单位

image-20220325135945486

3. java.time.format.DateTimeFormatter类

格式化与解析新时间类实例

image-20220325141456747

         //1. 预定义的标准格式
         //格式化:日期 ---> 字符串
         DateTimeFormatter isoLocalDateTime = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
         LocalDateTime localDateTime4 = LocalDateTime.now();
         String str = isoLocalDateTime.format(localDateTime4);
         System.out.println(str);
 
         System.out.println();
         //解析: 字符串 ---> 日期
         TemporalAccessor parse = isoLocalDateTime.parse("2022-03-25T14:17:47.2054108");
         System.out.println(parse);
 
 
         //2. 本地方式格式化
         // 格式化: 日期 ---> 字符串
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
         String str2 = dateTimeFormatter.format(localDateTime4);
         System.out.println(str2);
 
         System.out.println();
         DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
         String str3 = dateTimeFormatter2.format(localDateTime4);
         System.out.println(str3);
 
         System.out.println();
         //3. 自定义方式格式化 ofPattern("yyyy-MM-dd hh:mm:ss E");
         DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
         String str4 = dateTimeFormatter1.format(LocalDateTime.now());
         System.out.println(str4);
         // 解析
         TemporalAccessor parse1 = dateTimeFormatter1.parse("2022-03-25 02:29:17");
         System.out.println(parse1);

 

4. Java比较器

需求:java对象比较大小

  • 方式1 自然排序 : 实现Comparable接口,重写 compareTo(obj)方法

    • 一旦定义,保证 comparable 接口的实现类的对象在任何位置都可以比较大小

  • 方式2 定制排序 :实现 Comparator接口,重写 compare(obj1,obj2)方法

    • Comparator接口属于临时性比较

两种方法的区别

  • compareTo(obj) 在需要比较的类中定义的 , 使用 this.属性 和 对象名.属性 进行比较

  • compare(obj1,obj2) 临时在 sort方法中设置的定制排序器

 

  1. java中对象正常情况下只能进行 == != 不能使用 > / < 开发场景中需要对多个对象进行排序 需要比较对象大小 使用比较器接口 Comparable Comparator

  2. Comparable接口的使用

    • String , 包装类 等实现了 Comparable接口,重写了 ComparaTo(obj)方法,重写了比较两个对象大小的方式

    • 重写 comparaTo(obj)方法的规则:

      • 当前对象this 大于 形参对象obj 返回正整数

      • 小于 返回 负整数

      • 等于 返回 零

    • 对于自定义类,如果需要排序,可以将自定义类重写 Comparable接口中的 comparaTo(obj),指明如何排序

 package comparetest;
 
 import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
 import java.util.Comparator;
 
 /**
  * @author ZhongweiLeex
  * @Date 2022-03-25 14:43
  * 1. java中对象正常情况下只能进行 == != 不能使用 > / <
  * 开发场景中需要对多个对象进行排序 需要比较对象大小 使用比较器接口 Comparable Comparator
  *
  * 2. Comparable 使用
  */
 public class CompareTest {
     //Comparable 使用举例
     @Test
     public void test1(){
         Good[] goods = new Good[4];
         goods[0] = new Good(34, "asdfsf");
         goods[1] = new Good(50, "bdsfsdf");
         goods[2] = new Good(27, "cdfdf");
         goods[3] = new Good(12, "cadfsf");
         //没有排序
         System.out.println(Arrays.toString(goods));
         System.out.println();
 
         System.out.println("按照价格排序");
         //按照价格排序
         //方式1: Good类实现Comparable接口 重写其中的 compareTo()方法 之后调用 Arrays.sort()方法
         Arrays.sort(goods);
         System.out.println(Arrays.toString(goods));
         System.out.println();
         //按照价格排序
         //方式2: 直接重写 Arrays.sort(list,comparator)中的比较器
         Arrays.sort(goods,(a,b)->(int)(a.getPrice()- b.getPrice()));
         System.out.println(Arrays.toString(goods));
         System.out.println();
 
         //按照名字字符串的字符序排序
         System.out.println("按照字符序排序:");
         Arrays.sort(goods, new Comparator<Object>() { //匿名实现类对象
             //按照字符串从大到小的排列
             @Override
             public int compare(Object o1, Object o2) {
                 if (o1 instanceof Good && o2 instanceof Good){
                     String s1 = ((Good) o1).getName();
                     String s2 = ((Good) o2).getName();
                     return s1.compareTo(s2);
                }
                 throw new RuntimeException("输入数据类型不一致");
            }
        });
 
         //lambda 方式
 /*       Arrays.sort(goods, (Comparator<Object>) (o1, o2) -> {
             if (o1 instanceof Good && o2 instanceof Good){
                 String s1 = ((Good) o1).getName();
                 String s2 = ((Good) o2).getName();
                 return s1.compareTo(s2);
             }
             throw new RuntimeException("输入数据类型不一致");
         });*/
         System.out.println(Arrays.toString(goods));
         System.out.println();
 
 
 
         System.out.println("按照价格排序");
         //方式3 : 直接将 Arrays.sort 封装到 sort方法中
         System.out.println(Arrays.toString(sort(goods)));
 
    }
 
 
 
     private Good[] sort(Good[] goods){
         //按照什么样的排序
         Arrays.sort(goods,(a,b) -> (int) (b.getPrice()-a.getPrice()));
         return goods;
    }
 }
 
 
 
 
 
 class Good implements Comparable<Object>{
     private double price;
     private String name;
     public Good() { }
     public Good(double price, String name) {
         this.price = price;
         this.name = name;
    }
     public double getPrice() {
         return price;
    }
     public void setPrice(double price) {
         this.price = price;
    }
     public String getName() {
         return name;
    }
     public void setName(String name) {
         this.name = name;
    }
 
     @Override
     public String toString() {
         return "Good{" +
                 "price=" + price +
                 ", name='" + name + '\'' +
                 '}';
    }
     //指明比较大小方式 按照价格从低到高
     @Override
     public int compareTo(Object o) {
         if (o instanceof Good){
             Good good = (Good) o;
             //方式1 : 自己写
             if (this.price > good.price){
                 return 1;
            }else if (this.price < good.price){
                 return -1;
            }else{
                 return 0;
            }
             //方式2:使用double.compare
 //           return Double.compare(this.price,good.price);
        }
         throw new RuntimeException("传入的数据类型不一致");
    }
 }
 

5. System类

6. Math类

7. BigInteger 和 BigDecimal类

Integer 最大存储 2^31-1

Long 最大存储 2^63 -1

BigInteger:

  • 可以表示不可变的任意精度的整数

  • 构造器 : BigInteger(String val) 根据字符串构建 BigInteger对象

BigDecimal:

  • 可以表示不可变的, 任意精度的 有符号十进制定点数

  • 构造器:

    • public BigDecimal(double val)

    • public BigDecimal(String val)

 

总结

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-03-25 16:57  zhongweiLeex  阅读(96)  评论(0)    收藏  举报