第十三章、Java基础补充----常用类

第十三章、Java基础补充----常用类

本人也是刚入门Java语言,可能会有一些地方出现错误,描述的不对。如果发现不对的地方请及时指出,好对其进行修改。这样不仅可以让我学到东西,也可以让其他刚入门的朋友学习更正确的内容。

所有内容仅供参考。不具有完全的准确性!

注:关于Java的所有内容都会参考到尚硅谷在网上公开的学习视频及其提供的PPT

一、字符串相关的类
(一)String类

  • String是一个final类,代表不可变的字符序列。
  • String对象的字符内容是存储在一个字符数组value[]中的。在JDK 1.8 以后,改用byte类型的数组存放。
    JDK 1.7 及以前
    在这里插入图片描述JDK 1.8以后:
    在这里插入图片描述
  • String 实现了Serializable接口,表示字符串是支持序列化
    实现了Comparable接口,表示字符串是可以进行比较
  • String内部定义了final char[] value用于存储字符串数据 (字符串是一个char型的数组,数组长度确定后是不能修改的,即下边所述的不可变性。即使修改后的长度和原有的相同,也需要重新指定一块内存区。因为char数组是final的
  • String:代表不可变的字符序列,即:不可变 性 (表示在方法区中的值是不可以修改的,当修改Sring变量值时,其实是在方法区中重新指定了一块内存区,而不是修改了原有的内存区信息)
    体现:
    1. 当对字符串重新赋值时,需要重新指定内存区赋值,不能使用原有value(final char[] value)内存区进行赋值
    2. 当对现有的字符串进行连接操作时,也需要重新指定内存区赋值,不能使用原有value(final char[] value)内存区进行赋值
    3. 当调用String类中的replace()修改指定字符或字符串时,也需要重新指定内存区赋值,不能使用原有value(final char[] value)内存区进行赋值replace(char oldChar,char newChar)方法修改的是指定字符串中所有的oldchar
  • 通过字面量的方式给字符串赋值(区别于new的方式),此时的字符串值声明在字符串常量池中。
    字面量定义方式 —>直接赋值的方式
  • 字符串常量池中是不会存放相同内容的字符串的,(如果有两个变量的值相同吗,则指向同一个内存区)
String s1 = "abc";//字面量的定义方式
String s2 = "abc";

System.out.println(s1 == s2);//比较s1和s2的地址值

s1 = "hello";
System.out.println(s1 == s2);//再比较s1和s2的地址值
System.out.println(s1);//hello
System.out.println(s2);//abc

输出结果:

true
false
hello
abc

关于不可变性:
在这里插入图片描述

面试题:String s = new String(“abc”);这种方式创建对象,在内存中实际创建了几个对象?
答案:两个,一个在堆空间中new结构,另一个对应char[]对应常量池中"abc"

String类型与 char[]型数组之间的转换:

String —> char[] 使用toCharArray() char[] ch = s1.toCharArray();
char[] —> String 调用String构造器 String s2 = new String(chars);

 public void method4(){

        String s1 = new String("abc123");
        char[] ch = s1.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            System.out.println(ch[i]);//abc123
        }

        char[] chars = {'a','b','v'};
        String s2 = new String(chars);
        System.out.println(s2);
    }

String 与 byte[]型数组之间的转换

String —> byte[] 使用getBytes() byte[] b = s1.getBytes();
byte[] —> String 调用String构造器

 public void method5(){
        String s1 = "abc123";
        byte[] b = s1.getBytes();
//        for (int i = 0; i < b.length; i++) {
//            System.out.print(b[i] + "\t");//97	98	99	49	50	51
//        }
        //或
        System.out.println(Arrays.toString(b));
        String s2 = new String();
        System.out.println(s2);
    }

(二)StringBuffer
也是字符串类
java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。(可变字符序列也就是可以在原有内存的基础上进行值的修改。)
很多方法与String相同。
作为参数传递时,方法内部可以改变值。

