Java学习-面向对象进阶

目录

1 static 

1.1 static修饰成员变量

1.2 static修饰成员方法

1.3 static注意事项

1.4 工具类

1.5 工具类的应用练习

1.6 代码块

1.6.1 代码块概述

1.6.2 代码块案例

1.7 单例模式

2 继承

2.1 继承概述

2.2 继承特点(面试可能用到)

2.3 方法重写

2.4 构造器特点

3 语法

3.1 包

3.2 权限修饰符

3.3 final

4 抽象类

5 接口

6 多态

6.1 概述

6.2 多态优势

6.3 多态引用类型转换

6.4 多态案例

7 内部类

7.1 概述

7.2 静态内部类(了解)

7.3 成员内部类(非静态内部类) (了解)

7.4 匿名内部类(重点)

7.4.1 概述

7.4.2 使用形式

7.4.3 案例

8 常用API

8.1 Object

8.1.1 Object概述

8.1.2 toString()

8.1.3 equals

8.1.4 Objects

8.2 StringBuilder

8.2.1 StringBuilder概述

8.2.2 常用方法

8.2.3 案例

8.3 Math、System、BigDecimal

8.3.1 Math类常用方法

8.3.2 System常用方法

8.3.3 BigDecimal


1 static 

1.1 static修饰成员变量

static是什么

  • static是静态的意思,可以修饰成员变量和成员方法。
  • static修饰成 员变量表示该成员变量只在内存中只存储一份,可以被共享访问、修改。
  • 比如某网站在线人数是所有人共享的数据,只有一份。
     

成员变量可以分为2类

  • 静态成员变量(有static修饰, 属于类,内存中加载一次) :常表示如在线人数信息、等需要被共享的信息,可以被共享访问。可以直接类名.静态成员变量进行访问。
  • 实例成员变量(无static修饰, 存在于每个对象中) :常表示姓名name、年龄age、等属于每个对象的信息。
     

演示一波:

package com.itzw.staticdemo;

public class Test01 {
    public static void main(String[] args) {
        //直接用类名调用
        System.out.println(User.onlineNumber);//121
        //也可以用对象,不过建议用类名
        User u = new User();
        u.onlineNumber++;
        System.out.println(u.onlineNumber);//122
        
    }
}


class User{
    public static int onlineNumber = 121;
    private String name;
}

1.2 static修饰成员方法

在之前构造方法时,经常看见有的方法加了static而有的没有,这是为啥呢,有什么区别呢?

成员方法的分类:

  • 静态成员方法(有static修饰, 归属于类) ,建议用类名访问,也可以用对象访问。
  • 实例成员方法(无static修饰, 归属于对象) ,只能用对象触发访问。
     

演示:

package com.itzw.staticdemo;

public class Student {
    private int age;
    private String name;
    //静态成员方法,归属于类,可以直接类.方法进行访问
    /**
     * 静态成员方法
     * @param age1
     * @param age2
     * @return
     */
    public static int getMax(int age1, int age2){
        return age1 > age2 ? age1 : age2;
    }

    /**
     * 实例成员方法
     */
    public void study(){
        System.out.println(name + "正在好好学习!!");
    }

    public static void main(String[] args) {
        //1.静态成员方法的调用,使用类名调用
        System.out.println(Student.getMax(10, 20));
        //同一个类中,访问静态方法,可以省略类,直接调用方法
        System.out.println(getMax(10, 9));

        //study();不能直接访问

        //2.实例成员方法的调用,使用对象调用
        Student s1 = new Student();
        s1.name = "王德发";
        s1.study();

        //3.静态成员方法的调用,使用对象调用,但不推荐
        System.out.println(s1.getMax(10, 40));
    }




}

那么问题来了,什么时候使用static呢

  • 表示对象自己的行为的,且方法中需要访问实例成员的,则该方法必须申明成实例方法。
  • 如果该方法是以执行一一个共用功能为目的,则可以申明成静态方法。
     

1.3 static注意事项

static访问注意事项:

  • 静态方法只能访问静态的成员,不可以直接访问实例成员。
  • 实例方法可以访问静态的成员,也可以访问实例成员。
  • 静态方法中是不可以出现this关键字的。
package com.itzw.staticdemo;

public class Test03 {

    //静态成员
    public static int onlineNumber = 13;
    public static void test01(){
        System.out.println("静态方法执行了。。。");
    }

    //实例成员
    private String name;
    public void test02(){
        System.out.println("实例方法执行了。。。");
    }

    //1.静态方法只能访问静态成员,不能直接访问实例成员
    public static void run(){
        //可以访问静态成员
        System.out.println(onlineNumber);
        test01();
        //无法访问实例成员
        //System.out.println(name);
    }

    //2.实例方法可以访问静态和实例成员
    public void go(){
        //访问实例成员
        System.out.println(name);
        test02();

        //访问静态方法
        System.out.println(onlineNumber);
        test01();
    }

    //3.静态方法不能使用this
    public static void jump(){
        //System.out.println(this);//因为this代表的是当前对象,而静态方法可以用类调用
    }
}


1.4 工具类

工具类是什么?

  • 类中都是一一些静态方法,每个方法都是以完成一个共用的功能为目的, 这个类用来给系统开发人员共同使用的。

使用工具类的好处:

  • 是调用方便,二是提高了代码复用(一次编写,处处可用)

工具类定义时的其他要求:

  • 由于工具里面都是静态方法,直接用类名即可访问,因此,工具类无需创建对象,建议将工具类的构造器进行私有。

举个例子:

比如开发验证码,登录时候需要验证码,当出现异常时,需要用户输入验证码确认,这时又要使用验证码功能,使用工具类就可以只写一次验证码功能,可多次使用。

演示:

package com.itzw.static_util;

import java.util.Random;

public class ItZwUtil {

