dalvik Java如何使用反射调用超类方法?

时间:2015-09-22 07:45:07

标签: java android reflection

我的情况: 我想通过extends TextView覆盖TextView中的隐藏方法,并调用其超级方法。

public class MyTextView extends TextView {
    protected void makeNewLayout(int wantWidth, int hintWidth,
                                 BoringLayout.Metrics boring,
                                 BoringLayout.Metrics hintBoring,
                                 int ellipsisWidth, boolean bringIntoView) {
        // omit try catch for simple
        Method method = Class.forName("android.widget.TextView").getDeclaredMethod("makeNewLayout", int.class, int.class, BoringLayout.Metrics.class, BoringLayout.Metrics.class, int.class, boolean.class);
        method.setAccessible(true);
        method.invoke(this, wantWidth, hintWidth, boring, hintBoring, ellipsisWidth, bringIntoView);
    }
}

问题是我的自定义makeNewLayout被调用并且执行了method.invoke,但方法调用是 MyTextView::makeNewLayout 而不是 TextView::makeNewLayout ,这是一个死的递归电话。

我怎样才能实现它?

PS:makeNewLayout是一个隐藏功能,所以我不能通过super.makeNewLayout(...)

直接调用它

看起来java / android不可能轻松地完成这类工作。 java太安全了,无法入侵。

1 个答案:

答案 0 :(得分:1)

如果您可以接受打包某些* .so库,则在android 8.0以下有一个解决方案。 JNI接口(https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#CallNonvirtual_type_Method_routines)中有一个调用非虚拟方法的族 像这样使用它:

在Java中声明:

public native void callNonvirtualVoidMethodHelper(Object obj, String classNameOfMethod, String methodName, String methodSignature);

在cpp中的实现:

extern "C"
JNIEXPORT
void JNICALL
Java_yourpackage_yourclass_callNonvirtualVoidMethodHelper(
    JNIEnv *env,
    jobject /* this */,
    jobject obj,
    jstring classNameOfMethod,
    jstring methodName,
    jstring methodSignature) {
    const char *classNameStr = env->GetStringUTFChars(classNameOfMethod, JNI_FALSE);
    const char *methodNameStr = env->GetStringUTFChars(methodName, JNI_FALSE);
    const char *methodSignatureStr = env->GetStringUTFChars(methodSignature, JNI_FALSE);
    jclass classOfMethod = env->FindClass(classNameStr);
    jmethodID method = env->GetMethodID(classOfMethod, methodNameStr, methodSignatureStr);
    env->CallNonvirtualVoidMethod(obj, classOfMethod, method);
}

在Java中使用它:

callNonvirtualVoidMethodHelper(new SubClass(),
        "some/package/SuperClass", // specify the class of non-virtual method
        "foo",
        "()V"); // method signature

或者在android 8.0以上运行时使用MethodHandle(参考:https://stackoverflow.com/a/15674467/2300252)。