我的情况:
我想通过扩展 TextView
覆盖 TextView
中的隐藏方法,并调用它的 super 方法。
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 太安全了,无法破解。
最佳答案
android 8.0以下有一个解决方案,如果你能接受打包一些*.so库。 JNI 接口(interface)中有一系列调用非虚拟方法 ( 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)。
关于java - dalvik Java 如何使用反射调用父类(super class)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32711203/