1. 包装类
针对八种基本数据类型封装的相应的引用类型。
有了类的特点,就可以调用类中的方法。(为什么要封装)
| 基本数据类型 | 包装类 | 
|---|---|
| boolean | Boolean | 
| char | Character | 
| byte | Byte | 
| short | Short | 
| int | Integer | 
| long | Long | 
| float | Float | 
| double | Double | 
1.1 装箱与拆箱
装箱:基本类型 ——> 包装类型
拆箱:包装类型 ——> 基本类型
JDK5之后,都是自动拆箱与自动装箱,不用手动控制。
自动装箱底层调用的是valueOf方法,如 Integer.valueOf()。
代码示例:
public static void main(String[] args) {
    // 手动装箱 int->Integer
    int n1 = 100;
    Integer integer = new Integer(n1);
    Integer integer1 = Integer.valueOf(n1);
    // 手动拆箱 Integer -> int
    int i = integer.intValue();
    int n2 = 200;
    // 自动装箱 int->Integer
    Integer integer2 = n2; //底层使用的是 Integer.valueOf(n2)
    // 自动拆箱 Integer->int
    int n3 = integer2; //底层仍然使用的是 intValue()方法
} 
2. String类
保存的是一组字符序列。字符串的字符使用的是 Unicode 字符编码,一个字符(不区分字母还是汉字)占两个字节。
创建 String 对象的两种方式
// 直接赋值
String s = "路明非";
// 调用构造器
String s1 = new String("路明非"); 
两者有什么不同
- 直接赋值
 
先从常量池查看是否有 "路明非" 数据空间,如果有,直接指向;
如果没有这重新创建,然后指向,s最终指向的是常量池的空间地址。
- 构造器赋值
 
先在堆中创建空间,里面维护了value属性,指向常量池的 "路明非" 数据空间。
如果常量池没有 "路明非",创新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
内存分布图

注意:
String 是一个 final 类,代表不可变的字符序列。改变赋值,相当于就是再创建了一个对象。
jdk 源码

String类的常见方法
- equals // 区分大小写,判断内容是否相等
 - equalsIgnoreCase // 忽略大小写的判断内容是否相等
 - length // 获取字符的个数,字符串的长度
 - indexOf // 获取字符在字符串中第一次出现的索引,索引从0开始,如果找不到,返回-1
 - lastIndexOf // 获取字符在字符串中最后一次出现的索引,索引从0开始,如果找不到,返回-1
 - substring // 截取指定范围的子串
 - trim // 去除空格
 - charAt // 获取某索引处的字符
 
3. StringBuffer 类
String 保存的是字符串常量,里面的值不能更改,每次String类的更新实际上就是更改地址,效率较低。
StringBuffer 保存的是字符串变量,里面的值可以更改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率较高。(char[] value 这个放在堆中)
代码示例
public static void main(String[] args) {
    // 1. StringBuffer 的直接父类 是 AbstractStringBuilder
    // 2. StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
    // 3. 在父类中 AbstractStringBuilder 有属性 char[] value,不是 final
    // 该 value 数组存放 字符串内容,引出存放在堆中的
    // 4. StringBuffer 是一个 final 类,不能被继承
    // 5. 因为 StringBuffer 字符内容是存在 char[] value, 所有在变化(增加/删除)
    // 不用每次都更换地址(即不是每次创建新对象), 所以效率高于 String
    StringBuffer stringBuffer = new StringBuffer("hello");
} 
String 和 StringBuffer 相互转换
public static void main(String[] args) {
    // String —> StringBuffer
    String str = "hello tom";
    // 方式 1 使用构造器
    StringBuffer stringBuffer = new StringBuffer(str);
    // 方式 2 使用的是 append 方法
    StringBuffer stringBuffer1 = new StringBuffer();
    stringBuffer1 = stringBuffer1.append(str);
    // StringBuffer -> String
    StringBuffer stringBuffer3 = new StringBuffer("路明非");
    // 方式 1 使用 StringBuffer 提供的 toString 方法
    String s = stringBuffer3.toString();
    // 方式 2: 使用构造器来搞定
    String s1 = new String(stringBuffer3);
} 
4. StringBuilder类
一个可变的字符序列。相比于StringBuffer,StringBuilder不是线程安全的,但是速度要比StringBuffer要快。
代码示例
public static void main(String[] args) {
    // 1. StringBuilder 继承 AbstractStringBuilder 类
    // 2. 实现了 Serializable ,说明 StringBuilder 对象是可以串行化(对象可以网络传输,可以保存到文件)
    // 3. StringBuilder 是 final 类, 不能被继承
    // 4. StringBuilder 对象字符序列仍然是存放在其父类 AbstractStringBuilder 的 char[] value;
    // 因此,字符序列是堆中
    // 5. StringBuilder 的方法,没有做互斥的处理,即没有 synchronized 关键字,因此在单线程的情况下使用
    StringBuilder stringBuilder = new StringBuilder();
} 
String、StringBuffer、StringBuilder的比较
- String:不可变字符序列,效率低,但是复用率高。
 - StringBuffer:可变字符序列,效率较高,线程安全。
 - StringBuilder:可变字符序列,效率最高,线程不安全。
 
