时间类

Date类

Date类中的多数方法已经过时,常用的方法有:

  • public long getTime() 把日期对象转换成对应的时间毫秒值。
  • public void setTime(long time) 把方法参数给定的毫秒值设置给日期对象

    1. public class DateDemo02 {
    2. public static void main(String[] args) {
    3. //创建日期对象
    4. Date d = new Date();
    5. //public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值
    6. //System.out.println(d.getTime());
    7. //System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");
    8. //public void setTime(long time):设置时间,给的是毫秒值
    9. //long time = 1000*60*60;
    10. long time = System.currentTimeMillis();
    11. d.setTime(time);
    12. System.out.println(d);
    13. }
    14. }

    小结:Date表示特定的时间瞬间,我们可以使用Date对象对时间进行操作。

SimpleDateFormat类

格式规则
常用的格式规则为:

标识字母(区分大小写) 含义
y
M
d
H
m
s

备注:更详细的格式规则,可以参考SimpleDateFormat类的API文档。

  • public String format(Date date):将Date对象格式化为字符串。
  • public Date parse(String source):将字符串解析为Date对象。 ```java

import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;

public class A03_SimpleDateFormatDemo1 { public static void main(String[] args) throws ParseException { / public simpleDateFormat() 默认格式 public simpleDateFormat(String pattern) 指定格式 public final string format(Date date) 格式化(日期对象 ->字符串) public Date parse(string source) 解析(字符串 ->日期对象) /

  1. //1.定义一个字符串表示时间
  2. String str = "2023-11-11 11:11:11";
  3. //2.利用空参构造创建simpleDateFormat对象
  4. // 细节:
  5. //创建对象的格式要跟字符串的格式完全一致
  6. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  7. Date date = sdf.parse(str);
  8. //3.打印结果
  9. System.out.println(date.getTime());//1699672271000
  10. }
  11. private static void method1() {
  12. //1.利用空参构造创建simpleDateFormat对象,默认格式
  13. SimpleDateFormat sdf1 = new SimpleDateFormat();
  14. Date d1 = new Date(0L);
  15. String str1 = sdf1.format(d1);
  16. System.out.println(str1);//1970/1/1 上午8:00
  17. //2.利用带参构造创建simpleDateFormat对象,指定格式
  18. SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
  19. String str2 = sdf2.format(d1);
  20. System.out.println(str2);//1970年01月01日 08:00:00
  21. //课堂练习:yyyy年MM月dd日 时:分:秒 星期
  22. }

}

  1. > **小结:DateFormat可以将Date对象和字符串相互转换。**
  2. <a name="yHKFc"></a>
  3. ### Calendar类
  4. **常用方法**
  5. | **方法名** | **说明** |
  6. | --- | --- |
  7. | public static Calendar getInstance() | 获取一个它的子类GregorianCalendar对象。 |
  8. | public int get(int field) | 获取某个字段的值。field参数表示获取哪个字段的值,可以使用Calender中定义的常量来表示:Calendar.YEAR : Calendar.MONTH :月Calendar.DAY_OF_MONTH:月中的日期Calendar.HOUR:小时Calendar.MINUTE:分钟Calendar.SECOND:秒Calendar.DAY_OF_WEEK:星期 |
  9. | public void set(int field,int value) | 设置某个字段的值 |
  10. | public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
  11. <a name="QF0Qi"></a>
  12. #### get方法示例
  13. ```java
  14. public class Demo {
  15. public static void main(String[] args) {
  16. //1.获取一个GregorianCalendar对象
  17. Calendar instance = Calendar.getInstance();//获取子类对象
  18. //2.打印子类对象
  19. System.out.println(instance);
  20. //3.获取属性
  21. int year = instance.get(Calendar.YEAR);
  22. int month = instance.get(Calendar.MONTH) + 1;//Calendar的月份值是0-11
  23. int day = instance.get(Calendar.DAY_OF_MONTH);
  24. int hour = instance.get(Calendar.HOUR);
  25. int minute = instance.get(Calendar.MINUTE);
  26. int second = instance.get(Calendar.SECOND);
  27. int week = instance.get(Calendar.DAY_OF_WEEK);//返回值范围:1--7,分别表示:"星期日","星期一","星期二",...,"星期六"
  28. System.out.println(year + "年" + month + "月" + day + "日" +
  29. hour + ":" + minute + ":" + second);
  30. System.out.println(getWeek(week));
  31. }
  32. //查表法,查询星期几
  33. public static String getWeek(int w) {//w = 1 --- 7
  34. //做一个表(数组)
  35. String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
  36. // 索引 [0] [1] [2] [3] [4] [5] [6]
  37. //查表
  38. return weekArray[w - 1];
  39. }
  40. }

