JAVA基础深化提高(三) | 常用类

2024-02-28 21:50
文章标签 java 基础 常用 提高 深化

本文主要是介绍JAVA基础深化提高(三) | 常用类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.包装类

1.1 基本数据类型的包装类

在这里插入图片描述

1.2 Number类

在这里插入图片描述
Number 类是抽象类,因此它的抽象方法,所有子类都需要提供实现。Number 类提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的“数字型”包装类都可以互相转型。
【示例】初识包装类

public class WrapperClassTest {public static void main(String[ ] args) {Integer i = new Integer(10); //从 java9 开始被废弃Integer j = Integer.valueOf(50); //官方推荐}
}

示例内存分析如图所示:
在这里插入图片描述

1.3 自动拆箱和装箱

自动装箱(autoboxing)和拆箱(unboxing):将基本数据类型和包装类自动转换。
【示例】自动装箱

Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer.valueOf(100);//调用的是 valueOf(100),而不是 new Integer(100)

【示例】自动拆箱

Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();

1.4 包装类的缓存问题

  整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
  缓存原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
【示例】Integer 类相关源码

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
  1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。
  2. 一般情况下 IntegerCache.low为-128,IntegerCache.high为127

【示例】IntegerCache 类相关源码

 private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}

由上面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程会在类加载时完成。

总结

  • 自动装箱调用的是 valueOf()方法,而不是 new Integer()方法。
  • 自动拆箱调用的 xxxValue()方法。
  • 包装类在自动装箱时为了提高效率,对于-128~127 之间的值会进行缓存处理。超过范围后,对象之间不能再使用==进行数值的比较,而是使用 equals 方法。

2.字符串相关类

String 类代表不可变的字符序列
StringBuilder 类和 StringBuffer 类代表可变字符序列。

2.1 String 类源码分析

  String 类对象代表不可变的 Unicode 字符序列,因此我们可以将 String 对象称为“不可变对象”。 那什么叫做“不可变对象”呢?指的是对象内部的成员变量的值无法再改变。
我们打开 String 类的源码,如图所示:
在这里插入图片描述
  我们发现字符串内容全部存储到 value[ ]数组中,而变量 value 是 final 类型的,也就是常量(即只能被赋值一次)。 这就是“不可变对象”的典型定义方式。

在遇到字符串常量之间的拼接时,编译器会做出优化,即在编译期间就会完成字符串的拼接。因此,在使用==进行 String 对象之间的比较时,我们要特别注意,如示例所示。

【示例】字符串常量拼接时的优化

public class TestString2 {public static void main(String[ ] args) {//编译器做了优化,直接在编译的时候将字符串进行拼接String str1 = "hello" + " java";//相当于 str1 = "hello java";String str2 = "hellojava";System.out.println(str1 == str2);//trueString str3 = "hello";String str4 = " java";//编译的时候不知道变量中存储的是什么,所以没办法在编译的时候优化String str5 = str3 + str4;System.out.println(str2 == str5);//false}
}

2.2 StringBuffer 和 StringBuilder 可变字符序列

StringBuffer 和 StringBuilder 都是可变的字符序列。

  • StringBuffer 线程安全,做线程同步检查, 效率较低。
  • StringBuilder 线程不安全,不做线程同步检查,因此效率较高。建议采用该类。

【示例】StringBuffer/StringBuilder 基本用法

        public class TestStringBufferAndBuilder{public static void main(String[ ] args) {/**StringBuilder*/StringBuilder sb = new StringBuilder();for (int i = 0; i < 7; i++) {sb.append((char) ('a' + i));//追加单个字符}System.out.println(sb.toString());//转换成 String 输出sb.append(", I can sing my abc!");//追加字符串System.out.println(sb.toString());/**StringBuffer,下面的方法同样适用 StringBuilder*/StringBuffer sb2 = new StringBuffer("Java");sb2.insert(0, "爱").insert(0, "我");//插入字符串System.out.println(sb2);sb2.delete(0, 2);//删除子字符串System.out.println(sb2);sb2.deleteCharAt(0).deleteCharAt(0);//删除某个字符System.out.println(sb2.charAt(0));//获取某个字符System.out.println(sb2.reverse());//字符串逆序}}

2.3 不可变和可变字符序列使用陷阱

  String 一经初始化后,就不会再改变其内容了。对 String 字符串的操作实际上是对其副本(原始拷贝)的操作,原来的字符串一点都没有改变。比如:

	String s ="a"; 创建了一个字符串

