11.抽象类、接口、内部类,Object、Objects

一.抽象类

1.1 什么是抽象类

使用abstract关键字修饰的类称为抽象类,修饰的方法称为抽象方法。

1.2 抽象类的特点

  • 类有的成员(成员变量、成员方法、构造器、代码块、内部类),抽象类都具备。

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

  • 一个类如果继承了抽象类,那么这个类必须重写完抽象类的所有抽象方法,否则这个类也必须定义成抽象类。

  • 抽象方法只有方法签名,没有方法体。

  • 不能用abstract关键字修饰成员变量、构造器、代码块。

  • 最重要的特征:得到了抽象方法,失去了创造对象的能力。

1.3 抽象类的使用场景

  • 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。

  • 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。

1.4 final和abstract的关系

final 和 abstract 是互斥关系,

  • abstract修饰的类作为模板让子类继承,final定义的类不能被继承。

  • 抽象方法定义抽象功能让子类重写,final定义的方法子类不能重写。

二.接口

2.1 什么是接口

接口是一种规范,主要用来对类的行为进行约束,当类实现了某个接口就具有了对应的行为。接口的特征如下:

  • 接口中的方法默认都是 public abstract 类型,属性默认都是 public static final 类型。

  • 接口不能实例化。

2.2 接口定义的格式

public interface 接口名{
    //常量
    
    //抽象方法
}

2.3 接口的用法

  • 接口是用来被类实现的,实现接口的类称为实现类。接口可以被类单实现,也可以被类多实现。

  • 接口实现的注意事项:一个类实现接口,必须重写完全部接口的抽象方法,否则这个类需要定义成抽象类。

2.4 接口之间的继承

接口和接口之间的继承关系:接口和接口之间是多继承,一个接口可以继承多个接口。

接口多继承的作用:规范合并,整合多个接口为同一个接口,便于子类实现。

2.5 JDK8开始接口中新增方法

JDK8以后,接口新增了二种方法,分别为默认方法和静态方法。

1.默认方法:默认用public修饰,必须用default修饰,类似于普通实例方法。需要用接口的实现类的对象来调用。

例如:

2.静态方法:默认用public修饰,必须用static修饰。接口的静态方法必须用接口名来调用。

例如:

3.私有方法:从 JDK1.9 开始支持,使用private修饰,就是私有的实例方法。只能在本类中被其他的默认方法或私有方法访问。

例如:

4.为什么 JDK8 以后接口新增了方法

如果一个项目 Version1.0 成功上线之后没有问题,项目 Version2.0 需要对某些接口新增方法,这样的话,所有接口的子类都要重写这个新增方法,为了避免这种情况,Java 允许了接口新增方法。

2.7 接口的注意事项

  • 接口不能创建对象。

  • 一个类实现多个接口,多个接口的规范不能冲突。

  • 一个类实现多个接口,多个接口中有同样的静态方法不冲突。

  • 一个类继承了父类,同时又实现了接口,父类中和接口有同名方法,默认调用父类的。

  • 一个类实现了多个接口,多个接口中存在同名的默认方法,这个类重写此方法即可避免冲突。

  • 一个接口继承多个接口是没有问题的,如果多个接口存在规范冲突,则不能多继承。

三.内部类

3.1 内部类概述

什么是内部类

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

内部类的使用场景

当一个事物的内部,还有一个部分需要完整的结构进行描述时。

内部类的基本作用

  • 内部类通常可以方便的访问外部类的成员,包括私有的成员。

  • 内部类提供了更好的封装性,内部类本身就可以用private、protected等修饰,封装性可以做更多控制。

3.2 内部类的分类

  • 静态内部类

  • 成员内部类

  • 局部内部类

  • 匿名内部类

3.5 静态内部类

什么是静态内部类

有 static 修饰,属于外部类本身。它的使用与外部类完全一样,类有的成分他都有,只是位置在别人里面而已。

格式

静态内部类定义的格式:

静态内部类创建对象的格式:

外部类名.内部类名  对象名  =  new  外部类名.内部类名.构造器;

例如:

Outer.Inner in =  new Outer.Inner();

静态内部类访问外部类的特点

  • 静态内部类可以直接访问外部类的静态成员。

  • 静态内部类不可以直接访问外部类的实例成员,但可以在静态内部类中创建对象的方式间接访问。

3.6 成员内部类

什么是成员内部类