    /**
     * 注意;由于构造器无需创建对象,将构造器私有化显得更专业
     */
    private ItZwUtil(){
    }
    //静态方法完成验证码功能,可以共享
    public static String createVerifyCode(int n){
        String code = "";
        String data = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random r = new Random();
        for (int i = 0; i < n; i++) {
            int index = r.nextInt(data.length());
            code += data.charAt(index);
        }
        return code;
    }
}
package com.itzw.static_util;

public class Login {
    public static void main(String[] args) {
        //登陆时使用验证码
        System.out.println(ItZwUtil.createVerifyCode(5));
    }
}
package com.itzw.static_util;

public class Check {
    public static void main(String[] args) {
        //检查时使用验证码
        System.out.println(ItZwUtil.createVerifyCode(5));
        //依然可以创建对象,但我不想创建对象,可以将构造器私有化
        /*ItZwUtil i = new ItZwUtil();
        System.out.println(i.createVerifyCode(6));*/
    }
}

1.5 工具类的应用练习

需求:在实际开发中,经常会遇到一些数组使用的工具类。请按照如下要求编写-一个数组的工具类: ArraysUtils

  • 我们知道数组对象直接输出的时候是输出对象的地址的,而项目中很多地方都需要返回数组的内容,请在ArraysUtils中提供一个工具类方法toString,用于返回整数数组的内容,返回的字符串格式如: [10, 20, 50, 34,100] ( 只考虑整数数组,且只考虑一维数组)
  • 经常需要统计平均值,平均值为去掉最低分和最高分后的分值,请提供这样一个工具方法getAerage, 用于返回平均分。(只考 虑浮点型数组,且只考虑一维数组)
  • 定义一个测试类TestDemo,调用该工具类的工具方法,并返回结果。

代码如下:

package com.itzw.static_test;

public class ArraysUtils {

    /**
     * 私有构造器
     */
    private ArraysUtils(){
    }

    /**
     * 将数组转换为字符串
     * @param arr
     * @return
     */
    public static String toString(int[] arr){
        if (arr == null){
            return null;
        }
        String array="[";
        for (int i = 0; i < arr.length; i++) {
            if (i == arr.length - 1){
                array += arr[i];
            }else {
                array += arr[i] + ",";
            }

        }
        return array + "]";
    }

    /**
     * 计算数组中的平均值(去掉最大值和最小值)
     * @param arr
     * @return
     */
    public static double getAverage(double[] arr){
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j <arr.length - i - 1 ; j++) {
                if (arr[j] > arr[j+1]){
                    double temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        double sum = 0;
        for (int i = 1; i < arr.length - 1; i++) {
            sum += arr[i];
        }
        return sum / (arr.length - 2);
    }

}
package com.itzw.static_test;

public class TestDemo {
    public static void main(String[] args) {
        int[] arr = {1,2,6,9,21,33};
        System.out.println(ArraysUtils.toString(arr));

        double[] arr2 = {5,8,1,19,34,7};
        System.out.println(ArraysUtils.getAverage(arr2));
    }
}

1.6 代码块

1.6.1 代码块概述

  • 代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类) ,定义在类中方法外。
  • 在Java类下,使用{}括起来的代码被称为代码块。

代码块分为

  • 静态代码块:

        格式: static{}
        特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
        使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。

  • 构造代码块 (了解,见的少) :

        格式: {}
        特点:每次创建对象,调用构造器执行时,都会执行该代码块中的代码,并且在构造器执行前执行。
        使用场景:初始化实例资源。

静态代码块如下:

package com.itzw.static_code;

public class Test01 {
    public static String schoolName;
    /*
    静态代码块,有static修饰,属于类,与类一起优先加载一次,自动触发执行。
    作用:可用于初始化静态资源
     */
    static {
        System.out.println("静态代码块执行了。。。");
        //初始化schoolName
        schoolName = "马邦德实验中心小学";
    }

    public static void main(String[] args) {
        System.out.println("main方法执行了。。。");
    }
}

实例代码块如下(使用极少):

package com.itzw.static_code;

public class Test02 {

    private String name;

    public Test02(){
        System.out.println("无参构造执行了。。。");
    }

    /*
    实例代码块:无static修饰,每次构建对象时触发一次
    作用:初始化实例资源
     */
    {
        name = "马邦德";
        System.out.println("实例代码块执行....");
    }

    public static void main(String[] args) {
        //实例代码块先执行,对比静态代码块
        Test02 t1 = new Test02();
        System.out.println(t1.name);
        Test02 t2 = new Test02();
        System.out.println(t2.name);
    }

}

1.6.2 代码块案例

斗地主游戏

需求:

  • 在启动游戏房间的时候,应该提前准备好54张牌,后续才可以直接使用这些牌数据。

分析:

  1. 该房间只需要一副牌。
  2. 定义-个静态的ArrayList集合存储54张牌对象,静态的集合只会加载一份。
  3. 在启动游戏房间前,应该将54张牌初始化好
  4. 当系统启动的同时需要准备好54张牌数据,此时可以用静态代码块完成。
     
package com.itzw.static_code;

import java.util.ArrayList;

public class Test03 {
    /**
     * 定义一个静态集合,这样集合只加载一次,因为一个房间只需要一副牌
     */
    public static ArrayList<String> cards = new ArrayList<>();

    static {
        //定义牌的大小
        String[] size = {"A","1","2","3","4","5","6","7","8","9","10,","J","Q","K"};
        //定义牌的花色
        String[] color = {"♥","♦","♠","♣"};
        //定义每个牌
        String card="";
        //将大小和花色匹配
        for (int i = 0; i < size.length; i++) {
            for (int j = 0; j < color.length; j++) {
                card = size[i] + color[j];
                cards.add(card);
            }
        }
        //加入大小王
        cards.add("大🃏");
        cards.add("小🃏");
    }

    public static void main(String[] args) {
        //初始化54张牌
        System.out.println(cards);
    }
}