set方法示例

  1. public class Demo {
  2. public static void main(String[] args) {
  3. //设置属性——set(int field,int value):
  4. Calendar c1 = Calendar.getInstance();//获取当前日期
  5. //计算班长出生那天是星期几(假如班长出生日期为:1998年3月18日)
  6. c1.set(Calendar.YEAR, 1998);
  7. c1.set(Calendar.MONTH, 3 - 1);//转换为Calendar内部的月份值
  8. c1.set(Calendar.DAY_OF_MONTH, 18);
  9. int w = c1.get(Calendar.DAY_OF_WEEK);
  10. System.out.println("班长出生那天是:" + getWeek(w));
  11. }
  12. //查表法,查询星期几
  13. public static String getWeek(int w) {//w = 1 --- 7
  14. //做一个表(数组)
  15. String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
  16. // 索引 [0] [1] [2] [3] [4] [5] [6]
  17. //查表
  18. return weekArray[w - 1];
  19. }
  20. }

add方法示例

  1. public class Demo {
  2. public static void main(String[] args) {
  3. //计算200天以后是哪年哪月哪日,星期几?
  4. Calendar c2 = Calendar.getInstance();//获取当前日期
  5. c2.add(Calendar.DAY_OF_MONTH, 200);//日期加200
  6. int y = c2.get(Calendar.YEAR);
  7. int m = c2.get(Calendar.MONTH) + 1;//转换为实际的月份
  8. int d = c2.get(Calendar.DAY_OF_MONTH);
  9. int wk = c2.get(Calendar.DAY_OF_WEEK);
  10. System.out.println("200天后是:" + y + "年" + m + "月" + d + "日" + getWeek(wk));
  11. }
  12. //查表法,查询星期几
  13. public static String getWeek(int w) {//w = 1 --- 7
  14. //做一个表(数组)
  15. String[] weekArray = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
  16. // 索引 [0] [1] [2] [3] [4] [5] [6]
  17. //查表
  18. return weekArray[w - 1];
  19. }
  20. }

JDK8时间相关类

JDK8时间类类名 作用
ZoneId 时区
Instant 时间戳
ZoneDateTime 带时区的时间
DateTimeFormatter 用于时间的格式化和解析
LocalDate 年、月、日
LocalTime 时、分、秒
LocalDateTime 年、月、日、时、分、秒
Duration 时间间隔(秒,纳,秒)
Period 时间间隔(年,月,日)
ChronoUnit 时间间隔(所有单位)

ZoneId 时区

  1. /*
  2. static Set<string> getAvailableZoneIds() 获取Java中支持的所有时区
  3. static ZoneId systemDefault() 获取系统默认时区
  4. static Zoneld of(string zoneld) 获取一个指定时区
  5. */
  6. //1.获取所有的时区名称
  7. Set<String> zoneIds = ZoneId.getAvailableZoneIds();
  8. System.out.println(zoneIds.size());//600
  9. System.out.println(zoneIds);// Asia/Shanghai
  10. //2.获取当前系统的默认时区
  11. ZoneId zoneId = ZoneId.systemDefault();
  12. System.out.println(zoneId);//Asia/Shanghai
  13. //3.获取指定的时区
  14. ZoneId zoneId1 = ZoneId.of("Asia/Pontianak");
  15. System.out.println(zoneId1);//Asia/Pontianak