  s = s+“b”; 实际上原来的"a"字符串对象已经丢弃了,现在又产生了另一个字符串s+“b”(也就是"ab")。 如果多次执行这些改变串内容的操作,会导致大量副本字符串对象存留在内存中,降低效率。如果这样的操作放到循环中,会极大影响程序的时间和空间性能,甚至会造成服务器的崩溃。
  相反,StringBuilder 和 StringBuffer 类是对原字符串本身操作的,可以对字符串进行修改而不产生副本拷贝或者产生少量的副本。因此可以在循环中使用。
【示例】String 和 StringBuilder 在字符串频繁修改时的效率测试

public class Test {public static void main(String[ ] args) {
/**使用 String 进行字符串的拼接*/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 进行字符串的拼接*/StringBuilder sb1 = new StringBuilder("");long num3 = Runtime.getRuntime().freeMemory();long time3 = System.currentTimeMillis();for (int i = 0; i < 5000; i++) {sb1.append(i);}long num4 = Runtime.getRuntime().freeMemory();long time4 = System.currentTimeMillis();System.out.println("StringBuilder 占用内存 : " + (num3 - num4));System.out.println("StringBuilder 占用时间 : " + (time4 - time3));}
}

执行结果如图所示:
在这里插入图片描述

3.时间处理相关类

  “时间如流水,一去不复返”,时间是一维的。所以,我们需要一把刻度尺来表达和度量时间。在计算机世界,我们把 1970 年 1 月 1 日 00:00:00 定为基准时间,每个度量单位是毫秒(1 秒的千分之一),如图所示。
在这里插入图片描述
  我们用 long 类型的变量来表示时间,从基准时间前后几亿年都能表示。
  这个“时刻数值”是所有时间类的核心值,年月日都是根据这个“数值”计算出来的。

3.1 Date 时间类(java.util.Date)

【示例】Date 类的使用

System.currentTimeMillis():时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数

long nowNum = System.currentTimeMillis(); //当前时刻对应的毫秒数
Date d = new Date(); //当前时刻的对象
System.out.println(d.getTime()); //返回时间对应的毫秒数
Date d2 = new Date(1000L * 3600 * 24 * 365 * 150); //距离 1970年 150 年
System.out.println(d2);

3.2 DateFormat 类和 SimpleDateFormat 类

DateFormat 类的作用

  把时间对象转化成指定格式的字符串。反之,把指定格式的字符串转化成时间对象。
  DateFormat 是一个抽象类,一般使用它的的子类 SimpleDateFormat 类来实现。

【示例】DateFormat 类和 SimpleDateFormat 类的使用

import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;
public class TestDateFormat {public static void main(String[ ] args) throws ParseException {// new 出 SimpleDateFormat 对象SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd");// 将时间对象转换成字符串String daytime = s1.format(new Date());System.out.println(daytime);System.out.println(s2.format(new Date()));System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date()));// 将符合指定格式的字符串转成成时间对象.字符串格式需要和指定格式一致。String time = "2049-10-1";Date date = s2.parse(time);System.out.println("date1: " + date);time = "2049-10-1 20:15:30";date = s1.parse(time);System.out.println("date2: " + date);}
}
字母日期或时间元素表示示例
GEra 标志符TextAD
yYear1996; 96
M年中的月份MonthJuly; Jul; 07
w年中的周数Number27
W月份中的周数Number2
D年中的天数Number189
d月份中的天数Number10
F月份中的星期Number2
E星期中的天数TextTuesday; Tue
aAm/pm 标记TextPM
H一天中的小时数(0-23)Number0
k一天中的小时数(1-24)Number24
Kam/pm中的小时数(0-11)Number
ham/pm 中的小时数(1-12)Number12
m小时中的分钟数Number30
s分钟中的秒数Number55
S毫秒数Number978
z时区General time zonePacific Standard Time; PST; GMT-08:00
Z时区RFC 822 time zone0800

【示例】获取今天时本年度第几天

import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateFormat2 {public static void main(String[ ] args) {SimpleDateFormat s1 = new SimpleDateFormat("D");String daytime = s1.format(new Date());System.out.println(daytime);}
}

3.3 Calendar 日历类

Calendar 类是一个抽象类,为我们提供了关于日期计算的功能,比如:年、月、日、时、分、秒的展示和计算。

获取Calendar实例的方法

