首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有什么方法可以判断一个类是否是一个接口?

问有什么方法可以判断一个类是否是一个接口?
EN

Stack Overflow用户
提问于 2016-10-18 23:38:33
回答 5查看 2K关注 0票数 6

我试图检查(在字节码级别,ASM)实现一些特定接口的类(在本例中是java.sql.Connection),并发现在某些情况下,库有另一个接口扩展了我的一组接口.然后他们的类实现了这个接口。(在本例中,一个新的扩展接口com.mysql.jdbc.Connection扩展java.sql.Connection,然后扩展它们的实现,例如,ConnectionImpl实现com.mysql.jdbc.Connection。)因此,我怀念将ConnectionImpl识别为目标类。

所以..。其结果是,在加载类时,我需要将com.mysql.jdbc.Connection标识为“有趣的”接口。但我不知道如何将类识别为接口,而不是普通的类。ClassReader中有什么东西能给我提供这样的信息吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2016-10-19 21:51:26

根据标题,如果您想检查一个类是否是一个接口:

代码语言:javascript
复制
ClassNode node = // However you wish to load the class
if ((node.access & Opcodes.ACC_INTERFACE) != 0){
    // is interface
} else {
    // is not an interface
}

在您的文章中,您指出您希望找到java.sql.Connection的子/实现。

你现在面临的问题是:

java.sql.Connection -> com.mysql.jdbc.Connection -> ConnectionImpl

ConnectionImpl不直接实现java.sql.Connection,因此不会检测到它是子/实现。对于这样的问题,您必须做的是遍历类的层次结构。如果是在您的情况下,我将加载一个ClassNodes <String, ClassNode>映射,其中字符串是ClassNode的名称。然后,我将使用递归方法来检查给定的类是否是预期的类型。因此,如果您在其中发送一个ClassNode,它将使用节点的父节点调用自己,然后调用接口。最终,如果最初给定的节点是正确的类型,那么最终将传递并找到java.sql.Connection接口。另外,如果您想跳过冗余,您可以将每个ClassNode的结果存储在一个映射中,这样您就不必一次又一次地检查整个层次结构。

编辑:就像这样

代码语言:javascript
复制
public static boolean isMatch(ClassNode cn, Map<String,ClassNode> nodes, String target){
    if (cn.name.equals(target)) return true;
    else{
        if (nodes.containsKey(cn.superName) && isMatch(nodes.get(cn.superName),nodes,target)) return true;
        for (String interf : cn.interfaces){
            if (nodes.containsKey(interf) && isMatch(nodes.get(interf),nodes,target)) return true;
        }
    }
    return false;
}
票数 2
EN

Stack Overflow用户

发布于 2016-10-19 09:54:53

正如您已经提到的,您需要检查每个接口类型的接口,以确定这样一个子类型关系。但是,如果您可以访问所有资源,这并不困难。

在使用ASM时,只需获取原始类的接口名称,并在每个此类接口上查找类文件。然后,您可以解析其接口的每个类文件,等等。这样,您就可以确定整个图并决定子类型关系。

如果不想手动执行此操作,则可以使用字节巴迪,它提供了类似于卸载类型的反射API的方法:

代码语言:javascript
复制
ClassFileLocator cfl = ... // can be file system, class loader, etc.
TypePool.Default.of(cfl).describe("your.initial.type")
                        .resolve()
                        .isAssignableTo(someInterface);

如果目标接口不可用,也可以使用TypePool读取它。

票数 1
EN

Stack Overflow用户

发布于 2017-02-07 05:48:19

使用org.objectweb.asm.ClassReader,我们可以识别加载的类实际上是一个类或接口。示例代码片段如下

代码语言:javascript
复制
  public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, 
        ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException{

        ClassReader classReader = null;
        try{
            classReader=new ClassReader(classfileBuffer);
            if(isInterface(classReader)){
                return classfileBuffer;
            }
        }
        catch(Throwable exp){
            return classfileBuffer;
        }
       // Remaining logic here

    }

    public boolean isInterface(ClassReader cr) {
        return ((cr.getAccess() & 0x200) != 0);
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40119773

复制
相关文章

相似问题

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