Abstract 抽象类介绍
- 抽象类:
- 不可被实例化
- 可以实例化的东西一定要补全所有的方法体
- 可以包含抽象方法 - 非private/public
- 可以包含成员变量
- 声明:public abstract class Name {}
- JDK中有非常多这样的例子,比如:
- ArrayList -> AbstractList -> Collection -> Iterator
- AbstractMap
- …
- 具体的类去提供行为,覆盖抽象类的方法
- 抽象方法:abstract void method() {}
接口
- 接口部分地实现了多继承,一个类能够实现多个接口
- 接口不是类
- 接口的扩展
- 接口只代表一种功能实现的合约
接口能够包含什么
- 方法(默认public)
- 常量(默认public static final)
- extends接口
- 默认方法(有方法体的):
- Since Java 8
- 是一种妥协产物
- 可以用来实现mixin
- 菱形继承
- Java 8之前接口方法不能有方法体,只声明方法的签名
接口的限制
- 一个接口一旦发布,就不能修改了,否则会导致所有实现该接口的类失效,打破了向后兼容性
- Java 8 之后破解了这个限制,可以设置默认方法
default fn() {}
- 默认方法可以有方法体
- Java 8 之后破解了这个限制,可以设置默认方法
- 接口的设计本意是避免二义性,default接口方法的产生又引入的二义性
使用场景
- 当你想要复用一些代码,用抽象类
- 当你想要描述一个功能,用接口,接口抽象程度更高
抽象类和接口对比
1. 共同点:
抽象类和接口设计的意义
- 最大程度的灵活性
- 最大程度的代码复用
多态实战:FileFilter
- FIles.walkFileTree
- 实现FileVisitor接口
- FileVisitor的默认实现:SimpleFileVisitor
接口和抽象类实现策略模式
内部类详解
使用内部类有助于写代码时注意力的集中,同时提供足够程度的封装。
1. 匿名内部类
// ...
static class UserFilter implements XxFilter {
public boolean isValid () {}
}
public void main() {
return filter(users, new UserFilter() {
@Override
public boolean isValid(User user) {
return user.id % 2 == 0;
}
});
// lambda实现
// return filter(users, user -> user.id % 2 == 0});
}
// JDK内部有Predicate接口,其中test方法用于给定一个元素,返回判断布尔值
public static List<User> filter(List<User> users, Predicate<User> predicate) {
List<User> ret = new ArrayList<>();
for(User u : users) {
if(predicate.test(u)) ret.add(u);
}
return ret;
}
2.隐藏细节
- private内部类可以不受限地互相访问对方
- 而外部无法访问private的内部类
3.静态内部类
内部类: private class A {}:
- 和它的外围类的实例相绑定(是实例的内部类)
- 在里面调用的是外围类的实例的方法
- tips:编译器帮你在内部类中注入了一个外围类的实例
this$0
静态内部类:private static class A {}:
- 是外围类的内部类,不与实例相绑定
- 在里面调用的是外围类的类方法,不能调用实例方法
- 想调用外围类的实例方法,可使用A类的构造器将实例传入