一.抽象类
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方法在进行对象内容的比较时,会先判断对象的地址是否为空,所以比较时更安全。