首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在没有实例的情况下调用抽象类的非抽象方法

在没有实例的情况下调用抽象类的非抽象方法
EN

Stack Overflow用户
提问于 2015-09-22 13:36:03
回答 1查看 266关注 0票数 0

考虑下面的代码:

代码语言:javascript
复制
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提供的情况下调用skill#get()?

常规Java不允许使用class#newInstance()抽象类。问题是:有没有办法?

注意:我不能有static关键字。这件事我需要继承。

编辑:我读过关于不安全的文章--在这种情况下会有帮助吗?我知道你的日常java在这里是没用的。需要一些极端的东西。

EN

回答 1

Stack Overflow用户

发布于 2015-09-22 14:15:31

即使使用Unsafe也无法做到这一点,因为Unsafe.allocateInstance也为抽象类抛出了java.lang.InstantiationException。唯一可能的解决方案是创建一个匿名类,如下所示:

代码语言:javascript
复制
new Skill() {}.get();

这并不完全是您想要的,因为匿名类仍然是继承Skill类的新类。但在许多情况下,这是令人满意的。

更新:如果你真的想要一些极端的东西,你可以在运行时旋转匿名类。例如,使用ASM库可以做到这一点:

代码语言:javascript
复制
// 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();

通过这种方式,您可以在运行时创建抽象类的子类(子类不存在于已编译的代码中)。当然应该指出的是,这样的解决方案是,嗯,不安全的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32709110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档