二.基础篇: 面向对象进阶

1. 基础篇语法篇:一.基础篇:基础语法-CSDN博客

面向对象进阶

本章主要学习内容:

  • static
  • 继承
  • 包,final,权限修饰符,代码块
  • 抽象类
  • 接口
  • 多态
  • 内部类

1. static

  • static翻译过来就是静态的意思
  • static表示静态,是java中的一个修饰符,可以修饰成员方法,成员变量
  • 被static修饰的成员变量,叫做静态变量
    • 特点:
      • 被该类所有对象共享
      • 不属于对象,属于类
      • 随着类的加载而加载,优先于对象存在
  • 被static修饰的成员方法,叫做静态方法
    • 特点:
      • 多在测试类和工具类中
      • javabean类中很少会用
  • 调用方式:
    • 类名调用(推荐)
    • 对象名调用

需求:写一个javaBean类来描述班级的学生

  • 属性:姓名,年龄,性别
  • 行为:学习逆向
public class Test {
    public static void main(String[] args) {
        // 创建两个学生对象
        Student.teacherName = "刘老师";

        Student s1 = new Student();
        s1.setName("小明");
        s1.setAge(10);
        s1.setGender("男");

        s1.show();
        s1.study();

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

        Student s2 = new Student();
        s2.setGender("女");
        s2.setAge(12);
        s2.setName("小红");


        s2.show();
        s2.study();

    }
}



// 学生类
class Student{
    // 属性: 姓名,年龄,性别
    // 新增属性: 老师的姓名
    private String name;
    private int age;
    private String gender;
    // 使用static修饰后,Student类中所有对象都共享teacherName
    public static String teacherName;

    public Student() {

    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    // 重写toString方法
    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }

    // 行为: 学习方法
    public void study(){
        System.out.println(name + "正在学习");
    }

    // 输出学生信息
    public void show(){
        System.out.println(name + ", " + age + ", " + gender + ", " + teacherName);
    }
}

工具类

类的分类

工具类的定义规范:

  • 类名见名知意
  • 私有化构造方法
  • 方法都定义为静态的,方便调用

示例代码:

需求:在时机开发中,经常会遇到一些数组使用的工具类,按照以下要求编写一个数组的工具类: ArrayUtil

  • 提供一个工具类方法printArr,用于返回整数数组的内容
    • 返回的字符串格式如:[10,20,30,40] 
  • 提供一个工具方法 getAerage,用于返回平均分
  • 定义一个测试类TestDemo,调用工具类的工具方法
public class Test {
    public static void main(String[] args) {
        int[] arr1 = {1,2,3,4,5,6};
        String s = ArrayUtil.printArr(arr1);
        System.out.println(s); // [1, 2, 3, 4, 5, 6]

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

        double[] arr2 = {1.1,22.2,33.3,44.4};
        double average = ArrayUtil.getAverage(arr2);
        System.out.println(average);
    }
}


// ArrayUtil工具类
class ArrayUtil{
    // 私有化构造方法
    // 目的: 为了不让外界创建他的对象
    private ArrayUtil(){}

    // 定义静态方法,方便使用
    public static String printArr(int[] arr){
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < arr.length; i++) {
            // i 索引 arr[i] 元素
            if(i == arr.length - 1){
                sb.append(arr[i]);
            }else{
                sb.append(arr[i]).append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    public static double getAverage(double[] arr){
        double sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum = sum + arr[i];
        }
        return sum / arr.length;
    }
}

示例代码:

需求:定义一个集合,用于存储3个学生对象

  • 学生类的属性为:name,age,gender
  • 定义一个工具类,用于获取集合中最大学生的年龄
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // 1. 创建一个集合,用来存储学生对象Student
        ArrayList<Student > list = new ArrayList<>();

        // 2.创建3个学生对象
        Student stu1 = new Student("小明",1,"男");
        Student stu2 = new Student("小红",12,"女");
        Student stu3 = new Student("小芳",16,"女");

        // 3.把学生对象,添加到集合中
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);

        // 计算集合中年龄最大的学生
        int studentAgeMax = StudentUtil.getStudentAgeMax(list);
        System.out.println("最大学生的年龄: " + studentAgeMax);
    }
}