效率测试代码示例
public static void main(String[] args) {
    long startTime = 0L;
    long endTime = 0L;
    StringBuffer buffer = new StringBuffer("");
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//StringBuffer 拼接 20000 次
        buffer.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    System.out.println("StringBuffer 的执行时间:" + (endTime - startTime));
    StringBuilder builder = new StringBuilder("");
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//StringBuilder 拼接 20000 次
        builder.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    System.out.println("StringBuilder 的执行时间:" + (endTime - startTime));
    String text = "";
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 80000; i++) {//String 拼接 20000
        text = text + i;
    }
    endTime = System.currentTimeMillis();
    System.out.println("String 的执行时间:" + (endTime - startTime));
} 
如何选择
- 如果字符串存在大量修改操作,一般使用 Stringbuilder 或 StringBuffer
 - 如果字符串存在大量修改操作,并在单线程的情况,使用 StringBuilder
 - 如果字符串存在大量修改操作,并在多线程的情况,使用 StringBuffer
 - 如果字符串很少修改,被多个对象引用,使用 String ,比如配置信息等
 
5. Math类
Math类包含用于执行基本数学运算的方法。

代码示例
public static void main(String[] args) {
    // 1.abs 绝对值
    int abs = Math.abs(-9);
    System.out.println(abs);//9
    // 2.pow 求幂
    double pow = Math.pow(2, 4);//2 的 4 次方
    System.out.println(pow);//16
    // 3.ceil 向上取整,返回>=该参数的最小整数(转成 double);
    double ceil = Math.ceil(3.9);
    System.out.println(ceil);//4.0
    // 4.floor 向下取整,返回<=该参数的最大整数(转成 double)
    double floor = Math.floor(4.001);
    System.out.println(floor);//4.0
    // 5.round 四舍五入 Math.floor(该参数+0.5)
    long round = Math.round(5.51);
    System.out.println(round);//6
    // 6.sqrt 求开方
    double sqrt = Math.sqrt(9.0);
    System.out.println(sqrt);//3.0
    // 7.random 求随机数 random 返回的是 0 <= x < 1 之间的一个随机小数
    // Math.random()*6 返回的是 0 <= x < 6 小数
    // 思考:请写出获取 a-b 之间的一个随机整数,a,b 均为整数 ,比如 a = 2, b=7
    // 公式就是 (int)(a + Math.random() * (b-a +1) )
    for(int i = 0; i < 100; i++) {
        System.out.println((int)(2 + Math.random() * (7 - 2 + 1)));
    }
    // max , min 返回最大值和最小值
    int min = Math.min(1, 9);
    int max = Math.max(45, 90);
    System.out.println("min=" + min);
    System.out.println("max=" + max);
} 
6. Arrays类
Arrays里面包含了一系列静态方法,用于管理和操作数组。

常用方法
- toString:返回数组的字符串形式
 - sort:排序
 - binarySearch:二分查找、要求是有序列表
 - copyOf:数组元素的复制
 - fill:数组元素的填充
 - equals:比较两个数组元素内容是否完全一致
 - asList:将一组值,转换成list
 
7. System类
常用方法
- exit:退出当前程序
 - currentTimeMillens:返回当前时间距离1970-1-1的毫秒数
 - gc:运行垃圾回收机制
 

8. BigInteger类 和 BigDecimal类
应用场景
- BigInteger:保存比较大的整形。
 - BigDecimal:保存精度更高的浮点数。
 
常用方法
- add:加
 - subtract:减
 - multiply:乘
 - divide:除
 
代码示例
public static void main(String[] args) {
    // 需要处理很大的整数,long 不够用,可以使用 BigInteger 的类
    BigInteger bigInteger = new BigInteger("23788888899999999999999999999");
    BigInteger bigInteger2 = new BigInteger("10099999999999999999999999999999999999999999999999999999999999999999999999999999999");
    System.out.println(bigInteger);
    // 在对 BigInteger 进行加减乘除的时候,需要使用对应的方法,不能直接进行+ - * /
    BigInteger add = bigInteger.add(bigInteger2);
    System.out.println(add); //加
    BigInteger subtract = bigInteger.subtract(bigInteger2);
    System.out.println(subtract); //减
    BigInteger multiply = bigInteger.multiply(bigInteger2);
    System.out.println(multiply); //乘
    BigInteger divide = bigInteger.divide(bigInteger2);
    System.out.println(divide); //除
}
public static void main(String[] args) {
    // 需要保存一个精度很高的数时,double 不够用,用BigDecimal
    BigDecimal bigDecimal = new BigDecimal("1999.11");
    BigDecimal bigDecimal2 = new BigDecimal("3");
    System.out.println(bigDecimal);
    // 如果对 BigDecimal 进行运算,比如加减乘除,需要使用对应的方法
    System.out.println(bigDecimal.add(bigDecimal2));
    System.out.println(bigDecimal.subtract(bigDecimal2));
    System.out.println(bigDecimal.multiply(bigDecimal2));
    //System.out.println(bigDecimal.divide(bigDecimal2));//可能抛出异常 ArithmeticException
    // 在调用 divide 方法时,指定精度即可. BigDecimal.ROUND_CEILING
    // 如果有无限循环小数,就会保留 分子 的精度
    System.out.println(bigDecimal.divide(bigDecimal2, BigDecimal.ROUND_CEILING));
} 
9. 日期类
9.1 第一代日期类Date
- Date:精确到毫秒,代表特定的瞬间
 - SimpleDateFormat:格式化日期。(日期 -> 文本、文本 -> 日期)
 