这时候你可能有疑问,static代码块中的内容放入main方法不也是一样。确实,但是放入static中只会执行一次,更重要的是,这样写极其的优雅和专业,别人一看就懂。优雅永不过时。

1.7 单例模式

什么是设计模式(Design pattern )

  • 开发中经常遇到- - -些问题,一个问题通常有n种解法的,但其中肯定有-种解法是最优的,这个最优的解法被人总结出来了,称之为设计模式。
  • 设计模式有20多种,对应20多种软件开发中会遇到的问题。
  • 学设计模式主要是学2点:

        第一:这种模式用来解决什么问题。
        第二:遇到这种问题了,该模式是怎么写的,他是如何解决这个问题的。

单例模式

  • 可以保证系统中, 应用该模式的这个类永远只有一个实例, 即一个类永远只能创建一个对象。
  • 例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
     

饿汉单例设计模式

  • 在用类获取对象的时候,对象已经提前为你创建好了。

设计步骤:

  • 定义一个类,把构造器私有,防止别人继续创建对象。
  • 定义一个静态变量存储一个对象。
     
package com.itzw.singleinstance;

public class Demo01 {
    public static void main(String[] args) {
        //无法创建新的对象
        //SingleInstance singleInstance = new SingleInstance();

        SingleInstance s1 = SingleInstance.singleInstance;
        SingleInstance s2 = SingleInstance.singleInstance;
        //两个对象是一样的,这样就能保证有且只有一个对象
        System.out.println(s1 == s2);
    }
}


class SingleInstance {

    //定义一个静态对象,只加载一次
    public static SingleInstance singleInstance = new SingleInstance();

    private SingleInstance(){
    }
}

懒汉单例设计模式

  • 在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。

设计步骤:

  • 定义一个类,把构造器私有。
  • 定义一个静态变量存储一个对象。
  • 提供一个返回单例对象的方法。
     
package com.itzw.singleinstance;

public class Demo02 {
    public static void main(String[] args) {
        SingleInstance2 s1 = SingleInstance2.getInstance();
        SingleInstance2 s2 = SingleInstance2.getInstance();
        System.out.println(s1 == s2);
    }
}

class SingleInstance2{

    /**
     * 私有化构造器
     */
    private SingleInstance2(){
    }

    private static SingleInstance2 instance;//null

    public static SingleInstance2 getInstance(){
        if (instance == null){
            instance = new SingleInstance2();
            return instance;
        }
        return instance;
    }
}

2 继承

2.1 继承概述

  • Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另-个类建立起父子关系。

        public class Student extends People { }

  • Student称为子类(派生类) , People称为父类(基类或超类)。
  • 作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了

举个栗子:

package com.itzw.extends_demo;

public class Demo01 {
    public static void main(String[] args) {
        Student s = new Student();
        //Student类中没有run方法,但是父类有就可以使用
        s.run();//人会跑。。。
    }
}

class People{
    public void run(){
        System.out.println("人会跑。。。");
    }
}

class Student extends People{

}

继承的好处:

  • 提高代码复用性,减少代码冗余,增强类的功能扩展性。
     

案例:

需求:
在传马邦德教育的tlias教学资源管理系统中,存在学生、老师角色会进入系统。
分析:

  • 学生信息和行为(名称,年龄,所在班级,查看课表,填写听课反馈)
  • 老师信息和行为(名称, 年龄,部门名称,查看课表,发布问题)
  • 定义角色类作为父类包含属性(名称,年龄) ,行为(查看课表)
  • 定义子类:学生类包含属性(所在班级),行为(填写听课反馈)
  • 定义子类:老师类包含属性(部门名称),行为(发布问题)
     

代码如下:

package com.itzw.extends_demo;

public class Demo02 {
    public static void main(String[] args) {
        Student s1 = new Student("王德发",18,"计科1801");
        Student s2 = new Student("厚礼蟹",19,"计科1802");

        Teacher t1 = new Teacher("马邦德",45,"信息工程学院");
        Teacher t2 = new Teacher("张麻子",46,"麻匪部门");

        s1.feedback("老师讲的太水,我的评价是,不行");
        s2.feedback(("非常的好,睡的很舒服。"));
        s1.showSchedule();
        s2.showSchedule();

        t1.question("简简单单敲个2万行代码!!");
        t2.question("今晚抢劫,村口集合!!");
        t1.showSchedule();
        t2.showSchedule();
    }
}


//父类
class People{
    private String name;
    private int age;

    public People() {
    }

    public People(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;
    }

    public void showSchedule(){
        System.out.println(this.getName() + "正在查看课表。。。");
    }
}

//学生类
class Student extends People{
    private String clase;//班级

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

    public Student() {
    }

    public String getClase() {
        return clase;
    }

    public void setClase(String clase) {
        this.clase = clase;
    }

    /**
     * 填写听课反馈
     */
    public void feedback(String f){
        System.out.println(this.getName() + "的听课反馈为:" + f);
    }
}

class Teacher extends People{
    String department;//部门

    public Teacher(String name, int age, String department) {
        super(name, age);
        this.department = department;
    }

    public Teacher(){
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    /**
     * 发布问题
     * @param ques 问题内容
     */
    public void question(String ques){
        System.out.println(this.getName() + "发布的问题为:" + ques);
    }
}

2.2 继承特点(面试可能用到)

1、子类是否可以继承父类的构造器?

  • 不可以的,子类有自己的构造器,父类构造器用于初始化父类对象。

2、子类是否可以继承父类的私有成员?

  • 可以的,只是不能直接访问。比如张三他爸有个保险柜继承给了张三,但是密码不知道就无法打开,但确实是继承了。

3、子类是否可以继承父类的静态成员?

  • 有争议的知识点。
  • 子类可以直接使用父类的静态成员(共享)
  • 但个人认为:子类不能继承父类的静态成员。 (共享并非继承)
     

4、Java不支持多继承

