面向对象进阶(下)(JAVA笔记第二十二期)

p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解

目录

抽象方法和抽象类

抽象方法:如果一个方法抽取到父类中,不确定方法体,那就不要写方法体,再用abstract关键字修饰,那么这个方法就叫做抽象方法。

作用:父类有抽象方法,子类必须强制重写 抽象方法,否则子类代码直接报错

而抽象方法所在的类就叫抽象类

抽象方法:将共性(同名)的行为(方法)抽取到父类之后,由于每一个子类执行的内容不一样,所以在父类当中无法确定具体的方法体 ,该方法即可定义为抽象方法

抽象类:如果一个类里面存在抽象方法,,那么该类则必须声明为抽象类

抽象方法定义格式

java 复制代码
public abstract 返回值类型 方法名(参数列表);

抽象类定义格式

java 复制代码
public abstract class 类名{}

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

抽象类不能实例化(即不能创建对象)

抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

抽象类可以有构造方法

抽象类的子类要么重写抽象类中的所有 抽象方法,要么是抽象类

举例

java 复制代码
public abstract class Person {

    private String name;
    private int age;

    public abstract void work();


    public Person() {}
    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;
    }
}
//=============================================
class  Student extends Person{

    @Override
    public void work() {
        System.out.println("学生的工作就是学习");
    }
    //重写抽象类的所有抽象方法

    public Student() {}

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

}
//=============================================
class Test{
    public static void main(String[] args) {
        Student student = new Student("张三",18);
        System.out.println(student.getName()+", "+student.getAge());
    }
}

接口

接口是一个抽象类型,是抽象方法的集合,一个类通过继承接口的方式,从而来继承接口的抽象方法。(可以看作是一种规则)

.

接口的子类也叫实现类,其要么实现重写接口当中所有的抽象方法,要么其为一个抽象类

.

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

.

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。(具体原因参考抽象方法与抽象类)

.

接口无法被实例化,即不能创建接口的对象,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。

.

接口的定义

接口用interface来定义

格式

java 复制代码
public interface 接口名{}

接口与类之间是实现关系,通过implements关键字表示

格式

java 复制代码
public class 类名  implements 接口名{}

注意:一个类可以实现单个接口(单实现),也可以实现多个接口(多实现)

举例

java 复制代码
public class 类名  implements 接口名1,接口名2{}

注意:实现类可以在继承一个类的同时实现多个接口

举例

java 复制代码
public class 类名 extends 父类 implements 接口名1,接口名2{}

接口中成员变量的特点

只能是常量

默认修饰符:public static final (即就算你不加,系统也会自动给你加上)

调用方式:接口名.常量名

接口中没有构造方法

接口中成员方法的特点

JDK8以后接口中可以定义抽象方法、有方法体的方法(默认方法、静态方法)、私有方法。

其中抽象方法也有默认修饰符:pubilc abstract



在接口中定义具有方法体的方法

在接口中新增默认方法(解决接口升级的问题)

由于只要添加接口中的抽象方法时,其对应的实现类也要添加对应的抽象方法,否则实现类就会报错

所以JDK8以后允许在接口中定义默认方法 ,需要用关键字default修饰

定义格式为

java 复制代码
public default 返回值类型 方法名(参数列表){   }

注意:默认方法不是抽象方法,所以不强制重写。但是如果被重写,重写的时候要去掉default关键字

public可省略,但default关键字不可以省略

如果实现了多个接口,多个接口中存在同名的默认方法,则子类就必须对该方法进行重写(因为系统不知道你以后调用的是哪个接口中的默认方法,干脆让你重写得了)

在接口中新增静态方法(不能被重写)

JDK8以后允许在接口中定义静态方法,需要用关键字static修饰

定义格式为

java 复制代码
public static 返回值类型 方法名(参数列表){   }

注意:静态方法只能通过接口名调用,不能通过实现类名或对象名调用

public可省略,但static关键字不可以省略

接口和实现类中有两个重名的静态方法,这不叫重写,只是恰好同名而已

在接口中新增私有方法

由于在接口中有一些方法的代码重复了,但我又不想让这些代码被别的接口、类使用,于是我们便可以将这些代码写在一个方法里并将其私有化,使其只能在本接口中使用。

JDK9以后允许在接口中定义私有方法,需要用关键字private修饰,且不能加用default修饰

.

给默认方法调用的叫普通私有方法

java 复制代码
private 返回值类型 方法名(参数列表){   }

给静态方法调用的叫静态私有方法

java 复制代码
private static 返回值类型 方法名(参数列表){   }

.

接口与类之间的关系

类与类之间的关系

继承关系。只能单继承,不能多继承,但是可以多层继承

类与接口之间的关系

实现关系。可以单实现,也能多实现,还可以再继承一个类的时候同时实现多个接口

如果实现类实现了多个接口。那么就要把所有接口的所有抽象方法进行重写

如果有多个重名的抽象方法,这个抽象方法只需要重写一次就可以了

接口与接口之间的关系

继承关系。能单继承,也能多继承

如果实现类实现的是底层的子接口,那么实现类要把该接口以及其所有父类接口里面的抽象方法重写

接口的多态

当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称为接口多态

定义格式:接口类型 变量 = new 实现类对象();

其遵守编译看左边、运行看右边的原则

设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结(说白了就是一套公式)

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码的可用性、程序的重用性

适配器设计模式

解决接口和实现类之间的矛盾问题:接口中有n个抽象方法,但实现类只想使用其中一个。如果重写所有抽象方法会提高后期代码的维护难度

