Java笔记_9(面向对象进阶)

一、static-静态属性

static表示静态,是Java中的一个修饰符,可以修饰成员方法,成员变量

  1. 被static修饰的成员变量,叫做静态变量

    • 特点:
      • 被该类所有对象共享
      • 跟对象无关,随着类的加载而加载,优先于对象存在
    • 调用方式:
      • 类名调用(推荐)
      • 对象名调用
  2. 被static修饰的成员方法,叫做静态方法

    • 特点:
      • 多用在测试类和工具类中
      • Javabean类中很少会用
    • 调用方式:
      • 类名调用(推荐)
      • 对象名调用

  1. JavaBean类
    • 用来描述一类事物的类。比如,Student,Teacher,Dog,Cat等
  2. 测试类
    • 用来检查其他类是否书写正确,带有main方法的类,是程序的入口
  3. 工具类
    • 不是用来描述一类事物的,而是帮我们做一些事情的类。

1.1、工具类

  1. 类名见名知意
  2. 私有化构造方法
  3. 方法定义为静态

用工具类构造方法,相当于构造函数,如果定义好了工具类,那么直接再次想要复用方法时,可以直接复制类中的代码。

1.2、static的注意事项

  • 静态方法只能访问静态变量和静态方法
  • 非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
  • 静态方法中是没有this关键字

总结:

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

1.3、重新认识main方法

public class Helloworld {
    
    
	public static void main(String[] args) {
    
    
		system.out.println( "Helloworld");
	}
}
  • public : 被JVM调用,访问权限足够大
  • static:被JVM调用,不用创建对象,直接类名访问因为main方法是静态的,所以测试类中其他方法也需要是静态的。
  • void:被JVM调用,不需要给JVM返回值
  • main:一个通用的名称,虽然不是关键字,但是被JVM识别
  • String[] args:以前用于接收键盘录入数据的,现在没用

二、继承

2.1、继承的概念

封装:对象代表什么,就得封装对应的数据,并提供数据对应的行为

继承:

  • Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起继承关系。
public class Student/*子类*/ extends Person/*父类*/ {
    
    }
  • Student称为子类(派生类),Person称为父类(基类或者超类)

使用继承的好处:

  • 可以把多个子类中重复的代码抽取到父类中了,提高代码的复用性。
  • 子类可以在父类的基础上,增加其他的功能,使子类更强大。

什么时候用继承?
当类与类之间,存在相同(共性)的内容,并满足子类是父类中的一种,就可以考虑使用继承,来优化代码

2.2、继承的特点和继承体系的设计

Java只支持单继承,不支持多继承,但支持多层继承

  • 单继承:一个子类只能继承一个父类
  • 不支持多继承:子类不能同时继承多个父类
  • 多层继承:子类A继承父类B,父类B可以继承父类C

每一个类都直接或者间接的继承于Object(祖宗类)
在这里插入图片描述
总结

  1. Java只能单继承,不能多继承、但是可以多层继承。
  2. Java中所有的类都直接或者间接继承于Object类。
  3. 子类只能访问父类中非私有的成员

2.3、子类到底能继承父类中的那些内容

在这里插入图片描述

  1. 构造方法

    • 构造方法不能被子类继承下来
      构造方法的方法名需要与类名相同,如果继承下来的话两者就不相同了所以无法继承
  2. 成员变量

    • 无论是否私有都能被成员变量继承,不过私有的不能直接使用

无private修饰类型:
在这里插入图片描述

  1. 成员方法
    在这里插入图片描述

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

成员变量的访问特点

  • 就近原则:谁离得近访问谁
  • 先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。

重名:

package entends.aFUzientends;
public class Text{
    
    
    public static void main(String[] args){
    
    
        zi z = new zi();
        z.ziShow();
    }
}
class Fu {
    
    
    String name = "fu";
}
class zi extends Fu{
    
    
    String name = "zi";
    public void ziShow(){
    
    
        String name = "zishow";
        System.out.println(name);//zishow
        System.out.println(this.name);//zi
        System.out.println(super.name);//fu
    }
}

super指向下会调用父类里面的成员变量

this指向下会调用子类里面的成员变量,如果子类没有就会向父类寻找

