1.API

1.1 API概述-帮助文档的使用

  • 什么是API
    API (Application Programming Interface) :应用程序编程接口
  • java中的API
    指的就是 JDK 中提供的各种功能的 Java类,这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可,我们可以通过帮助文档来学习这些API如何使用。

如何使用API帮助文档 :

  • 打开帮助文档
  • 找到索引选项卡中的输入框
  • 在输入框中输入Random
  • 看类在哪个包下
  • 看类的描述
  • 看构造方法
  • 看成员方法

1.2 键盘录入字符串

Scanner类 :

  1. next() : 遇到了空格, 就不再录入数据了 , 结束标记: 空格, tab
  2. nextLine() : 可以将数据完整的接收过来 , 结束标记: 回车换行符

2. String类

2.1 String概述

1 String 类在 java.lang 包下,所以使用的时候不需要导包

2 String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象

3 字符串不可变,它们的值在创建后不能被更改

2.2 String类的构造方法

常用的构造方法
1590939947722.png

2.4 创建字符串对象的区别对比

  • 通过构造方法创建
    通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同
  • 直接赋值方式创建
    以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一个 String 对象,并在字符串池中维护

2.5 字符串的比较

2.5.1 字符串的比较

  • == 比较基本数据类型:比较的是具体的值
  • == 比较引用数据类型:比较的是对象地址值

String类 : public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写

代码 :

package com.itheima.stringmethod;

public class Demo1Equals {
    public static void main(String[] args) {
        String s1 = "abc";
        String s2 = "ABC";
        String s3 = "abc";

        // equals : 比较字符串内容, 区分大小写
        System.out.println(s1.equals(s2));
        System.out.println(s1.equals(s3));

        // equalsIgnoreCase : 比较字符串内容, 忽略大小写
        System.out.println(s1.equalsIgnoreCase(s2));
    }
}

2.6 用户登录案例

案例需求 :

已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示

实现步骤 :

  1. 已知用户名和密码,定义两个字符串表示即可
  2. 键盘录入要登录的用户名和密码,用 Scanner 实现
  3. 拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。
  4. 字符串的内容比较,用equals() 方法实现
  5. 用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循

代码实现 :

package com.itheima.test;

import java.util.Scanner;

public class Test1 {
    /*
        需求:已知用户名和密码,请用程序实现模拟用户登录。
              总共给三次机会,登录之后,给出相应的提示

        思路:
        1. 已知用户名和密码,定义两个字符串表示即可
        2. 键盘录入要登录的用户名和密码,用 Scanner 实现
        3. 拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。
            字符串的内容比较,用equals() 方法实现
        4. 用循环实现多次机会,这里的次数明确,采用for循环实现,并在登录成功的时候,使用break结束循环

     */
    public static void main(String[] args) {
        // 1. 已知用户名和密码,定义两个字符串表示即可
        String username = "admin";
        String password = "123456";
        // 2. 键盘录入要登录的用户名和密码,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        // 4. 用循环实现多次机会,这里的次数明确,采用for循环实现
        for(int i = 1; i <= 3; i++){
            System.out.println("请输入用户名:");
            String scUsername = sc.nextLine();
            System.out.println("请输入密码:");
            String scPassword = sc.nextLine();
            // 3. 拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。
            if(username.equals(scUsername) && password.equals(scPassword)){
                System.out.println("登录成功");
                break;
            }else{
                if(i == 3){
                    System.out.println("您的登录次数已达到今日上限, 请明天再来");
                }else{
                    System.out.println("登录失败,您还剩余" + (3-i) +"次机会");
                }

            }
        }

    }
}

2.7 遍历字符串案例

案例需求 :

键盘录入一个字符串,使用程序实现在控制台遍历该字符串

实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现
  2. 遍历字符串,首先要能够获取到字符串中的每一个字符, public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的
  3. 遍历字符串,其次要能够获取到字符串的长度, public int length():返回此字符串的长度
  4. 遍历打印

代码实现 :

package com.itheima.test;

import java.util.Scanner;

public class Test2 {
    /*
        需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串

        思路:
        1. 键盘录入一个字符串,用 Scanner 实现
        2. 遍历字符串,首先要能够获取到字符串中的每一个字符
            public char charAt(int index):返回指定索引处的char值,字符串的索引也是从0开始的
        3. 遍历字符串,其次要能够获取到字符串的长度
            public int length():返回此字符串的长度
        4. 遍历打印
9
     */
    public static void main(String[] args) {
        //  1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        String s = sc.nextLine();
        // 2. 遍历字符串,首先要能够获取到字符串中的每一个字符
        for(int i = 0; i < s.length(); i++){
            // i : 字符串的每一个索引
            char c = s.charAt(i);
            System.out.println(c);
        }
    }
}

2.8 统计字符次数案例

案例需求 :

键盘录入一个字符串,使用程序实现在控制台遍历该字符串

实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现
  2. 将字符串拆分为字符数组 , public char[] toCharArray( ):将当前字符串拆分为字符数组并返回
  3. 遍历字符数

代码实现 :

package com.itheima.test;

import java.util.Scanner;

public class Test3 {
    /*
       需求:键盘录入一个字符串,使用程序实现在控制台遍历该字符串

       思路:
       1. 键盘录入一个字符串,用 Scanner 实现
       2. 将字符串拆分为字符数组
                public char[] toCharArray( ):将当前字符串拆分为字符数组并返回
       3. 遍历字符数组

    */
    public static void main(String[] args) {
        //  1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        String s = sc.nextLine();
        // 2. 将字符串拆分为字符数组
        char[] chars = s.toCharArray();
        // 3. 遍历字符数组
        for (int i = 0; i < chars.length; i++) {
            System.out.println(chars[i]);
        }
    }
}

2.9 手机号屏蔽-字符串截取

案例需求 :

以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽<br />        最终效果为:1561234

实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现
  2. 截取字符串前三位
  3. 截取字符串后四位
  4. 将截取后的两个字符串,中间加上进行拼接,输出结果

代码实现 :

package com.itheima.test;

import java.util.Scanner;

public class Test5 {
    /*
        需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
        最终效果为:156****1234

        思路:
        1. 键盘录入一个字符串,用 Scanner 实现
        2. 截取字符串前三位
        3. 截取字符串后四位
        4. 将截取后的两个字符串,中间加上****进行拼接,输出结果

     */
    public static void main(String[] args) {
        // 1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入手机号:");
        String telString = sc.nextLine();
        // 2. 截取字符串前三位
        String start = telString.substring(0,3);
        // 3. 截取字符串后四位
        String end = telString.substring(7);
        // 4. 将截取后的两个字符串,中间加上****进行拼接,输出结果
        System.out.println(start + "****" + end);
    }
}

2.10 敏感词替换-字符串替换

案例需求 :

键盘录入一个 字符串,如果字符串中包含(TMD),则使用***替换

