Skip to content

多态、内部类、常用API

1 多态

1.1 面向对象三大特征 ?

  • 封装 , 继承 , 多态

1.2 什么是多态 ?

  • 一个对象在不同时刻体现出来的不同形态

  • 举例 : 一只猫对象

    • 我们可以说猫就是猫 : Cat cat = new Cat();
    • 我们也可以说猫是动物 : Animal cat = new Cat();
    • 这里对象在不同时刻,体现出来的不同形态 , 我们就可以理解为多态

1.3 多态的前提

  • 有继承/实现关系
  • 有方法重写
  • 父类的引用指向子类的对象
java
package com.fan.polymorphism_demo;
/*
    多态的三个前提条件
        1 需要有继承/实现关系
        2 需要有方法重写
        3 父类的引用指向子类的对象
 */
public class AnimalTest {
    public static void main(String[] args) {
        // 3 父类的引用指向子类的对象
        // 多态形式对象
        Animal a = new Cat();
    }
}

class Animal{
    public void eat(){
        System.out.println("吃东西");
    }
}

class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼....");
    }
}

1.4 多态的成员访问特点

  • 构造方法 : 和继承一样 , 子类通过super()访问父类的构造方法
  • 成员变量 : 编译看左边(父类) , 执行看左边(父类)
  • 成员方法 : 编译看左边(父类) , 执行看右边(子类)
java
package com.fan.polymorphism_demo;

/*
    多态的成员访问特点 :
        1 构造方法 : 和继承一样 , 都是通过super()访问父类的构造方法
        2 成员变量 : 编译看左边(父类) , 执行看左边(父类)
        3 成员方法 : 编译看左边(父类) , 执行看右边(子类) , 注意 , 如果执行时
            1) 子类没有回动态去找父类中的方法
            2) 子类的特有方法无法进行调用(多态的缺点)
 */
public class MemberTest {
    public static void main(String[] args) {
        // 父类的引用指向子类的对象
        Fu f = new Zi();

        // 多态对象调用成员变量
        System.out.println(f.num);

        // 多态对新乡调用调用成员方法
        f.show();

        // 多态对象不能调用子类特有的方法
        // f.show2();
    }
}

class Fu {
    int num = 100;

    public void show() {
        System.out.println("父类的show方法");
    }
}

class Zi extends Fu {
    int num = 10;

    public void show() {
        System.out.println("子类的show方法");
    }

    public void show2(){
        System.out.println("子类特有的方法");
    }
}

1.5 多态的优缺点

  • 优点 : 提高代码的扩展性
  • 缺点 : 不能调用子类特有的功能
java
package com.fan.polymorphism_test;

public abstract class Animal {
    private String breed;
    private String color;

    public Animal() {
    }

    public Animal(String breed, String color) {
        this.breed = breed;
        this.color = color;
    }

    public String getBreed() {
        return breed;
    }

    public void setBreed(String breed) {
        this.breed = breed;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public abstract void eat();
}
java
package com.fan.polymorphism_test;

public class Cat extends Animal {
    public Cat() {
    }

    public Cat(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }

    public void catchMouse() {
        System.out.println("抓老鼠...");
    }
}
java
package com.fan.polymorphism_test;

public class Dog extends Animal {
    public Dog() {
    }

    public Dog(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("狗吃骨头!");
    }

    public void lookDoor(){
        System.out.println("狗看门...");
    }
}
java
package com.fan.polymorphism_test;

public class Pig extends Animal {
    public Pig() {
    }

    public Pig(String breed, String color) {
        super(breed, color);
    }

    @Override
    public void eat() {
        System.out.println("猪拱白菜...");
    }

    public void sleep() {
        System.out.println("一直再睡...");
    }
}
java
package com.fan.polymorphism_test;

/*
    如果方法的参数是一个类的话 , 那么调用此方法需要传入此类的对象 , 或者子类对象

    多态的好处 :
        提高代码的扩展性 , 灵活性
    多态的缺点:
        不能调用子类的特有功能
 */
public class AnimalTest {
    public static void main(String[] args) {
        useAnimal(new Cat());

        System.out.println("---------");

        useAnimal(new Dog());

        System.out.println("---------");

        useAnimal(new Pig());
    }

    public static void useAnimal(Animal a){// Animal a = new Dog()
        a.eat();
        // 多态不能访问子类特有的功能
        // 如果解决 ?

        // 向下转型
        if(a instanceof Cat) {
            Cat cat = (Cat) a;
            cat.catchMouse();
        }
        if(a instanceof Dog) {
            Dog dog = (Dog) a;
            dog.lookDoor();
        }

        if(a instanceof Pig) {
            ((Pig) a).sleep();
        }
    }

//    // 定义一个使用猫类的方法
//    public static void useAnimal(Cat c) {// Cat c = new Cat();
//        c.eat();
//        c.catchMouse();
//    }
//
//    // 定义一个使用狗类的方法
//    public static void useAnimal(Dog d) {// Dog d = new Dog();
//        d.eat();
//        d.lookDoor();
//    }
//
//    // 定义一个使用猪类的方法
//    public static void useAnimal(Pig pig) {
//        pig.eat();
//        pig.sleep();
//    }
}

1.6 多态的转型

  • 向上转型 : 把子类类型数据转成父类类型数据 Animal a = new Cat();
  • 向下转型 : 把父类类型数据转成子类类型数据 Cat cat = (Cat)a;

1.7 多态的转型注意