  • 使用Calendar.getInstance()方法
  • 调用它的子类GregorianCalendar的构造器。

注意月份的表示,一月是 0,二月是 1,以此类推,12 月是 11。 因为大多数人习惯于使用单词而不是使用数字来表示月份,这样程序也许更易读,父类 Calendar 使用常量来表示月份:JANUARY、FEBRUARY 等等。

【示例】GregorianCalendar 类和 Calendar 类的使用

import java.util.*;
public class TestCalendar {public static void main(String[ ] args) {// 得到相关日期元素GregorianCalendar calendar = new GregorianCalendar(2049, 9, 1, 22, 10, 50);int year = calendar.get(Calendar.YEAR); // 打印:2049int month = calendar.get(Calendar.MONTH); // 打印:9int day = calendar.get(Calendar.DAY_OF_MONTH); // 打印:1int day2 = calendar.get(Calendar.DATE); // 打印:1// 日:Calendar.DATE 和 Calendar.DAY_OF_MONTH 同义int date = calendar.get(Calendar.DAY_OF_WEEK); // 打印:1// 星期几 这里是:1-7.周日是 1,周一是 2,。。。周六是 7System.out.println(year);System.out.println(month);System.out.println(day);System.out.println(day2);System.out.println(date);// 设置日期GregorianCalendar calendar2 = new GregorianCalendar();calendar2.set(Calendar.YEAR, 2049);calendar2.set(Calendar.MONTH, Calendar.OCTOBER); // 月份数:0-11calendar2.set(Calendar.DATE, 1);calendar2.set(Calendar.HOUR_OF_DAY, 10);calendar2.set(Calendar.MINUTE, 20);calendar2.set(Calendar.SECOND, 23);printCalendar(calendar2);// 日期计算GregorianCalendar calendar3 = new GregorianCalendar(2049, 9, 1, 22, 10,50);calendar3.add(Calendar.MONTH, -7); // 月份减 7calendar3.add(Calendar.DATE, 7); // 增加 7 天printCalendar(calendar3);// 日历对象和时间对象转化Date d = calendar3.getTime();GregorianCalendar calendar4 = new GregorianCalendar();calendar4.setTime(new Date());}static void printCalendar(Calendar calendar) {int year = calendar.get(Calendar.YEAR);int month = calendar.get(Calendar.MONTH) + 1;int day = calendar.get(Calendar.DAY_OF_MONTH);int date = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 星期几String week = "" + ((date == 0) ? "日" : date);int hour = calendar.get(Calendar.HOUR);int minute = calendar.get(Calendar.MINUTE);int second = calendar.get(Calendar.SECOND);System.out.printf("%d 年%d 月%d 日,星期%s %d:%d:%d\n", year, month, day,week, hour, minute, second);}
}

【示例】Calendar.getInstance()

    @Testpublic void test3() throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");//产生Calendar c = Calendar.getInstance(); //当前时间new Date()//得到fieldSystem.out.println(c.get(Calendar.YEAR)); //得到年System.out.println(c.get(Calendar.MONTH)); //得到月 传统日期月从0开始,周从周日=1开始System.out.println(c.get(Calendar.DAY_OF_MONTH));System.out.println(c.get(Calendar.HOUR_OF_DAY));//设置fieldc.set(Calendar.MONTH, 0); //传统日期月从0开始System.out.println(sdf.format(c.getTime()));//得到date//减3个月c.add(Calendar.MONTH, -3);System.out.println(sdf.format(c.getTime()));//得到date//创建1970-1-1 8:0:0.0时间//方式1:String dateStr = "1970-01-1 08:0:0.0";//把字符串解析成日期,string->dateDate date1 = sdf.parse(dateStr);System.out.println(date1.getTime());//方式2Calendar c2 = Calendar.getInstance();c2.set(1970, 0, 1,8,0,0);c2.set(Calendar.MILLISECOND, 0);System.out.println(sdf.format(c2.getTime()));//当前时间的4周后Calendar c3 = Calendar.getInstance(); //当前时间c3.add(Calendar.WEEK_OF_YEAR, 5);System.out.println(sdf.format(c3.getTime()));}

3.4 JDK8新日期API

Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理。

  • java.time – 包含值对象的基础包
  • java.time.chrono – 提供对不同的日历系统的访问
  • java.time.format – 格式化和解析时间和日期
  • java.time.temporal – 包括底层框架和扩展特性
  • java.time.zone – 包含时区支持的类

3.4.1 LocalDateTime

LocalDate、 LocalTime、 LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

  • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储 生日、纪念日等日期。
  • LocalTime表示一个时间,而不是日期。
  • LocalDateTime是用来表示日期和时间的, 这是一个最常用的类之一。
    注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
方法描述
now() / * now(ZoneId zone)静态方法, 根据当前时间创建对象/指定时区的对象
of()静态方法, 根据指定日期/时间创建对象
getDayOfMonth()/getDayOfYear()获得月份天数(1-31) /获得年份天数(1-366)
getDayOfWeek()获得星期几(返回一个 DayOfWeek 枚举值)
getMonth()获得月份, 返回一个 Month 枚举值
getMonthValue() / getYear()获得月份(1-12) /获得年份
getHour()/getMinute()/getSecond()获得当前对象对应的小时、 分钟、 秒
withDayOfMonth()/withDayOfYear()/ withMonth()/withYear()将月份天数、 年份天数、 月份、 年份修改为指定的值并返回新的对象
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours()向当前对象添加几天、 几周、 几个月、 几年、 几小时
minusMonths() / minusWeeks()/ minusDays()/minusYears()/minusHours()从当前对象减去几月、 几周、 几天、 几年、 几小时

3.4.2 Instant

  • Instant:时间线上的一个瞬时点。 这可能被用来记录应用程序中的事件时间戳。
  • 在处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。 在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。
  • java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。 Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲, 它只是简单的表示自1970年1月1日0时0分0秒( UTC)开始的秒数。 因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。
  • (1 ns = 10-9 s) 1秒 = 1000毫秒 =106微秒=109纳秒
方法描述
now()静态方法, 返回默认UTC时区的Instant类的对象
ofEpochMilli(long epochMilli)静态方法 数之后的,Instant 返回在类的对象 1970-01-01 00:00:00基础上加上指定毫秒
atOffset(ZoneOffset offset)结合即时的偏移来创建一个 OffsetDateTime
toEpochMilli()返回1970-01-01 00:00:00到当前时间的毫秒数, 即为时间戳

**注意:**时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数

3.4.3 DateTimeFormatter

java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  • 本地化相关的格式。如: ofLocalizedDateTime(FormatStyle.LONG)
  • 自定义的格式。如: ofPattern(“yyyy-MM-dd hh:mm:ss”)
方 法描 述
ofPattern(String pattern)静 态 方 法 , 返 回 一 个 指 定 字 符 串 格 式 的 DateTimeFormatter
format(TemporalAccessor t)格式化一个日期、 时间, 返回字符串
parse(CharSequence text)将指定格式的字符序列解析为一个日期、 时间
    @Testpublic void test5() throws ParseException {//得到当前时间//LocalDateTime:(UTC)日期时间,理解成Date + Calander//LocalDate:日期//LocalTime:时间LocalDateTime l1 = LocalDateTime.now();System.out.println("l1 = " + l1);//得到fieldSystem.out.println(l1.getMonth().getValue()); //新时间api,月从1开始System.out.println(l1.getYear());System.out.println(l1.get(ChronoField.HOUR_OF_DAY)); //时//设置field,支持chain方法链,设置1月1日LocalDateTime l2 = l1.withMonth(1).withDayOfMonth(1);System.out.println(l2);//加3个月,加3周
//        l2.plusMonths(3).plus(3, ChronoUnit.WEEKS)LocalDateTime l3 = l2.plusMonths(3).plusWeeks(3);System.out.println(l3);//减3月LocalDateTime l4 = l3.minusMonths(3);System.out.println(l4);//创建1970-1-1 8:0:0.0时间LocalDateTime l5 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0);System.out.println(l5);//时间戳操作 InstantInstant i1 = l5.toInstant(ZoneOffset.UTC); //得到utc时间的InstantSystem.out.println(i1.toEpochMilli());//        ZoneOffset.getAvailableZoneIds().forEach(s -> System.out.println(s));LocalDateTime l6 = LocalDateTime.of(1970, 1, 1, 8, 0, 0, 0);Instant i2 = l6.toInstant(ZoneOffset.ofHours(8)); //得到东8区的InstantSystem.out.println(i2.toEpochMilli()); //utc时间的1970.1.1.0点,北京时间的8点,是时间戳的0//格式化DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒.SSS");System.out.println(formatter.format(LocalDateTime.now()));
//        formatter.parse() //解析一个时间}

4.其他常用类

4.1 Math 类

【示例】Math 类的常用方法

public class TestMath {public static void main(String[ ] args) {//取整相关操作System.out.println(Math.ceil(3.2));System.out.println(Math.floor(3.2));System.out.println(Math.round(3.2));System.out.println(Math.round(3.8));//绝对值、开方、a 的 b 次幂等操作System.out.println(Math.abs(-45));System.out.println(Math.sqrt(64));System.out.println(Math.pow(5, 2));System.out.println(Math.pow(2, 5));//Math 类中常用的常量System.out.println(Math.PI);System.out.println(Math.E);//随机数System.out.println(Math.random());// [0,1)}
}

执行结果如图所示:
在这里插入图片描述

4.2 System和Random 类

System
  • System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
  • 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的, 所以也可以很方便的进行调用。
  • 成员变量
    • System类内部包含in、 out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
  • 成员方法
    • native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
    • void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。 使用该方法可以在图形界面编程中实现程序的退出功能等。
    • void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
    • String getProperty(String key):该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
public class SystemDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in); //得到用户控制台输入System.out.println("请输入i,输入0退出");int i = in.nextInt();if (i == 0) {System.exit(0);}System.out.println("i=" + i);}@Testpublic void test1() {Scanner in = new Scanner(System.in); //得到用户控制台输入System.out.println("请输入i,输入0退出");int i = in.nextInt();if (i == 0) {System.exit(0);}System.out.println("i=" + i);}@Testpublic void test2() {System.out.println(System.currentTimeMillis());}@Testpublic void test3() {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);}
}
Random

public void addShutdownHook(Thread hook):捕获jvm退出时间

import java.util.Random;
public class TestRandom {public static void main(String[ ] args) {Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {@Overridepublic void run() {System.out.println("捕获了jvm退出--释放资源");}}));Random rand = new Random();//随机生成[0,1)之间的 double 类型的数据System.out.println(rand.nextDouble());//随机生成 int 类型允许范围之内的整型数据System.out.println(rand.nextInt());//随机生成[0,1)之间的 float 类型的数据System.out.println(rand.nextFloat());//随机生成 false 或者 trueSystem.out.println(rand.nextBoolean());//随机生成[0,10)之间的 int 类型的数据System.out.print(rand.nextInt(10));//随机生成[20,30)之间的 int 类型的数据System.out.print(20 + rand.nextInt(10));}
}

4.3 File 类

File 类的基本用法