  • 为何不支持多继承:因为假如一个类继承了两个类,这两个类都有一个方法为学习,一个是学习数学一个是学习语文,这就会冲突,有二义性。可以直接理解为,一个人不能有两个爸爸。

5、Java支持多重继承

  • 子类A继承父类B,父类B可以继承父类C。
  • 当B、C类有同一个方法时,会继承B类的,就近原则。
     

6、0bject特点:

  • Java中所有类,要么直接继承了Object ,要么默认继承了Object ,要么间接继承了Object, Object是祖宗类。

7、在子类方法中访问成员(成员变量、成员方法)满足:就近原则

  • 先子类局部范围找
  • 然后子类成员范围找
  • 然后父类成员范围找,如果父类范围还没有找到则报错。

如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?

  • 可以通过super关键字,指定访问父类的成员。

        格式: super.父类成员变量/父类成员方法

演示一波:

package com.itzw.extends_demo;

public class Demo03 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        //就近原则,访问的都是Dog类中的name和run方法
        dog.run();
        System.out.println(dog.name);

        dog.showName();
    }
}

class Animal{
    String name = "动物名";

    public void run(){
        System.out.println("动物在跑。。。");
    }
}

class Dog extends Animal{
    String name = "狗名";

    public void run(){
        System.out.println("狗狗在跑,。。");
    }

    public void showName(){
        String name = "局部名";
        System.out.println(name);//就近访问方法里的name
        System.out.println(this.name);//可以用this访问当前类名
        System.out.println(super.name);//可以用super访问当父类名
        run();
        super.run();
    }

}

2.3 方法重写

什么是方法重写?

  • 在继承体系中,子类出现了和父类中一-模-样的方法声明,我们就称子类这个方法是重写的方法。

方法重写的应用场景

  • 当子类需要父类的功能,但父类的该功能不完全满足自己的需求时。
  • 子类 可以重写父类中的方法。
     

案例演示:

  • 旧手机的功能只能是基本的打电话,发信息。
  • 新手机的功能需要能够:基本的打电话下支持视频通话。基本的发信息下支持发送语音和图片。
     
package com.itzw.extends_override;

public class Test01 {
    public static void main(String[] args) {
        NewPhone boluo = new NewPhone();//美国有苹果,中国有菠萝,菠萝手机帧tmd好
        boluo.call();
        boluo.sendMes();
    }
}


class NewPhone extends Phone{
    public void call(){
        super.call();
        System.out.println("打视频。。。");
    }

    public void sendMes(){
        super.sendMes();
        System.out.println("发送语音和图片。。。");
    }
}

class Phone{
    public void call(){
        System.out.println("打电话。。。");
    }

    public void sendMes(){
        System.out.println("发送短信。。。");
    }
}

@Override重写注解

  • @Override是放在重写后的方法上,作为重写是否正确的校验注解。
  • 加上该注解后如果重写错误,编译阶段会出现错误提示。
  • 建议重写方法都加@Override注解,代码安全,优雅!

方法重写注意事项和要求:

  • 重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。
  • 私有方法不能被重写。
  • 子类重写父类方法时, 访问权限必须大于或者等于父类(暂时了解:缺省< protected < public)
  • 子类不能重写父类的静态方法,如果重写会报错的。
     

比如方法名不一致就会报错

 重写静态方法会报错 

私有方法不能被重写:

 由此可见,Override的作用很大,不仅美观优雅一眼看出这是重写的方法,而且可以提示你是否写的正确。

2.4 构造器特点

子类继承父类后构造器的特点:

  • 子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己。

为什么?

  • 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
  • 子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。

怎么调用父类构造器的?

  • 子类构造器的第一行语句 默认都是: super(), 不写也存在。
  • package com.itzw.extends_demo;
    
    public class Deno04 {
        public static void main(String[] args) {
            Test01 t = new Test01();
            Test01 t2 = new Test01(1);
            /*
            输出结果:
            父类无参构造执行了。。。
            子类无参构造执行了。。。
            父类无参构造执行了。。。
            子类有参构造执行了
             */
        }
    }
    
    class Test{
        public Test(){
            System.out.println("父类无参构造执行了。。。");
        }
    }
    
    class Test01 extends Test{
        public Test01(){
            super();
            System.out.println("子类无参构造执行了。。。");
        }
    
        public  Test01(int a){
            super();
            System.out.println("子类有参构造执行了");
        }
    }
    

super调用父类有参数构造器的作用:

  • 初始化继承自父类的数据。

如果父类中没有无参数构造器,只有有参构造器,会出现什么现象呢?

  • 会报错。因为子类默认是调用父类无参构造器的。
  • 所以还是建议直接写好无参构造,你用不用是一回事,我都写上为以后方便。
package com.itzw.extends_demo;

public class Deno04 {
    public static void main(String[] args) {
        Test01 t = new Test01();
        Test01 t2 = new Test01(1,2);
        
    }
}

class Test{
    public Test(){
        System.out.println("父类无参构造执行了。。。");
    }

    public Test(int a,int b){
        System.out.println("父类有参构造执行了...");
    }
}

class Test01 extends Test{
    public Test01(){
        super();
        System.out.println("子类无参构造执行了。。。");
    }

    public Test01(int a,int b){
        super(a,b);
    }
}

如上,在继承父类时,若子类写有参构造,可用super完成继承,当然这部分不需要手写,idea可以自动生成,非常的人性。

this(...)和super(..)使用注意点:

  • 子类通过 this ...去调用本类的其他构造器,本类其他构造器会通过super去手动调用父类的构造器,最终还是会调用父类构造器的。
  • 注意: this(..) super(..)都只能放在构造器的第一 行,所以二者不能共存在同一个构造器中。

this()的用法:假如有业务需要填写姓名和学校,但不填学校会默认一个,此时可以用this()

package com.itzw.extends_this;