Instant 时间戳

  1. /*
  2. static Instant now() 获取当前时间的Instant对象(标准时间)
  3. static Instant ofXxxx(long epochMilli) 根据(秒/毫秒/纳秒)获取Instant对象
  4. ZonedDateTime atZone(ZoneIdzone) 指定时区
  5. boolean isxxx(Instant otherInstant) 判断系列的方法
  6. Instant minusXxx(long millisToSubtract) 减少时间系列的方法
  7. Instant plusXxx(long millisToSubtract) 增加时间系列的方法
  8. */
  9. //1.获取当前时间的Instant对象(标准时间)
  10. Instant now = Instant.now();
  11. System.out.println(now);
  12. //2.根据(秒/毫秒/纳秒)获取Instant对象
  13. Instant instant1 = Instant.ofEpochMilli(0L);
  14. System.out.println(instant1);//1970-01-01T00:00:00z
  15. Instant instant2 = Instant.ofEpochSecond(1L);
  16. System.out.println(instant2);//1970-01-01T00:00:01Z
  17. Instant instant3 = Instant.ofEpochSecond(1L, 1000000000L);
  18. System.out.println(instant3);//1970-01-01T00:00:027
  19. //3. 指定时区
  20. ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
  21. System.out.println(time);
  22. //4.isXxx 判断
  23. Instant instant4=Instant.ofEpochMilli(0L);
  24. Instant instant5 =Instant.ofEpochMilli(1000L);
  25. //5.用于时间的判断
  26. //isBefore:判断调用者代表的时间是否在参数表示时间的前面
  27. boolean result1=instant4.isBefore(instant5);
  28. System.out.println(result1);//true
  29. //isAfter:判断调用者代表的时间是否在参数表示时间的后面
  30. boolean result2 = instant4.isAfter(instant5);
  31. System.out.println(result2);//false
  32. //6.Instant minusXxx(long millisToSubtract) 减少时间系列的方法
  33. Instant instant6 =Instant.ofEpochMilli(3000L);
  34. System.out.println(instant6);//1970-01-01T00:00:03Z
  35. Instant instant7 =instant6.minusSeconds(1);
  36. System.out.println(instant7);//1970-01-01T00:00:02Z

ZoneDateTime 带时区的时间

  1. /*
  2. static ZonedDateTime now() 获取当前时间的ZonedDateTime对象
  3. static ZonedDateTime ofXxxx(。。。) 获取指定时间的ZonedDateTime对象
  4. ZonedDateTime withXxx(时间) 修改时间系列的方法
  5. ZonedDateTime minusXxx(时间) 减少时间系列的方法
  6. ZonedDateTime plusXxx(时间) 增加时间系列的方法
  7. */
  8. //1.获取当前时间对象(带时区)
  9. ZonedDateTime now = ZonedDateTime.now();
  10. System.out.println(now);
  11. //2.获取指定的时间对象(带时区)1/年月日时分秒纳秒方式指定
  12. ZonedDateTime time1 = ZonedDateTime.of(2023, 10, 1,
  13. 11, 12, 12, 0, ZoneId.of("Asia/Shanghai"));
  14. System.out.println(time1);
  15. //通过Instant + 时区的方式指定获取时间对象
  16. Instant instant = Instant.ofEpochMilli(0L);
  17. ZoneId zoneId = ZoneId.of("Asia/Shanghai");
  18. ZonedDateTime time2 = ZonedDateTime.ofInstant(instant, zoneId);
  19. System.out.println(time2);
  20. //3.withXxx 修改时间系列的方法
  21. ZonedDateTime time3 = time2.withYear(2000);
  22. System.out.println(time3);
  23. //4. 减少时间
  24. ZonedDateTime time4 = time3.minusYears(1);
  25. System.out.println(time4);
  26. //5.增加时间
  27. ZonedDateTime time5 = time4.plusYears(1);
  28. System.out.println(time5);

DateTimeFormatter 用于时间的格式化和解析

  1. /*
  2. static DateTimeFormatter ofPattern(格式) 获取格式对象
  3. String format(时间对象) 按照指定方式格式化
  4. */
  5. //获取时间对象
  6. ZonedDateTime time = Instant.now().atZone(ZoneId.of("Asia/Shanghai"));
  7. // 解析/格式化器
  8. DateTimeFormatter dtf1=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm;ss EE a");
  9. // 格式化
  10. System.out.println(dtf1.format(time));