  java.io.File 类:代表文件和目录,用于:读取文件、创建文件、删除文件、修改文件。
【示例】使用 File 类创建文件
File 类的常见构造方法:public File(String pathname)
  以 pathname 为路径创建 File 对象,如果 pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储。

import java.io.File;
public class TestFile1 {public static void main(String[ ] args) throws Exception {System.out.println(System.getProperty("user.dir"));File f = new File("a.txt"); //相对路径:默认放到 user.dir 目录下面f.createNewFile();//创建文件File f2 = new File("d:/b.txt");//绝对路径f2.createNewFile();}
}

user.dir 就是本项目的目录。上面代码执行后,在本项目和 D 盘下都生成了新的文件。

1.通过 File 对象可以访问文件的属性:
在这里插入图片描述
2.通过 File 对象创建空文件或目录(在该对象所指的文件或目录不存在的情况下)
在这里插入图片描述

4.4 BigInteger和BigDecimal

BigInteger
  • Integer类作为int的包装类,能存储的最大整型值为231-1, Long类也是有限的,最大为263-1。 如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
  • java.math包的BigInteger可以表示不可变的任意精度的整数。 BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外, BigInteger 还提供以下运算:模算术、 GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
  • 构造器 BigInteger(String val): 根据字符串构建BigInteger对象
  • 常用方法
    • 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
  • 一般的Float类和Double类可以用来做科学计算或工程计算,但在商业计算中,要求数字精度比较高,故用到java.math.BigDecimal类。
  • BigDecimal类支持不可变的、任意精度的有符号十进制定点数。
  • 构造器
    • public BigDecimal(double val)
    • public BigDecimal(String val)
  • 常用方法
    • public BigDecimal add(BigDecimal augend)
    • public BigDecimal subtract(BigDecimal subtrahend)
    • public BigDecimal multiply(BigDecimal multiplicand)
    • public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
public class BigIntegerDemo {@Testpublic void test1() {System.out.println(Integer.MAX_VALUE);Integer i1 = 2147483647;//        Integer i2 = 2147483648;BigInteger i3= new BigInteger("10");System.out.println(i3);BigInteger i4 = new BigInteger("15");BigInteger i5 = i3.add(i4);System.out.println(i5);BigInteger[] arrs = i3.divideAndRemainder(new BigInteger("3"));System.out.println(Arrays.toString(arrs));}
}

4.5 正则表达式

正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。
简单来说,正则表达式就是一个很牛逼的字符串处理工具。

正则在线工具 : https://c.runoob.com/front-end/854/?optionGlobl=global

4.5.1 String类中的正则表达式
public class StringRegexDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in);while (true) {System.out.println("请输入qq");String s1 = in.nextLine();//匹配s1中是否是6-12位数字System.out.println(s1.matches("^[0-9]{6,12}$"));}}@Testpublic void test1() {String s = "Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统";
//        s = s.replaceAll("[a-zA-Z]{1,}", "hello");s = s.replaceAll("[a-zA-Z]+", "hello");s = s.replaceAll("\\d+", "world");System.out.println(s);}@Testpublic void test2() {String s1 = "aaa,bbb,123,456,hello,word";String[] arrs = s1.split(",");for (int i = 0; i < arrs.length; i++) {System.out.println(arrs[i]);}}@Testpublic void test3() {String s2 = "hello12333world4567welcome34to4beijing";String[] arrs2 = s2.split("\\d+");for (int i = 0; i < arrs2.length; i++) {System.out.println(arrs2[i]);}}
}
4.5.2 正则表达式常用类
(1) Pattern类

pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。

