我可以在
static initialization block中添加
abstract关键字,但我不能添加抽象方法
abstract void draw();
所以我只能在静态块中添加抽象类,如下所示:@H_502_5@
static { abstract class Abstract { abstract String test(); } class Extends extends Abstract { @Override String test() { return null; } } new Extends().test();
但是在静态块中添加类层次结构并不是真实的,因为静态块的访问级别低于私有,静态块内是否还有其他抽象用法?@H_502_5@
解决方法
TL; DR此功能没有合理的使用方法.如果我在代码审查中看到这一点,我会强迫作者重构它.
有时,Java规范允许您编写您不应该在理智的生产代码中执行的操作,对我而言,这是一个示例.@H_502_5@
我们被允许在静态初始化块中使用abstract关键字.这只能在定义类时,通过声明类本身是抽象的,以及可选的某些方法来完成.@H_502_5@
这个类在初始化块之外是不可见的,因此我们可以推断出我们将在内部使用它. abstract是关于创建实例或定义实例方法的.因此,仅当我们计划创建抽象类的实例时,它才有用.@H_502_5@
现在,该类是抽象的,因此为了能够创建实例,我们至少需要一个子类.@H_502_5@
如果我们只有一个子类,为什么我们将它的功能分为抽象父类和一个子类?这将是不必要的复杂,所以我们可以假设我们有多个子类.@H_502_5@
因此,要在静态初始化块中使用abstract关键字(至少半理智),此块必须定义一个抽象父类,多个子类,以及创建这些类的实例的代码,如下面的最小示例:@H_502_5@
static private int value; static { abstract class Abstract { abstract int method1(); } class Child1 extends Abstract { int method1() { return 1; } } class Child2 extends Abstract { int method1() { return 2; } } Abstract instance1 = new Child1(); Abstract instance2 = new Child2(); value = instance1.method1() + instance2.method1(); }
恕我直言,使用静态初始化器应该是例外,并且这样的怪物呼吁重构,例如将类移出初始化块以成为普通的嵌套类,甚至更好,将它们移动到自己的文件中.@H_502_5@
这个抽象初始化模式与重构版本不同的唯一方面是类可见性.您只能在静态{…}块内获得可见性.但是如果你的课程如此复杂和漫长,以至于你害怕在静态{…}块之外误用,那你无论如何都会迷失…@H_502_5@