LocalDate 年、月、日

  1. //1.获取当前时间的日历对象(包含 年月日)
  2. LocalDate nowDate = LocalDate.now();
  3. //System.out.println("今天的日期:" + nowDate);
  4. //2.获取指定的时间的日历对象
  5. LocalDate ldDate = LocalDate.of(2023, 1, 1);
  6. System.out.println("指定日期:" + ldDate);
  7. System.out.println("=============================");
  8. //3.get系列方法获取日历中的每一个属性值//获取年
  9. int year = ldDate.getYear();
  10. System.out.println("year: " + year);
  11. //获取月//方式一:
  12. Month m = ldDate.getMonth();
  13. System.out.println(m);
  14. System.out.println(m.getValue());
  15. //方式二:
  16. int month = ldDate.getMonthValue();
  17. System.out.println("month: " + month);
  18. //获取日
  19. int day = ldDate.getDayOfMonth();
  20. System.out.println("day:" + day);
  21. //获取一年的第几天
  22. int dayofYear = ldDate.getDayOfYear();
  23. System.out.println("dayOfYear:" + dayofYear);
  24. //获取星期
  25. DayOfWeek dayOfWeek = ldDate.getDayOfWeek();
  26. System.out.println(dayOfWeek);
  27. System.out.println(dayOfWeek.getValue());
  28. //is开头的方法表示判断
  29. System.out.println(ldDate.isBefore(ldDate));
  30. System.out.println(ldDate.isAfter(ldDate));
  31. //with开头的方法表示修改,只能修改年月日
  32. LocalDate withLocalDate = ldDate.withYear(2000);
  33. System.out.println(withLocalDate);
  34. //minus开头的方法表示减少,只能减少年月日
  35. LocalDate minusLocalDate = ldDate.minusYears(1);
  36. System.out.println(minusLocalDate);
  37. //plus开头的方法表示增加,只能增加年月日
  38. LocalDate plusLocalDate = ldDate.plusDays(1);
  39. System.out.println(plusLocalDate);
  40. //-------------
  41. // 判断今天是否是你的生日
  42. LocalDate birDate = LocalDate.of(2000, 1, 1);
  43. LocalDate nowDate1 = LocalDate.now();
  44. MonthDay birMd = MonthDay.of(birDate.getMonthValue(), birDate.getDayOfMonth());
  45. MonthDay nowMd = MonthDay.from(nowDate1);
  46. System.out.println("今天是你的生日吗? " + birMd.equals(nowMd));//今天是你的生日吗?

LocalTime 时、分、秒

  1. // 获取本地时间的日历对象。(包含 时分秒)
  2. LocalTime nowTime = LocalTime.now();
  3. System.out.println("今天的时间:" + nowTime);
  4. int hour = nowTime.getHour();//时
  5. System.out.println("hour: " + hour);
  6. int minute = nowTime.getMinute();//分
  7. System.out.println("minute: " + minute);
  8. int second = nowTime.getSecond();//秒
  9. System.out.println("second:" + second);
  10. int nano = nowTime.getNano();//纳秒
  11. System.out.println("nano:" + nano);
  12. System.out.println("------------------------------------");
  13. System.out.println(LocalTime.of(8, 20));//时分
  14. System.out.println(LocalTime.of(8, 20, 30));//时分秒
  15. System.out.println(LocalTime.of(8, 20, 30, 150));//时分秒纳秒
  16. LocalTime mTime = LocalTime.of(8, 20, 30, 150);
  17. //is系列的方法
  18. System.out.println(nowTime.isBefore(mTime));
  19. System.out.println(nowTime.isAfter(mTime));
  20. //with系列的方法,只能修改时、分、秒
  21. System.out.println(nowTime.withHour(10));
  22. //plus系列的方法,只能修改时、分、秒
  23. System.out.println(nowTime.plusHours(10));