  • compile():通过正则得到一个Pattern
  • matchers():方便正则表达式只是用一次,进行匹配
  • matcher():产生Matcher对象,多次正则匹配推荐使用
(2) Matcher类

Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

  1. 索引方法

索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:

  • public int start()返回以前匹配的初始索引。
  • public int start(int group) 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
  • public int end()返回最后匹配字符之后的偏移量。
  • public int end(int group)返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
  1. 查找方法:

查找方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:

  • public boolean lookingAt() 尝试将从区域开头开始的输入序列与该模式匹配。
  • public boolean find()尝试查找与该模式匹配的输入序列的下一个子序列。
  • public boolean find(int start)重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
  • public boolean matches()尝试将整个区域与模式匹配。
  • group()返回上一个匹配项匹配的输入子序列。
  • group(int group)返回上一个匹配操作期间给定组捕获的输入子序列。
  1. 替换方法

替换方法是替换输入字符串里文本的方法:

  • public Matcher appendReplacement(StringBuffer sb, String replacement)实现非终端添加和替换步骤。
  • public StringBuffer appendTail(StringBuffer sb)实现终端添加和替换步骤。
  • public String replaceAll(String replacement)替换模式与给定替换字符串相匹配的输入序列的每个子序列。
  • public String replaceFirst(String replacement) 替换模式与给定替换字符串匹配的输入序列的第一个子序列。
  • public static String quoteReplacement(String s)返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
public class RegexDemo1 {public static void main(String[] args) {Scanner in = new Scanner(System.in);//Pattern pattern = Pattern.compile("^[0-9]{5,12}$"); //正则的编译对象while (true) {System.out.println("请输入qq");String s1 = in.nextLine();Matcher matcher = pattern.matcher(s1);System.out.println(matcher.matches()); //全部匹配
//            System.out.println(s1.matches("^[0-9]{5,12}$"));}}@Testpublic void test1() {//正则编译对象,只匹配一次可以使用matches方法System.out.println(Pattern.matches("^[0-9]{5,12}$", "77546313")); //正则是否全部匹配System.out.println(Pattern.matches("^[0-9]{5,12}$", "123456")); //正则是否全部匹配System.out.println(Pattern.matches("^[0-9]{5,12}$", "333333")); //正则是否全部匹配Pattern pattern = Pattern.compile("^[0-9]{5,12}$");pattern.matcher("77546313").matches();pattern.matcher("123456").matches();pattern.matcher("333333").matches();}@Testpublic void test2() {//全部匹配Pattern pattern = Pattern.compile("\\d{5,12}");Matcher matcher = pattern.matcher("12345a34343434");System.out.println(matcher.matches()); //全部匹配}@Testpublic void test3() {//全部匹配Pattern pattern = Pattern.compile("\\d{5,12}");Matcher matcher = pattern.matcher("12345a34343434abc9878989");while (matcher.find()) {//查找匹配,如果匹配返回tureString target = matcher.group();//得到上一次匹配的子序列System.out.println(target + "-" + matcher.start() + "-" + matcher.end()); //start得到上一个匹配的索引开始}}@Testpublic void test4() {String content ="Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";Pattern pattern = Pattern.compile("([a-zA-Z]+) | (\\d+)");Matcher matcher = pattern.matcher(content);while (matcher.find()) {String target = matcher.group(2); //0:全部的正则捕获组,1:的一个小括号的正则补货组System.out.println(target);}}@Testpublic void test6() {String content ="Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。\n"+ "Java 可运行于多个平台,如 windows,Mac OS 及其他多种 UNIX 版本的系统。\n"+ "本教程通过简单的实例将让大家更好的了解 Java 编程语言。\n"+ "移动操作系统 Android 大部分的代码采用 Java 编程语言编程。";//创建一个Pattern对象Pattern pattern = Pattern.compile("Java");//创建一个匹配对象Matcher matcher = pattern.matcher(content);StringBuffer sb = new StringBuffer();while (matcher.find()) {//将Java替换为java后,将最后匹配到之前的子串都添加到sb对象中matcher.appendReplacement(sb, "java");System.out.println("sb:" + sb);System.out.println("---------分割线-----------");}//将最后匹配到的子串添加到sb中matcher.appendTail(sb);System.out.println("sb: " + sb);}}

4.6 正则表达式的语法

4.6.1 正则转义符

元符号-转义号\
\符号说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义字符,否则检测不到结果,甚至会报错。
需要用到转义符的字符有:. * + ( )$ / \ ? [ ] ^ { }
注意:在Java的正则表达式中,两个\代表其他语言中的一个\

4.6.2 正则表达式支持字符

正则表达式所支持的合法字符

字符解释
X字符x(x 可代表任何合法的字符)
\0mnn八进制数 0mnn 所表示的字符
\xhh十六进制值 0xhh 所表示的字符
\uhhhh十六进制值 0xhhhh 所表示的 Unicode 字符
\t制表符(“\u0009”)
\n新行(换行)符(‘\u000A’)
\r回车符(‘\u000D’)
\f换页符(‘\u000C’)
\a报警(bell)符(‘\u0007’)
\eEscape 符(‘\u001B’)
\cxx 对应的的控制符。例如,\cM匹配 Ctrl-M。x 值必须为 A~Z 或 a~z 之一。

正则表达式中的特殊字符

特殊字符说明
$匹配一行的结尾。要匹配 $ 字符本身,请使用$
^匹配一行的开头。要匹配 ^ 字符本身,请使用^
()标记子表达式的开始和结束位置。要匹配这些字符,请使用(和)
[]用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用[和]
{}用于标记前面子表达式的出现频度。要匹配这些字符,请使用{和}
*指定前面子表达式可以出现零次或多次。要匹配 * 字符本身,请使用*
+指定前面子表达式可以出现一次或多次。要匹配 + 字符本身,请使用+
?指定前面子表达式可以出现零次或一次。要匹配 ?字符本身,请使用?
.匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用.
\用于转义下一个字符,或指定八进制、十六进制字符。如果需匹配\字符,请用\
|指定两项之间任选一项。如果要匹配丨字符本身,请使用|

预定义字符

预定义字符说明
.可以匹配任何字符
\d匹配 0~9 的所有数字
\D匹配非数字
\s匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等
\S匹配所有的非空白字符
\w匹配所有的单词字符,包括 0~9 所有数字、26 个英文字母和下画线_
\W匹配所有的非单词字符

方括号表达式
方括号表达式 说明 表示枚举 例如 [abc]表示 a、b、c 其中任意一个字符; [gz]表示 g、z 其中任意一个字符 表示范围:- 例如 [a-f]表示 a~f 范围内的任意字符; [\u0041-\u0056]表示十六进制字符 \u0041 到 \u0056 范围的字符。范围可以和枚举结合使用,如 [a-cx-z],表示 ac、xz 范围内的任意字符 表示求否:^ 例如 [^abc]表示非 a、b、c 的任意字符; [^a-f]表示不是 a~f 范围内的任意字符 表示“与”运算:&& 例如 [a-z&&[def]]是 a~z 和 [def] 的交集,表示 d、ef[a-z&&^bc]]是 a~z 范围内的所有字符,除 b 和 c 之外[ad-z] [a-z&&[m-p]]是 a~z 范围内的所有字符,除 m~p 范围之外的字符 表示“并”运算 并运算与前面的枚举类似。例如 [a-d[m-p]]表示 [a-dm-p]

补充:
Java正则表达式默认是区分字母大小写的,如要实现不区分大小写
(?i)abc表示abc都不区分大小写
a(?i)bc表示bc不区分大小写
a((?i)b)c表示只有b不区分大小写
Pattern pattern=Pattern.compile(regStr,Pattern.CASE_INSENSITIVE);
//当创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,表示匹配不区分字母大小写
细节:Java匹配默认贪婪匹配,即尽可能匹配多的,比如"a{3,4}“,表示匹配aaa或者aaaa,但是优先匹配aaaa,例如原字符串中包括"aaaaaa”,匹配"a{3,4}“时,会找到"aaaa”

4.6.3 捕获组(capture group)

从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。常用分组构造形式(pattern)
对于时间字符串:2017-04-25,表达式如下
(\d{4})-((\d{2})-(\d{2}))
有 4 个左括号,所以有 4 个分组:

编号捕获组匹配
0(\d{4})-((\d{2})-(\d{2}))2017-04-25
1(\d{4})2017
2((\d{2})-(\d{2}))04-25
3(\d{2})04
4(\d{2})25

4.7 正则表达式的常见应用