  • 如果被转的对象 , 对应的实际类型和目标类型不是同一种数据类型 , 那么转换时会出现ClassCastException异常

  • java
    异常代码如下
    public static void main(String[] args) {
        Animal a = new Cat();
        useAnimal(a);
    }
    public static void useAnimal(Animal a) {
        Dog d = (Dog) a;
        d.eat();
    }

1.8 解决转型安全隐患

  • 使用关键字 instanceof
  • 作用 : 判断一个对象是否属于一种引用数据类型
  • 格式 : 对象名 instanceof 引用数据类型
    • 通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果

2 内部类

2.1 内部类的分类

  • 什么是内部类 ?
    • 一个A类 中 定义一个B类 , 那么B类就属于A类的内部类 , A类就属于B类的外部类

      image-20210402191054318

  • 什么时候使用内部类 ?
    • 多个事物之间有包含关系, 可以使用内部类
  • 内部类分类 ?
    • 成员内部类
    • 局部内部类
    • 匿名内部类

2.2 成员内部类

  • 定义的位置 : 类中方法外

  • 创建成员内部类对象格式 : 外部类名.内部类名 对象名 = new 外部类名().new 内部类名(参数);

    java
    package com.fan.innerclass_demo.member_innerclass;
    
    // 外部类
    public class Person {
        // 成员内部类
        public class Heart {
            // 频率变量
            private int rate;
            // 跳动方法
            public void beats() {
                System.out.println("咚咚咚!");
            }
        }
    }
    
    class Test {
        public static void main(String[] args) {
            // 创建内部类对象
            Person.Heart heart = new Person().new Heart();
            // 调用内部类中的方法
            heart.beats();
        }
    }
  • 成员内部类访问外部类的成员
    • 在内部类中有代表外部类对象的格式 : 外部类名的.this , 私有的也可以访问
    • 外部类要想访问内部类成员 , 需要创建内部类对象
    java
    package com.fan.innerclass_demo.member_innerclass;
    
    public class Person {
        private String name = "张三";
        private int num = 10;
        
        // 成员内部类
        public class Heart {
            int num = 100;
            // 频率
            private int rate;
            // 跳动
            public void beats() {
                System.out.println("咚咚咚!");
            }
            // 调用外部类的成员
            public void show(){
                int num = 1000;
                System.out.println(Person.this.name);
                System.out.println(num);// 1000 就近原则
                System.out.println(this.num);// 100
                System.out.println(Person.this.num);// 10
    
            }
        }
    }
    
    class Test {
        public static void main(String[] args) {
            Person.Heart heart = new Person().new Heart();
            heart.beats();
            heart.show();
        }
    }

2.3 匿名内部类

  • 匿名内部类 : 没有名字的类 , 一次性产品
  • 使用场景 : 直接调用方法 , 作为方法的传参 , 返回值类型
  • 好处 : 简化代码 , 快速实现接口或者抽象的抽象方法
  • 格式 :
    • new 类名/接口名(){ 重写抽象方法 } 注意 : 此处创建的是子类对象!!!
  • 使用方式 :
    • 直接调用方法
    • 作为方法的参数传递
    • 作为方法的返回值类型
java
//接口
interface Flyable {
    void fly();
}
java
// 直接调用方法
Flyable f1 = new Flyable() {
    @Override
    public void fly() {
        System.out.println("不知道什么在飞.....");
    }
};
f1.fly();
java
// 作为方法的参数传递
showFlyable(
    new Flyable() {
        @Override
        public void fly() {
            System.out.println("不知道什么在飞3333");
        }
    }
);

public static void showFlyable(Flyable flyable) {
	flyable.fly();
}
java
// 作为方法的返回值类型
public static Flyable getFlyable() {
	return new Flyable() {
        @Override
        public void fly() {
            System.out.println("3333333333333");
        }
    };
}
java
package com.fan.innerclass_demo.anonymous_innerclass;

/*
    1 如果方法的参数是一个类的话 , 调用此方法需要传入此类的对象或者此类的子类对象
    2 如果方法的返回值类型是一个类的话 , 需要返回此类的对象 , 或者此类的子类对象

     3 如果方法的参数是一个接口的话 , 调用此方法需要传入此接口的实现类对象
     4 如果方法的返回值类型是一个接口的话 , 需要返回此接口的实现类对象


     匿名内部类 : 代表的就是子类对象!!!
        new 类名/接口名(){
            重写抽象类或者接口中的抽象方法
        };

     使用方向 :
        1 调用方法
        2 作为方法参数传递
        3 作为方法的返回值
 */
public interface Swim {
    public abstract void swimming();
}

class Test {
    public static void main(String[] args) {
//        // 子类对象!!!
        //  1 调用方法
//       new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        }.swimming();


//        //   2 作为方法参数传递
//        useSwim(new Swim() {
//            @Override
//            public void swimming() {
//                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
//            }
//        });

//        // 3 作为方法的返回值
//        Swim s = getSwim();
//        s.swimming();
    }


    public static Swim getSwim() {
        return new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
            }
        };
    }


    /*
        Swim swim = new Swim() {
            @Override
            public void swimming() {
                System.out.println("匿名内部类 , 重写了接口中的抽象方法...");
            }
        };
     */
    public static void useSwim(Swim swim) {
        swim.swimming();
    }
}

3 API