// 学生类(标准的javaBean类)
class Student{
    private String name;
    private int age;
    private String gender;


    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return gender
     */
    public String getGender() {
        return gender;
    }

    /**
     * 设置
     * @param gender
     */
    public void setGender(String gender) {
        this.gender = gender;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
    }
}

// 定义一个工具类,用于获取最大学生的年龄
class StudentUtil{
    private StudentUtil(){}

    // 静态方法
    public static int getStudentAgeMax(ArrayList<Student> list){
        //1.定义一个参照物
        int max = list.get(0).getAge();

        for (Student student : list) {
            int age = student.getAge();
            if (age > max){
                max = age;
            }
        }
        return max;
    }
}

static注意事项

  • 静态方法中,只能访问静态
  • 非静态方法,可以访问所有
  • 静态方法中没有this关键字


2. 继承

  • 继承是面向对象三大特征之一
  • java中提供了一个关键字 extends,用这个关键字,可以让一个类和另一个类建立起继承关系
    • public class Student extends Person{}
    • Student称为子类(派生类), Person称为父类(基类或超类)
  • 使用继承的好处:
    • 可以把多个子类重复的代码抽取到父类中,提高代码的复用性
    • 子类可以在父类的基础上,增加其他的功能,使子类更强大
  • 什么时候使用到继承?
    • 当类与类之间,存在相同(共性)的内容,并满足子类是父类中的哪一种,就可以考虑使用继承,来优化代码
  • 继承需要学习的点:
    • 编写自己的父类,使用子类继承
    • 继承已经写好的父类
  • 继承的特点:
    • java只支持单继承,不支持多继承,但支持多层继承

示例代码:

public class Test {
    public static void main(String[] args) {
        // 创建对象并调用方法
        Ragdoll ragdoll = new Ragdoll();
        ragdoll.eat();
        ragdoll.drink();
        ragdoll.catchMouse();
    }
}


// 动物类(父类)
class Animal{
    public void eat(){
        System.out.println("吃饭");
    }

    public void drink(){
        System.out.println("喝水");
    }

}

// 猫类
class Cat extends Animal{
    public void catchMouse(){
        System.out.println("猫在抓老鼠");
    }
}

// 狗类
class Dog extends Animal{
    public void lookHome(){
        System.out.println("狗看家");
    }
}

// 布偶猫
class Ragdoll extends Cat{

}

// 狸花猫
class LiHuaMao extends Cat{

}

// 哈士奇
class Husky extends Dog{
    public void breakHome(){
        System.out.println("哈士奇在拆家");
    }
}

// 泰迪
class Teddy extends Dog{
    public void touch(){
        System.out.println("泰迪又在蹭腿");
    }
}

继承中的成员变量和成员方法访问特点

继承中成员变量的访问特点

  • 通过this关键字,访问自身类上的属性
  • 通过super关键字,访问父类上的属性

小结:

  • 继承中成员变量的访问特点:就近原则
    • 先在局部位置找,本类成员位置找,父类成员位置找,逐级往上
  • 如果出现重名的成员变量怎么办?

继承中成员方法的访问特点,和成员变量访问特点一样


方法的重写

  • 当父类的方法不能满足子类现在的需求时,需要进行方法重写
  • 方法重写格式:
    • 在继承体系中,子类出现了和父类一模一样的方法声明,就称子类这个方法是重写的方法
    • @Override重写注解:@Override是放在重写后的方法上,校验子类重写时语法是否正确

示例代码:

public class Test {
    public static void main(String[] args) {
        XM xm = new XM();
        xm.jn();
    }
}

class Person{
    public void jn(){
        System.out.println("java");
    }
}


class XM extends Person{

    // 重写父类的jn方法
    // 注意: 子类重写父类的方法需要在方法上加上 @Override
    @Override
    public void jn(){
        System.out.println("逆向");
    }
}

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


继承中的构造方法

构造方法的访问特点:

小结:

3. 多态

基本使用

