public抽象类能否在自身内部创建自身类型的对象?
关于责任链示例中
private AbstractHandler next;的疑问解答 为什么抽象类内部可以定义自身类型的成员变量?
抽象类的核心限制是无法直接通过new 抽象类名()的方式创建实例,从来没有规则禁止抽象类作为引用类型来声明变量。
Java的引用变量只要求编译时类型符合约束即可,AbstractHandler next只是声明了一个指向AbstractHandler类型实例的引用,它实际存储的可以是任何AbstractHandler非抽象子类的实例——这本身就是面向对象多态特性的常规用法,和你用List<String> list = new ArrayList<>()声明父类类型变量指向子类实例的逻辑完全一致。这种写法是否属于在类内部实例化自身?
完全不属于。
你需要明确两个完全独立的动作:- 声明引用变量:
private AbstractHandler next;只是给类定义了一个成员属性,这个属性的默认值是null,整个过程没有调用构造方法,没有创建任何实际对象。 - 实例化对象:只有显式写出
new 类名(构造参数)的时候才会触发对象创建。这段代码里AbstractHandler的构造方法、setNext方法都只是接收外部传入的实例引用赋值给next,根本没有在类内部创建自身实例的逻辑,不存在自实例化的问题。
- 声明引用变量:
这种写法会不会导致无限递归问题?
正常使用不会。
和next相关的请求传递逻辑如下:
public void handleRequest(AbstractRequest request) { if (next != null) { next.handleRequest(request); } }
方法里先做了非空判断,只要责任链是线性配置、最后一个节点的next保持为null,请求传递到链尾就会自动终止,不会出现无限递归。
只有当你错误配置责任链,让节点引用形成闭环(比如A的next是B,B的next是C,C的next又指回A)的时候,才会出现循环调用的栈溢出问题,这属于使用错误,和写法本身无关。
实际上这种「持有同类型引用作为下一节点」的写法是所有链式结构(链表、责任链、拦截器链)的标准实现方式,不存在设计层面的问题。
内容的提问来源于stack exchange,提问作者Ken Adams
相关产品推荐
相关产品推荐