没有指向就会采用就近原则来调用变量

成员方法的访问特点

  • 直接调用满足就近原则:谁离我近,我就用谁
  • super调用,直接访问父类

方法的重写
当父类的方法不能满足子类现在的需求时,需要进行方法重写

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

@Override重写注解

  1. @Override是放在重写后的方法上,校验子类重写时语法是否正确。

  2. 加上注解后如果有红色波浪线,表示语法错误。

  3. 建议重写方法都加@Override注解,代码安全,优雅!
    在这里插入图片描述
    方法重写注意事项和要求

    1. 重写方法的名称、形参列表必须与父类中的一致。
    2. 子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解 :空着不写< protected < public)
    3. 子类重写父类方法时,返回值类型子类必须小于等于父类
    4. 建议:重写的方法尽量和父类保持一致。
    5. 只有添加到虚方法表中的方法才能被重写

2.5、利用方法的重写设计继承结构

在这里插入图片描述

package entends.chongxieAnimal;

public class Text {
    
    
    public static void main(String[] args) {
    
    
        hasky dog1 = new hasky();
        shapi dog2 = new shapi();
        chineseDog dog3 = new chineseDog();

        dog1.Eat();
        dog2.Eat();
        dog3.Eat();

        dog1.play();
        dog2.drink();
        dog3.lookhome();
    }
}
package entends.chongxieAnimal;

public class Dog {
    
    
    public void Eat(){
    
    
        System.out.println("吃狗粮");
    }
    public void drink(){
    
    
        System.out.println("喝水");
    }
    public void lookhome(){
    
    
        System.out.println("看家");
    }
}

package entends.chongxieAnimal;

public class chineseDog extends Dog{
    
    
    @Override
    public void Eat(){
    
    
        System.out.println("吃剩饭");
    }
}

package entends.chongxieAnimal;

public class hasky extends Dog {
    
    
    public void play(){
    
    
        System.out.println("拆家");
    }
}
package entends.chongxieAnimal;

public class shapi extends Dog {
    
    
    @Override
    public void Eat(){
    
    
    	super.Eat()
        System.out.println("吃骨头);
    }
}

2.6、继承中的构造方法

  • 父类中的构造方法不会被子类继承
  • 子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。

为什么?

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

怎么调用父类构造方法的?

  • 子类构造方法的第一行语句默认都是: super(),不写也存在,且必须在第一行
  • 如果想调用父类有参构造,必须手动写**super()**进行调用。
public class Person (){
    
    
	String name;
	int age;
	pnblic Person(){
    
    
		System.out.println("父类的无参构造")
	}
	pnblic Person(String name,int age){
    
    
		this.name = name;
		this.age = age;
	}
}

public class Student (){
    
    
	public Student(){
    
    
		super();
		System.out.println("子类的无参构造")
	}
	public Student (String name,int age){
    
    
		super(name,age);
	}
}
public class Text(){
    
    
	public static void main(String[] args){
    
    
		Student s = new Student(zhangsan,23);
	}
}

2.7、this super关键字

  • this:理解为一个变量,表示当前方法调用者的地址值;
  • super:代表父类存储空间。
关键字 访问成员变量 访问成员方法 访问构造方法
this this.成员变量 访问本类成员变量 this.成员方法 访问本类成员方法 this.(…) 访问本类构造方法
super super.成员变量 访问父类成员变量 super.成员方法 访问父类成员方法 super.(…) 访问父类构造方法

2.8、练习-带有继承结构的标准JavaBean类

在这里插入图片描述

package entends.extendsjavabean;

public class text {
    
    
    Manger a = new Manger(001,"xiaoli",8000,3000);
    cooker b = new cooker(002,"xiaowang",8000);

}

package entends.extendsjavabean;

public class Emplyee {
    
    
    private int num;
    private String name;
    private int money;


    public void work(){
    
    
        System.out.println("员工在工作");
    }
    public void eat(){
    
    
        System.out.println("吃米饭");
    }
    public Emplyee() {
    
    
    }

    public Emplyee(int num, String name, int money) {
    
    
        this.num = num;
        this.name = name;
        this.money = money;
    }

    public int getNum() {
    
    
        return num;
    }