LocalDateTime 年、月、日、时、分、秒

  1. // 当前时间的的日历对象(包含年月日时分秒)
  2. LocalDateTime nowDateTime = LocalDateTime.now();
  3. System.out.println("今天是:" + nowDateTime);//今天是:
  4. System.out.println(nowDateTime.getYear());//年
  5. System.out.println(nowDateTime.getMonthValue());//月
  6. System.out.println(nowDateTime.getDayOfMonth());//日
  7. System.out.println(nowDateTime.getHour());//时
  8. System.out.println(nowDateTime.getMinute());//分
  9. System.out.println(nowDateTime.getSecond());//秒
  10. System.out.println(nowDateTime.getNano());//纳秒
  11. // 日:当年的第几天
  12. System.out.println("dayofYear:" + nowDateTime.getDayOfYear());
  13. //星期
  14. System.out.println(nowDateTime.getDayOfWeek());
  15. System.out.println(nowDateTime.getDayOfWeek().getValue());
  16. //月份
  17. System.out.println(nowDateTime.getMonth());
  18. System.out.println(nowDateTime.getMonth().getValue());
  19. LocalDate ld = nowDateTime.toLocalDate();
  20. System.out.println(ld);
  21. LocalTime lt = nowDateTime.toLocalTime();
  22. System.out.println(lt.getHour());
  23. System.out.println(lt.getMinute());
  24. System.out.println(lt.getSecond());

Duration 时间间隔(秒,纳,秒)

  1. // 本地日期时间对象。
  2. LocalDateTime today = LocalDateTime.now();
  3. System.out.println(today);
  4. // 出生的日期时间对象
  5. LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
  6. System.out.println(birthDate);
  7. Duration duration = Duration.between(birthDate, today);//第二个参数减第一个参数
  8. System.out.println("相差的时间间隔对象:" + duration);
  9. System.out.println("============================================");
  10. System.out.println(duration.toDays());//两个时间差的天数
  11. System.out.println(duration.toHours());//两个时间差的小时数
  12. System.out.println(duration.toMinutes());//两个时间差的分钟数
  13. System.out.println(duration.toMillis());//两个时间差的毫秒数
  14. System.out.println(duration.toNanos());//两个时间差的纳秒数

Period 时间间隔(年,月,日)

  1. // 当前本地 年月日
  2. LocalDate today = LocalDate.now();
  3. System.out.println(today);
  4. // 生日的 年月日
  5. LocalDate birthDate = LocalDate.of(2000, 1, 1);
  6. System.out.println(birthDate);
  7. Period period = Period.between(birthDate, today);//第二个参数减第一个参数
  8. System.out.println("相差的时间间隔对象:" + period);
  9. System.out.println(period.getYears());
  10. System.out.println(period.getMonths());
  11. System.out.println(period.getDays());
  12. System.out.println(period.toTotalMonths());

ChronoUnit 时间间隔(所有单位)

  1. // 当前时间
  2. LocalDateTime today = LocalDateTime.now();
  3. System.out.println(today);
  4. // 生日时间
  5. LocalDateTime birthDate = LocalDateTime.of(2000, 1, 1,0, 0, 0);
  6. System.out.println(birthDate);
  7. System.out.println("相差的年数:" + ChronoUnit.YEARS.between(birthDate, today));
  8. System.out.println("相差的月数:" + ChronoUnit.MONTHS.between(birthDate, today));
  9. System.out.println("相差的周数:" + ChronoUnit.WEEKS.between(birthDate, today));
  10. System.out.println("相差的天数:" + ChronoUnit.DAYS.between(birthDate, today));
  11. System.out.println("相差的时数:" + ChronoUnit.HOURS.between(birthDate, today));
  12. System.out.println("相差的分数:" + ChronoUnit.MINUTES.between(birthDate, today));
  13. System.out.println("相差的秒数:" + ChronoUnit.SECONDS.between(birthDate, today));
  14. System.out.println("相差的毫秒数:" + ChronoUnit.MILLIS.between(birthDate, today));
  15. System.out.println("相差的微秒数:" + ChronoUnit.MICROS.between(birthDate, today));
  16. System.out.println("相差的纳秒数:" + ChronoUnit.NANOS.between(birthDate, today));
  17. System.out.println("相差的半天数:" + ChronoUnit.HALF_DAYS.between(birthDate, today));
  18. System.out.println("相差的十年数:" + ChronoUnit.DECADES.between(birthDate, today));
  19. System.out.println("相差的世纪(百年)数:" + ChronoUnit.CENTURIES.between(birthDate, today));
  20. System.out.println("相差的千年数:" + ChronoUnit.MILLENNIA.between(birthDate, today));
  21. System.out.println("相差的纪元数:" + ChronoUnit.ERAS.between(birthDate, today));

包装类

