考虑以下代码:
public interface IRegistryClass
{
public IRegistryClass get();
}
public abstract class Skill implements IRegistryClass
{
@Override
public Skill get()
{
return new SkillFake();
}
private final class SkillFake extends Skill
{}
}
当只提供Skill.class时,是否可以调用技能#get()?
Regular Java不允许类#newInstance()抽象类。问题是:有办法吗?
注意:我不能拥有static关键字。我需要继承这个。
编辑:我读过不安全的信息 - 在这种情况下会有帮助吗?我知道你的日常java在这里没用。需要一些极端的东西。
答案 0 :(得分:0)
即使使用Unsafe
也无法执行此操作,因为Unsafe.allocateInstance
也会为抽象类抛出java.lang.InstantiationException
。唯一可行的解决方案是创建一个这样的匿名类:
new Skill() {}.get();
这并不是你想要的,因为匿名类仍然是继承Skill
类的新类。但在许多情况下这是令人满意的。
更新:如果你真的想要一些极端的东西,你可以在运行时旋转匿名类。例如,这是使用ASM库完成的方法:
// Generate subclass which extends existing Skill.class
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
String superClassName = Skill.class.getName().replace('.', '/');
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + Opcodes.ACC_FINAL
+ Opcodes.ACC_SYNTHETIC, "anonymous", null, superClassName, null);
// Create constructor which calls superclass constructor
MethodVisitor ctor = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
ctor.visitCode();
// load this
ctor.visitVarInsn(Opcodes.ALOAD, 0);
// call superclass constructor
ctor.visitMethodInsn(Opcodes.INVOKESPECIAL, superClassName, "<init>", "()V", false);
// return
ctor.visitInsn(Opcodes.RETURN);
ctor.visitMaxs(-1, -1);
ctor.visitEnd();
cw.visitEnd();
// Get the Unsafe object
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
sun.misc.Unsafe UNSAFE = (sun.misc.Unsafe) field.get(null);
// Create new anonymous class
Class<? extends Skill> clazz = UNSAFE.defineAnonymousClass(Skill.class,
cw.toByteArray(), null).asSubclass(Skill.class);
// instantiate new class and call the `get()` method
clazz.newInstance().get();
这样,您可以在运行时子类化抽象类(子类在编译的代码中不存在)。当然应该注意的是,这种解决方案是不安全的。