    public void setNum(int num) {
    
    
        this.num = num;
    }

    public String getName() {
    
    
        return name;
    }

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

    public int getMoney() {
    
    
        return money;
    }

    public void setMoney(int money) {
    
    
        this.money = money;
    }

    public String toString() {
    
    
        return "Emplyee{num = " + num + ", name = " + name + ", money = " + money + "}";
    }
}
package entends.extendsjavabean;

public class Manger extends Emplyee{
    
    
    private int boen;
    public Manger() {
    
    
    }
    public Manger(int num,String name,int money,int boen) {
    
    
        super(num,name,money);
        this.boen = boen;
    }

    public int getBoen() {
    
    
        return boen;
    }
    public void setBoen(int boen) {
    
    
        this.boen = boen;
    }

    public String toString() {
    
    
        return "Manger{boen = " + boen + "}";
    }

    @Override
    public void work() {
    
    
        System.out.println("管理别人");
    }
}
package entends.extendsjavabean;

public class cooker extends Emplyee{
    
    
    @Override
    public void work() {
    
    
        System.out.println("炒菜");
    }
    public cooker(){
    
    

    }
    public cooker(int num,String name,int money){
    
    
        super(num,name,money);
    }
}

三、多态

3.1、认识多态

什么是多态?
同类型的对象,表现出的不同形态。

多态的表现形式
父类类型 对象名称=子类对象;

多态的前提

  • 有继承关系
  • 有父类引用指向子类对象
    Fu f = new Zi();
  • 方法重写

多态的好处
使用父类型作为参数,可以接受所有子类对象,体现多态的扩展性与便利

3.2、多态中调用成员的特点

  • 变量调用:编译看左边,运行也看左边。
    • 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。
    • 运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
  • 方法调用:编译看左边,运行看右边。
    • 编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。
    • 运行看右边: java运行代码的时候,实际上运行的是子类中的方法。

3.3、多态的优势和弊端

优势:

  • 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
  • 定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。

弊端:

  • 不能调用子类的特有功能
//假设有三个类,其中animal类是Dog类和Cat类的父类
//进行类的转换
animal a = new Dog;

if(a instanceof Dog){
    
    
	Dog b = (Dog)a;
	b.lookhome();
}else if (a instanceof Cat c){
    
    
	Cat c = (Cat)a;
	c.catmouse();
}else{
    
    
	System.out.println("没有这个类型,无法转换")
}

//JDK14之后的新特性
if(a instanceof Dog b){
    
    
	b.lookhome();
}else if (a instanceof Cat c){
    
    
	c.catmouse();
}else{
    
    
	System.out.println("没有这个类型,无法转换")
}


3.4、多态的综合练习

package entends.Polymorphism02;

public class Text {
    
    
    public static void main(String[] args) {
    
    
        Dog b = new Dog(2,"黑色");
        Cat c = new Cat(2,"白色");

        Person p = new Person("老王",40);

        p.keepPet(b,"骨头");
        p.keepPet(c,"小鱼干");
    }
}
package entends.Polymorphism02;

public class animal {
    
    
    private int age;
    private String color;

    public animal() {
    
    
    }

    public animal(int age, String color) {
    
    
        this.age = age;
        this.color = color;
    }
    public int getAge() {
    
    
        return age;
    }
    public void setAge(int age) {
    
    
        this.age = age;
    }
    public String getColor() {
    
    
        return color;
    }
    public void setColor(String color) {
    
    
        this.color = color;
    }

    public void eat(String somthing){
    
    
        System.out.println("正在吃东西");
    }

}
package entends.Polymorphism02;

public class Dog extends animal {
    
    

    public Dog(int age,String color){
    
    
        super(age,color);
    }
    @Override
    public void eat(String somthing){
    
    
        System.out.println(getAge()+"岁的"+getColor()+"的狗正在抱着"+somthing+"吃");
    }
    public void lookHome(){
    
    
        System.out.println("狗正在看家");
    }
}
package entends.Polymorphism02;

public class Cat extends animal{
    
    

    public Cat(int age,String color){
    
    
        super(age,color);
    }
    @Override
    public void eat(String somthing){
    
    
        System.out.println(getAge()+"岁的"+getColor()+"的猫正在抱着"+somthing+"吃");
    }
    public void catchMouse(){
    
    
        System.out.println("猫正在抓老鼠");
    }
}
package entends.Polymorphism02;

public class Person {
    
    
    private String name;
    private int age;


    public Person() {
    
    
    }

    public void keepPet(animal a,String something){
    
    
        if(a instanceof Dog b){
    
    
            System.out.println(getAge()+"岁的"+getName()+"正在用"+something+"喂养狗");
            b.eat(something);
        } else if (a instanceof Cat c) {
    
    
            System.out.println(getAge()+"岁的"+getName()+"正在用"+something+"喂养猫");
            c.eat(something);
        }
    }

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

}

3.5、包和final

包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护。

  • 包名的规则:公司域名反写+包的作用,需要全部英文小写,见名知意。

包名+类名 被称为:全类名或者全限定名

使用其他类的规则

  • 使用同一个包中的类时,不需要导包。
  • 使用java.lang包中的类时,不需要导包。
  • 其他情况都需要导包
  • 如果同时使用两个包中的同名类,需要用全类名。

final

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

常量
实际开发中,常量一般作为系统的配置信息,方便维护,提高可读性。常量的命名规范:

  • 单个单词:全部大写
  • 多个单词:全部大写,单词之间用下划线隔开

细节:

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

3.6、权限修饰符

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

在这里插入图片描述
实际开发中,一般只用private和public

  • 成员变量私有
  • 方法公开

特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有。

3.7、代码块

  • 局部代码块
    • 写在括号里面的代码块
  • 构造代码块
    • 作用:可以把多个构造方法中重复的代码抽取出来
    • 执行时机:我们在创建本类对象的时候会先执行构造代码块在执行代码块
    • 写在成员位置中,把带参构造以及无参构造的函数里面相同的代码抽取出来,放在代码块(括号),就是构造代码块
  • 静态代码块
    • 格式 static{}
    • 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
    • 使用场景:在类加载的时候,做一些数据初始化的时候使用

四、抽象类与接口

4.1、抽象类和抽象方法

  • 抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。
  • 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类

抽象类和抽象方法的定义格式

  • 抽象方法的定义格式:
    public abstract 返回值类型 方法名(参数列表)
  • 抽象类的定义格式:
    public abstract class 类名{}

抽象类和抽象方法到的注意事项

  • 抽象类不能实例化
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
  • 可以有构造方法
  • 抽象类的子类
    • 要么重写抽象类中的所有抽象方法
    • 要么是抽象类

在这里插入图片描述
在这里插入图片描述

package abstract_.A0dome1;

public abstract class animal {
    
    
    private String name;
    private int age;

    public animal() {
    
    
    }

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

    public void drink(){
    
    };
    public abstract void eat();

    /**
     * 获取
     * @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 + "}";
    }
}
package abstract_.A0dome1;

public class Dog extends animal {
    
    
    public Dog(String name,int age) {
    
    
        super(name,age);
    }
    @Override
    public void eat() {
    
    
        System.out.println("吃骨头");
    }
}
package abstract_.A0dome1;

public class frog extends animal{
    
    
    public frog(String name,int age) {
    
    
        super(name,age);
    }

    @Override
    public void eat() {
    
    
        System.out.println("吃虫子");
    }
}
package abstract_.A0dome1;

public class sheep extends animal{
    
    
    public sheep(String name,int age) {
    
    
        super(name,age);
    }
    @Override
    public void eat() {
    
    
        System.out.println("吃草");
    }
}
package abstract_.A0dome1;

public class Text {
    
    
    public static void main(String[] args) {
    
    
        Dog d = new Dog("quiqui",2);

        frog f = new frog("xiao",2);

        sheep s = new sheep("meiyangyang",3);

        d.eat();
        f.eat();
        s.eat();

    }
}

4.2、接口

接口的定义和使用

  • 接口用关键字interface来定义
    public interface接口名{}
  • 接口不能实例化
  • 接口和类之间是实现关系,通过implements关键字表示
    public class类名implements接口名l
  • 接口的子类(实现类)
    要么重写接口中的所有抽象方法
    要么是抽象类

注意1:接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements接口名1,接口名2{}
注意2:实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements接口名1,接口名2{}

在这里插入图片描述

package interface_.aDome1;

public abstract class animal {
    
    
    private String name;
    private int age;

    public animal() {
    
    
    }

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

    public abstract void eat();

    /**
     * 获取
     * @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 + "}";
    }
}
package interface_.aDome1;

public class dog extends animal implements swim{
    
    
    public dog(){
    
    };
    public dog(String name ,int age){
    
    
        super();
    }
    @Override
    public void eat() {
    
    
        System.out.println("狗吃骨头");
    }

    @Override
    public void swim() {
    
    
        System.out.println("狗刨");
    }
}
package interface_.aDome1;

public class forg extends animal implements swim{
    
    
    public forg(){
    
    };
    public forg(String name ,int age){
    
    
        super(name,age);
    }
    @Override
    public void eat() {
    
    
        System.out.println("青蛙吃虫子");
    }

    @Override
    public void swim() {
    
    
        System.out.println("蛙泳");
    }
}
package interface_.aDome1;

public class rabbit extends animal{
    
    

    public rabbit(){
    
    };
    public rabbit(String name ,int age){
    
    
        super();
    }
    @Override
    public void eat() {
    
    
        System.out.println("兔子吃胡萝卜");
    }
}
package interface_.aDome1;

public  interface swim {
    
    
    void eat();

    public abstract void swim();
}
package interface_.aDome1;

public class Text {
    
    
    public static void main(String[] args) {
    
    
        dog g = new dog("quiqui",2);
        forg f =new forg("qiongwa",2);
        rabbit r = new rabbit("tuzxi",3);

        g.eat();
        g.swim();

        f.eat();
        f.swim();

        r.eat();
    }
}

4.3、接口的细节

接口中成员的特点

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

接口和类之间的关系

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

4.4、练习-编写带有接口和抽象类的标准JavaBean类

在这里插入图片描述

package interface_.aDome2;

public 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 + "}";
    }
}
package interface_.aDome2;

public abstract class Player extends Person {
    
    
    public Player(){
    
    };
    public Player(String name,int age){
    
    
        super(name,age);
    };
    public abstract void study();
}
package interface_.aDome2;

public abstract class trainer extends Person {
    
    
    public trainer(){
    
    };
    public trainer(String name,int age){
    
    
        super(name,age);
    };
    public abstract void teaching();
}
package interface_.aDome2;

public interface english {
    
    
    public abstract void sayenglish();
}
package interface_.aDome2;

public class basketballplay extends Player{
    
    
    public basketballplay(){
    
    };
    public basketballplay(String name,int age){
    
    
        super(name,age);
    };
    @Override
    public void study() {
    
    
        System.out.println("学篮球");
    }
}
package interface_.aDome2;

public class basketballtariner extends trainer {
    
    
    public basketballtariner(){
    
    };
    public basketballtariner(String name,int age){
    
    
        super(name,age);
    };
    @Override
    public void teaching() {
    
    
        System.out.println("学篮球");
    }

}
package interface_.aDome2;

public class pingpangplayer extends Player implements english{
    
    
    public pingpangplayer(){
    
    };
    public pingpangplayer(String name,int age){
    
    
        super(name,age);
    };
    @Override
    public void study() {
    
    
        System.out.println("学乒乓球");
    }

    @Override
    public void sayenglish() {
    
    
        System.out.println("说英语");
    }
}
package interface_.aDome2;

public class pingpangtrainer extends Player implements english{
    
    
    public pingpangtrainer(){
    
    };

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

    @Override
    public void study() {
    
    
        System.out.println("教乒乓球");
    }

    @Override
    public void sayenglish() {
    
    
        System.out.println("说英语");
    }
}

4.5、多学三招

JDK8开始接口中新增的方法

JDK7以前:接口中只能定义抽象方法。
JDK8的新特性:接口中可以定义有方法体的方法。(默认、静态)
JDK9的新特性:接口中可以定义私有方法。

JDK8新特性

  • 允许在接口中定义默认方法,需要使用关键字default修饰

    • 作用:解决接口升级的问题
  • 接口中默认方法的定义格式:
    格式:public default 返回值类型 方法名(参数列表){};

  • 接口中默认方法的注意事项:

    • 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字
    • public可以省略,default不能省略
    • 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
  • 允许在接口中定义定义静态方法,需要用static修饰

  • 接口中静态方法的定义格式:

    • 格式: public static 返回值类型 方法名 (参数列表) {}
    • 范例: public static void show(){ }
  • 接口中静态方法的注意事项:

    • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
    • public可以省略,static不能省略

JDK9新增的方法
接口的私有方法,此方法只为Inter接口提供服务,不需要外类访问

接口中私有方法的定义格式:
普通的私有方法(为普通的方法服务):

  • 格式1: private 返回值类型 方法名 (参数列表) {}
  • 范例1: private void show(){}

静态的私有方法(为静态的方法服务):

  • 格式2: private static 返回值类型 方法名 (参数列表){}
  • 范例2: private static void method(){}

接口的应用

  1. 接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
  2. 当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。

适配器设计模式

  1. 当一个接口中抽象方法过多,但是我只要使用其中一部分的
    时候,就可以适配器设计模式
  2. 书写步骤:
    1. 编写中间类XXXAdapter实现对应的接口
    2. 对接口中的抽象方法进行空实现
    3. 让真正的实现类继承中间类,并重写需要用的方法
    4. 为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰

五、内部类

5.1、初始内部类

类的五大成员:
属性,方法,构造方法,代码块,内部类

  • 在一个类的里面,再定义一个类

当B类表示的事物是A类的一部分,且B单独存在没有意义,此时就可以使用到内部类

5.2、内部类的分类

  • 成员内部类
  • 静态内部类
  • 局部内部类
  • 匿名内部类

成员内部类的代码如何书写

  • 写在成员位置的,属于外部类的成员
  • 成员内部类可以被一些修饰符所修饰,比如:private,默认,protected, public, static等
  • 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
public class Car{
    
    //外部类
	String carName;
	int carAge;
	int carColor;
	class Engine(//成员内部类
		String engineName;
		int engineAge;
	)
}
  • 用private修饰的成员内部类只能在本类里面进行实例化

获取成员内部类对象

  • 方法一:
    在外部类中编写方法,对外提供内部类的对象。
  • 方式二:
    直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

成员内部类如何获取外部类的成员变量

外部类变量名和内部类变量成员变量重名时,在内部类如何访问

System.out.println(Outer.this.变量名)

在这里插入图片描述

package innerclass.aDome1;

public class Outer {
    
    
    String name;
    private int a = 10;
    public class Inner{
    
    
        private int a = 20;
        public void show(){
    
    
            int a = 30;
            System.out.println(a);
            System.out.println(this.a);
            System.out.println(Outer.this.a);
        }
    }
}
package innerclass.aDome1;

public class text {
    
    
    public static void main(String[] args) {
    
    
         Outer.Inner o = new Outer().new Inner();

         o.show();
    }
}

5.3、静态内部类

静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。

创建静态内部类对象的格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

  • 例:Outer.inner oi = new Outer.inner()

调用非静态方法的格式:先创建对象,用对象调用
调用静态方法的格式:外部类名.内部类名.方法名();

5.4、局部内部类

  1. 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。
  2. 外界是无法直接使用,需要在方法内部创建对象并使用。
  3. 该类可以直接访问外部类的成员,也可以访问方法内的局部变量。

5.5、匿名内部类

匿名内部类本质上就是隐藏了名字的内部类

//格式:
new 类名或者接口名(){
    
    
	重写方法;
};
  • 继承\实现
  • 方法重写
  • 创建对象

例:

new Inter(){
    
    
	public void show(){
    
    
	}
};
  • 什么是匿名内部类?
    隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。

  • 格式的细节
    包含了继承或实现,方法重写,创建对象。
    整体就是一个类的子类对象或者接口的实现类对象

  • 使用场景
    当方法的参数是接口或者类时,
    以接口为例,可以传递这个接口的实现类对象,
    如果实现类只要使用一次,就可以用匿名内部类简化代码。

猜你喜欢

转载自blog.csdn.net/weixin_74155781/article/details/129961121