public class Test {
    public static void main(String[] args) {
        Student s1 = new Student("张麻子","麻匪学校");
        s1.showInfo();
        //但我若不想填学校,会有默认值
        Student s2 = new Student("王德发");
        s2.showInfo();
    }
}


class Student{
    String name;
    String schoolName;

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

    public Student(String name){
        this(name,"马邦德学院");
    }

    public void showInfo(){
        System.out.println("姓名:" + name);
        System.out.println("学校:" + schoolName);
    }
}

3 语法

3.1 包

什么是包?

  • 包是用来分别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
  • 建包的语法格式: package 公司域名倒写.技术名称。报名建议全部英文小写,且具备意义。
  • 建包语句必须在第一行,一般IDEA工具会帮助创建

导包:

  • 相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!导包格式: import 包名.类名; 
  • 如果一个类中使用不同类但相同名,只能导入一个包,另一个要写全名。

3.2 权限修饰符

什么是权限修饰符?

  • 权限修饰符:是用来控制-一个成员能够被访问的范围。
  • 可以修饰成员变量,方法,构造器,内部类,不同权限修饰符修饰的成员能够被访问的范围将受到限制。

权限修饰符的分类和具体作用范围:

  • 权限修饰符:有四种作用范围由小到大( private ->缺省-> protected - > public )

学完权限修饰符需要具备如下能力

  • 能够识别别人定义的成员的访问范围。
  • 自己定义成员(方法,成员变量,构造器等) -般需要满足如下要求:
  1. 成员变量一般私有
  2. 方法一般公开
  3. 如果该成员只希望本类访问,使用private修饰。
  4. 如果该成员只希望本类,同-个包下的其他类和子类访问,使用protected修饰。

 演示:

先创建一个类包含四个类型修饰的函数,本类都可以访问

package com.itzw.d1_modify;

public class Father {

    /*
    private修饰,只能本类访问
     */
    private void privateMethod(){
        System.out.println("---privateMethod---");
    }

    /*
    缺省修饰,本类、同包下可以访问
    */
    void method(){
        System.out.println("---method---");
    }

    /*
    protected修饰,本类、同包、不同包但是子类可以访问
    */
    protected void protectedMethod(){
        System.out.println("---protectedMethod---");
    }

    /*
    public修饰,本类、同包、不同包都可以可以访问
    */
    public void publicMethod(){
        System.out.println("---publicMethod---");
    }

    public static void main(String[] args) {
        Father f = new Father();
        //同类下都可以访问
        f.privateMethod();
        f.method();
        f.protectedMethod();
        f.publicMethod();
    }
}

同包下:

Father f = new Father();
        //f.privateMethod();//报错
        //除了private修饰都可以访问
        f.method();
        f.protectedMethod();
        f.publicMethod();

不同包且不继承:

Father f = new Father();
        //.privateMethod();//报错
        //f.method();//报错
        //f.protectedMethod();//报错

        //不同包且不继承只能访问public修饰的,
        f.publicMethod();

不同包且继承:

        Son s = new Son();
        //s.privateMethod();
        //s.method();

        //不同包但是继承可以访问protected和public
        s.protectedMethod();
        s.publicMethod();

3.3 final

final的作用

  • final 关键字是最终的意思,可以修饰(类、方法、变量)
  • 修饰类:表明该类是最终类,不能被继承。
  • 修饰方法: 表明该方法是最终方法,不能被重写。
  • 修饰变量:表示该变量第一次赋值后, 不能再次被赋值(有且仅能被赋值一次)。 .
     

final修饰变量的注意

  • final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
  • final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
     

4 抽象类

5 接口

6 多态

6.1 概述

什么是多态?

  • 同类型的对象,执行同一一个行为,会表现出不同的行为特征。

多态的常见形式
父类类型  对象名称= new  子类构造器;
接口  对象名称= new  实现类构造器;

多态中成员访问特点

  • 方法调用:编译看左边,运行看右边。
  • 变量调用:编译看左边,运行也看左边。(多态侧重行为多态)

多态的前提

  • 有继承/实现关系; 有父类引用指向子类对象;有方法重写。

6.2 多态优势

优势

  • 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。

Animal a = new Dog();
a.run(); //后续业务行为随对象而变,后续代码无需修改

  • 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。

多态下会产生的一个问题:

  • 多态下不能使用子类的独有功能
package com.itzw.d1_polymorphism;

public class Test {
    public static void main(String[] args) {

        //左边都是Animal,因为Dog和Wugui都继承了Animal
        Animal a1 = new Dog();
        a1.run();
        //变量调用运行看左边,编译看左边,所以输出小动物
        System.out.println(a1.name);
        Animal a2 = new Wugui();
        a2.run();
        //变量调用运行看左边,编译看左边,所以输出小动物
        System.out.println(a2.name);
    }
}

abstract class Animal{
    public String name = "小动物";
    public abstract void run();
}

class Dog extends Animal{
    public String name = "小狗狗";
    @Override
    public void run() {
        System.out.println("狗跑得很快。。。");
    }
}

class Wugui extends Animal{
    public String name = "小乌龟";
    @Override
    public void run() {
        System.out.println("乌龟跑的很慢。。。");
    }
}

6.3 多态引用类型转换

自动类型转换(从子到父):子类对象赋值给父类类型的变量指向。
强制类型转换吗(从父到子)

  • 此时必须进行强制类型转换: 子类对象变量= (子类)父类类型的变量
  • 作用: 可以解决多态下的劣势,可以实现调用子类独有的功能。
  • 注意: 如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException

Animal t = new Tortoise();
Dog d = (Dog)t; //出现异常ClassCastException

Java建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换

变量名  instanceof  真实类型

判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true, 反之。
 

package com.itzw.d1_polymorphism_convert;