示例代码:

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("小明");
        student.setAge(10);


        Teacher teacher = new Teacher();
        teacher.setName("王老师");
        teacher.setAge(32);

        Administrator administrator = new Administrator();
        administrator.setAge(53);
        administrator.setName("管理员");


        register(student);
        register(teacher);
        register(administrator);
    }

    // 注册
    // 这个方法即能接收老师,又能接收学生,又能接收管理员
    public static void register(Person p){
        p.show();
    }
}


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


    public Person() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }

    public void show(){
        System.out.println(name + ", " + age);
    }
}

// 学生类(子类) 基础 父类
class Student extends  Person{

    // 重写父类方法
    @Override
    public void show(){
        System.out.println("学生的信息为: " + getName() + ", " + getAge());
    }
}


// 老师类(子类) 基础 父类
class Teacher extends  Person{
    // 重写父类方法
    @Override
    public void show(){
        System.out.println("老师的信息为: " + getName() + ", " + getAge());
    }
}

// 管理员类(子类) 基础 父类
class Administrator extends  Person{
    // 重写父类方法
    @Override
    public void show(){
        System.out.println("管理员的信息为: " + getName() + ", " + getAge());
    }
}

小结:


多态调用成员的特点

  • 变量调用:编译看左边,运行也看左边
  • 方法调用:编译看左边,运行看右边

示例代码:

public class Test {
    public static void main(String[] args) {
        // 创建对象(多态的方式创建)
        Animal cat = new Cat();
        // 多态中调用成员变量: 编译看左边,运行也看左边
        // 编译看左边: javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有就编译失败
        // 运行也看左边: java运行代码的时候,实际获取的是左边父类中成员变量的值
        System.out.println(cat.name); // 调用的是父类的name

        // 多态中调用成员方法: 编译看左边,运行看右边
        // 编译看左边: javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有就编译失败
        // 运行看右边: java运行代码的时候,实际上是运行子类中的方法
        cat.show(); // Cat-show方法
    }
}

class Animal{
    String name = "动物";

    public void show(){
        System.out.println("Animal-show方法");
    }
}

class Cat extends Animal{
    String name = "猫";

    @Override
    public void show(){
        System.out.println("Cat-show方法");
    }
}

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

    @Override
    public void show(){
        System.out.println("Dog-show方法");
    }
}


多态的优势和弊端

多态的练习

需求:

代码:

public class Test {
    public static void main(String[] args) {
        // 创建对象并调用方法
        Person p1 = new Person("老王",30);
        Dog dog = new Dog(2,"黑");
        p1.keepPet(dog,"骨头");

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

        Cat cat = new Cat(10,"白");
        p1.keepPet(cat,"鱼");
    }
}


// 动物的父类(将猫和狗的共性包装到父类中)
class Animal{
    // 属性
    private int age;
    private String color;

    public Animal() {
    }

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



    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return color
     */
    public String getColor() {
        return color;
    }

    /**
     * 设置
     * @param color
     */
    public void setColor(String color) {
        this.color = color;
    }

    public String toString() {
        return "Animal{age = " + age + ", color = " + color + "}";
    }


    /**
     * 吃东西的方法
     * @param something
     */
    public void eat(String something){
        System.out.println("动物再吃" + something);
    }
}

// 狗类
class Dog extends Animal{
    // 空参构造
    public Dog() {

    }

    // 带父类全部参数的构造
    public Dog(int age,String color) {
        super(age,color);
    }

    // 重写父类的eat方法
    @Override
    public void eat(String something) {
        System.out.println(getAge() + "岁 " + getColor() +"颜色的狗在吃" + something );
    }

    // 狗特有的方法
    public void lookHome(){
        System.out.println("狗看家");
    }
}

// 猫类
class Cat extends Animal{
    // 空参构造
    public Cat() {

    }

    // 带父类全部参数的构造
    public Cat(int age,String color) {
        super(age,color);
    }

    @Override
    public void eat(String something) {
        System.out.println(getAge() + "岁 " + getColor() +"颜色的猫在吃" + something );
    }

    // 猫特有的方法
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}


// 饲养员
class Person{
    private String name;
    private int age;