这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Boolean 、Character。
Integer的默认值是null; int的默认值是0。
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。

  1. Integer x = 2; // 装箱 调用了 Integer.valueOf(2)
  2. int y = x; // 拆箱 调用了 X.intValue()

自动装箱演示:

  1. //考虑以下代码:
  2. List<Integer> li = new ArrayList<>();
  3. for (int i = 1; i < 50; i += 2)
  4. li.add(i);
  5. //实际上是:
  6. List<Integer> li = new ArrayList<>();
  7. for (int i = 1; i < 50; i += 2)
  8. li.add(Integer.valueOf(i));

自动拆箱演示:

  1. //考虑以下方法:
  2. public static int sumEven(List<Integer> li) {
  3. int sum = 0;
  4. for (Integer i: li)
  5. if (i % 2 == 0)
  6. sum += i;
  7. return sum;
  8. }
  9. //实际上是:
  10. public static int sumEven(List<Integer> li) {
  11. int sum = 0;
  12. for (Integer i : li)
  13. if (i.intValue() % 2 == 0)
  14. sum += i.intValue();
  15. return sum;
  16. }

Integer.parseInt()
重点方法:
static int parseInt(String s)
静态方法,传参String,返回int

  1. int retValue=Integer.parseInt("123")
  2. System.out.println(retValue+100);

(面试)手写一个Integer.parseInt()方法

  1. public class Demo {
  2. public static void main(String[] args) {
  3. int num = parseInt("123456");
  4. System.out.println(num);
  5. }
  6. public static int parseInt(String str) {
  7. //声明一个字符数组
  8. char[] chars = new char[str.length()];
  9. //声明一个整型数组(用来装字符转换成整型数字结果)
  10. int[] ints = new int[str.length()];
  11. for (int i = 0; i < str.length(); i++) {
  12. //分解字符串,装入字符数组
  13. chars[i] = str.charAt(i);
  14. //把字符数组里的字符通过-'0'转换成整型数字,装入整型数组
  15. ints[i] = chars[i] - '0';
  16. }
  17. //把整型数组转换成整型
  18. int num = 0;
  19. for (int i = 0; i < ints.length; i++) {
  20. num = num * 10 + ints[i];
  21. }
  22. return num;
  23. }
  24. }

缓存池

new Integer(123) 与 Integer.valueOf(123) 的区别在于:

  • new Integer(123) 每次都会新建一个对象;
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用。
    1. Integer x = new Integer(123);
    2. Integer y = new Integer(123);
    3. System.out.println(x == y); // false
    4. Integer z = Integer.valueOf(123);
    5. Integer k = Integer.valueOf(123);
    6. System.out.println(z == k); // true
    valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。
    1. public static Integer valueOf(int i) {
    2. if (i >= IntegerCache.low && i <= IntegerCache.high)
    3. return IntegerCache.cache[i + (-IntegerCache.low)];
    4. return new Integer(i);
    5. }
    在 Java 8 中,Integer 缓存池的大小默认为 -128~127。 ```java static final int low = -128;////缓存下届,不可改变了,只有上届可以改变 static final int high; static final Integer cache[];

static { // high value may be configured by property int h = 127;/h值,可以通过设置jdk的AutoBoxCacheMax参数调整(以下有解释), 自动缓存区间设置为[-128,N]。注意区间的下界是固定 / String integerCacheHighPropValue = sun.misc.VM.getSavedProperty(“java.lang.Integer.IntegerCache.high”); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127);//取较大的作为上界 //但要注意不能比Integer的边界MAX_VALUE大 // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h;

  1. cache = new Integer[(high - low) + 1];
  2. int j = low;
  3. for(int k = 0; k < cache.length; k++)
  4. cache[k] = new Integer(j++);
  5. // range [-128, 127] must be interned (JLS7 5.1.7)
  6. assert IntegerCache.high >= 127;

}

  1. 编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象。
  2. ```java
  3. Integer m = 123;
  4. Integer n = 123;
  5. System.out.println(m == n); // true

基本类型对应的缓冲池如下:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \u0000 to \u007F

在使用这些基本类型对应的包装类型时,如果该数值范围在缓冲池范围内,就可以直接使用缓冲池中的对象。

在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax= 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。

注意:float和double 是没有缓存池的,每次都是new一个新的对象。