实现步骤 :

  1. 键盘录入一个字符串,用 Scanner 实现
  2. 替换敏感词
    String replace(CharSequence target, CharSequence replacement)
    将当前字符串中的target内容,使用replacement进行替换,返回新的字符串
  3. 输出结果

代码实现 :

package com.itheima.test;

import java.util.Scanner;

public class Test6 {
    /*
        需求:键盘录入一个 字符串,如果字符串中包含(TMD),则使用***替换

        思路:
        1. 键盘录入一个字符串,用 Scanner 实现
        2. 替换敏感词
                String replace(CharSequence target, CharSequence replacement)
                将当前字符串中的target内容,使用replacement进行替换,返回新的字符串
        3. 输出结果

     */
    public static void main(String[] args) {
        // 1. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入:");
        String s = sc.nextLine();
        // 2. 替换敏感词
        String result = s.replace("TMD","***");
        // 3. 输出结果
        System.out.println(result);
    }
}

2.11 切割字符串

案例需求 :

以字符串的形式从键盘录入学生信息,例如:“张三 , 23”

从该字符串中切割出有效数据,封装为Student学生对象

实现步骤 :

  1. 编写Student类,用于封装数据
  2. 键盘录入一个字符串,用 Scanner 实现
  3. 根据逗号切割字符串,得到(张三)(23)
    String[] split(String regex) :根据传入的字符串作为规则进行切割
    将切割后的内容存入字符串数组中,并将字符串数组返回
  4. 从得到的字符串数组中取出元素内容,通过Student类的有参构造方法封装为对象
  5. 调用对象getXxx方法,取出数据并打印。

代码实现 :

package com.itheima.test;

import com.itheima.domain.Student;

import java.util.Scanner;

public class Test7 {
    /*
         需求:以字符串的形式从键盘录入学生信息,例如:“张三 , 23”
                从该字符串中切割出有效数据,封装为Student学生对象
         思路:
            1. 编写Student类,用于封装数据
            2. 键盘录入一个字符串,用 Scanner 实现
            3. 根据逗号切割字符串,得到(张三)(23)
                    String[] split(String regex) :根据传入的字符串作为规则进行切割
                    将切割后的内容存入字符串数组中,并将字符串数组返回
            4. 从得到的字符串数组中取出元素内容,通过Student类的有参构造方法封装为对象
            5. 调用对象getXxx方法,取出数据并打印。

     */
    public static void main(String[] args) {
        // 2. 键盘录入一个字符串,用 Scanner 实现
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学生信息:");
        String stuInfo = sc.nextLine();
        // stuInfo = "张三,23";
        // 3. 根据逗号切割字符串,得到(张三)(23)
        String[] sArr = stuInfo.split(",");

//        System.out.println(sArr[0]);
//        System.out.println(sArr[1]);

        // 4. 从得到的字符串数组中取出元素内容,通过Student类的有参构造方法封装为对象
        Student stu = new Student(sArr[0],sArr[1]);

        // 5. 调用对象getXxx方法,取出数据并打印。
        System.out.println(stu.getName() + "..." + stu.getAge());
    }
}

2.12 String方法小结

String类的常用方法 :

public boolean equals(Object anObject)  比较字符串的内容,严格区分大小写

public boolean equalsIgnoreCase(String anotherString)  比较字符串的内容,忽略大小写

public int length()  返回此字符串的长度

public char charAt(int index)  返回指定索引处的 char 值

public char[] toCharArray()  将字符串拆分为字符数组后返回

public String substring(int beginIndex, int endIndex)  根据开始和结束索引进行截取,得到新的字符串(包含头,不包含尾)

public String substring(int beginIndex)  从传入的索引处截取,截取到末尾,得到新的字符串

public String replace(CharSequence target, CharSequence replacement)  使用新值,将字符串中的旧值替换,得到新的字符串

public String[] split(String regex)  根据传入的规则切割字符串,得到字符串数组

3 StringBuilder类

3.1 StringBuilder类概述

**概述 :** StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的内容是可变的

3.2 StringBuilder类和String类的区别

  • String类:内容是不可变的
  • StringBuilder类:内容是可变的

3.3StringBuilder类的构造方法

常用的构造方法

方法名 说明
public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象

示例代码

public class StringBuilderDemo01 {
    public static void main(String[] args) {
        //public StringBuilder():创建一个空白可变字符串对象,不含有任何内容
        StringBuilder sb = new StringBuilder();
        System.out.println("sb:" + sb);
        System.out.println("sb.length():" + sb.length());

        //public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象
        StringBuilder sb2 = new StringBuilder("hello");
        System.out.println("sb2:" + sb2);
        System.out.println("sb2.length():" + sb2.length());
    }
}

3.4 StringBuilder常用的成员方法

  • 添加和反转方法
    | 方法名 | 说明 | | —- | —- | | public StringBuilder append(任意类型) | 添加数据,并返回对象本身 | | public StringBuilder reverse() | 返回相反的字符序列 |

  • 示例代码

public class StringBuilderDemo01 {
    public static void main(String[] args) {
        //创建对象
        StringBuilder sb = new StringBuilder();

        //public StringBuilder append(任意类型):添加数据,并返回对象本身
//        StringBuilder sb2 = sb.append("hello");
//
//        System.out.println("sb:" + sb);
//        System.out.println("sb2:" + sb2);
//        System.out.println(sb == sb2);

//        sb.append("hello");
//        sb.append("world");
//        sb.append("java");
//        sb.append(100);

        //链式编程
        sb.append("hello").append("world").append("java").append(100);

        System.out.println("sb:" + sb);

        //public StringBuilder reverse():返回相反的字符序列
        sb.reverse();
        System.out.println("sb:" + sb);
    }
}

3.5StringBuilder和String相互转换

  • StringBuilder转换为String
    public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
  • String转换为StringBuilder
    public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
  • 示例代码
public class StringBuilderDemo02 {
    public static void main(String[] args) {
        /*
        //StringBuilder 转换为 String
        StringBuilder sb = new StringBuilder();
        sb.append("hello");

        //String s = sb; //这个是错误的做法

        //public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
        String s = sb.toString();
        System.out.println(s);
        */

        //String 转换为 StringBuilder
        String s = "hello";

        //StringBuilder sb = s; //这个是错误的做法

        //public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
        StringBuilder sb = new StringBuilder(s);

        System.out.println(sb);
    }
}

3.6 StringBuilder拼接字符串案例

案例需求 :

定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,

并在控制台输出结果。例如,数组为int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]

实现步骤 :

  1. 定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
  2. 定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
    返回值类型 String,参数列表 int[] arr
  3. 在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
  4. 调用方法,用一个变量接收结果
  5. 输出结果

代码实现 :

/*
    思路:
        1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
        2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。
          返回值类型 String,参数列表 int[] arr
        3:在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
        4:调用方法,用一个变量接收结果
        5:输出结果
 */