  1. 验证字符串是否全是汉字
    Pattern pattern=Pattern.compile("^[\u0391-\uffe5]+$");
  2. 验证字符串是否是邮编
    Pattern pattern=Pattern.compile("^\\d{6}$");
  3. 验证字符串是否是QQ号码
    Pattern pattern=Pattern.compile("^[1-9]d{4,9}$");
  4. 验证字符串是否是手机号码(要求:必须以13,14,15,18开头的11位数)
    Pattern pattern=Pattern.compile("^1[3|4|5|8]\\d{9}$");
  5. 验证字符串是否是url
    Pattern pattern=Pattern.compile("^((http|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$");

4.4 枚举

JDK1.5 引入了枚举类型。枚举类型的定义包括枚举声明和枚举体。格式如下:

enum 枚举名 {枚举体(常量列表)}
  • 当需要定义一组常量时,强烈建议使用枚举类 使用说明:
    • 使用 enum 定义的枚举类默认继承了 java.lang.Enum类,因此不能再继承其他类
    • 枚举类的构造器只能使用 private 权限修饰符
    • 枚举类的所有实例必须在枚举类中显式列出(, 分隔 ; 结尾)。列出的实例系统会自动添加 public static final 修饰
    • 必须在枚举类的第一行声明枚举类对象
  • Enum类的主要方法:
    • values()方法:返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值。
    • valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运行时异常:IllegalArgumentException。
    • toString():返回当前枚举类对象常量的名称
      枚举体就是放置一些常量。我们可以写出我们的第一个枚举类型,如示例所示:

【示例】创建枚举类型

enum Season {SPRING, SUMMER, AUTUMN, WINTER
}