代码示例
public static void main(String[] args) throws ParseException {
    // Date 类是在 java.util 包
    // 默认输出的日期格式是国外的方式, 因此通常需要对格式进行转换
    Date d1 = new Date(); //获取当前系统时间
    System.out.println("当前日期=" + d1);
    // 创建 SimpleDateFormat 对象,可以指定相应的格式
    // 这里的格式使用的字母是规定好,不能乱写
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy 年 MM 月 dd 日 hh:mm:ss E");
    String format = sdf.format(d1); // format:将日期转换成指定格式的字符串
    System.out.println("当前日期=" + format);
    // 把 String -> Date , 使用的 sdf 格式需要和你给的 String 的格式一样,否则会抛出转换异常            
    String s = "1996 年 01 月 01 日 10:20:30 星期一";
    Date parse = sdf.parse(s);
    System.out.println("parse=" + sdf.format(parse));
} 
9.2 第二代日期类Calendar
Calendar类是一个抽象类,它为特定瞬间与一组诸如YERA、MONTH、DAY_OF_MONTH、HOUR等日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法。

代码示例
public static void main(String[] args) {
    // Calendar 是一个抽象类, 并且构造器是 private,通过 getInstance() 来获取实例
    // Calendar 没有提供对应的格式化的类,因此需要程序员自己组合来输出(灵活)
    // 如果需要按照 24 小时进制来获取时间, Calendar.HOUR ==改成=> Calendar.HOUR_OF_DAY
    Calendar c = Calendar.getInstance(); 
    System.out.println("c=" + c);
    // 获取日历对象的某个日历字段
    System.out.println("年:" + c.get(Calendar.YEAR));
    // 这里为什么要 + 1, 因为 Calendar 返回月时候,是按照 0 开始编号
    System.out.println("月:" + (c.get(Calendar.MONTH) + 1));
    System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
    System.out.println("小时:" + c.get(Calendar.HOUR));
    System.out.println("分钟:" + c.get(Calendar.MINUTE));
    System.out.println("秒:" + c.get(Calendar.SECOND));
    // Calender 没有专门的格式化方法,所以需要程序员自己来组合显示
    System.out.println(c.get(Calendar.YEAR) + "-" + (c.get(Calendar.MONTH) + 1) + "-" +c.get(Calendar.DAY_OF_MONTH) +
" " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) );
} 
9.3 第三代日期类
JDK8新加入的
- LocalDate:获取日期(年月日)
 - LocalTime:获取时间(时分秒)
 - LocalDateTime:获取日期 + 时间
 

代码示例
public static void main(String[] args) {
    // 1. 使用 now() 返回表示当前日期时间的对象
    LocalDateTime ldt = LocalDateTime.now(); 
    System.out.println(ldt);
    // 2. 使用 DateTimeFormatter 对象来进行格式化
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String format = dateTimeFormatter.format(ldt);
    System.out.println("格式化的日期=" + format);
    System.out.println("年=" + ldt.getYear());
    System.out.println("月=" + ldt.getMonth());
    System.out.println("月=" + ldt.getMonthValue());
    System.out.println("日=" + ldt.getDayOfMonth());
    System.out.println("时=" + ldt.getHour());
    System.out.println("分=" + ldt.getMinute());
    System.out.println("秒=" + ldt.getSecond());
    LocalDate now = LocalDate.now(); //可以获取年月日
    LocalTime now2 = LocalTime.now();//获取到时分秒
    // 提供 plus 和 minus 方法可以对当前时间进行加或者减
    // 看看 890 天后,是什么时候 把 年月日-时分秒
    LocalDateTime localDateTime = ldt.plusDays(890);
    System.out.println("890 天后=" + dateTimeFormatter.format(localDateTime));
    // 看看在 3456 分钟前是什么时候,把 年月日-时分秒输出
    LocalDateTime localDateTime2 = ldt.minusMinutes(3456);
    System.out.println("3456 分钟前 日期=" + dateTimeFormatter.format(localDateTime2));
} 
                
















![[ C++ ] 类和对象( 下 )](https://img-blog.csdnimg.cn/direct/5f2b3c0c463d425dadae2a0bc6442f27.png)