    public Person() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Person{name = " + name + ", age = " + age + "}";
    }


    public void keepPet(Animal a,String something){
        if(a instanceof Dog d) {
            System.out.println("年龄为" + age + "岁的" + name + "养了一只" + a.getColor() + "颜色的" + a.getAge() + "岁的" + "狗");
            a.eat(something);
        } else if (a instanceof Cat d) {
            System.out.println("年龄为" + age + "岁的" + name + "养了一只" + a.getColor() + "颜色的" + a.getAge() + "岁的" + "猫");
            a.eat(something);
        }else{
            System.out.println("没有这种动物");
        }
    }
}

4.  包

什么是包?

  • 包就是文件夹。用来管理各种不同功能的java类,方便后期维护
  • 包名的规则:域名反写+包的作用,需要全部英文小写,见名知意。
    • 例如:
      • 域名为:spider.github.com
      • 包那么就命名为:com.github.spider

使用规则:

  1. 在com.spider.github 软件包下软件一个名为Student的类
  2. 在Test类中通过import关键字引用Student类

小结:

5. final关键字

  • final表示是最终的,不能被改变的
  • final可以修饰,方法,类,变量
  • 被final修饰的方法,表示该方法是最终方法,不能被重写
    • 应用场景:当父类中定义的一些方法不希望别人(子类)去改变,就可以使用final修饰
  • 被final修饰的类,表示该类是最终类,不能被继承
    • 应用场景:
      • 安全性:如果一个类的实现已经是完整和安全的,不希望被其他类继承并改变其行为,则可以将该类声明为final。这样可以确保该类的行为不会被修改或者被继承后导致不安全的变化
  • 被final修饰的变量,叫常量,只能被赋值一次
    • 应用场景,当不想变量发生改变时,可以使用final修饰

示例代码:

  • 被final修饰的方法,表示该方法是最终方法,不能被重写
  • 被final修饰的类,表示该类是最终类,不能被继承
  • 被final修饰的变量,叫常量,只能被赋值一次

6. 常量

  • 实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性
  • 常量的命名规范:
    • 单个单词:全部大写
    • 多个单词:全部大写,单词之间用下划线隔开
  • 细节:
    • final修饰的变量是基本类型:那么变量存储的数据值不能发送改变
    • final修饰的变量是引用类型:那么变量存储的地址值不能发送改变,对象内部可以改变

示例代码:


public class Test {
    public static void main(String[] args) {
        // final修饰的变量是基本类型:记录的值不能发生改变
        final double  PI = 3.14;

        // final修饰的变量是引用类型:记录的地址值不能发生改变,内部的属性值还是可以改变的
        final Student S = new Student("小红",13);
        // 记录的地址值不能发生改变
        // S = new Student(); // 报错

        // 内部的属性值还是可以改变的
        S.setAge(100);
        S.setName("小芳");
        System.out.println(S.getName() + ", " + S.getAge());
    }
}

class Student{
    private String name;
    private int age;

    public Student() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

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

7. 权限修饰符

  • 权限修饰符:是用来控制一个成员能够被访问的范围的
  • 权限修饰符可以修饰:成员变量,方法,构造方法,内部类
  • 权限修饰符的分类:有4种
    • 权限修饰符四种范围由大到小:public > protected > default > private。
    • public:public 修饰的成员变量和方法可以被任何类访问。如果一个类是 public 类,那么这个类所在的源文件的文件名必须与类名相同
    • protected:protected 修饰的成员变量和方法可以被同一类、同一包内的类以及其他包中的子类
    • default:默认的权限修饰符,即不写任何修饰符。同一包内的类可以访问 default 修饰的成员变量和方法,不同包内的类不能访问。
    • private:private 修饰的成员变量和方法只能被同一类内的方法访问,其他类无法直接访问。
  • 权限修饰符的使用规则:
    • 实际开发中,一般只用private和public
      • 成员变量私有
      • 方法公开
      • 特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有

8. 代码块

  • 局部代码块:
  • 构造代码块:
  • 静态代码块:
    • 格式:static {}
    • 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只执行一次
    • 使用场景:在类加载的时候,做一些数据初始化的时候使用

小结:

9. 抽象类与抽象方法