public class StringBuilderTest01 {
    public static void main(String[] args) {
        //定义一个 int 类型的数组,用静态初始化完成数组元素的初始化
        int[] arr = {1, 2, 3};

        //调用方法,用一个变量接收结果
        String s = arrayToString(arr);

        //输出结果
        System.out.println("s:" + s);

    }

    //定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回
    /*
        两个明确:
            返回值类型:String
            参数:int[] arr
     */
    public static String arrayToString(int[] arr) {
        //在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回
        StringBuilder sb = new StringBuilder();

        sb.append("[");

        for(int i=0; i<arr.length; i++) {
            if(i == arr.length-1) {
                sb.append(arr[i]);
            } else {
                sb.append(arr[i]).append(", ");
            }
        }

        sb.append("]");

        String s = sb.toString();

        return  s;
    }
}

4 Math

  • 1、Math类概述
    • Math 包含执行基本数字运算的方法
  • 2、Math中方法的调用方式
    • Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用
  • 3、Math类的常用方法
    | 方法名 方法名 | 说明 | | —- | —- | | public static int abs(int a) | 返回参数的绝对值 | | public static double ceil(double a) | 返回大于或等于参数的最小double值,等于一个整数 | | public static double floor(double a) | 返回小于或等于参数的最大double值,等于一个整数 | | public static int round(float a) | 按照四舍五入返回最接近参数的int | | public static int max(int a,int b) | 返回两个int值中的较大值 | | public static int min(int a,int b) | 返回两个int值中的较小值 | | public static double pow (double a,double b) | 返回a的b次幂的值 | | public static double random() | 返回值为double的正值,[0.0,1.0) |

5 System

  • System类的常用方法
    | 方法名 | 说明 | | —- | —- | | public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 | | public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |

  • 示例代码

    • 需求:在控制台输出1-10000,计算这段代码执行了多少毫秒
      public class SystemDemo {
      public static void main(String[] args) {
         // 获取开始的时间节点
         long start = System.currentTimeMillis();
         for (int i = 1; i <= 10000; i++) {
             System.out.println(i);
         }
         // 获取代码运行结束后的时间节点
         long end = System.currentTimeMillis();
         System.out.println("共耗时:" + (end - start) + "毫秒");
      }
      }
      

6 object

6.1 Object类的toString方法

  • Object类概述
    • Object 是类层次结构的根,每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类,换句话说,该类所具备的方法,所有类都会有一份
  • 查看方法源码的方式
    • 选中方法,按下Ctrl + B
  • 重写toString方法的方式
      1. Alt + Insert 选择toString
      1. 在类的空白区域,右键 -> Generate -> 选择toString
  • toString方法的作用:
    • 以良好的格式,更方便的展示对象中的属性值
  • 示例代码:

    class Student extends Object {
     private String name;
     private int age;
    
     public Student() {
     }
    
     public Student(String name, int age) {
         this.name = name;
         this.age = age;
     }
    
     public String getName() {
         return name;
     }
    
     public void setName(String name) {
         this.name = name;
     }
    
     public int getAge() {
         return age;
     }
    
     public void setAge(int age) {
         this.age = age;
     }
    
     @Override
     public String toString() {
         return "Student{" +
                 "name='" + name + '\'' +
                 ", age=" + age +
                 '}';
     }
    }
    public class ObjectDemo {
     public static void main(String[] args) {
         Student s = new Student();
         s.setName("林青霞");
         s.setAge(30);
         System.out.println(s); 
         System.out.println(s.toString()); 
     }
    }
    
  • 运行结果:
    Student{name='林青霞', age=30}
    Student{name='林青霞', age=30}
    

6.2 Object类的equals方法

  • equals方法的作用
    • 用于对象之间的比较,返回true和false的结果
    • 举例:s1.equals(s2); s1和s2是两个对象
  • 重写equals方法的场景
    • 不希望比较对象的地址值,想要结合对象属性进行比较的时候。
  • 重写equals方法的方式
      1. alt + insert 选择equals() and hashCode(),IntelliJ Default,一路next,finish即可
      1. 在类的空白区域,右键 -> Generate -> 选择equals() and hashCode(),后面的同上。
  • 示例代码:

    class Student {
     private String name;
     private int age;
    
     public Student() {
     }
    
     public Student(String name, int age) {
         this.name = name;
         this.age = age;
     }
    
     public String getName() {
         return name;
     }
    
     public void setName(String name) {
         this.name = name;
     }
    
     public int getAge() {
         return age;
     }
    
     public void setAge(int age) {
         this.age = age;
     }
    
     @Override
     public boolean equals(Object o) {
         //this -- s1
         //o -- s2
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
    
         Student student = (Student) o; //student -- s2
    
         if (age != student.age) return false;
         return name != null ? name.equals(student.name) : student.name == null;
     }
    }
    public class ObjectDemo {
     public static void main(String[] args) {
         Student s1 = new Student();
         s1.setName("林青霞");
         s1.setAge(30);
    
         Student s2 = new Student();
         s2.setName("林青霞");
         s2.setAge(30);
    
         //需求:比较两个对象的内容是否相同
         System.out.println(s1.equals(s2));
     }
    }
    
  • 面试题 ```java // 看程序,分析结果 String s = “abc”; StringBuilder sb = new StringBuilder(“abc”); s.equals(sb); sb.equals(s);

public class InterviewTest { public static void main(String[] args) { String s1 = “abc”; StringBuilder sb = new StringBuilder(“abc”); //1.此时调用的是String类中的equals方法. //保证参数也是字符串,否则不会比较属性值而直接返回false //System.out.println(s1.equals(sb)); // false

    //StringBuilder类中是没有重写equals方法,用的就是Object类中的.
    System.out.println(sb.equals(s1)); // false
}

}



<a name="Gj1jp"></a>
## 6.3 Objects 

-  常用方法  
| 方法名 | 说明 |
| --- | --- |
| public static String toString(对象) | 返回参数中对象的字符串表示形式。 |
| public static String toString(对象, 默认字符串) | 返回对象的字符串表示形式。 |
| public static Boolean isNull(对象) | 判断对象是否为空 |
| public static Boolean nonNull(对象) | 判断对象是否不为空 |

-  示例代码<br />学生类 
```java
class Student {
      private String name;
      private int age;

      public Student() {
      }

      public Student(String name, int age) {
          this.name = name;
          this.age = age;
      }

      public String getName() {
          return name;
      }

      public void setName(String name) {
          this.name = name;
      }

      public int getAge() {
          return age;
      }

      public void setAge(int age) {
          this.age = age;
      }

      @Override
      public String toString() {
          return "Student{" +
                  "name='" + name + '\'' +
                  ", age=" + age +
                  '}';
      }
  }

