面向对象进阶(下)(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();
}
相关推荐
向宇it3 分钟前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行5 分钟前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate
星河梦瑾1 小时前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富1 小时前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想1 小时前
JMeter 使用详解
java·jmeter
言、雲1 小时前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇1 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil72 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。2 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven