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

news2024/11/27 22:30:40

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();
}

小结:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

wordpress增加谷歌分析

wordpress增加谷歌分析 为了更好的浏览体验&#xff0c;欢迎光顾勤奋的凯尔森同学个人博客 http://www.huerpu.cc:7000 一、创建谷歌分析账号与媒体应用 谷歌分析地址&#xff1a;https://analytics.google.com/analytics 创建一个账号&#xff0c;如果你没有的话。 在该账…

基于51单片机的遥控开关仿真

基于51单片机的遥控开关设计 &#xff08;仿真&#xff0b;程序&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 本课题研究的是一款遥控开关&#xff0c;采用51单片机进行发射电路与接收电路的设计&#xff0c;发射电路由单片机最小系统及四个按键构成&am…

鸿蒙应用开发DevEco Studio工程目录模块介绍

面向开发者&#xff0c;HarmonyOS 推出了 DevEco Studio 和 Dev Device Tool 两款开发工具&#xff0c;前者目前迭代至 3.1 版本&#xff08;对外开放版本&#xff09;&#xff0c;用于开发 HarmonyOS 应用&#xff1b;后者用于开发智能设备 应用的工程主体结构如上图 在这里我…

Python网络爬虫原理及实践(2)

2.4.1.2. HTML源码分析 Web端站点和M端站点返回结果都是HTML格式&#xff0c;部分站点为了提升页面渲染速度&#xff0c;或者为了增加代码分析难度&#xff0c;通过动态JavaScrip执行等方式&#xff0c;动态生成HTML页面&#xff0c;网络爬虫缺少JS执行和渲染过程&#xff0c;…

【计算机网络篇】数据链路层(9)使用集线器的共享式以太网

文章目录 &#x1f6f8;使用同轴电缆的共享总线以太网 &#x1f386;使用集线器的共享式以太网&#x1f95a;集线器的特点 &#x1f354;10BASE-T星型以太网 &#x1f6f8;使用同轴电缆的共享总线以太网 若总线上的某个机械连接点接触不良或断开&#xff0c;则整个网络通信就不…

【UnityRPG游戏制作】Unity_RPG项目_PureMVC框架应用

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

易图讯智慧公安警用三维电子沙盘系统

智慧公安警用三维电子沙盘系统是一个结合现代科技手段&#xff0c;为公安部门提供全面、高效、智能的警务管理解决方案的系统。该系统以“情报大数据、指挥扁平化、勤务可视化、情指勤一体化”为设计思想&#xff0c;整合了多台设备、有无线通讯、短信平台、天网、交通平台、治…

【Dash】开始学习dash

安装Dash 网上很多安装dash的教程&#xff0c;不再赘述 开始Dash 一个dash页面的基本写法 # dash 的基本写法 import dash from dash import html,dcc,callback,Input,Output# 创建一个 dash 应用 app dash.Dash()# 定义布局&#xff0c;定义一个输入框和一个输出框 app.l…

三、RocketMQ应用

RocketMQ应用 一、测试环境工程准备二、消息响应1.消息发送的状态-SendStatus2.producer消息Id-msgId3.broker消息Id-offsetMsgId 三、普通消息1.消息发送分类1.1 同步发送消息1.2 异步发送消息1.3 单向发送消息 2.代码举例2.1 同步消息发送生产者2.2 异步消息发送生产者2.3 单…

【C++11】线程库 | 互斥量 | 原子性操作 | 条件变量

文章目录 一、线程库 - thread1. 线程对象的构造方式无参构造带可变参数包的构造移动构造 2. thread类的成员函数thread::detach()thread::get_id()thread::join()thread::joinable() 线程函数参数的问题 二、互斥量库 - mutex标准库提供的四种互斥锁1. std::mutex2. std::recu…

报告!Golang冲上来啦!

今天又来讲Go语言&#xff0c;根据全球知名的编程语言排行榜TIOBE在4月份公布的最新的编程语言排名&#xff0c;令人瞩目的是&#xff0c;Go语言已经跃升至历史最高位&#xff0c;位列排行榜第七名&#xff0c;并且Go语言是前十榜单中最年轻的编程语言。这一成绩不仅彰显了Go语…

java1.8 的 client runtime compiler和server runtime compiler

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

MySQL数据查询优化

MySQL调优是开发中必不可少的内容&#xff0c;以下是对MySQL查询性能优化的部分总结 1. explain关键字的使用 explain关键字可以模拟优化器执行sql查询语句&#xff0c;获取sql的执行信息&#xff0c;使用方法&#xff1a; explainsql语句 1.1 字段详解 id&#xff08;select …

Linux---在Xshell上配置软件包管理器yum

一、什么是yum 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软…

练习题(2024/5/12)

1二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 1: 输入: nums [-1,0,3,5,9,12], target 9 输出: 4…

解决vue3项目打包后部署后某些静态资源图片不加载问题

目录 问题 原因 解决方案 问题 开发完项目打包并部署 然后访问时发现导航栏背景图片没加载 打开浏览器控制台发现这张图片报错404 原因 可能是因为在部署后的服务器环境中对中文文件名的支持不完善。服务器在解析 URL 时可能无法正确识别或编码中文字符&#xff0c;导致无…

数据结构(四)——二叉树和堆(下)

制作不易&#xff0c;三连支持一下呗&#xff01;&#xff01;&#xff01; 文章目录 前言一、二叉树链式结构的实现总结 前言 这篇博客我们将来了解普通二叉树的实现和应用&#xff0c;对大家之前分治和递归的理解有所挑战。 一、二叉树链式结构的实现 1.前置说明 在学习二叉…

网络编程套接字详解

目录 1. 预备介绍 2.网络字节序 3.udp网络程序 4.地址转换函数 5.udp网络编程 1.预备介绍 1.1源IP地址和目标IP地址 举个例子: 从北京出发到上海旅游, 那么源IP地址就是北京, 目标IP地址就是上海. 1.2 端口号 作用: 标识一个进程, 告诉OS这个数据交给那个进程来处理; (1)…

爱分析基于杭州云器Lakehouse实现成本最优的一体化管理,新一代数据平台的建设方式

导读 1.当前&#xff0c;企业在大数据和数据中台建设上取得成果&#xff0c;但数据开发管理仍具挑战性&#xff08;成本、效率、复杂度&#xff09;。 2.随数据平台领域成熟&#xff0c;厂商应结合自身需求&#xff0c;重新思考“基于开源自建数据平台”的重资产模式与“购买…

【AMBA Bus ACE 总线 7.1 -- ACE Domains 介绍 2】

请阅读【AMBA Bus ACE 总线与Cache 专栏 】 欢迎学习:【嵌入式开发学习必备专栏】 文章目录 AxDOMAINAxDOMAIN[1:0]的值及含义AxDOMAIN 在ARM的AXI Coherency Extensions (ACE) 协议中,AxDOMAIN[1:0]是一个重要的信号字段,用于指示传输的域类型。这个字段影响了传输对系统…