7 BigDecimal

  • 作用
    可以用来进行精确计算
  • 构造方法
    | 方法名 | 说明 | | —- | —- | | BigDecimal(double val) | 参数为double | | BigDecimal(String val) | 参数为String |

  • 常用方法
    | 方法名 | 说明 | | —- | —- | | public BigDecimal add(另一个BigDecimal对象) | 加法 | | public BigDecimal subtract (另一个BigDecimal对象) | 减法 | | public BigDecimal multiply (另一个BigDecimal对象) | 乘法 | | public BigDecimal divide (另一个BigDecimal对象) | 除法 | | public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) | 除法 |

  • 总结

    1. BigDecimal是用来进行精确计算的
    2. 创建BigDecimal的对象,构造方法使用参数类型为字符串的。
    3. 四则运算中的除法,如果除不尽请使用divide的三个参数的方法。

代码示例:

BigDecimal divide = bd1.divide(参与运算的对象,小数点后精确到多少位,舍入模式);
参数1 ,表示参与运算的BigDecimal 对象。
参数2 ,表示小数点后面精确到多少位
参数3 ,舍入模式  
  BigDecimal.ROUND_UP  进一法
  BigDecimal.ROUND_FLOOR 去尾法
  BigDecimal.ROUND_HALF_UP 四舍五入
BigDecimal bignum1 = new BigDecimal(1000);
BigDecimal bignum2 = new BigDecimal(500);
//总页数
int xhcs = bignum1.divide(bignum2).setScale( 0, BigDecimal.ROUND_UP ).intValue();

8.包装类

8.1 基本类型包装类

  • 基本类型包装类的作用
    将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
    常用的操作之一:用于基本数据类型与字符串之间的转换
  • 基本类型对应的包装类
    | 基本数据类型 | 包装类 | | —- | —- | | byte | Byte | | short | Short | | int | Integer | | long | Long | | float | Float | | double | Double | | char | Character | | boolean | Boolean |

8.2 Integer类

  • Integer类概述
    包装一个对象中的原始类型 int 的值
  • Integer类构造方法
    | 方法名 | 说明 | | —- | —- | | public Integer(int value) | 根据 int 值创建 Integer 对象(过时) | | public Integer(String s) | 根据 String 值创建 Integer 对象(过时) | | public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 | | public static Integer valueOf(String s) | 返回一个保存指定值的 Integer 对象 String |

  • 示例代码

    public class IntegerDemo {
     public static void main(String[] args) {
         //public Integer(int value):根据 int 值创建 Integer 对象(过时)
         Integer i1 = new Integer(100);
         System.out.println(i1);
    
         //public Integer(String s):根据 String 值创建 Integer 对象(过时)
         Integer i2 = new Integer("100");
    //        Integer i2 = new Integer("abc"); //NumberFormatException
         System.out.println(i2);
         System.out.println("--------");
    
         //public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 实例
         Integer i3 = Integer.valueOf(100);
         System.out.println(i3);
    
         //public static Integer valueOf(String s):返回一个保存指定值的Integer对象 String
         Integer i4 = Integer.valueOf("100");
         System.out.println(i4);
     }
    }
    

8.3 自动拆箱和自动装箱

  • 自动装箱
    把基本数据类型转换为对应的包装类类型
  • 自动拆箱
    把包装类类型转换为对应的基本数据类型
  • 示例代码
    Integer i = 100;  // 自动装箱
    i += 200;         // i = i + 200;  i + 200 自动拆箱;i = i + 200; 是自动装箱
    

8.4 int和String类型的相互转换

  • int转换为String
    • 转换方式
      • 方式一:直接在数字后加一个空字符串
      • 方式二:通过String类静态方法valueOf()
    • 示例代码
      public class IntegerDemo {
      public static void main(String[] args) {
        //int --- String
        int number = 100;
        //方式1
        String s1 = number + "";
        System.out.println(s1);
        //方式2
        //public static String valueOf(int i)
        String s2 = String.valueOf(number);
        System.out.println(s2);
        System.out.println("--------");
      }
      }
      
  • String转换为int
    • 转换方式
      • 方式一:先将字符串数字转成Integer,再调用valueOf()方法
      • 方式二:通过Integer静态方法parseInt()进行转换
    • 示例代码
      public class IntegerDemo {
      public static void main(String[] args) {
        //String --- int
        String s = "100";
        //方式1:String --- Integer --- int
        Integer i = Integer.valueOf(s);
        //public int intValue()
        int x = i.intValue();
        System.out.println(x);
        //方式2
        //public static int parseInt(String s)
        int y = Integer.parseInt(s);
        System.out.println(y);
      }
      }
      

9.递归

9.1 递归

  • 递归的介绍
    • 以编程的角度来看,递归指的是方法定义中调用方法本身的现象
    • 把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
    • 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算
  • 递归的基本使用

    public class MyFactorialDemo2 {
     public static void main(String[] args) {
         int sum = getSum(100);
         System.out.println(sum);
     }
    
     private static int getSum(int i) {
         //1- 100之间的和
             //100 + (1-99之间的和)
                     // 99 + (1- 98之间的和)
                         //....
                             //1
         //方法的作用: 求 1- i 之间和
         if(i == 1){
             return 1;
         }else{
             return i + getSum(i -1);
         }
     }
    }
    
  • 递归的注意事项
    • 递归一定要有出口。否则内存溢出
    • 递归虽然有出口,但是递归的次数也不宜过多。否则内存溢出

9.2 递归求阶乘

  • 案例需求
    用递归求5的阶乘,并把结果在控制台输出
  • 代码实现

    public class DiGuiDemo01 {
     public static void main(String[] args) {
         //调用方法
         int result = jc(5);
         //输出结果
         System.out.println("5的阶乘是:" + result);
     }
    
     //定义一个方法,用于递归求阶乘,参数为一个int类型的变量
     public static int jc(int n) {
         //在方法内部判断该变量的值是否是1
         if(n == 1) {
             //是:返回1
             return 1;
         } else {
             //不是:返回n*(n-1)!
             return n*jc(n-1);
         }
     }
    }
    
  • 内存图
    API与异常 - 图2

10.数组的高级操作