适配器设计模式解决方案:定义一个中间类(即适配器)(xxxAdapter)(一般是抽象类,目的是为了让外界无法创建它的对象)实现接口并且对接口中的抽象方法进行空实现(即重写接口中的抽象方法但不写方法体)

这时再让原本的实现类不再实现接口,而是继承中间类。这样需要使用哪个方法,就重写那个方法就行了

内部类

内部类就是在一个类里面再定义一个类

我们可以在外部其他类中创建内部类的对象并调用内部类的方法

意义:假如创建一个汽车的JavaBean类型,属性有发动机的年龄、最大功率、汽车颜色、汽车品牌。

这时我们便可以将发动机的属性定义在一个内部类里面,从而提高了代码的可读性
内部类一般来说遵循以下规则:

内部类中的事物是外部类中的一部分;内部类单独出现没有任何意义(比如汽车的发动机、人的大脑)
内部类的访问特点:

内部类可以直接访问外部类的成员,包括私有;外部类要访问内部类的成员,必须创建对象

内部类分为四种:成员内部类、静态内部类、局部内部类、匿名内部类

成员内部类

写在成员位置(类中方法外)的,属于外部类的成员之一(比如汽车的发动机)

成员内部类可以被一些修饰符所修饰,比如private、默认、protected、public等

用private修饰则外部其他类不能直接创建内部类的对象,只能在外部类里面创建内部类的对象

默认的话则内部类只能在本包当中使用,在其他包里面不起作用

用protected修饰则在其他包的子类中也可以使用

用public修饰则所有的地方都可以创建成员内部类的对象

.

JDK16以后,在成员内部类里面可以定义静态变量

获取成员内部类的对象

方法一:在外部类中编写方法,对外提供内部类的对象(成员内部类被private修饰的时候)

举例:

java 复制代码
   public Inner getInstance(){
       return new Inner();
 } 

方法二:直接创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象

举例:Outer.Inner inner = new Outer().new Inner();

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

若没有重名,就直接调用

若重名,则外部类名.this.变量名

举例

java 复制代码
public class Outer {
    private int a = 10;
    class Inner{
        private int a = 20;

        public void show(){
            int a = 30;

            System.out.println(Outer.this.a);//a==10
            System.out.println(this.a);//a==20
            System.out.println(a);//a==30
        }
    }
}

内存原理分析

特殊的成员内部类:静态内部类

如果成员内部类前面用static修饰,则这个成员内部类就叫做静态内部类

静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象,再用外部类的对象进行调用
静态内部类的实例不依赖于外部类的实例。

创建静态内部类的对象

创建格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象

举例:Outer.Inner inner = new Outer.Inner();

只要是静态的东西,都可以用类名.来获取

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

局部内部类

将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量

外界无法直接使用,需要在方法内创建对象并使用

该类可以直接访问外部类的成员,也可以访问方法内的局部变量

举例

java 复制代码
public class Outer1 {
    int a = 10;

    public void show(){
        int b = 20;

        class Inner{//局部内部类
            String name;
            int age;

            public void method(){
                System.out.println("访问外部类的成员"+a);
                System.out.println("访问局部变量"+b);

                System.out.println("局部内部类的方法");
            }

            public static void method1(){
                System.out.println("局部内部类的静态方法");
            }
        }

        //在局部方法中创建内部类的对象
        Inner inner = new Inner();

        System.out.println(inner.age);
        System.out.println(inner.name);

        inner.method();
        Inner.method1();


    }
}
//=========================================================
class Test1{
    public static void main(String[] args) {
        Outer1 outer1 = new Outer1();
        outer1.show();
    }
}

匿名内部类

匿名内部类,即隐藏了名字的内部类。可以写在成员位置,也可以写在局部位置


格式

java 复制代码
new 类名或接口名(){
    重写方法;
};

上面的整体格式为创建一个匿名内部类对象 的格式

其中包含了三部分:继承/实现、方法重写、创建对象
理解匿名内部类的定义格式

使用场景

当方法的参数是接或者类的时候

以接口为例,可以传递这个接口的实现类对象
如果实现类中使用一次的话,就可以使用匿名内部类简化代码

举例

java 复制代码
public class Test2 {
    public static void main(String[] args) {
        

        method( new Animal(){
            @Override
            public void eat() {
                System.out.println("狗吃骨头");
            }
        });
        //创建一个匿名内部类对象并作为参数
        
    }

    public static void method(Animal animal){
        animal.eat();
    }

}

abstract class Animal{
    public abstract void eat();
}
相关推荐
不爱学习的YY酱27 分钟前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
丁总学Java32 分钟前
Maven项目打包,com.sun.tools.javac.processing
java·maven
kikyo哎哟喂42 分钟前
Java 代理模式详解
java·开发语言·代理模式
duration~1 小时前
SpringAOP模拟实现
java·开发语言
小码ssim1 小时前
IDEA使用tips(LTS✍)
java·ide·intellij-idea
潜洋1 小时前
Spring Boot教程之五:在 IntelliJ IDEA 中运行第一个 Spring Boot 应用程序
java·spring boot·后端
暮志未晚Webgl2 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
红色的山茶花2 小时前
YOLOv8-ultralytics-8.2.103部分代码阅读笔记-block.py
笔记·深度学习·yolo
坚硬果壳_2 小时前
《硬件架构的艺术》笔记(六):流水线的艺术
笔记·硬件架构
小叶lr2 小时前
idea 配置 leetcode插件 代码模版
java·leetcode·intellij-idea