4

コンパイル時には利用できないが、実行時には利用できるJavaオブジェクトに、次のようにvarsでハンドルを設定しようとしています。

(def component-manager (delay (SomeJavaObject/getHandle)))

(遅延よりも優れたメカニズムが利用できる場合、これは歓迎されます)。

これらのオブジェクトを使用すると、反射警告が生成されます。これらはかなり頻繁に発生することがあるため、次の方法で回避しようとしました。

(def my-handle ^SomeJavaObject (delay (SomeJavaObject/getHandle)))

残念ながら、この場合でも反射警告が生成されます。


参照の変更は機能します:

(.foo ^SomeJavaObject @my-handle)

...しかし、これはコードを大幅に醜くします。


タイプヒントを追加するマクロでラップすることは、明らかなアプローチのようです。

(def my-handle' (delay (SomeJavaObject/getHandle)))
(defmacro my-handle []
  (with-meta '(deref my-handle')
             {:tag SomeJavaObject}))

...そしてそれは正しいことをするはずのように見えます:

=> (set! *print-meta* true)
=> (macroexpand '(my-handle))
^SomeJavaObject (deref my-handle')

...しかし、ゴムが道路にぶつかったとき、これは当てはまりません:

=> (.foo (my-handle))
Reflection warning, NO_SOURCE_PATH:1 - reference to field foo can't be resolved.

これを行う正しい方法は何ですか?

4

2 に答える 2

3

ここで遅延が最善かどうか、またはこれらのJavaオブジェクトを管理するためのはるかに優れた解決策があるかどうかはわかりませんが、以下のリフレクション警告に関する限り、コードは遅延値アクセスをタイプヒント付きの関数にラップすることで解決します。

user=> (set! *warn-on-reflection* true)
true
user=> (def myobj (delay "hello world"))
#'user/myobj
user=> (defn ^String get-my-obj [] @myobj)
#'user/get-my-obj
user=> (.length (get-my-obj))
11

はるかに簡単にするために、遅延オブジェクトを作成するマクロを作成し、get-<delay object name>タイプヒントを使用してその遅延オブジェクトにアクセスする関数を作成することもできます。

于 2012-06-05T04:28:43.690 に答える
2

2つの異なるソリューションを提供したいと思います。

1.遅延

まず、問題を再現する方法を示す回答を投稿したいと思います。(言い換えると、あなたの質問は抽象的であり、REPLで実行することはできません。)

(set! *warn-on-reflection* true)
(def rt (delay (Runtime/getRuntime)))
(.availableProcessors @rt) ; Reflection warning

あなたはそれが冗長であると考えるのであなたが次のアプローチが好きではないと言います:

(.availableProcessors ^java.lang.Runtime @rt) ; no warning

次のことを試しましたが、反射の警告は解決しませんでした。

(def rt (delay ^java.lang.Runtime (Runtime/getRuntime)))
(.availableProcessors @rt) ; Reflection warning

結論:遅延を使用したい場合は、Ankurの答えがうまく機能します。この例に適合させるには:

(def delayed-runtime (delay (Runtime/getRuntime)))
(defn ^java.lang.Runtime get-runtime [] @delayed-runtime)
(.availableProcessors (get-runtime)) ; no warning

2.メモ化

必要なコードが少ないため、メモ化の使用を検討することもできます。

(def ^java.lang.Runtime get-runtime (memoize #(Runtime/getRuntime)))
(.availableProcessors (get-runtime)) ; no warning
于 2014-03-01T00:20:34.420 に答える