10.1 二分查找

  • 二分查找概述
    查找指定元素在数组中的位置时,以前的方式是通过遍历,逐个获取每个元素,看是否是要查找的元素,这种方式当数组元素较多时,查找的效率很低
    二分查找也叫折半查找,每次可以去掉一半的查找范围,从而提高查找的效率
  • 适用于:有序的数组并且无重复元素的数组
  • 需求
    在数组{1,2,3,4,5,6,7,8,9,10}中,查找某个元素的位置
  • 实现步骤
    1. 定义两个变量,表示要查找的范围。默认min = 0 ,max = 最大索引
    2. 循环查找,但是min <= max
    3. 计算出mid的值
    4. 判断mid位置的元素是否为要查找的元素,如果是直接返回对应索引
    5. 如果要查找的值在mid的左半边,那么min值不变,max = mid -1.继续下次循环查找
    6. 如果要查找的值在mid的右半边,那么max值不变,min = mid + 1.继续下次循环查找
    7. 当min > max 时,表示要查找的元素在数组中不存在,返回-1.
  • 代码实现 ```java public class MyBinarySearchDemo { public static void main(String[] args) {

     int [] arr = {1,2,3,4,5,6,7,8,9,10};
     int number = 11;
    
     //1,我现在要干嘛? --- 二分查找
     //2.我干这件事情需要什么? --- 数组 元素
     //3,我干完了,要不要把结果返回调用者 --- 把索引返回给调用者
     int index = binarySearchForIndex(arr,number);
     System.out.println(index);
    

    }

    private static int binarySearchForIndex(int[] arr, int number) {

     //1,定义查找的范围
     int min = 0;
     int max = arr.length - 1;
     //2.循环查找 min <= max
     while(min <= max){
         //3.计算出中间位置 mid
         int mid = (min + max) >> 1;
         //mid指向的元素 > number
         if(arr[mid] > number){
             //表示要查找的元素在左边.
             max = mid -1;
         }else if(arr[mid] < number){
             //mid指向的元素 < number
             //表示要查找的元素在右边.
             min = mid + 1;
         }else{
             //mid指向的元素 == number
             return mid;
         }
     }
     //如果min大于了max就表示元素不存在,返回-1.
     return -1;
    

    }

}



-  注意事项<br />有一个前提条件,数组内的元素一定要按照大小顺序排列,如果没有大小顺序,是不能使用二分查找法的 

<a name="uucg9"></a>
## 10.2 冒泡排序

-  冒泡排序概述<br />一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,依次对所有的数据进行操作,直至所有数据按要求完成排序<br />如果有n个数据进行排序,总共需要比较n-1次<br />每一次比较完毕,下一次的比较就会少一个数据参与 
-  代码实现 
```java
public class MyBubbleSortDemo2 {
    public static void main(String[] args) {
        int[] arr = {3, 5, 2, 1, 4};
        //1 2 3 4 5
        bubbleSort(arr);
    }

