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

时间:2016-05-03 03:14:19

标签: 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.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

大!我从docs知道我应该能够使用.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)

好的快速谷歌告诉我这可以通过类型提示来解决:

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)

咦。在我进一步搜索Google时,请阅读interop上的整页,但我没有运气。

查看TXTRecord的来源,我看到它扩展了TXTBase,这是一个实现getStrings的抽象类。由于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));
            }
        }

    }
}

2 个答案:

答案 0 :(得分:3)

它看起来是一个已知的错误CLJ-1243。您可以通过阅读Netty issue description

找到更多详细信息和可能的根本原因
  

无法调用从AbstractBootstrap继承的公共方法   由于长期存在的错误,通过Java反射API   JDK-4283544。

     

对于使用的替代JVM语言来说,这是一个严重的问题   反思发现Java方法。例如,Clojure使用   在它的编译器中反射,它根本不能调用这些方法,   如CLJ-1243中所述。

部分描述来自JDK bug

  

java.lang.reflect.Field(get *和set *)和Method(invoke)基于它们   访问检查声明类。这与JLS相反,   它根据参考类型定义可访问性。

答案 1 :(得分:1)

Piotrek似乎对它为什么会发生是正确的。 Clojure错误报告建议编写一个Java类来获取信息。它并不漂亮,但我设法用

来解决它
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} ^/our-services/individual-medical-dental-insurance
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !^/our-services/individual-medical-dental-insurance
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]   
</IfModule>