无static修饰,属于外部类的对象。JDK16 之前,成员内部类中不能定义静态成员,JDK16 开始也可以定义静态成员了。

格式

成员内部类定义格式:

成员内部类创建对象的格式:

成员内部类访问外部类的特点

  • 成员内部类可以直接访问外部类的静态成员。

  • 成员内部类可以直接访问外部类的实例成员。

Note:在成员内部类的方法中访问外部类的重名成员,用 外部类名.this.名称 访问

3.7 局部内部类

局部内部类放在成员变量、成员方法、构造器中,基本没啥作用,了解即可。

3.8 匿名内部类

什么是匿名内部类

本质上是一个没有名字的局部内部类。匿名内部类必须基于一个普通的类抽象类接口来创建。有了匿名内部类之后,可以不用单独写实现类,可以直接在创建对象时写一个匿名内部类代替子类,从而简化代码编写。

匿名内部类的格式

其中,new 关键字后面紧跟要创建的类,可以是父类、抽象类的构造器或接口,然后在代码块的花括号里实现匿名内部类的内容。花括号内部可以实现该类的任意方法,包括重写父类中的方法和定义新的方法。

new 父类构造器或接口() {
    // 匿名内部类的类体部分
}

假设有一个接口如下:

public interface MyInterface {
    void doSomething();
}

如果我们想要创建一个实现该接口的类的对象,并在其中实现doSomething()方法,可以使用匿名内部类,如下所示:

MyInterface myObj = new MyInterface() {
    @Override
    public void doSomething() {
        // 实现具体的操作
    }
};

假设有一个类如下:

public class Student {
    public void test(){
        System.out.println("====================");
    }
}

可以创建一个该类的匿名内部类对象

Student student = new Student() {
            @Override
            public void test() {
                System.out.println(":;;;;;;;;;;;;;");
            }
        };

匿名内部类的特点

  • 匿名内部类是一个没有名字的内部类,同时也代表一个对象。

  • 匿名内部类的对象类型,相当于是当前 new 的那个类型的子类类型。

  • 匿名内部类可以作为一个对象,直接传输给方法。

四.Object类

4.1 什么是Object类

Object 类是所有类的父类,Java 中的类都直接或间接的继承自 Object 类。因此,所有的类都是Object类的子类,都可以使用Object类中的方法。

4.2 Object类中的方法

/**
 * native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。
 */
public final native Class<?> getClass()
/**
 * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的 HashMap。
 */
public native int hashCode()
/**
 * 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
 */
public boolean equals(Object obj)
/**
 * native 方法,用于创建并返回当前对象的一份浅拷贝。
 */
protected native Object clone() throws CloneNotSupportedException
/**
 * 用于返回一个描述对象的字符串表示,默认的 toString()方法会返回一个由类的名称、@ 符号和
 * 对象的哈希码组成的字符串。建议 Object 所有的子类都重写这个方法。
 */
public String toString()
/**
 * native 方法,不能被重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。
 * 如果有多个线程在等待只会唤醒任意一个。
 */
public final native void notify()
/**
 * native 方法,不能被重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
 */
public final native void notifyAll()
/**
 * native方法,不能被重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
 */
public final native void wait(long timeout) throws InterruptedException
/**
 * 多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 
 * 所以超时的时间还需要加上 nanos 纳秒。。
 */
public final void wait(long timeout, int nanos) throws InterruptedException
/**
 * 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
 */
public final void wait() throws InterruptedException
/**
 * 实例被垃圾回收器回收的时候触发的操作
 */
protected void finalize() throws Throwable { }

但是,子类经常会重写 toString 方法和 equals 方法,因为

toString方法:开发中直接输出对象,默认输出对象的地址是没有意义的。开发中输出对象变量,更多的时候是希望看到对象的内容数据。所以,toString方法存在的意义就是为了让子类重写,以便返回对象的内容信息,而不是地址。

equals方法:直接比较二个对象的地址是否相同可以用==代替equals,开发时的很多业务场景,更希望判断二个对象的内容是否一样。所以,equals存在的意义也是为了让子类重写,以便子类自己来定制比较规则。

四.Objects

4.1 什么是Objects

Objects是一个工具类,提供了一些方法去完成一些功能。

4.2 Objects的常用方法

4.3 Objects中equals方法的特点

Objects的equals方法比起String对象的equals方法更安全。因为 Objects 的equals方法在进行对象内容的比较时,会先判断对象的地址是否为空,所以比较时更安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真滴book理喻

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值