    private static void bubbleSort(int[] arr) {
        //外层循环控制的是次数 比数组的长度少一次.
        for (int i = 0; i < arr.length -1; i++) {
            //内存循环就是实际循环比较的
            //-1 是为了让数组不要越界
            //-i 每一轮结束之后,我们就会少比一个数字.
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        printArr(arr);
    }

    private static void printArr(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

}

10.3 快速排序

  • 快速排序概述
    冒泡排序算法中,一次循环结束,就相当于确定了当前的最大值,也能确定最大值在数组中应存入的位置
    快速排序算法中,每一次递归时以第一个数为基准数,找到数组中所有比基准数小的.再找到所有比基准数大的.小的全部放左边,大的全部放右边,确定基准数的正确位置
  • 核心步骤
    1. 从右开始找比基准数小的
    2. 从左开始找比基准数大的
    3. 交换两个值的位置
    4. 红色继续往左找,蓝色继续往右找,直到两个箭头指向同一个索引为止
    5. 基准数归位
  • 代码实现

    public class MyQuiteSortDemo2 {
     public static void main(String[] args) {
    //        1,从右开始找比基准数小的
    //        2,从左开始找比基准数大的
    //        3,交换两个值的位置
    //        4,红色继续往左找,蓝色继续往右找,直到两个箭头指向同一个索引为止
    //        5,基准数归位
         int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
    
         quiteSort(arr,0,arr.length-1);
    
         for (int i = 0; i < arr.length; i++) {
             System.out.print(arr[i] + " ");
         }
     }
    
     private static void quiteSort(int[] arr, int left, int right) {
          // 递归结束的条件
         if(right < left){
             return;
         }
    
         int left0 = left;
         int right0 = right;
    
         //计算出基准数
         int baseNumber = arr[left0];
    
         while(left != right){
    //        1,从右开始找比基准数小的
             while(arr[right] >= baseNumber && right > left){
                 right--;
             }
    //        2,从左开始找比基准数大的
             while(arr[left] <= baseNumber && right > left){
                 left++;
             }
    //        3,交换两个值的位置
             int temp = arr[left];
             arr[left] = arr[right];
             arr[right] = temp;
         }
         //基准数归位
         int temp = arr[left];
         arr[left] = arr[left0];
         arr[left0] = temp;
    
         // 递归调用自己,将左半部分排好序
         quiteSort(arr,left0,left-1);
           // 递归调用自己,将右半部分排好序
         quiteSort(arr,left +1,right0);
    
     }
    }
    

10.4 Arrays

  • Arrays的常用方法
    | 方法名 | 说明 | | —- | —- | | public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 | | public static void sort(int[] a) | 按照数字顺序排列指定的数组 | | public static int binarySearch(int[] a, int key) | 利用二分查找返回指定元素的索引 |

  • 示例代码

    public class MyArraysDemo {
       public static void main(String[] args) {
    //        public static String toString(int[] a)    返回指定数组的内容的字符串表示形式
    //        int [] arr = {3,2,4,6,7};
    //        System.out.println(Arrays.toString(arr));
    
    //        public static void sort(int[] a)      按照数字顺序排列指定的数组
    //        int [] arr = {3,2,4,6,7};
    //        Arrays.sort(arr);
    //        System.out.println(Arrays.toString(arr));
    
    //        public static int binarySearch(int[] a, int key) 利用二分查找返回指定元素的索引
           int [] arr = {1,2,3,4,5,6,7,8,9,10};
           int index = Arrays.binarySearch(arr, 0);
           System.out.println(index);
           //1,数组必须有序
           //2.如果要查找的元素存在,那么返回的是这个元素实际的索引
           //3.如果要查找的元素不存在,那么返回的是 (-插入点-1)
               //插入点:如果这个元素在数组中,他应该在哪个索引上.
       }
    }
    
  • 工具类设计思想
    1. 构造方法用 private 修饰
    2. 成员用 public static 修饰

11.时间日期类

11.1 Date类

  • 计算机中时间原点
    1970年1月1日 00:00:00
  • 时间换算单位
    1秒 = 1000毫秒
  • Date类概述
    Date 代表了一个特定的时间,精确到毫秒
  • Date类构造方法
    | 方法名 | 说明 | | —- | —- | | public Date() | 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 | | public Date(long date) | 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |

  • 示例代码

    public class DateDemo01 {
     public static void main(String[] args) {
         //public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒
         Date d1 = new Date();
         System.out.println(d1);
    
         //public Date(long date):分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数
         long date = 1000*60*60;
         Date d2 = new Date(date);
         System.out.println(d2);
     }
    }
    

11.2 Date类常用方法

  • 常用方法
    | 方法名 | 说明 | | —- | —- | | public long getTime() | 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 | | public void setTime(long time) | 设置时间,给的是毫秒值 |

  • 示例代码

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

11.3 SimpleDateFormat类

  • SimpleDateFormat类概述
    SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
    我们重点学习日期格式化和解析
  • SimpleDateFormat类构造方法
    | 方法名 | 说明 | | —- | —- | | public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 | | public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |

  • SimpleDateFormat类的常用方法

    • 格式化(从Date到String)
      • public final String format(Date date):将日期格式化成日期/时间字符串
    • 解析(从String到Date)
      • public Date parse(String source):从给定字符串的开始解析文本以生成日期
  • 示例代码

    public class SimpleDateFormatDemo {
     public static void main(String[] args) throws ParseException {
         //格式化:从 Date 到 String
         Date d = new Date();
    //        SimpleDateFormat sdf = new SimpleDateFormat();
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
         String s = sdf.format(d);
         System.out.println(s);
         System.out.println("--------");
    
         //从 String 到 Date
         String ss = "2048-08-09 11:11:11";
         //ParseException
         SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
         Date dd = sdf2.parse(ss);
         System.out.println(dd);
     }
    }
    


    11.4 JDK8时间日期类

11.4.1 JDK8新增日期类

  • LocalDate 表示日期(年月日)
  • LocalTime 表示时间(时分秒)
  • LocalDateTime 表示时间+ 日期 (年月日时分秒)

11.4.2 LocalDateTime创建方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public static LocalDateTime now() | 获取当前系统时间 | | public static LocalDateTime of (年, 月 , 日, 时, 分, 秒) | 使用指定年月日和时分秒初始化一个LocalDateTime对象 |

  • 示例代码

    public class JDK8DateDemo2 {
     public static void main(String[] args) {
         LocalDateTime now = LocalDateTime.now();
         System.out.println(now);
    
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
         System.out.println(localDateTime);
     }
    }
    

11.4.3 LocalDateTime获取方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public int getYear() | 获取年 | | public int getMonthValue() | 获取月份(1-12) | | public int getDayOfMonth() | 获取月份中的第几天(1-31) | | public int getDayOfYear() | 获取一年中的第几天(1-366) | | public DayOfWeek getDayOfWeek() | 获取星期 | | public int getMinute() | 获取分钟 | | public int getHour() | 获取小时 |

  • 示例代码

    public class JDK8DateDemo3 {
     public static void main(String[] args) {
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
         //public int getYear()           获取年
         int year = localDateTime.getYear();
         System.out.println("年为" +year);
         //public int getMonthValue()     获取月份(1-12)
         int month = localDateTime.getMonthValue();
         System.out.println("月份为" + month);
    
         Month month1 = localDateTime.getMonth();
    //        System.out.println(month1);
    
         //public int getDayOfMonth()     获取月份中的第几天(1-31)
         int day = localDateTime.getDayOfMonth();
         System.out.println("日期为" + day);
    
         //public int getDayOfYear()      获取一年中的第几天(1-366)
         int dayOfYear = localDateTime.getDayOfYear();
         System.out.println("这是一年中的第" + dayOfYear + "天");
    
         //public DayOfWeek getDayOfWeek()获取星期
         DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
         System.out.println("星期为" + dayOfWeek);
    
         //public int getMinute()        获取分钟
         int minute = localDateTime.getMinute();
         System.out.println("分钟为" + minute);
         //public int getHour()           获取小时
    
         int hour = localDateTime.getHour();
         System.out.println("小时为" + hour);
     }
    }
    

11.4.4 LocalDateTime转换方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public LocalDate toLocalDate () | 转换成为一个LocalDate对象 | | public LocalTime toLocalTime () | 转换成为一个LocalTime对象 |

  • 示例代码

    public class JDK8DateDemo4 {
     public static void main(String[] args) {
         LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
         //public LocalDate toLocalDate ()    转换成为一个LocalDate对象
         LocalDate localDate = localDateTime.toLocalDate();
         System.out.println(localDate);
    
         //public LocalTime toLocalTime ()    转换成为一个LocalTime对象
         LocalTime localTime = localDateTime.toLocalTime();
         System.out.println(localTime);
     }
    }
    

11.4.5 LocalDateTime格式化和解析

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public String format (指定格式) | 把一个LocalDateTime格式化成为一个字符串 | | public LocalDateTime parse (准备解析的字符串, 解析格式) | 把一个日期字符串解析成为一个LocalDateTime对象 | | public static DateTimeFormatter ofPattern(String pattern) | 使用指定的日期模板获取一个日期格式化器DateTimeFormatter对象 |

  • 示例代码

    public class JDK8DateDemo5 {
     public static void main(String[] args) {
         //method1();
         //method2();
     }
    
     private static void method2() {
         //public static LocalDateTime parse (准备解析的字符串, 解析格式) 把一个日期字符串解析成为一个LocalDateTime对象
         String s = "2020年11月12日 13:14:15";
         DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
         LocalDateTime parse = LocalDateTime.parse(s, pattern);
         System.out.println(parse);
     }
    
     private static void method1() {
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
         System.out.println(localDateTime);
         //public String format (指定格式)   把一个LocalDateTime格式化成为一个字符串
         DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
         String s = localDateTime.format(pattern);
         System.out.println(s);
     }
    }
    

    11.4.6 LocalDateTime增加或者减少时间的方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public LocalDateTime plusYears (long years) | 添加或者减去年 | | public LocalDateTime plusMonths(long months) | 添加或者减去月 | | public LocalDateTime plusDays(long days) | 添加或者减去日 | | public LocalDateTime plusHours(long hours) | 添加或者减去时 | | public LocalDateTime plusMinutes(long minutes) | 添加或者减去分 | | public LocalDateTime plusSeconds(long seconds) | 添加或者减去秒 | | public LocalDateTime plusWeeks(long weeks) | 添加或者减去周 |

  • 示例代码

    /**
    * JDK8 时间类添加或者减去时间的方法
    */
    public class JDK8DateDemo6 {
     public static void main(String[] args) {
         //public LocalDateTime plusYears (long years)   添加或者减去年
    
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
         //LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
         //System.out.println(newLocalDateTime);
    
         LocalDateTime newLocalDateTime = localDateTime.plusYears(-1);
         System.out.println(newLocalDateTime);
     }
    }
    

11.4.7 LocalDateTime减少或者增加时间的方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public LocalDateTime minusYears (long years) | 减去或者添加年 | | public LocalDateTime minusMonths(long months) | 减去或者添加月 | | public LocalDateTime minusDays(long days) | 减去或者添加日 | | public LocalDateTime minusHours(long hours) | 减去或者添加时 | | public LocalDateTime minusMinutes(long minutes) | 减去或者添加分 | | public LocalDateTime minusSeconds(long seconds) | 减去或者添加秒 | | public LocalDateTime minusWeeks(long weeks) | 减去或者添加周 |

  • 示例代码

    /**
    * JDK8 时间类减少或者添加时间的方法
    */
    public class JDK8DateDemo7 {
     public static void main(String[] args) {
         //public LocalDateTime minusYears (long years)  减去或者添加年
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
         //LocalDateTime newLocalDateTime = localDateTime.minusYears(1);
         //System.out.println(newLocalDateTime);
    
         LocalDateTime newLocalDateTime = localDateTime.minusYears(-1);
         System.out.println(newLocalDateTime);
    
     }
    }
    

11.4.8 LocalDateTime修改方法

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public LocalDateTime withYear(int year) | 直接修改年 | | public LocalDateTime withMonth(int month) | 直接修改月 | | public LocalDateTime withDayOfMonth(int dayofmonth) | 直接修改日期(一个月中的第几天) | | public LocalDateTime withDayOfYear(int dayOfYear) | 直接修改日期(一年中的第几天) | | public LocalDateTime withHour(int hour) | 直接修改小时 | | public LocalDateTime withMinute(int minute) | 直接修改分钟 | | public LocalDateTime withSecond(int second) | 直接修改秒 |

  • 示例代码

    /**
    * JDK8 时间类修改时间
    */
    public class JDK8DateDemo8 {
     public static void main(String[] args) {
         //public LocalDateTime withYear(int year)   修改年
         LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
        // LocalDateTime newLocalDateTime = localDateTime.withYear(2048);
        // System.out.println(newLocalDateTime);
    
         LocalDateTime newLocalDateTime = localDateTime.withMonth(20);
         System.out.println(newLocalDateTime);
    
     }
    }
    

11.4.9 Period

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public static Period between(开始时间,结束时间) | 计算两个“时间”的间隔 | | public int getYears() | 获得这段时间的年数 | | public int getMonths() | 获得此期间的总月数 | | public int getDays() | 获得此期间的天数 | | public long toTotalMonths() | 获取此期间的总月数 |

  • 示例代码

    /**
    *  计算两个时间的间隔
    */
    public class JDK8DateDemo9 {
     public static void main(String[] args) {
         //public static Period between(开始时间,结束时间)  计算两个"时间"的间隔
    
         LocalDate localDate1 = LocalDate.of(2020, 1, 1);
         LocalDate localDate2 = LocalDate.of(2048, 12, 12);
         Period period = Period.between(localDate1, localDate2);
         System.out.println(period);//P28Y11M11D
    
         //public int getYears()         获得这段时间的年数
         System.out.println(period.getYears());//28
         //public int getMonths()        获得此期间的月数
         System.out.println(period.getMonths());//11
         //public int getDays()          获得此期间的天数
         System.out.println(period.getDays());//11
    
         //public long toTotalMonths()   获取此期间的总月数
         System.out.println(period.toTotalMonths());//347
    
     }
    }
    

11.4.10 Duration

  • 方法说明
    | 方法名 | 说明 | | —- | —- | | public static Durationbetween(开始时间,结束时间) | 计算两个“时间”的间隔 | | public long toSeconds() | 获得此时间间隔的秒 | | public int toMillis() | 获得此时间间隔的毫秒 | | public int toNanos() | 获得此时间间隔的纳秒 |

  • 示例代码

    /**
    *  计算两个时间的间隔
    */
    public class JDK8DateDemo10 {
     public static void main(String[] args) {
         //public static Duration between(开始时间,结束时间)  计算两个“时间"的间隔
    
         LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
         LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
         Duration duration = Duration.between(localDateTime1, localDateTime2);
         System.out.println(duration);//PT21H57M58S
         //public long toSeconds()           获得此时间间隔的秒
         System.out.println(duration.toSeconds());//79078
         //public int toMillis()               获得此时间间隔的毫秒
         System.out.println(duration.toMillis());//79078000
         //public int toNanos()             获得此时间间隔的纳秒
         System.out.println(duration.toNanos());//79078000000000
     }
    }
    

12.异常

12.1 异常

  • 异常的概述
    异常就是程序出现了不正常的情况
  • 异常的体系结构
    01_异常体系结构.png

12.2 编译时异常和运行时异常的区别

  • 编译时异常
    • 都是Exception类及其子类
    • 必须显示处理,否则程序就会发生错误,无法通过编译
  • 运行时异常
    • 都是RuntimeException类及其子类
    • 无需显示处理,也可以和编译时异常一样处理
  • 图示
    02_编译时异常和运行时异常.png

12.3 JVM默认处理异常的方式

  • 如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
    • 把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
    • 程序停止执行

12.4 查看异常信息

控制台在打印异常信息时,会打印异常类名,异常出现的原因,异常出现的位置

我们调bug时,可以根据提示,找到异常出现的位置,分析原因,修改异常代码

03_查看异常信息.png

12.5 throws方式处理异常

  • 定义格式 ```java public void 方法() throws 异常类名 {

}



-  示例代码 
```java
public class ExceptionDemo {
    public static void main(String[] args) throws ParseException{
        System.out.println("开始");
//        method();
          method2();

        System.out.println("结束");
    }

    //编译时异常
    public static void method2() throws ParseException {
        String s = "2048-08-09";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date d = sdf.parse(s);
        System.out.println(d);
    }

    //运行时异常
    public static void method() throws ArrayIndexOutOfBoundsException {
        int[] arr = {1, 2, 3};
        System.out.println(arr[3]);
    }
}
  • 注意事项
    • 这个throws格式是跟在方法的括号后面的
    • 编译时异常必须要进行处理,两种处理方案:try…catch …或者 throws,如果采用 throws 这种方案,在方法上进行显示声明,将来谁调用这个方法谁处理
    • 运行时异常因为在运行时才会发生,所以在方法后面可以不写,运行时出现异常默认交给jvm处理

12.6 throw抛出异常

  • 格式
    throw new 异常();
  • 注意
    这个格式是在方法内的,表示当前代码手动抛出一个异常,下面的代码不用再执行了
  • throws和throw的区别
    | throws | throw | | —- | —- | | 用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 | | 表示声明异常,调用该方法有可能会出现这样的异常 | 表示手动抛出异常对象,由方法体内的语句处理 |

  • 示例代码 ```java public class ExceptionDemo8 { public static void main(String[] args) {

     //int [] arr = {1,2,3,4,5};
     int [] arr = null;
     printArr(arr);//就会 接收到一个异常.
                     //我们还需要自己处理一下异常.
    

    }

    private static void printArr(int[] arr) {

     if(arr == null){
         //调用者知道成功打印了吗?
         //System.out.println("参数不能为null");
         throw new NullPointerException(); //当参数为null的时候
                                         //手动创建了一个异常对象,抛给了调用者,产生了一个异常
     }else{
         for (int i = 0; i < arr.length; i++) {
             System.out.println(arr[i]);
         }
     }
    

    }

}



<a name="heuyT"></a>
## 12.7 try-catch方式处理异常

-  定义格式 
```java
try {
    可能出现异常的代码;
} catch(异常类名 变量名) {
    异常的处理代码;
}
  • 执行流程
    • 程序从 try 里面的代码开始执行
    • 出现异常,就会跳转到对应的 catch 里面去执行
    • 执行完毕之后,程序还可以继续往下执行
  • 示例代码

    public class ExceptionDemo01 {
     public static void main(String[] args) {
         System.out.println("开始");
         method();
         System.out.println("结束");
     }
    
     public static void method() {
         try {
             int[] arr = {1, 2, 3};
             System.out.println(arr[3]);
             System.out.println("这里能够访问到吗");
         } catch (ArrayIndexOutOfBoundsException e) {
             System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
         }
     }
    }
    
  • 注意
    1. 如果 try 中没有遇到问题,怎么执行?
      会把try中所有的代码全部执行完毕,不会执行catch里面的代码
    2. 如果 try 中遇到了问题,那么 try 下面的代码还会执行吗?
      那么直接跳转到对应的catch语句中,try下面的代码就不会再执行了
      当catch里面的语句全部执行完毕,表示整个体系全部执行完全,继续执行下面的代码
    3. 如果出现的问题没有被捕获,那么程序如何运行?
      那么try…catch就相当于没有写.那么也就是自己没有处理.
      默认交给虚拟机处理.
    4. 同时有可能出现多个异常怎么处理?
      出现多个异常,那么就写多个catch就可以了.
      注意点:如果多个异常之间存在子父类关系.那么父类一定要写在下面

12.8 Throwable成员方法

  • 常用方法
    | 方法名 | 说明 | | —- | —- | | public String getMessage() | 返回此 throwable 的详细消息字符串 | | public String toString() | 返回此可抛出的简短描述 | | public void printStackTrace() | 把异常的错误信息输出在控制台 |

  • 示例代码

    public class ExceptionDemo02 {
     public static void main(String[] args) {
         System.out.println("开始");
         method();
         System.out.println("结束");
     }
    
     public static void method() {
         try {
             int[] arr = {1, 2, 3};
             System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
             System.out.println("这里能够访问到吗");
         } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
    //            e.printStackTrace();
    
             //public String getMessage():返回此 throwable 的详细消息字符串
    //            System.out.println(e.getMessage());
             //Index 3 out of bounds for length 3
    
             //public String toString():返回此可抛出的简短描述
    //            System.out.println(e.toString());
             //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    
             //public void printStackTrace():把异常的错误信息输出在控制台
             e.printStackTrace();
    //            java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    //            at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
    //            at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11)
    
         }
     }
    }
    

12.9 自定义异常