public class Test {
    public static void main(String[] args) {
        Animal a1 = new Wugui();
        //此时a1无法调用Wugui类中的lay方法
        //采用强制类型转换
        /*Wugui w = (Wugui) a1;
        w.lay();*/

        //但是有可能转换的不是乌龟,编译器依然不会报错,但运行时会报错,如下:
        //Dog d = (Dog) a1;

        //为了防止上面错误的出现,利用instance先判断是否转换的正确
        if (a1 instanceof Wugui){
            Wugui w = (Wugui) a1;
            w.lay();
        }

    }
}

abstract class Animal{
    public abstract void run();
}

class Dog extends Animal{

    @Override
    public void run() {
        System.out.println("狗跑的很快");
    }
}

class Wugui extends Animal{

    @Override
    public void run() {
        System.out.println("乌龟跑的很慢。。");
    }

    //乌龟中特有的方法
    public void lay(){
        System.out.println("乌龟下蛋,下蛋乌龟,乌龟中的战斗机,欧耶!");
    }
}

6.4 多态案例

需求:

  • 使用面向对象编程模拟:设计一个电脑对象,可以安装2个USB设备
  • 鼠标:被安装时可以完成接入、调用点击功能、拔出功能。
  • 键盘:被安装时可以完成接入、调用打字功能、拔出功能。

分析

  1. 定义一个USB的接口(申明USB设备的规范必须是:可以接入和拔出)。
  2. 提供2个USB实现类代表鼠标和键盘,让其实现USB接口,并分别定义独有功能。
  3. 创建电脑对象,创建2个USB实现类对象,分别安装到电脑中并触发功能的执行。
     

首先创建USB接口

public interface USB {

    void connect();

    void unconnect();
}

然后创建鼠标类实现接口,并有独有的方法

package com.itzw.d3_polymorphism_test;

public class Mouse implements USB{
    private String name;

    public Mouse() {
    }

    public Mouse(String name) {
        this.name = name;
    }

    /**
     * 独有方法
     */
    public void click(){
        System.out.println(name + "正在疯狂点击。。。。");
    }

    @Override
    public void connect() {
        System.out.println(name + "成功连接电脑。。。");
    }

    @Override
    public void unconnect() {
        System.out.println(name + "成功从电脑拔出。。。");
    }

    public String getName() {
        return name;
    }

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

然后创建键盘类实现接口,并有独有的方法

package com.itzw.d3_polymorphism_test;

public class KeyBoard implements USB{

    private String name;

    public KeyBoard() {
    }

    public KeyBoard(String name) {
        this.name = name;
    }

    /**
     * 独有方法
     */
    public void keyDown(){
        System.out.println(name + "正在打字。。。。");
    }

    @Override
    public void connect() {
        System.out.println(name + "成功连接电脑。。。");
    }

    @Override
    public void unconnect() {
        System.out.println(name + "成功从电脑拔出。。。");
    }

    public String getName() {
        return name;
    }

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

创建电脑对象,有方法实现对键盘和鼠标的接入

package com.itzw.d3_polymorphism_test;


public class Computer {
    private String name;

    public Computer() {
    }

    public Computer(String name) {
        this.name = name;
    }

    public void start(){
        System.out.println(name + "启动了。。。。");
    }

    public void install(USB usb){
        usb.connect();
        if (usb instanceof KeyBoard){
            KeyBoard keyBoard = (KeyBoard) usb;
            keyBoard.keyDown();
        }else if (usb instanceof Mouse){
            Mouse mouse = (Mouse) usb;
            mouse.click();
        }
        usb.unconnect();
    }

    public String getName() {
        return name;
    }

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

测试

package com.itzw.d3_polymorphism_test;

public class Test {
    public static void main(String[] args) {
        //创建一个电脑对象
        Computer c = new Computer("👽");
        c.start();
        //创建一个键盘对象
        USB u1 = new KeyBoard("马邦德键盘");
        //连接到电脑
        c.install(u1);

        System.out.println("======================");
        //创建一个键盘对象
        USB u2 = new Mouse("张麻子鼠标");
        //连接到电脑
        c.install(u2);
    }
}


7 内部类

7.1 概述

内部类

  • 内部类就是定义在一个类里面的类,里面的类可以理解成(寄生) ,外部类可以理解成(宿主)。

public class People{
        //内部类
        public class Heart{
}

内部类的使用场景、作用

  • 当一个事物的内部, 还有-一个部分需要一个完整 的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类来设计。
  • 内部类通 常可以方便访问外部类的成员,包括私有的成员。
  • 内部类提供了更好的封装性,内部类本身就可以用private protectecd等修饰,封装性可以做更多控制。
     

内部类的分类

  • 静态内部类[了解]
  • 成员内部类(非静态内部类) [了 解]
  • 局部内部类[了解]
  • 匿名内部类(重点)

7.2 静态内部类(了解)

什么是静态内部类?

  • 有static修饰,属于外部类本身。
  • 它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。

public class Outer{
        //静态成员内部类
        public static class Inner{

        }

}

静态内部类创建对象的格式:

格式:外部类名.内部类名对象名= new外部类名.内部类构造器;
范例: Outer.Inner in= new Outer.Inner()s

静态内部类中是否可以直接访问外部类的静态成员?

  • 可以,外部类的静态成员只有一-份可以被共享访问。

静态内部类中是否可以直接访问外部类的实例成员?

  • 不可以的,外部类的实例成员必须用外部类对象访问。

7.3 成员内部类(非静态内部类) (了解)

什么是成员内部类?

  • 无static修饰,属于外部类的对象。
  • JDK16之前,成员内部类中不能定义静态成员, JDK 16开始也可以定义静态成员了。

public class Outer {
        //成员内部类
        public class Inner {
}

成员内部类创建对象的格式:

格式:外部类名.内部类名对象名= new外部类构造器.new内部类构造器(); 
范例: Outer.Inner in = new Outer().new Inner();

1、成员内部类中是否可以直接访问外部类的静态成员?

  • 可以,外部类的静态成员只有一份可以被共享访问。

2、成员内部类的实例方法中是否可以直接访问外部类的实例成员?