3.1 Object类

  • 概述 : 类Object是类层次结构的根,每个类都把Object作为超类。 所有对象(包括数组)都实现了这个类的方法
  • 方法 : public String toString()
    • 如果一个类没有重写toString方法 , 那么打印此类的对象 , 打印的是此对象的地址值
    • 如果一个类重写了toString方法 , 那么打印此类的对象 , 打印的是此对象的属性值
    • 好处 : 把对象转成字符串 , 快速查看一个对象的属性值
    • 执行时机 : 打印对象时会默认调用toString方法
  • 方法 : public boolean equals()
    • 如果一个类没有重写equals方法 , 那么比较此类的对象 . 比较的是地址值
    • 如果一个类重写了equals方法 . 那么比较此类的对象 , 比较的是属性值是否相等
    • 好处 : 可以比较对象的内容

3.2 Objects类

  • Objects是JDK1.7新增的一个对象工具类,里面都是静态方法可以用来操作对象。比如对象的比较,计算对象的hash值,判断对手是否为空....比如里面的equals方法,可以避免空指针异常
java
public static boolean equals(Object a, Object b):判断两个对象是否相等
    
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}
a.equals(b) :如果a是null值,肯定会空指针
Objects.equals(a,b);:如果a是null,不会导致空指针异常

3.2 Date类

  • 概述 : java.util.Date 表示特定的瞬间,精确到毫秒
  • 构造方法 :
    • public Date(): 创建的对象,表示的是当前计算机系统的时间
    • public Date(long time): Date对象 = 1970/1/1 0:0:0 + time毫秒值
  • 成员方法 :
    • public long getTime(): 返回毫秒值 = 当前Date代表的时间 - 1970/1/1 0:0:0
    • public void setTime(long t): Date对象 = 1970/1/1 0:0:0 + time毫秒值
java
package com.fan.api_demo.date_demo;

import java.util.Date;

/*
    Date类 : 代表的是一个瞬间 , 精确到毫秒

    构造方法 :
        public Date() : 代表的是当前系统时间
        public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值

    成员方法 :
        public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
        public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0
 */
public class DateDemo {
    public static void main(String[] args) {
        //  public Date() : 代表的是当前系统时间
//        Date d = new Date();
//        System.out.println(d);

        //  public Date(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
//        Date d2 = new Date(1000L * 60 * 60 * 24); // 1970/1/1 0:0:0 + 一天的毫秒值
//        System.out.println(d2);

        Date d = new Date();
        // public void setTime(long date) : Date对象 = 1970/1/1 0:0:0 + long类型的毫秒值
        // d.setTime(1000L * 60 * 60 * 24);
        System.out.println(d);

        // public long getTime() : 返回的是毫秒值 = Date代表的时间 - 1970/1/1 0:0:0
        // System.out.println(d.getTime());

    }
}

3.3 DateFormat类

  • 概述 : 主要用于操作日期格式的一个类

  • 作用 :

    • 格式化 : Date --> String
    • 解析 : String --> Date
  • 构造方法 :

    • SimpleDateFormat(String pattern) 给定日期模板创建日期格式化对象

      image-20210402212755339

  • 成员方法 :

    • public String format ( Date d ):格式化,将日期对象格式化为字符串
    • public Date parse ( String s ):解析,将字符串解析为日期对象
java
package com.fan.api_demo.dateformat_demo;

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

/*
    SimpleDateFormat类 :
        "2021年04月03日 16:48:10"  ---> Date
        Date(Sat Apr 03 16:41:38 CST 2021) --> "2021年04月03日 16:48:10"

        作用 :
            格式化 : Date --> String
            解析   : String --> Date

        构造方法 :
            public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板

        成员方法 ;
            public final String format(Date date) : 接收一个Date对象返回指定模式的字符串
            public Date parse(String source) : 接收一个字符串  , 返回一个Date对象



        1 获取当前的日期对象,使用格式:yyyy-MM-dd HH:mm:ss 来表示,例如:2020-10-31 17:00:00【格式化】

        2 将字符串的 2020年10月31日  17:00:00,转换为日期Date对象。【解析】

 */
public class SimpleDateFormatDemo {
    public static void main(String[] args) throws ParseException {
        // 解析   : String --> Date
        String strDate = "2020年10月31日 17:00:00";
        // 注意 : 解析时 , SimpleDateFormat的参数(日期模板) , 必须和要解析字符串的模式匹配
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        //  public Date parse(String source) : 接收一个字符串  , 返回一个Date对象
        Date date = sdf.parse(strDate);
        System.out.println(date); // Sat Oct 31 17:00:00 CST 2020
    }

    private static void method() {
        // 格式化 : Date --> String
        // 获取当前系统时间
        Date date = new Date();
        // System.out.println(date);// Sat Apr 03 16:53:35 CST 2021

        // public SimpleDateFormat(String pattern) : pattern : 字符串类型的日期模板
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // public final String format(Date date) : 接收一个Date对象返回指定模式的字符串
        String strDate = sdf.format(date);

        System.out.println(strDate);
    }
}