  • 抽象方法:将共性的行为(方法)抽取到父类之后,由于每一个子类执行的内容是不一样的,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。
  • 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类
  • 抽象类和抽象方法的定义格式:
    • ​​​​​​​抽象方法语法格式:public abstract 返回值类型 方法名(参数列表);
    • 抽象类语法格式:public abstract class 类名{}
  • 注意事项:
    • 抽象类不能创建对象
    • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
    • 抽象类可以有构造方法
    • 抽象类的子类:
      • 要么重写抽象类中的所有抽象方法
      • 要么是抽象类


 

练习:​​​​​​​

public class Test {
    public static void main(String[] args) {
        // 创建对象
        Frog frog = new Frog("小青蛙",1);
        frog.drink();
        frog.eat();
    }
}

// 抽象类(父类)
abstract class Animal{
    private String name;
    private int age;


    public Animal() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }

    public void drink(){
        System.out.println(getName() + "在喝水");
    }

    // 抽象方法
    public abstract void eat();
}


// 青蛙-子类
class Frog extends Animal{


    public Frog() {
    }

    public Frog(String name, int age) {
        super(name,age);
    }

    // 实现父类的抽象方法
    @Override
    public void eat() {
        System.out.println("青蛙吃虫子");
    }

}


// 狗-子类
class Dog extends Animal{


    public Dog() {
    }

    public Dog(String name,int age) {
        super(name,age);
    }

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

    public String toString() {
        return "Dog{}";
    }
}


// 山羊-子类
class Sheep extends Animal{

    public Sheep() {
    }

    public Sheep(String name,int age) {
        super(name,age);
    }

    @Override
    public void eat() {
        System.out.println("山羊吃草");
    }
}

小结:

10. 接口

接口的定义和使用

  • 接口用关键字interface来定义:public interface 接口名称 {}
  • 接口不能实例化
  • 接口和类之间是实现关系,通过 implements 关键字表示:public class 类名 implements 接口名称 {}
  • 接口的子类(实现类)
    • 要么重写接口中的所有抽象方法
    • 要么是抽象类
  • 注意1:接口和类的实现关系,可以单实现,也可以多实现
    • public class 类名 implements 接口1,接口2 {}
  • 注意2:实现类还可以在继承一个类的同时实现多个接口
    • public class 类名 extends 父类 implements 接口名1,接口名2 {}

练习:

public class Test {
    public static void main(String[] args) {
        // 创建青蛙的对象
        Frog frog = new Frog("小青蛙",1);
        frog.eat();
        frog.swim();
    }
}


/*
 * 接口
 * */
interface Swim {
    public abstract void swim();
}

/*
* 父类-动物
* */
abstract class Animal{
    private String name;
    private int age;

    public Animal() {
    }

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

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Animal{name = " + name + ", age = " + age + "}";
    }

    // 吃的-行为
    public abstract void eat();
}



/*
* 兔子-子类
* */
class Rabbit extends Animal{


    public Rabbit() {
    }

    public Rabbit(String name,int age) {
        super(name,age);
    }

    @Override
    public void eat() {
        System.out.println(getName() + "吃胡萝卜");
    }
}

/*
* 狗类-子类
* */
class Dog extends Animal implements Swim{


    public Dog() {
    }

    public Dog(String name,int age) {
        super(name,age);
    }

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

    // 实现Swim接口的swim方法
    @Override
    public void swim() {
        System.out.println(getName() + "狗刨式游泳");
    }
}



/*
* 青蛙-子类
* */
class Frog extends Animal implements Swim{

    public Frog() {
    }

    public Frog(String name,int age) {
        super(name,age);
    }

    @Override
    public void swim() {
        System.out.println(getName() + "蛙泳");
    }

    @Override
    public void eat() {
        System.out.println(getName() + "吃虫子");
    }
}


接口中成员的特点

  • 成员变量
    • 只能是常量
    • 默认修饰符:public static final
  • 构造方法
    • 接口中没有构造方法
  • 成员方法
    • 只能是抽象方法
    • 默认修饰符:public abstract 
    • jdk7以前:接口中只能定义抽象方法
    • jdk8的新特性:接口中可以定义有方法体的方法
    • jdk9的新特性:接口中可以定义私有方法


接口和类之间的关系

  • 类和类之间的关系
    • 继承关系,只能单继承,不能多继承,但是可以多层继承
  • 类和接口的关系
    • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系
    • 继承关系,可以单继承,也可以多继承