  • 自定义异常概述
    当Java中提供的异常不能满足我们的需求时,我们可以自定义异常
  • 实现步骤
    1. 定义异常类
    2. 写继承关系
    3. 提供空参构造
    4. 提供带参构造
  • 代码实现
    异常类

    public class AgeOutOfBoundsException extends RuntimeException {
     public AgeOutOfBoundsException() {
     }
    
     public AgeOutOfBoundsException(String message) {
         super(message);
     }
    }
    

13.Optional

13.1获取对象

  • Optional概述
    可能包含或不包含非null值的容器对象
  • 方法介绍
    | 方法名 | 说明 | | —- | —- | | static Optional of(T value) | 获取一个Optional对象,封装的是非null值的对象 | | static Optional ofNullable(T value) | 获取一个Optional对象,Optional封装的值对象可以是null也可以不是null |

  • 示例代码

    public class OptionalDemo1 {
     public static void main(String[] args) {
         //method1();
    
         //public static <T> Optional<T> ofNullable(T value)
         //获取一个Optional对象,Optional封装的值对象可以是null也可以不是null
         //Student s = new Student("zhangsan",23);
         Student s = null;
         //ofNullable方法,封装的对象可以是null,也可以不是null。
         Optional<Student> optional = Optional.ofNullable(s);
    
         System.out.println(optional);
     }
    
