1 public class TestDemo { 2 //测试 3 @Test 4 public void fun01() { 5 TestDemo q=new TestDemo(); 6 A a = new A(); 7 q.adapter(a); 8 } 9 10 private void adapter(Base base){ 11 12 HashMap<Class<? extends Base>,String> class2methodName=new HashMap<Class<? extends Base>,String>() 13 { 14 private static final long serialVersionUID = 1L; 15 { 16 put(A.class,"printA"); 17 put(B.class,"printB"); 18 } 19 }; 20 System.out.println(class2methodName.get(base.getClass())); 21 invokeMethod(this,class2methodName.get(base.getClass()),new Class<?>[]{Base.class},new Object[]{base}); 22 } 23 24 public void printA(Base base) { 25 A a=(A)base; 26 System.out.println("is A:"+a.num); 27 } 28 public void printB(Base base) { 29 B b=(B)base; 30 System.out.println("is B:"+b.num); 31 } 32 33 @SuppressWarnings("unchecked") 34 private static <T> T invokeMethod(T obj, String methodName, Class<?>[] classes, Object[] objects) { 35 T val = null; 36 try { 37 Method m = null; 38 if(objects != null && classes != null){ 39 m = obj.getClass().getDeclaredMethod(methodName, classes); 40 val = (T)m.invoke(obj, objects); 41 }else{ 42 m = obj.getClass().getDeclaredMethod(methodName); 43 val = (T)m.invoke(obj); 44 } 45 } catch (Exception e) { 46 e.printStackTrace(); 47 } 48 return val; 49 } 50 51 private class Base{ 52 public int num = 1; 53 } 54 55 private class A extends Base{ 56 public int num = 2; 57 } 58 59 private class B extends Base{ 60 public int num = 3; 61 } 62 }
见知乎 : https://www.zhihu.com/question/66705139 也有大佬的点评
上述代码第21行 :
invokeMethod(this,class2methodName.get(base.getClass()),new Class<?>[]{Base.class},new Object[]{base});
改成:
invokeMethod(this,class2methodName.get(base.getClass()),new Class<?>[]{base.getClass},new Object[]{base});
就会报错,NoSuchMethodException
原因是什么?
首先看,map中有两个值,一个是{key:运行时类A,value:"printA"}{key:"运行时类B",value:"printB"}
测试方法中传的是A的对象
没改的情况 : invokeMethod(testDemo对象,"printA",运行时类A,数组存放的一个A对象)
改后的情况 : invokeMethod(testDemo对象,"printA",运行时类Base,数组存放的一个A对象)
最后执行的 invokeMethod方法中的,obj.getClass().getDeclaredMethod方法时 会出问题
public void printA(Base base) { A a=(A)base; System.out.println("is A:"+a.num); }
仔细看,此方法 一个参数Base base,反射的invoke方法要求我们必须是Base对象..