3.4 Calendar类

  • 概述 :
    • java.util.Calendar类表示日历,内含有各种时间信息,以及获取,计算时间的方法。
    • Calendar本身是一个抽象类,可以通过Calendar提供的静态方法getInstance日历子类对象
  • Calendar常用方法 :
    方法名说明
    public static Calendar getInstance()获取一个它的子类GregorianCalendar对象。
    public int get(int field)获取指定日历字段的时间值。
    public void set(int field,int value)设置指定字段的时间值
    public void add(int field,int amount)为某个字段增加/减少指定的值
  • get,set,add方法参数中都有一个整数类型的参数field,field用来区分当前要获取或者操作的日期时间数据的。field数据的值使用Calender中定义的整数常量来表示

    • Calendar.YEAR : 年
    • Calendar.MONTH :月
    • Calendar.DAY_OF_MONTH:月中的周
    • Calendar.HOUR:小时
    • Calendar.MINUTE:分钟,
    • Calendar.SECOND:秒
    • Calendar.DAY_OF_WEEK:星期
  • 星期对应的关系

    ​ 字段时间值 : 1 2 3 ... 7 ​ 真正的时间 : SUNDAY MONDAY TUESDAY ... SATURDAY

  • 月份对应的关系

    ​ 字段时间值 : 0 1 .... 11 ​ 正真的时间 : JANUARY FEBRUARY .... DECEMBER

java
package com.fan.api_demo.calendar_demo;
/*

    月份对应的关系
    字段时间值     :       0           1           ....        11
    正真的时间     :     JANUARY     FEBRUARY      ....      DECEMBER


 */
import java.util.Calendar;
/*
    成员方法 :
        public int get(int field)	获取指定日历字段的时间值。
        public void set(int field,int value)	设置指定字段的时间值
        public void add(int field,int amount)	为某个字段增加/减少指定的值
 */
public class CalendarDemo {
    public static void main(String[] args) {
        // 获取Calendar对象 , rightNow对象
        Calendar rightNow = Calendar.getInstance();

        // public void set(int field , int value)	设置指定字段的时间值
        // rightNow.set(Calendar.YEAR , 2024);
        // rightNow.set(Calendar.MONTH , 5);
        // rightNow.set(Calendar.DAY_OF_MONTH, 10);

        // public void add(int field,int amount)	为某个字段增加/减少指定的值
        // rightNow.add(Calendar.DAY_OF_MONTH , -3);

        //  public int get(int field)	 : 获取指定日历字段的时间值。
        int year = rightNow.get(Calendar.YEAR);
        int month = rightNow.get(Calendar.MONTH);
        int day = rightNow.get(Calendar.DAY_OF_MONTH);


        System.out.println(year); // 2021
        System.out.println(month);// 3
        System.out.println(day);  // 3
    }
}
java
package com.fan.api_demo.calendar_demo;

import java.util.Calendar;

/*
    1 写代码使用get方法,将年,月,日,时,分,秒,周获取出来
    特别注意获取月份,和星期有以下特点:
    直接获取的月份数据是从0开始的, 0表示1月,.....11表示12月
    周的获取,从周日开始计算,1就是周日,2就是周一 ......7就是周六


星期对应的关系
     字段时间值  :   1           2            3          ...        7
     真正的时间  : SUNDAY        MONDAY      TUESDAY     ...        SATURDAY

月份对应的关系
    字段时间值     :       0           1           ....        11
    正真的时间     :     JANUARY     FEBRUARY      ....      DECEMBER

 */
public class Test1 {
    public static void main(String[] args) {
        // 拿到当前时间
        Calendar now = Calendar.getInstance();

        System.out.println(now.get(Calendar.YEAR));
        System.out.println(now.get(Calendar.MONTH));
        System.out.println(now.get(Calendar.DAY_OF_MONTH));
        System.out.println(now.get(Calendar.HOUR));
        System.out.println(now.get(Calendar.MINUTE));
        System.out.println(now.get(Calendar.SECOND));

        int week = now.get(Calendar.DAY_OF_WEEK);// 7
        System.out.println(getWeek(week));// 字段值
    }

    public static String getWeek(int field){
        String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
        return str[field];
    }
}
java
package com.fan.api_demo.calendar_demo;

import java.util.Calendar;

/*
    2 写代码实现,获取2022年10月1日是星期几?
    参考思路:
    直接获取日历对象,得到的是当前系统的日历时间信息。
    获取日历对象后,要重新设置日期
    再获取星期数据

 */
public class Test2 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2022);
        cal.set(Calendar.MONTH, 9);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        int week = cal.get(Calendar.DAY_OF_WEEK);
        System.out.println(getWeek(week));// 字段值
    }

    public static String getWeek(int field){
        String[] str = { "" , "SUNDAY" , "MONDAY" , "TUESDAY" , "WEDNESDAY" , "THURSDAY" , "FRIDAY" , "SATURDAY"};
        return str[field];
    }
}
java
package com.fan.api_demo.calendar_demo;

import java.util.Calendar;

/*
    3 计算10000天之后的年月日

    参考思路:
    先获取当前日历对象
    再调用add方法,指定DATE或者DAY_OF_MONTH,添加10000天
    再获取日历的年,月,日

 */
public class Test3 {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, 10000);


        System.out.println(cal.get(Calendar.YEAR));
        System.out.println(cal.get(Calendar.MONTH));
        System.out.println(cal.get(Calendar.DAY_OF_MONTH));
    }
}

3.5 Math类

  • 概述 : Math包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。所提供的都是静态方法,可以直接调用

  • 常用方法 :

    public static int abs(int a)获取参数a的绝对值:
    public static double ceil(double a)向上取整
    public static double floor(double a)向下取整
    public static double pow(double a, double b)获取a的b次幂
    public static long round(double a)四舍五入取整