  • 可以的,因为必须先有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员。
  • 请观察如下代码,写出合适的代码对应其注释要求输出的结果。

class People{
        private int heartbeat = 150;
        public class Heart{
                private int heartbeat = 110;
                public void show(){
                        int heartbeat = 78;
                       System.out . println(??); // 78
                        System.out .print1n(??); // 110
                        System. out . println(??); // 150
                }
        }
}

第一空:heartbeat        第二空:this.heartbeat        第三空:People.this.heartbeat
注意:在成员内部类中访问所在外部类对象,格式:外部类名.this。

7.4 匿名内部类(重点)

7.4.1 概述

匿名内部类:

  • 本质上是一个没有名字的局部内部类,定义在方法中、代码块中、等。
  • 作用:方便创建子类对象,最终目的为了简化代码编写。
     

演示:

package com.itzw.d3_polymorphism_anonymous;

public class Test {
    public static void main(String[] args) {
        //之前学的方法,非常的麻烦,不人性
        /*Animal a = new Tiger();
        a.run();*/

        //使用匿名内部类,和上面效果一样,但是不用再创建子类
        Animal a1 = new Animal() {
            @Override
            public void run() {
                System.out.println("两只老虎跑得快。。。");
            }
        };
        a1.run();
    }
}


abstract class Animal{
    public abstract void run();
}

//要想实现Animal中的run方法必须要有子类继承才行,很麻烦
/*class Tiger extends Animal{
    @Override
    public void run() {
        System.out.println("两只老虎跑得快。。。");
    }
}*/

7.4.2 使用形式

匿名内部类在开发中的使用形式了解

  • 某个学校需要让老师,学生,运动员- -起参加游泳比赛
package com.itzw.d3_polymorphism_anonymous;

import com.sun.xml.internal.ws.api.client.WSPortInfo;

public class Test02 {
    public static void main(String[] args) {
        //这是之前的方法
        /*Swimming s1 = new Student();
        go(s1);*/

        //直接用匿名内部类
        Swimming s2 = new Swimming() {
            @Override
            public void swim() {
                System.out.println("学生正在愉快的学游泳。。。");
            }
        };
        go(s2);

        System.out.println("-----------------------");
        //还可以更简单,可以直接放入方法参数中
        go(new Swimming() {
            @Override
            public void swim() {
                System.out.println("老师正在快速的游泳。。。");
            }
        });
    }

    public static void go(Swimming swimming){
        System.out.println("开始。。。");
        swimming.swim();
        System.out.println("结束。。。");
    }
}

//还需要创建学生类,非常的麻烦,垃圾
/*class Student implements Swimming{

    @Override
    public void swim() {
        System.out.println("学生正在愉快的学游泳。。。");
    }
}*/

interface Swimming{
    void swim();
}

总结:匿名内部类可以作为方法的实际参数进行传输。
 

7.4.3 案例

案例有没学到的知识,暂时不写,大概理解了匿名内部类

总结:开发中不是我们主动去定义匿名内部类的,而是别人需要我们写或者我们可以写的时候才会使用。匿名内部类的代码可以实现代码进一步的简化
 

8 常用API

8.1 Object

8.1.1 Object概述

0bject类的作用:

  • 一个类要么默认继承了Object类, 要么间接继承了Object类,Object类是Java中的祖宗类。
  • Object类的方法是一切子类都可以直接使用的,所以我们要学习0bject类的方法。

0bject类的常用方法:

8.1.2 toString()

  • public String toString():默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址
  • 在类中重写toString方法可以返回类中的具体信息,是个字符串
package com.itzw.d4_api_object;

public class tostringTest {

    public static void main(String[] args) {
        Student student = new Student("112123","张麻子",23);
        System.out.println(student.toString());
    }
}

class Student{
    private String no;
    private String name;
    private int age;

    public Student() {
    }

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


    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    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{" +
                "no='" + no + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

8.1.3 equals

public Boolean equals(Object o):默认是比较当前对象与另一个对象的地址是否相同,相同返回true,不同返回false

equals存在的意义,

  • 父类equals方 法存在的意义就是为了被子类重写,以便子类自己来定制比较规则。
        Student student = new Student("112123","张麻子",23);
        System.out.println(student.toString());

        Student student1 = new Student("112123","张麻子",23);
        //此时只能比较地址
        //System.out.println(student.equals(student1));//false
        //我想比较内容,重写完equals方法后比较
        System.out.println(student.equals(student1));//true
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(no, student.no) &&
                Objects.equals(name, student.name);
    }

8.1.4 Objects

  • Objects类 与Object还是继承关系,Objects类是从JDK 1.7开始之后才有的。

官方在进行字符串比较时,没有对象自己的equals方法,而是选择了Objects的equals方法来比较两个对象。
0bjects的equals方法比较的结果是一样的,但是更安全。

package com.itzw.d5_api_objects;

import java.util.Objects;

public class Test {
    public static void main(String[] args) {
        String a = null;
        String b = "张麻子";

        //System.out.println(a.equals(b));//若a是null就会出错

        System.out.println(Objects.equals(a, b));//false
    }
}

8.2 StringBuilder

8.2.1 StringBuilder概述

  • StringBuilder是一 个可变的字符串类,我们可以把它看成是一 个对象容器。
  • 作用:提高字符串的操作效率,如拼接、修改等。

StringBuilder构造器
public StringBuilder()        创建一个空白的可变的字符串对象,不包含任何内容
public StringBuilder(String str)        创建一个指定字符串内容的可变字符串对象

8.2.2 常用方法

public StringBuilder append(任意类型)         添加数据并返回StringBuilder对象本身
public StringBuilder reverse()                        将对象的内容反转
public int length()                                           返回对象内容长度
public String toString()                                   通过toString()就可以实现把StringBuilder转换为String

演示:

package com.itzw.d6_api_stringbuilder;

public class Test01 {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();

