私はMethodHandle
をAndroid用にプロジェクトに使用しようとしています。現時点では、既存のJavaコードをAndroidと互換性を持つように変換していますが、問題が発生しました。プレーンJava 7/8で NoSuchMethodError:MethodHandle、Androidで仮想メソッドが呼び出されない
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
public class Example {
public static void main(String[] args) throws Throwable {
MethodHandle arrayReader = MethodHandles.arrayElementGetter(String[].class);
Object array = new String[]{"Hi", "there", "Jim"};
Object item = arrayReader.invoke(array, 2);
System.out.println(item);
}
}
同じコードは、Androidのためにコンパイルしますが、例外が実行時にスローされます。
java.lang.NoSuchMethodError: No virtual method invoke(Ljava/lang/Object;I)Ljava/lang/Object; in class Ljava/lang/invoke/MethodHandle; or its super classes (declaration of 'java.lang.invoke.MethodHandle' appears in /system/framework/core-oj.jar)
MethodHandle.invoke varargs機能を使用して任意の数のObject
引数を渡しますが、実行時にはパラメータ型がObject
およびint
の2を持つメソッドを見つけようとします。
私は配列パラメータでinvoke
コールを交換しようとしている:arrayReader.invoke(new Object[]{array, 2})
が、これはちょうど別の問題が作成されます:MethodHandles.arrayElementGetter
によって生成MethodHandle
以来、私はこれがとにかく動作するように期待しなかったであろう
java.lang.UnsupportedOperationException: MethodHandle.invoke cannot be invoked reflectively.
をコールは2つの引数(配列とインデックス)をとりますが、私はそれがショットに値すると思っていました。
私はこれがbuild.gradle
ファイルの一部であるAPIレベル26でAndroidのエミュレータを実行しています:
android {
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
minSdkVersion 26
targetSdkVersion 26
versionCode 1
versionName "1.0"
...
この問題を解決するためにどのような方法、または同じ結果を達成するための別の方法はありますか?
MethodHandleはAPIレベル26で追加された可能性があります。 –
MethodHandleにはAPIレベル26が必要なため、Android 8.0を実行するデバイス(またはエミュレータ)が必要です。あなたのマニフェストの 'minSdkVersion'を26に設定する必要があります。 – Robert
謝罪、私は自分自身に「APIレベル26のエミュレータを実行していることを覚えている」と繰り返し言いましたが、まだ忘れました。今私の投稿を編集します。 –