3.6 System类

  • System类包含几个有用的类字段和方法。 它不能被实例化

  • 常用方法 :

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

4 BigInteger类

4.1 概述

  • 概述 : java.math.BigInteger类是一个引用数据类型 , 可以用于计算一些大的整数 , 当超出基本数据类型数据范围的整数运算时就可以使用BigInteger了。

4.2 构造方法

  • 构造方法 : 可以将整数的字符串 . 转成BigInteger类型的对象

4.3 成员方法

  • 方法声明描述
    public BigInteger add (BigInteger value)超大整数加法运算
    public BigInteger subtract (BigInteger value)超大整数减法运算
    public BigInteger multiply (BigInteger value)超大整数乘法运算
    public BigInteger divide (BigInteger value)超大整数除法运算,除不尽取整数部分
java
package com.fan.api_demo.biginteger_demo;

import java.math.BigInteger;

/*
    构造方法 :
        BigInteger(String value)	可以将整数的字符串,转换为BigInteger对象
    成员方法 :
        public BigInteger add (BigInteger value)	    超大整数加法运算
        public BigInteger subtract (BigInteger value)	超大整数减法运算
        public BigInteger multiply (BigInteger value)	超大整数乘法运算
        public BigInteger divide (BigInteger value)	超大整数除法运算,除不尽取整数部分

 */
public class BigIntegerDemo {
    public static void main(String[] args) {
        // 获取大整数对象
        BigInteger bigInteger1 = new BigInteger("2147483648");
        // 获取大整数对象
        BigInteger bigInteger2 = new BigInteger("2");
        // public BigInteger add (BigInteger value)	    超大整数加法运算
        BigInteger add = bigInteger1.add(bigInteger2);
        System.out.println(add);

        System.out.println("=============");

        // public BigInteger subtract (BigInteger value)	超大整数减法运算
        BigInteger subtract = bigInteger1.subtract(bigInteger2);
        System.out.println(subtract);

        System.out.println("=============");

        // public BigInteger multiply (BigInteger value)	超大整数乘法运算
        BigInteger multiply = bigInteger1.multiply(bigInteger2);
        System.out.println(multiply);

        System.out.println("=============");
        // public BigInteger divide (BigInteger value)	超大整数除法运算,除不尽取整数部分
        BigInteger divide = bigInteger1.divide(bigInteger2);
        System.out.println(divide);
    }
}

5 BigDecimal类

5.1 概述

  • 概述 : java.math.BigDecimal可以对大浮点数进行运算,保证运算的准确性。float,double 他们在存储及运算的时候,会导致数据精度的丢失。如果要保证运算的准确性,就需要使用BigDecimal。

5.2 构造方法

  • 构造方法 :
    • public BigDecimal(String val) : 将 BigDecimal 的字符串表示形式转换为 BigDecimal

5.3 成员方法

  • 成员方法 :

    • 方法声明描述
      public BigDecimal add(BigDecimal value)加法运算
      public BigDecimal subtract(BigDecimal value)减法运算
      public BigDecimal multiply(BigDecimal value)乘法运算
      public BigDecimal divide(BigDecimal value)除法运算(除不尽会有异常)
      public BigDecimal divide(BigDecimal divisor, int roundingMode)除法运算(除不尽,使用该方法)参数说明:scale 精确位数,roundingMode取舍模式 BigDecimal.ROUND_HALF_UP 四舍五入 BigDecimal.ROUND_FLOOR 去尾法 BigDecimal.ROUND_UP 进一法
java
package com.fan.api_demo.bigdecimal_demo;

import java.math.BigDecimal;

/*
    构造方法 :
        public BigDecimal(String val)	将 BigDecimal 的字符串表示形式转换为 BigDecimal
    成员方法 :
        public BigDecimal add(BigDecimal value)	加法运算
        public BigDecimal subtract(BigDecimal value)	减法运算
        public BigDecimal multiply(BigDecimal value)	乘法运算
        public BigDecimal divide(BigDecimal value)	除法运算(除不尽会有异常)
        public BigDecimal divide(BigDecimal value, int scale, RoundingMode roundingMode)	除法运算(除不尽,使用该方法)
        参数说明:
        scale 精确位数,
        roundingMode取舍模式
                   BigDecimal.ROUND_HALF_UP 四舍五入
                   BigDecimal.ROUND_FLOOR 去尾法
                   BigDecimal.ROUND_UP  进一法
 */
public class BigDecimalDemo {
    public static void main(String[] args) {
        BigDecimal bigDecimal1 = new BigDecimal("0.1");
        BigDecimal bigDecimal2 = new BigDecimal("0.2");

        // public BigDecimal add(BigDecimal value)	加法运算
        BigDecimal add = bigDecimal1.add(bigDecimal2);
        System.out.println(add);

        System.out.println("=================");

        // public BigDecimal subtract(BigDecimal value)	减法运算
        BigDecimal subtract = bigDecimal1.subtract(bigDecimal2);
        System.out.println(subtract);

        System.out.println("=================");

        // public BigDecimal multiply(BigDecimal value)	乘法运算
        BigDecimal multiply = bigDecimal1.multiply(bigDecimal2);
        System.out.println(multiply);

        System.out.println("=================");

        // public BigDecimal divide(BigDecimal value)	除法运算(除不尽会有异常)
        // BigDecimal divide = bigDecimal1.divide(bigDecimal2);
        // System.out.println(divide);

        /*
            public BigDecimal divide(BigDecimal divisor, int roundingMode)	除法运算(除不尽,使用该方法)
            参数说明:
            scale 精确位数,
            roundingMode : 取舍模式
                       BigDecimal.ROUND_HALF_UP 四舍五入
                       BigDecimal.ROUND_FLOOR 去尾法
                       BigDecimal.ROUND_UP  进一法
        */

        // BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_HALF_UP);
        // BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_FLOOR);
        // BigDecimal divide = bigDecimal1.divide(bigDecimal2, 3, BigDecimal.ROUND_UP);
        // System.out.println(divide);

    }
}