在这里插入图片描述
StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:
StringBuffer():初始容量为16的字符串缓冲区
StringBuffer(int size):构造指定容量的字符串缓冲区
StringBuffer(String str):将内容初始化为指定字符串内容

 public void method2(){
        StringBuffer sb1 = new StringBuffer("abc");
        sb1.append(1);
        System.out.println(sb1);//abc1
        sb1.append('2');
        System.out.println(sb1);//abc12
        sb1.append(false);
        System.out.println(sb1);//abc12false
        System.out.println(sb1.length()); //10  (虽然有boolean型,但实际仍是根据字符串长度)

        //删除指定范围内容 从 2开始(包含)到4(不包含)
        sb1.delete(2,4);
        System.out.println(sb1);//ab2false
        //删除指定索引内容
        sb1.deleteCharAt(1);
        System.out.println(sb1);//a2false

        //在指定索引位置插入字符或字符串,原位置上的字符或字符串后移
        sb1.insert(2,'a');
        System.out.println(sb1);

        //转为逆序
        System.out.println(sb1.reverse());//eslafa2a

    }

(三)StringBuilder
同为字符串类
和StringBuffer几乎完全一样,区别就是StringBuffer是线程安全的,
StringBuilder线程不安全

(四)String、StringBuffer、StringBuilder三者的区别

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

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

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

  • 在JDK 8.0以后底层都改为了byte数组。

  • 三者的效率:
    从高到低排列:StringBuilder > StringBuffer > String

二、JDK8之前日期时间API

  • System类中currentTimeMillis();
  • java.util.Date和子类java.sql.Date
  • SimpleDateFormat
  • Calendar

(一)System类的方式
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。

此方法适于计算时间差
例:

long l = System.currentTimeMillis();
System.out.println(l);

输出结果

1609071625604

(二) java.util.Date及子类java.sql.Date

  • java.util.Date类
    1. 两个构造器的使用
      构造器一:Date():创建一个对应当前时间的Date对象
      构造器二:创建指定毫秒数的Date对象
    2. 两个方法的使用
      toString():显示当前的年、月、日、时、分、秒
      getTime():获取当前Date对象对应的毫秒数。(时间戳)
    3. java.sql.Date对应着数据库中的日期类型的变量
      如何实例化
      如何将java.util.Date对象转换为java.sql.Date对象
@Test
    public void test2(){
        //构造器一:Date():创建一个对应当前时间的Date对象
        // java.util.Date类
        Date date1 = new Date();
        System.out.println(date1.toString());//Sat Feb 16 16:35:31 GMT+08:00 2019

        System.out.println(date1.getTime());//1550306204104

        //构造器二:创建指定毫秒数的Date对象
        Date date2 = new Date(155030620410L);
        System.out.println(date2.toString());//Sat Nov 30 16:03:40 CST 1974

        //创建java.sql.Date对象
        java.sql.Date date3 = new java.sql.Date(35235325345L);
        System.out.println(date3);//1971-02-13

        //如何将java.util.Date对象转换为java.sql.Date对象
        //情况一:
//        Date date4 = new java.sql.Date(2343243242323L);
//        java.sql.Date date5 = (java.sql.Date) date4;
        //情况二:
        Date date6 = new Date();
        java.sql.Date date7 = new java.sql.Date(date6.getTime());
    }

(三)java.text.SimpleDataFormat类
Date类的API不易于国际化,大部分被废弃了
SimpleDateFormat 对日期Date类的格式化和解析

  1. 两个操作:
    ① 格式化:日期 —>字符串
    ② 解析:格式化的逆过程,字符串 —> 日期

  2. SimpleDateFormat的实例化:new + 构造器

		// 创建指定格式的SimpleDateFormat类的对象
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Date date1 = new Date();

        //格式化
        String str = simpleDateFormat1.format(date1);
        System.out.println(str);

        //解析
        Date date2 = simpleDateFormat1.parse(str);
        System.out.println(date2);

输出结果

2020-12-27 083859
Sun Dec 27 08:38:59 CST 2020

将字符串格式转换为sql下的Date

public void testExer() throws ParseException {

        String birth = "2020-1-1";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        //字符串格式和SimpleDateFormat类的指定格式必须一样
        Date date = simpleDateFormat.parse(birth);
        System.out.println(date);
        //先转换成util下的Date 再通过util下的Date调用getTime()转换成sql下的Date
        java.sql.Date birthDate = new java.sql.Date(date.getTime());
        System.out.println(birthDate);
    }