        //1.append可以一个一个添加
        sb.append(1);
        sb.append(2);
        //也可以链式添加
        sb.append('a').append('b').append("我爱你中国");
        System.out.println(sb);//12ab我爱你中国

        //2.reverse
        sb.reverse();
        System.out.println(sb);//国中你爱我ba21

        //3.length
        System.out.println(sb.length());//9

        //4.toString,最终我们要传入别的方法中需要转成字符串,因为及时它表明输出的是字符串但其实是StringBuilder类型
        //test(sb);//报错

        StringBuilder sb2 = new StringBuilder();
        sb2.append(2).append("嘿嘿嘿").append('s');
        String s = sb2.toString();
        test(s);
    }

    public static void test(String s){

    }
}

之前学到,String在进行加法操作的时候,每加一次都会创建一个StringBuilder对象再转为String对象,每次加法都要再创建两个对象。而用StringBuilder进行加法操作就不需要额外创建对象,都只在一个StringBuilder对象里面加,效率相当的高。

所以如果要拼接字符串,优先选用StingBuilder拼接。

但StringBuilder只是用来提高效率,我们还是习惯用String接受字符串,所以最终要转成String。

8.2.3 案例

打印整型数组内容
需求:

  • 设计一个方法用于输出任意整型数组的内容,要求输出成如下格式:
  • “该数组内容为: [11, 22, 33, 44, 55]”

分析:

  1. 定义一个方法,要求该方法能够接收数组,并输出数组内容。 需要参数吗?需要返回值类型申明吗?
  2. 定义一个静态初始化的数组,调用该方法,并传入该数组。
     
package com.itzw.d6_api_stringbuilder;

public class Test02 {
    public static void main(String[] args) {
        int[] a = {11,22,33,44,55};
        System.out.println(getString(a));
    }

    public static String getString(int[] arr){
        StringBuilder sb = new StringBuilder("[");
        if (arr == null){
            return null;
        }else {
            for (int i = 0; i < arr.length; i++) {
                /*if (i == arr.length - 1){
                    sb.append(arr[i]).append("]");
                }else {
                    sb.append(arr[i]).append(",");
                }*/

                sb.append(arr[i]).append(i == arr.length - 1 ? "" : ",");
            }
            sb.append("]");
            return sb.toString();
        }

    }
}

8.3 Math、System、BigDecimal

Math类

  • 包含执行基本数字运算的方法,Math类没有提供公开的构造器。
  • 如何使用类中的成员呢?看类的成员是否都是静态的,如果是,通过类名就可以直接调用
     

8.3.1 Math类常用方法

public static int abs(int a)                                      获取参数绝对值
public static double ceil(double a)                         向上取整
public static double floor( double a)                       向下取整
public static int round(float a)                                 四舍五入
public static int max(int a,int b)                               获取两个int值中的较大值
public static double pow(double a, double b)         返回a的b次幂的值
public static double random( )                                返回值为double的随机值,范围[0.0,1.0)

package com.itzw.d7_api_math;

public class Test01 {
    public static void main(String[] args) {
        //abs返回绝对值
        System.out.println(Math.abs(-10));//10
        System.out.println(Math.abs(3.14));//3.14
        System.out.println("==================");

        //ceil向上取整
        System.out.println(Math.ceil(3.14));//4.0
        System.out.println(Math.ceil(7.0));//7.0
        System.out.println("==================");

        //floor向下取整
        System.out.println(Math.floor(3.999));//3.0
        System.out.println(Math.floor(4.0));//4.0
        System.out.println("==================");

        //四舍五入
        System.out.println(Math.round(3.1999));//3
        System.out.println(Math.round(2.99));//3
        System.out.println("==================");

        //pow返回a的b次幂的值
        System.out.println(Math.pow(2,4));//16
        System.out.println(Math.pow(-2,5));//-32
        System.out.println("==================");

        //random 返回double的随机值,范围[0.0,1.0)
        System.out.println(Math.random());
        System.out.println("==================");
    }
}

8.3.2 System常用方法

System类概述

  • System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化。

System类的常用方法
public static void exit(int status)           终止当前运行的Java虚拟机,非零表示异常终止
public static long currentTimeMillis()    返回当前系统的时间毫秒值形式
public static void arraycopy(数据源数组,起始索引,目的地数组,起始索引,拷贝个数)      数组拷贝

package com.itzw.d8_api_system;

public class Test {
    public static void main(String[] args) {
        System.out.println("程序开始。。。");
        //一般用不到
        //System.exit(0);

        //返回当前系统时间的毫秒值 从1970年1月1日开始到现在
        long time = System.currentTimeMillis();
        System.out.println(time);

        //可以用来计算性能
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            System.out.println(i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("所用时间:" + (endTime - startTime)/1000.0 + "s");

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

8.3.3 BigDecimal

BigDecimal作用

  • 用于解决浮点型运算精度失真的问题
        double a = 0.1, b = 0.2;
        System.out.println(a + b);//0.30000000000000004
//使用BigDecimal
        BigDecimal aa = BigDecimal.valueOf(a);
        BigDecimal bb = BigDecimal.valueOf(b);
        BigDecimal rs = aa.add(bb);
        //加
        System.out.println(rs);//0.3
        //减
        System.out.println(aa.subtract(bb));
        //乘
        System.out.println(aa.multiply(bb));
        //除
        System.out.println(aa.divide(bb));

同StingBuilder一样,BigDecimal的目的是double类型,所以最后要转成double

        double rss = rs.doubleValue();
        System.out.println(rss);

        //但有时相除可能除不尽,这时就会报错
        BigDecimal a1 = BigDecimal.valueOf(10);
        BigDecimal b1 = BigDecimal.valueOf(3);
        //System.out.println(a1.divide(b1));
        //                          被除数 保留几位小数   向上取整
        System.out.println(a1.divide(b1,2, RoundingMode.UP));

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值