从Clojure访问抽象基类上定义的公共方法

从Clojure访问抽象基类上定义的公共方法,clojure,clojure-java-interop,Clojure,Clojure Java Interop,我正在尝试使用clojure的DNSJava库。我尝试以下几点: dmarced.dns> (def results (.run (Lookup. "google.com" Type/TXT))) #'dmarced.dns/results dmarced.dns> (def r (get results 0)) #'dmarced.dns/r dmarced.dns> r #object[org.xbill.DNS.TXTRecord 0x687a3556 "google.c

我正在尝试使用clojure的DNSJava库。我尝试以下几点:

dmarced.dns> (def results (.run (Lookup. "google.com" Type/TXT)))
#'dmarced.dns/results
dmarced.dns> (def r (get results 0))
#'dmarced.dns/r
dmarced.dns> r
#object[org.xbill.DNS.TXTRecord 0x687a3556 "google.com.\t\t3599\tIN\tTXT\t\"v=spf1 include:_spf.google.com ~all\""]
dmarced.dns> (class r)
org.xbill.DNS.TXTRecord
dmarced.dns> (instance? TXTRecord r)
true
太好了!从中我知道我应该能够使用.getStrings来获取记录的内容

dmarced.dns> (.getStrings r)
Reflection warning, *cider-repl dmarced*:150:13 - reference to field getStrings can't be resolved.
IllegalArgumentException Can't call public method of non-public class: public java.util.List org.xbill.DNS.TXTBase.getStrings()  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:88)
Ok quick google告诉我这可以通过类型提示解决:

dmarced.dns> (.getStrings ^TXTRecord r)
Reflection warning, *cider-repl dmarced*:153:13 - call to method getStrings on org.xbill.DNS.TXTRecord can't be resolved (argument types: ).
IllegalArgumentException Can't call public method of non-public class: public java.util.List org.xbill.DNS.TXTBase.getStrings()  clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:88)
嗯。目前,我已经在谷歌上搜索了更多,并在上阅读了整个页面,但我没有任何运气

查看的源代码,我看到它扩展了一个抽象类,实现了这个抽象类。由于TXTRecord扩展了它,我应该可以通过它访问getStrings(我甚至编写了一个Java程序来验证它)

有人知道我如何通过Clojure访问此文件吗

编辑工作java程序

import org.xbill.DNS.*;

class Main {
    public static void main(String [] args) throws TextParseException {
        Lookup l = new Lookup("google.com", Type.TXT);
        Record [] rs = l.run();
        for(int i = 0; i < rs.length; i++) {
            TXTRecord tr = (TXTRecord)rs[i];
            for(int j = 0; j < tr.getStrings().size(); j ++) {
                System.out.println(tr.getStrings().get(j));
            }
        }

    }
}
import org.xbill.DNS.*;
班长{
公共静态void main(字符串[]args)引发TextParseException{
Lookup l=新查找(“google.com”,Type.TXT);
记录[]rs=l.run();
对于(int i=0;i
看起来这是一个已知的错误。您可以通过阅读以下内容找到更多详细信息和可能的根本原因:

无法调用从AbstractBootstrap继承的公共方法 由于长期存在的bug,例如 JDK-4283544

对于使用 反射来发现Java方法 它的编译器中的反射,并且它根本不能调用这些方法, 如CLJ-1243所述

以及以下部分描述:

java.lang.reflect.Field(get*和set*)和方法(invoke)是它们的基础 对声明类进行访问检查。这与JLS相反, 它根据引用类型定义可访问性


Piotrek关于它发生的原因似乎是正确的。Clojure bug报告建议编写一个Java类来获取信息。这并不漂亮,但我设法解决了这个问题

dmarced.core> (def txt-strings-method (doto (.getDeclaredMethod TXTBase "getStrings" nil) (.setAccessible true)))
#'dmarced.core/txt-strings-method
dmarced.core> (defn get-txt-strings [r]
                (.invoke m r nil))
#'dmarced.core/get-txt-strings
dmarced.core> (get-txt-strings r)
["v=spf1 include:_spf.google.com ~all"]
dmarced.core> 

嗯,
TXTBase
没有声明为
public
。所以我不知道为什么您可以访问
org.xbill.dns
包之外的该类上声明的任何方法。这正是异常消息所暗示的--“不能在非公共类上调用public方法”(重点添加)。您能添加运行正常的Java程序,以便我们可以与Clojure版本进行比较吗?添加。两者都使用dnsjava 2.1.7 off maven。如果需要,我可以提供gradle和project.clj文件。