6 Arrays类

6.1 概述

  • 概述 : java.util.Arrays是数组的工具类,里面有很多静态的方法用来对数组进行操作(如排序和搜索),还包含一个静态工厂,可以将数组转换为List集合(后面会讲到集合知识

6.2 构造方法

  • 构造方法 : private Arrays(){}

  • public static void sort(int[] a)按照数字顺序排列指定的数组
    public static String toString(int[] a)返回指定数组的内容的字符串表示形式
java
package com.fan.api_demo.arrays_demo;

import java.util.Arrays;
import java.util.Random;

/*
    1 随机生成10个[0,100]之间的整数,放到整数数组中,按照从小到大的顺序排序并打印元素内容。
 */
public class ArraysDemo {
    public static void main(String[] args) {
        // 创建数组
        int[] arr = new int[10];

        // 创建随机数对象
        Random r = new Random();

        // 采用随机数给数组的每一个元素赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = r.nextInt(101);
        }

        // 对数组进行排序
        Arrays.sort(arr);

        // 把数组转成指定格式的字符串
        System.out.println(Arrays.toString(arr));
    }
}

7 包装类

7.1 概述

  • 概述 :
    • Java中基本数据类型对应的引用数据类型

7.2 包装类的作用

  • 包装类的作用 :
    • 基本数据类型 , 没有变量 , 没有方法 , 包装类就是让基本数据类型拥有变量和属性 , 实现对象化交互
    • 基本数据类型和字符串之间的转换

7.3 基本数据类型和包装类对应

  • 基本数据类型和包装类的对应关系
    基本数据类型包装类型
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleDouble
    charCharacter
    booleanBoolean

7.4 自动装箱和自动拆箱

  • 自动转型和自动拆箱

    • 自动装箱和拆箱是JDK1.5开始的
    • 自动装箱 : 基本数据类型自动转成对应的包装类类型
    • 自动拆箱 : 包装类类型自动转成对应的基本数据类型
    java
    Integer i1 = 10;
    int i2 = i1;

7.5 基本数据类型和字符串之间的转换

  • 使用包装类, 对基本数据类型和字符串之间的转换

    • 在开发过程中数据在不同平台之间传输时都以字符串形式存在的,有些数据表示的是数值含义,如果要用于计算我们就需要将其转换基本数据类型.

    • 基本数据类型--> String

      • 直接在数值后加一个空字符串
      • 通过String类静态方法valueOf()
    • String --> 基本数据类型

      • public static byte parseByte(String s):将字符串参数转换为对应的byte基本类型。
        public static short parseShort(String s):将字符串参数转换为对应的short基本类型。
        public static int parseInt(String s):将字符串参数转换为对应的int基本类型。
        public static long parseLong(String s):将字符串参数转换为对应的long基本类型。
        public static float parseFloat(String s):将字符串参数转换为对应的float基本类型。
        public static double parseDouble(String s):将字符串参数转换为对应的double基本类型。
        public static boolean parseBoolean(String s):将字符串参数转换为对应的boolean基本类型。
  • 注意事项 :

    • 包装类对象的初始值为null(是一个对象)

    • Java中除了float和double的其他基本数据类型,都有常量池

      • 整数类型:[-128,127]值在常量池
      • 字符类型:[0,127]对应的字符在常量池
      • 布尔类型:true,false在常量池
    • 在常量池中的数据 , 会进行共享使用 , 不在常量池中的数据会创建一个新的对象

8 String类的常用方法

8.1 常用方法

image-20210404212729376

java
package com.fan.api_demo.string_demo;

/*
    已知字符串,完成需求
    String str = "I Love Java, I Love Heima";
    判断是否存在  “Java”
    判断是否以Heima字符串结尾
    判断是否以Java开头
    判断 Java在字符串中的第一次出现位置
    判断  itcast 所在的位置

 */
public class Test {
    public static void main(String[] args) {
        String str = "I Love Java, I Love Heima";

        // 判断是否存在  “Java”
        System.out.println(str.contains("Java"));// true

        // 判断是否以Heima字符串结尾
        System.out.println(str.endsWith("Heima"));// true

        // 判断是否以Java开头
        System.out.println(str.startsWith("Java"));// false

        // 判断 Java在字符串中的第一次出现位置
        System.out.println(str.indexOf("Java"));// 7

        // 判断  itcast 所在的位置
        System.out.println(str.indexOf("itcast"));// -1
    }
}
java
package com.fan.api_demo.string_demo;

/*
    已知字符串,完成右侧需求
    String str = "I Love Java, I Love Heima";
    需求:
    1.将所有 Love 替换为 Like ,打印替换后的新字符串
    2.截取字符串 "I Love Heima"
    3.截取字符串 "Java"

 */