11. 内部类

初始内部类

内部类的分类:

  • 成员内部类:了解
  • 静态内部类:了解
  • 局部内部类:了解
  • 匿名内部类:需要掌握

什么是内部类?

  • 就是在一个类的里面,在定义一个类。
    • 举例:在A类的内部定义B类,B类就被称为内部类

为什么要学习内部类?

  • 需求:写一个javabean类描述汽车
  • 属性:汽车的品牌,车龄,颜色,发动机的品牌,使用年限​​​​​​​

小结:

匿名内部类

  • 匿名内部类本质上就是隐藏了名字的内部类
  • 语法格式:new 类名或者接口名(){ 重写方法; };

示例代码:

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

        // 编写匿名内部类的代码
        new Swim() {
            // 重写方法
            @Override
            public void swim() {
                System.out.println("重写了游泳的方法");
            }
        };
    }

}

interface Swim {
    public abstract void swim();
}

小结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/621230.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

家用洗地机哪款最好用?附热门洗地机品牌推荐,看完这篇不踩坑

随着技术的不断发展&#xff0c;现在的洗地机功能已经越来越强大了&#xff0c;它可以高效的扫地、拖地、不用手动清洗滚刷&#xff0c;甚至有些中高端型号还能边洗地边除菌&#xff0c;远程操控自清洁&#xff0c;简直就是家居清洁的小能手&#xff01;那么&#xff0c;家用洗…

‘vue-cli-service‘ is not recognized as an internal or external command解决方案

vue-cli-service is not recognized as an internal or external command, operable program or batch file.解决方案 先进行 &#xff1a; npm install -g vue/cli 命令安装vue cli 是必须的。 如果 npm run build 还是报错 遇到同样的提示&#xff1a; 这时候先安装依赖 np…

深入理解与应用C++ Vector

1. C Vector 简介与基本使用 C 的 vector 是一个序列容器&#xff0c;用于表示可变大小的数组。它结合了数组的高效元素访问和动态大小调整的灵活性。与静态数组相比&#xff0c;vector 的大小可以根据需要自动调整&#xff0c;这是通过在底层使用动态数组来实现的。当新元素被…

返回倒数第K个节点(C语言)———链表经典算法题

题目描述​​​​​​&#xff1a;面试题 02.02. 返回倒数第 k 个节点 - 力扣&#xff08;LeetCode&#xff09;&#xff1a; 答案展示: /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/int kthToLast(struct Li…

娱乐营销的新玩法:Kompas.ai如何让内容更加趣味化

在数字化时代&#xff0c;内容营销已成为品牌与消费者沟通的重要桥梁。然而&#xff0c;随着信息的爆炸式增长&#xff0c;用户的注意力越来越分散&#xff0c;传统的营销方式已经难以吸引用户的兴趣。在这种背景下&#xff0c;娱乐营销应运而生&#xff0c;它通过将娱乐元素融…

2023年30米分辨率土地利用遥感监测数据

改革开放以来&#xff0c;中国经济的快速发展对土地利用模式产生了深刻的影响。同时&#xff0c;中国又具有复杂的自然环境背景和广阔的陆地面积&#xff0c;其土地利用变化不仅对国家发展&#xff0c;也对全球环境变化产生了深刻的影响。为了恢复和重建我国土地利用变化的现代…

R语言:GSEA分析

#安装软件包 > if (!requireNamespace("BiocManager", quietly TRUE)) install.packages("BiocManager") > BiocManager::install("limma") > BiocManager::install("org.Hs.eg.db") > BiocManager::install("…

【回溯 栈 代数系统 动态规划】282. 给表达式添加运算符

本文涉及知识点 回溯 栈 代数系统 动态规划 LeetCode 282. 给表达式添加运算符 给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target &#xff0c;在 num 的数字之间添加 二元 运算符&#xff08;不是一元&#xff09;、- 或 * &#xff0c;返回 所有 能够得到 ta…

C++深度解析教程笔记8

C深度解析教程笔记8 第17课 - 对象的构造&#xff08;上&#xff09;类定义中成员变量i和j的初始值&#xff1f;实验-成员变量的初始值对象初始化解决方案1实验-手动调用函数初始化对象对象初始化解决方案2&#xff1a;构造函数实验-构造函数小结 第18课 - 对象的构造&#xff…