     private static void method1() {
         //static <T> Optional<T> of(T value)    获取一个Optional对象,封装的是非null值的对象
    
         //Student s = new Student("zhangsan",23);
         Student s = null;
         //Optional可以看做是一个容器,里面装了一个引用数据类型的对象。
         //返回值就是Optional的对象
         //如果使用of方法,封装的对象如果为空,那么还是会抛出空指针异常
         Optional<Student> optional1 = Optional.of(s);
         System.out.println(optional1);
     }
    }
    

13.2常用方法

  • 方法介绍
    | 方法名 | 说明 | | —- | —- | | T get() | 如果存在值,返回值,否则抛出NoSuchElementException | | boolean isPresent() | 如果存在值,则返回true,否则为false |

  • 示例代码

    public class OptionalDemo2 {
     public static void main(String[] args) {
         //get() 如果存在值,返回值,否则抛出NoSuchElementException
         //public boolean isPresent()    判断Optional所封装的对象是否不为空,如果不为空返回true , 否则返回false
    
         //Student s = new Student("zhangsan",23);
         Student s = null;
         Optional<Student> optional = Optional.ofNullable(s);
         //如果封装的是一个null,那么通过get方法再次获取会抛出NoSuchElementException。
         if(optional.isPresent()){
             Student student = optional.get();
             System.out.println(student);
         }else{
             System.out.println("Optional封装的对象为空");
         }
     }
    }
    

13.3处理空指针的方法

  • 方法介绍
    | 方法名 | 说明 | | —- | —- | | T orElse(T other) | 如果不为空,则返回具体的值,否则返回参数中的值 | | T orElseGet(Supplier<? extends T> supplier) | 如果不为空,则返回具体的值,否则返回由括号中函数产生的结果 | | void ifPresent (Consumer<? super T> action) | 如果不为空,则使用该值执行给定的操作,否则不执行任何操作 | | void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) | 如果不为空,则使用该值执行给定的操作,否则执行给定的基于空的操作 |

  • 示例代码

    public class OptionalDemo3 {
     public static void main(String[] args) {
         //method1();
    
         //method2();
         //method3();
         //method4();
    
     }
    
     private static void method4() {
         //Student s = new Student("zhangsan",23);
         Student s = null;
         Optional<Student> optional = Optional.ofNullable(s);
         //public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)、
         //如果不为空,则使用该值执行给定的操作,否则执行给定的基于空的操作。
         optional.ifPresentOrElse(student -> System.out.println(student),
                 ()->System.out.println("为空了"));
     }
    
     private static void method3() {
         //Student s = new Student("zhangsan",23);
         Student s = null;
         Optional<Student> optional = Optional.ofNullable(s);
         //ifPresent (Consumer<? super T> action)
         //如果不为空,则使用该值执行给定的操作,否则不执行任何操作
         optional.ifPresent(student -> System.out.println(student));
     }
    
     private static void method2() {
         Student s = new Student("zhangsan",23);
         //Student s = null;
         Optional<Student> optional = Optional.ofNullable(s);
         //orElseGet(Supplier<? extends T> supplier)
         //如果不为空,则返回具体的值,否则返回由括号中函数产生的结果
    
         Student student = optional.orElseGet(()-> new Student("lisi" , 24));
         System.out.println(student);
     }
    
     private static void method1() {
         //Student s = new Student("zhangsan",23);
         Student s = null;
         Optional<Student> optional = Optional.ofNullable(s);
         //orElse(T other) 如果不为空,则返回具体的值,否则返回参数中的值
         Student student = optional.orElse(new Student("lisi", 24));
         System.out.println(student);
     }
    }