  所有的枚举类型隐性地继承自 java.lang.Enum。枚举实质上还是类!而每个被枚举的
成员实质就是一个枚举类型的实例,他们默认都是 public static final 修饰的。可以直接通
过枚举类型名使用它们。

【示例】枚举的使用

import java.util.Random;
public class TestEnum {public static void main(String[ ] args) {// 枚举遍历for (Week k : Week.values()) {System.out.println(k);}// switch 语句中使用枚举int a = new Random().nextInt(4); // 生成 0,1,2,3 的随机数switch (Season.values()[a]) {case SPRING:System.out.println("春天");break;case SUMMER:System.out.println("夏天");break;case AUTUMN:System.out.println("秋天");break;case WINTER:System.out.println("冬天");break;}}
}
/**季节*/
enum Season {SPRING, SUMMER, AUTUMN, WINTER
}
/**星期*/
enum Week {星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日
}

【示例】订单状态的枚举

package a_enum;/***   订单状态: Nonpayment(未付款)、 Paid(已付款) 、 Delivered(已发货)、Return(退货)、 Checked(已确认) Fulfilled(已配货)、*/
public class StateDemo3 {public static void main(String[] args) {OrderState[] states = OrderState.values();for (int i = 0; i < states.length; i++) {System.out.println(states[i] + "-" + states[i].getValue() + "-" + states[i].getCode());}}public enum OrderState {//static OrderState NON_PAYMENT = new OrderState("未付款")NON_PAYMENT(1, "未付款"),PAID(2, "已付款"),DELIVERED(3, "已发货"),RETURN(4, "退货"),CHECKED(5, "已确认"),FULFILLED(6, "已配货");private OrderState(int code, String value) {this.code = code;this.value = value;}private int code;private String value;public String getValue() {return value;}public int getCode() {return code;}}
}

这篇关于JAVA基础深化提高(三) | 常用类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/756728

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis