如何避免;“非法反射访问”;Clojure互操作中的警告。(演员?)

如何避免;“非法反射访问”;Clojure互操作中的警告。(演员?),clojure,Clojure,尽管我相信我对Clojure有着坚实的初学者理解,但在与Java进行互操作时,我还是茫然不知所措 因此,我正在努力修复一些(不可避免的)生成JVM警告的互操作代码。这是代码,它获取一个W3C dom节点并从中创建一个LS序列化程序,这样我就可以输出相应的XML字符串: (defn serializer [node] (let [serializer (-> node .getOwnerDocument

尽管我相信我对Clojure有着坚实的初学者理解,但在与Java进行互操作时,我还是茫然不知所措

因此,我正在努力修复一些(不可避免的)生成JVM警告的互操作代码。这是代码,它获取一个W3C dom节点并从中创建一个LS序列化程序,这样我就可以输出相应的XML字符串:

(defn serializer
  [node]
  (let [serializer (-> node
                       .getOwnerDocument
                       .getImplementation
                       .createLSSerializer)]
    (.setParameter (.getDomConfig serializer) "xml-declaration" false)
    serializer))
该代码工作正常,直到最近的系统更新后才出现警告

但是JVM(对于openjdk 11.0.10)似乎不喜欢调用
.getOwnerDocument
,它也不喜欢调用
.getImplementation
,正如我在重写以避免调用
.getOwnerDocument
时发现的那样。确切的警告(添加了箭头/换行符):

似乎表明Clojure中不需要强制转换,您可以通过类型暗示来避免反射:

 (defn bar [^String x] 
         (.toCharArray x))
(defn serializer
  [^com.sun.org.apache.xerces.internal.dom.NodeImpl node]
  (let [serializer (-> node
                       .getOwnerDocument
                       .getImplementation
                       .createLSSerializer)]
    (.setParameter (.getDomConfig serializer) "xml-declaration" false)
    serializer))
因此,我重写了我的函数以使用类型提示:

 (defn bar [^String x] 
         (.toCharArray x))
(defn serializer
  [^com.sun.org.apache.xerces.internal.dom.NodeImpl node]
  (let [serializer (-> node
                       .getOwnerDocument
                       .getImplementation
                       .createLSSerializer)]
    (.setParameter (.getDomConfig serializer) "xml-declaration" false)
    serializer))
这似乎让我越过了
.getOwnerDocument
.getImplementation
上的警告。但是现在它警告我调用
.createLSSerializer
,这有点令人沮丧,因为我似乎在调用最后一个方法,并且调用的对象类型与我上面引用的答案完全相同。这是我在类型提示中遇到的错误(添加了箭头/换行符):

警告:clojure.lang.InjectedInvoker/0x00000008401e8040非法反射访问
(文件:/home/user/.m2/repository/org/clojure/clojure/1.10.1/clojure-1.10.1.jar)

-->对于方法com.sun.org.apache.xerces.internal.dom.CoredomImplementImpl.createLSSerializer(),答案显然是提供一个额外的类型提示,如下所示:

 DOMImplementationLS domImplementation = (DOMImplementationLS) doc.getImplementation();
 LSSerializer lsSerializer = domImplementation.createLSSerializer();
(defn serializer
  [^com.sun.org.apache.xerces.internal.dom.NodeImpl node]
  (let [serializer (-> node
                       .getOwnerDocument
                       ^com.sun.org.apache.xerces.internal.dom.CoreDOMImplementationImpl
                       (.getImplementation)
                       .createLSSerializer)]
    (.setParameter (.getDomConfig serializer) "xml-declaration" false)
    serializer))

我之所以发现这一点,是因为在我的问题旁边找到了一个“相关”的问题/答案。抱歉没有提前找到它,如果有人遇到相同的问题,此线程可能会提供一些帮助。

您还可以通过使用javax.xml.transform.Transformer进行序列化来避免非法的反射访问(和xerces引用)。获取一个TransformerFactory,生成一个DOMSource(给它一个DOM节点),设置一个StreamResult(给一个StringWriter),并将源“转换”为结果(没有实际的XSL转换)。