File类~路径、创建文件对象

路径分为相对路径&#xff08;不带盘符&#xff09;&#xff0c;绝对路径&#xff08;带盘符&#xff09; 路径是可以存在的&#xff0c;也可以是不存在的 创建文件对象的三个方法&#xff1a;

QT设计模式:策略模式

基本概念 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列方法&#xff0c;并使它们可以相互替换。策略模式使得算法可以独立于客户端而变化&#xff0c;使得客户端可以根据需要选择相应的算法。 策略模式通常由以下角色组…

使用非官网购买Chatgpt的api调用

测试代码 from openai import OpenAI client OpenAI(api_key用户密钥) import json import os import timeclass ChatGPT:def __init__(self, user):self.user userself.messages [{"role": "system", "content": "Agent"}]def as…

每周一算法:传递闭包

题目描述 不等式排序 给定 n n n个变量和 m m m个不等式。其中 n n n小于等于 26 26 26&#xff0c;变量分别用前 n n n 的大写英文字母表示。 不等式之间具有传递性&#xff0c;即若 A > B A>B A>B 且 B > C B>C B>C&#xff0c;则 A > C A>C …

linux下的进程通信

进程通信 进程为什么需要通信呢&#xff1f;进程通信的技术背景进程通信本质 进程通信分类管道匿名管道pipe匿名管道原理管道特点 命名管道创建命名管道命名管道原理 System V IPC管道与 System V的区别共享内存函数ftok()shmget() shmat()shmdt()shmctl()删除共享内存System V…

【笔记】EF_PNN获取及运营商名称显示(待完善)

问题背景 当设备无法成功解析EONS(PNN)的值(即SIM卡EF文件内容),则会用次优先级的NITZ去refresh了SPN。(问题代码如下,是通过Phone对象拿到plmn为空) 运营商名称一般显示优先级:Eons > NITZ > XML OPL id 0 对应的是PNN第一条 功能逻辑 (定制)当卡中的spn为空…

生产制造行业推拉式生产的复合应用

一、案例分析&#xff08;汽配行业&#xff09; 重点&#xff1a; 1. MTO/MTS 与 PUSH/PULL 有关系但是不是充分关系 2. MTO/MTS 是公司经营策略&#xff0c;更多是对市场需求的经营策略&#xff0c;体现在生产时机上的不同&#xff0c;一个是等客户需求&#xff0c;一个是填…

做国外问卷调查,一天能挣多少钱?

大家好​&#xff0c;我是汇舟问卷&#xff0c;专注于国外问卷调查项目已经五年的时间了&#xff0c;目前做的一直比较稳定。 这个项目说白了就是通过搭建国外的环境&#xff0c;登录问卷平台&#xff0c;通过参与国外企业发布的问卷调查来获取​美金奖励。 那么参与的问卷的…

AI算法-高数5.2-线性代数-向量间的线性相关、无关定义和结论

宋浩老师课程&#xff1a;3.2 向量间的线性关系&#xff08;二&#xff09;_哔哩哔哩_bilibili 线性相关、不相关结论&#xff1a; 判断线性有关\无关&#xff0c;转化成方程组&#xff1a; 判断条件> 向量线性相关、无关的本质是&#xff1a;除0外能不能找到非0的数据。

交流负载箱:电力系统的智能升级

随着科技的不断发展&#xff0c;电力系统也在不断地进行升级和改进。在这个过程中&#xff0c;交流负载箱作为一种新型的电力设备&#xff0c;为电力系统的智能升级提供了有力的支持。本文将对交流负载箱在电力系统中的应用及其优势进行简要分析。 首先&#xff0c;交流负载箱…

【Qt】常用控件(一)

文章目录 一、核心属性1、enabled代码示例: 通过按钮2 切换按钮1 的禁用状态 2、geometry代码示例: 控制按钮的位置代码示例&#xff1a;window frame 的影响代码示例: 感受 geometry 和 frameGeometry 的区别 3、windowTitle4、windowIcon代码示例: 通过 qrc 管理图片作为图标…