public class Test2 {
    public static void main(String[] args) {
        String str = "I Love Java, I Love Heima";

        // 1.将所有 Love 替换为 Like ,打印替换后的新字符串
        System.out.println(str.replace("Love", "Like"));
        // 2.截取字符串 "I Love Heima"
        System.out.println(str.substring(13));
        // 3.截取字符串 "Java"
        System.out.println(str.substring(7 , 11));

    }
}
java
package com.fan.api_demo.string_demo;

/*
    已知字符串,完成右侧需求
    String str = "I Love Java, I Love Heima";
    需求:
    1 计算字符 a 出现的次数(要求使用toCharArray)
    2 计算字符 a 出现的次数(要求使用charAt)
    3 将字符串中所有英文字母变成小写
    4 将字符串中所有英文字母变成大写
 */
public class Test3 {
    public static void main(String[] args) {
        String str = "I Love Java, I Love Heima";

//        1 计算字符 a 出现的次数(要求使用toCharArray)
        int count1 = 0;
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == 'a') {
                count1++;
            }
        }
        System.out.println("字符a出现了" + count1 + "次");


//        2 计算字符 a 出现的次数(要求使用charAt)
        int count2 = 0;
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if(ch == 'a'){
                count2++;
            }
        }
        System.out.println("字符a出现了" + count2 + "次");

//        3 将字符串中所有英文字母变成小写
        String s1 = str.toLowerCase();
        System.out.println(s1);

//        4 将字符串中所有英文字母变成大写
        String s2 = str.toUpperCase();
        System.out.println(s2);
    }
}

9 正则表达式

9.1 概述 :

  • 正则表达式通常用来校验,检查字符串是否符合规则的

9.2 体验正则表达式

java
package com.fan.regex_demo;

import java.util.Scanner;

/*
    设计程序让用户输入一个QQ号码,验证QQ号的合法性:
    1. QQ号码必须是5--15位长度
    2. 而且首位不能为0
    3. 而且必须全部是数字

 */
public class Test1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.println("请输入您的qq号码:");
        String qq = sc.nextLine();

        System.out.println(checkQQ2(qq));

    }

    private static boolean checkQQ(String qq) {
//        1. QQ号码必须是5--15位长度
        if (qq.length() < 5 || qq.length() > 15) {
            return false;
        }
//       2 . 而且首位不能为0
        if (qq.charAt(0) == '0') {
            return false;
        }

//        2. 而且必须全部是数字
        for (int i = 0; i < qq.length(); i++) {
            char ch = qq.charAt(i);
            if (ch < '0' || ch > '9') {
                return false;
            }
        }

        return true;
    }

    // 正则表达式改进
    private static boolean checkQQ2(String qq) {
        return qq.matches("[1-9][0-9]{4,14}");
    }
}