注意:解析的时候,字符串的格式必须严格按照SimpleDateFormat类的对象指定的格式,否则会抛异常

(四)Calendar类:日历类
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。

public void testCalender(){

        //实例化
        //方式一: 创建其子类GregorianCalendar的对象 ---省略
        //方式二:调用其静态方法getInstance()
        Calendar instance = Calendar.getInstance();
        
        //此时返回的是class java.util.GregorianCalendar的对象 
        System.out.println(instance.getClass());//java.util.GregorianCalendar

        //常用方法
        //get  返回给定日历字段的值。
        int days = instance.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);
        System.out.println(instance.get(Calendar.DAY_OF_YEAR));

        //set 将给定的日历字段设置为给定值。
        instance.set(Calendar.DAY_OF_WEEK, 6);
        days = instance.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);
        System.out.println(instance.get(Calendar.DAY_OF_YEAR));//332

        //add 为给定的日历字段添加或减去指定的时间量。
        instance.add(Calendar.DAY_OF_YEAR,-331);//表示将获取到的时间减去331天
        days = instance.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);
        System.out.println(instance.get(Calendar.DAY_OF_YEAR));

        //getTime  返回一个表示此 Calendar 时间值(从历元至现在的毫秒偏移量)的 Date 对象。
        // Calendar ---> Date
        Date date = instance.getTime();
        System.out.println(date); //Wed Jan 01 14:35:15 CST 2020  星期 月 日 CST:中部标准时间(Central Standard Time)

        //setTime  使用给定的 Date 设置此 Calendar 的时间。
        //注 :使用 Date(Long.MAX_VALUE) 或 Date(Long.MIN_VALUE) 调用 setTime() 可能产生来自 get() 的错误字段值。
        //  Date ---> Calendar
        instance.setTime(date);
        days = instance.get(Calendar.DAY_OF_WEEK);
        System.out.println(days);
    }

注意:

获取月份时:一月是0,二月是1,以此类推,12月是11
获取星期时:周日是1,周二是2 , 。。。。周六是7

三、JDK8中新日期时间API

(一)为什么要引入新的时间API
因为Date类和Calendar类存在一些问题:

可变性:像日期和时间这样的类应该是不可变的。
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date用,Calendar则不行。
此外,它们也不是线程安全的;不能处理闰秒等。

例:

 public void testDate(){
        //偏移量
        Date date1 = new Date(2020,9,8);
        System.out.println(date1);
    }

当我们想获取2020年9月8号这一天,但此时得到的结果却并不是我们想要的。

输出结果:

Fri Oct 08 00:00:00 CST 3920

发现输出的是3920年,比我们想要的多了1900年。月份也比我们想要的多了一个月。这就是偏移量的问题。

在JDK 8.0版本发布了新的时间相关API以后,就完全解决了以上问题。

(二)java 8 中新的日期时间API涉及到的包
在这里插入图片描述(三)java 8 中新的日期时间提供的类

本地日期 - - - LocalDate
本地时间 - - - LocalTime
本地日期时间 - - - LocalDateTime
时区 - - - ZonedDateTime
持续时间 - - - Duration

  • LocalDateTime相较于LocalDate、LocalTime,使用频率要高
  • 类似于Calendar

实例化:

 		//now():获取当前的日期、时间、日期+时间
        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, 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 localDate1 = localDate.withDayOfMonth(22);
        System.out.println(localDate);
        System.out.println(localDate1);


        LocalDateTime localDateTime2 = localDateTime.withHour(4);
        System.out.println(localDateTime);
        System.out.println(localDateTime2);

        //不可变性
        LocalDateTime localDateTime3 = localDateTime.plusMonths(3);
        System.out.println(localDateTime);
        System.out.println(localDateTime3);

        LocalDateTime localDateTime4 = localDateTime.minusDays(6);
        System.out.println(localDateTime);
        System.out.println(localDateTime4);

(四)Instant的使用

  • 时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
  • Instant的精度可以达到纳秒级。
  • 类似于 java.util.Date类
