场景:存在着两个不同的实体类(ParentEntity、ChildEntity),这两个实体类中都有头像这一个属性,对应着服务器的图片保存位置。需要一个方法,可以获取这一属性,然后将图片下载保存到本地指定位置,同时将路径保存到该实体类,然后更新数据库。
因为需要执行的操作基本相同,都是调用实体类的相应方法获取图片保存地址,然后发起请求,保存到本地。由于存在着两个实体类,为了简化方法,理应使用泛型方法。
之前在学习Java的时候没有好好看过泛型,今天用到了不禁有点丈二和尚摸不着头脑。
翻阅一番资料后有了一定的了解,完成了这个方法的设计,记录如下:
不同于一般的方法声明,泛型方法需要声明成如下格式:
public <T> void func(T t){}
也就是需要在作用域关键字后边声明关键字 <T>
,这样方法才能接受一个泛型作为参数。
现在我们的方法可以接收任意类型的对象作为参数了,但是存在一个问题,那就是这个t对象是一个Object对象,如下图所示:
对于方法而言,方法不管传入的对象是什么类型的实例,只对传入的对象做统一处理。那么首先我们应该先知道,传入的对象到底是ParentEntity、ChildEntity中的哪个?
我们可以使用 Class clazz = t.getClass();
来获取传入对象的“类”,使用 String clazzName=clazz.getName();
可以得知传入的对象的类的名字,这样我们就可以判断传入的对象是不是我们需要的了。
1 2 3 4 5
| if (clazzName.equals(ParentEntity.class.getName())) {
} else if (clazzName.equals(ChildEntity.class.getName())) {
}
|
那我们怎么才能调用我们传入的实体的方法呢?当然我们可以直接使用强制转型,但是这样就不够优雅了。选择反射则优雅很多,网上很多关于反射的介绍,我就不多赘述了。
反射获取方法与调用:
1 2 3 4 5 6 7 8 9 10 11 12
| try { Method method1 = clazz.getMethod("method1"); Method method2 = clazz.getMethod("method1",String.class); method1.invoke(t); method2.invoke(t, "xxx"); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); }
|
注意这里会抛出NoSuchMethodException异常,表示无法通过反射获取这个方法。
反射获取的方法需要通过 method.invoke(odj,obj....args)
来调用,使用这个方法会抛出两个异常,InvocationTargetException、IllegalAccessException
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
public <T> void syncAvatarToLocal(final T entity) { try { Class entityClass = entity.getClass(); Method getAvatar = null; final Method setLocalAvatarPath = entityClass.getMethod("setLocalAvatarPath", String.class); final Method setSync = entityClass.getMethod("setSync", boolean.class); if (entityClass.getName().equals(ParentEntity.class.getName())) { getAvatar = entityClass.getMethod("getParentsavatar"); } else if (entityClass.getName().equals(ChildEntity.class.getName())) { getAvatar = entityClass.getMethod("getAvatar"); } if (getAvatar != null && setLocalAvatarPath != null && setSync != null) { String avatarPath = (String) getAvatar.invoke(entity); if (avatarPath.startsWith("/Public")) { String avatarUrl = Constants.getServer() + avatarPath; String picName = avatarPath.substring(avatarPath.lastIndexOf("/") + 1); OkHttpUtils .get() .url(avatarUrl) .build() .execute(new FileCallBack(Constants.AVATAR_IMAGES_LOCATION, picName) { @Override public void onError(Call call, Exception e, int id) { }
@Override public void onResponse(File response, int id) { Log.e("NetApi", "onResponse :" + response.getAbsolutePath()); try { setLocalAvatarPath.invoke(entity, response.getAbsolutePath()); setSync.invoke(entity, true); if (entity instanceof ParentEntity) PunchApplication.sParentEntityDao.update((ParentEntity) entity); if (entity instanceof ChildEntity) PunchApplication.sChildEntityDao.update((ChildEntity) entity); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
|