6.3 正则表达式的语法

  • boolean matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false
    • boolean matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false
  • 字符类
    • [abc] :代表a或者b,或者c字符中的一个。
    • [^abc]:代表除a,b,c以外的任何字符。
    • [a-z] :代表a-z的所有小写字符中的一个。
    • [A-Z] :代表A-Z的所有大写字符中的一个。
    • [0-9] :代表0-9之间的某一个数字字符。
    • [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
    • [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符
java
package com.fan.regex_demo;
/*
    字符类 : 方括号被用于指定字符
    [abc] :代表a或者b,或者c字符中的一个。
    [^abc]:代表除a,b,c以外的任何字符。
    [a-z] :代表a-z的所有小写字符中的一个。
    [A-Z] :代表A-Z的所有大写字符中的一个。
    [0-9] :代表0-9之间的某一个数字字符。
    [a-zA-Z0-9]:代表a-z或者A-Z或者0-9之间的任意一个字符。
    [a-dm-p]:a 到 d 或 m 到 p之间的任意一个字符

    需求 :
    1 验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符
    2 验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符
    3 验证str是否a-z的任何一个小写字符开头,后跟ad
    4 验证str是否以a-d或者m-p之间某个字符开头,后跟ad
    注意: boolean  matches(正则表达式) :如果匹配正则表达式就返回true,否则返回false
 */
public class RegexDemo {
    public static void main(String[] args) {
//        1 验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符
        System.out.println("had".matches("h[aeiou]d"));

//        2 验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符
        System.out.println("hwd".matches("h[^aeiou]d"));

//        3 验证str是否a-z的任何一个小写字符开头,后跟ad
        System.out.println("aad".matches("[a-z]ad"));

//        4 验证str是否以a-d或者m-p之间某个字符开头,后跟ad
        System.out.println("bad".matches("[a-dm-p]ad"));

    }
}
  • 逻辑运算符
    • && :并且
    • | :或者
java
package com.fan.regex_demo;
/*
    逻辑运算符 :
        1 && : 并且
        2 |  : 或者

    需求 :
        1 要求字符串是除a、e、i、o、u外的其它小写字符开头,后跟ad
        2 要求字符串是aeiou中的某个字符开头,后跟ad
 */
public class RegexDemo2 {
    public static void main(String[] args) {
//        1 要求字符串是除a、e、i、o、u外的其它小写字符开头,后跟ad
        System.out.println("vad".matches("[a-z&&[^aeiou]]ad"));
//        2 要求字符串是aeiou中的某个字符开头,后跟ad
        System.out.println("aad".matches("[a|e|i|o|u]ad"));
    }
}
  • 预定义字符类
    • "." : 匹配任何字符。
    • "\d":任何数字[0-9]的简写;
    • "\D":任何非数字[^0-9]的简写;
    • "\s" : 空白字符:[ \t\n\x0B\f\r] 的简写
    • "\S" : 非空白字符:[^\s] 的简写
    • "\w" :单词字符:[a-zA-Z_0-9]的简写
    • "\W":非单词字符:[^\w]
java
package com.fan.regex_demo;
/*
    预定义字符 : 简化字符类的书写

    "."  :匹配任何字符。
    "\d" :任何数字[0-9]的简写
    "\D" :任何非数字[^0-9]的简写
    "\s" :空白字符:[\t\n\x0B\f\r] 的简写
    "\S" :非空白字符:[^\s] 的简写
    "\w" :单词字符:[a-zA-Z_0-9]的简写
    "\W" :非单词字符:[^\w]

    需求 :
       1 验证str是否3位数字
       2 验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字
       3 验证字符串是否以h开头,以d结尾,中间是任何字符

 */
public class RegexDemo3 {
    public static void main(String[] args) {
//        1 验证str是否3位数字
        System.out.println("123".matches("\\d\\d\\d"));

//        2 验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字 )
        System.out.println("15188888888".matches("1[358]\\d\\d\\d\\d\\d\\d\\d\\d\\d"));

//        3 验证字符串是否以h开头,以d结尾,中间是任何字符
        System.out.println("had".matches("h.d"));
    }
}
  • 数量词
    • X? : 0次或1次
    • X* : 0次到多次
    • X+ : 1次或多次
    • X{n} : 恰好n次
    • X{n,} : 至少n次
    • X{n,m}: n到m次(n和m都是包含的)
java
package com.fan.regex_demo;

/*
    数量词 :
        - X?    : 0次或1次
        - X*    : 0次到多次
        - X+    : 1次或多次
        - X{n}  : 恰好n次
        - X{n,} : 至少n次
        - X{n,m}: n到m次(n和m都是包含的)

    需求 :
      1 验证str是否3位数字
      2 验证str是否是多位(大于等于1次)数字
      3 验证str是否是手机号 ( 1开头,第二位:3/5/8,剩下9位都是0-9的数字)
      4 验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0

 */
public class RegexDemo4 {
    public static void main(String[] args) {
//        1 验证str是否3位数字
        System.out.println("123".matches("\\d{3}"));

//        2 验证str是否是多位(大于等于1次)数字
        System.out.println("123456".matches("\\d+"));

//        3 验证str是否是手机号 ( 1开头,第二位:3/5/8,剩下9位都是0-9的数字)
        System.out.println("15188888888".matches("1[358]\\d{9}"));

//        4 验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0
        System.out.println("122103987".matches("[1-9]\\d{4,14}"));
    }
}
  • 分组括号 :
    • 将要重复使用的正则用小括号括起来,当做一个小组看待
java
package com.fan.regex_demo;
/*
    分组括号 : 将要重复使用的正则用小括号括起来,当做一个小组看待
    需求 :  window秘钥 , 分为5组,每组之间使用 - 隔开 , 每组由5位A-Z或者0-9的字符组成 , 最后一组没有 -
    举例 :
        xxxxx-xxxxx-xxxxx-xxxxx-xxxxx
        DG8FV-B9TKY-FRT9J-99899-XPQ4G
    分析:
        前四组其一  :DG8FV-    正则:[A-Z0-9]{5}-
        最后一组    :XPQ4G     正则:[A-Z0-9]{5}

    结果 : ([A-Z0-9]{5}-){4}[A-Z0-9]{5}

 */
public class RegexDemo5 {
    public static void main(String[] args) {
        System.out.println("DG8FV-B9TKY-FRT9J-99899-XPQ4G".matches("([A-Z0-9]{5}-){4}[A-Z0-9]{5}"));
    }
}
  • 字符串中常用含有正则表达式的方法
    • public String[] split ( String regex ) 可以将当前字符串中匹配regex正则表达式的符号作为"分隔符"来切割字符串。
    • public String replaceAll ( String regex , String newStr ) 可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。
java
package com.fan.regex_demo;

import java.util.Arrays;

/*

    1 字符串中常用含有正则表达式的方法
        public String[] split ( String regex ) 可以将当前字符串中匹配regex正则表达式的符号作为"分隔符"来切割字符串。
        public String replaceAll ( String regex , String newStr ) 可以将当前字符串中匹配regex正则表达式的字符串替换为newStr。

    需求:
        1 将以下字符串按照数字进行切割
        String str1 = "aa123bb234cc909dd";

        2 将下面字符串中的"数字"替换为"*“a
        String str2 = "我卡里有100000元,我告诉你卡的密码是123456,要保密哦";

 */
public class RegexDemo6 {
    public static void main(String[] args) {
        // 1 将以下字符串按照数字进行切割
        String str1 =  "aa123bb234cc909dd";
        String[] strs = str1.split("\\d+");
        System.out.println(Arrays.toString(strs));

        // 2 将下面字符串中的"数字"替换为"*“a
        String str2 = "我卡里有100000元,我告诉你卡的密码是123456,要保密哦";
        System.out.println(str2.replaceAll("\\d+" , "*"));
    }
}

Released under the MIT License.