ublic void test2(){
        //now():获取本初子午线对应的标准时间
        Instant instant = Instant.now();
        System.out.println(instant);//2019-02-18T07:29:41.719Z

        //添加时间的偏移量
        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

  • 格式化或解析日期、时间

  • 类似于SimpleDateFormat

  • 预定义的标准格式。
    如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
    本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
    自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

方式一:预定义

 		// 方式一:预定义的标准格式
        DateTimeFormatter isoDateTime = DateTimeFormatter.ISO_DATE_TIME;
        //格式化 : 日期 --->字符串
        LocalDateTime now = LocalDateTime.now();
        String format = isoDateTime.format(now);
        System.out.println(now); //2020-11-29T15:01:31.485934300  日期格式
        System.out.println(format);//2020-11-29T15:01:01.848602   字符串格式

        //解析 字符串 ---> 日期
        //格式必须保持一致
        TemporalAccessor parse = isoDateTime.parse("2020-11-29T15:01:31.4859343");
        System.out.println(parse);//{},ISO resolved to 2020-11-29T15:01:31.485934300

方式二:本地化相关的格式

        DateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
        //格式化
        String str3 = formatter2.format(LocalDate.now());
        System.out.println(str3);//2019-2-18
		
		//解析方式与方式一相同

方式三:自定义的格式(重要)

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);

四、Java比较器
Java中的对象,正常情况下,只能进行比较:== 或 != 。不能使用 > 或 < 的但是在开发场景中,我们需要对多个对象进行排序,就需要比较对象的大小。就用到了下边两个排序接口:

自然排序:java.lang.Comparable
定制排序:java.util.Comparator

(一)自然排序

  1. 像String、包装类等也都实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
  2. 像String、包装类重写compareTo()方法以后,进行了从小到大的排列
  3. 重写compareTo(obj)的规则:
    如果当前对象this大于形参对象obj,则返回正整数,
    如果当前对象this小于形参对象obj,则返回负整数,
    如果当前对象this等于形参对象obj,则返回零。
  4. 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
public class Goods implements  Comparable{

    private String name;
    private double price;

    //指明商品比较大小的方式:照价格从低到高排序,再照产品名称从高到低排序
    @Override
    public int compareTo(Object o) {
//        System.out.println("**************");
        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 -this.name.compareTo(goods.name);
            }
            //方式二:
//           return Double.compare(this.price,goods.price);
        }
//        return 0;
        throw new RuntimeException("传入的数据类型不一致!");
    }
// getter、setter、toString()、构造器:省略
}

(二)定制排序

  1. 背景:
    当元素的类型没实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
  2. 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
    如果方法返回正整数,则表示o1大于o2;
    如果返回0,表示相等;
    返回负整数,表示o1小于o2。
Comparator com = 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接口的方式一旦一定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
Comparator接口属于临时性的比较。

五、其他类

(一)System类

  • System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
  • 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。
  • 常用方法:
    native long currentTimeMillis()
    void exit(int status)
    void gc()
    String getProperty(String key)
public void test1() {
        String javaVersion = System.getProperty("java.version");
        System.out.println("java的version:" + javaVersion);

        String javaHome = System.getProperty("java.home");
        System.out.println("java的home:" + javaHome);

        String osName = System.getProperty("os.name");
        System.out.println("os的name:" + osName);

        String osVersion = System.getProperty("os.version");
        System.out.println("os的version:" + osVersion);

        String userName = System.getProperty("user.name");
        System.out.println("user的name:" + userName);

        String userHome = System.getProperty("user.home");
        System.out.println("user的home:" + userHome);

        String userDir = System.getProperty("user.dir");
        System.out.println("user的dir:" + userDir);

    }

(二)Math类

java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。
常用方法:
在这里插入图片描述(三)BigInteger

Integer类作为int的包装类,能存储的最大整型值为2^31-1, Long类也是有限的,最大为2^63 - 1。如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。

java.math包的BigInteger可以表示不可变的任意精度的整数。当需要使用的数值超出了Long类型的长度时,就可以使用该类。

BigInteger bi = new BigInteger("1243324112445554485234324324325235245346567657653");

常用方法:
在这里插入图片描述
(四)BigDecimal

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

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

在这里插入图片描述

常用方法
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值