Java 实例化接口或抽象类

1、 实例化接口:

某一天,我们想通过反射调用一个类的方法,但发现方法参数中有一个接口,我们都知道接口不能被实例化,这该怎么办呢?

举例:

public class TestLib {
public static final String TAG = "TestLib";

void myTest(MyInterface myInterface) {
Log.i(TAG, "myTest start executing ");
myInterface.doFail();
myInterface.doSucc();
}
}

我们想通过反射调用TestLib.myTest(...)方法,
public interface MyInterface {
void doFail();

void doSucc();
}
但参数是个接口,仔细一想,我们可以通过动态代理实现接口啊!
实现:
// Step one:
val TestLibClass = Class.forName("demo.apt.aptyyb.TestLib")
val TestLibObject = TestLibClass.newInstance()

// Step two:
val myTestMethod = TestLibClass.getDeclaredMethod("myTest",
Class.forName("demo.apt.aptyyb.MyInterface"))

//Step three:
val interfaceObject = Proxy.newProxyInstance(classLoader,
arrayOf<Class<*>>(Class.forName("demo.apt.aptyyb.MyInterface")), MyInvoke())
//Step four:
myTestMethod.invoke(TestLibObject, interfaceObject)

再看MyInvoke的定义:
inner class MyInvoke : InvocationHandler {

override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?) {
if (method?.name.equals("doFail")){
Log.i(TAG,"doFail")
}else if (method?.name.equals("doSucc")){
Log.i(TAG,"doSucc")
}

}


最后Run,看结果:

I/TestLib: myTest start executing
I/MainActivity: doFail
I/MainActivity: doSucc

 
2、实例抽象类
上面通过动态代理在内存中实例化了接口,那么抽象类该如何处理呢?
2018年的某天,风和日丽,像往常一样开始码代码,生命不止,码码不息:
现在在TestLib中又多了一个方法,
void abstractTest(MyAbstract myAbstract){
Log.i(TAG, "abstractTest start executing ");
myAbstract.doFail();
myAbstract.doSucc();
}

what is the “
MyAbstract”???
public abstract class MyAbstract {

static {
Log.i("Lib", "MyAbstract Main is load");
}

private static final String TAG = "MyAbstract";

public void doFail() {
Log.i(TAG, "MyAbstract Main doFail");
}

public abstract void doSucc();
}
原来是一个抽象类啊!那么问题来了,如何通过反射调用含抽象类的方法呢?
使用DexClassLoader!插件化技术来实现!

新建一个Lib工程,放置两个类,
 
 
public abstract class MyAbstract {
static {
Log.i("Lib","MyAbstract Plugin is load");
}
public void doFail() {
}

public abstract void doSucc();
}

public class LibPlugin extends MyAbstract {
private static final String TAG = "LibPlugin";
public LibPlugin() {
Log.i(TAG,"LibPlugin Plugin constructor is executing" +
"!");
}

@Override
public void doFail() {
Log.i(TAG,"LibPlugin Plugin doFail" +
"!");
}

@Override
public void doSucc() {
Log.i(TAG,"LibPlugin Plugin doSucc" +
"!");
}
}
生成apk文件,push到sd卡中, 然后使用DexClassLoader加载LibPlugin 这个类:

// 第一步加载LibPlugin类:

val dexPath=Environment.getExternalStorageDirectory().absolutePath+"/dexlib-debug.apk"

val dexLoader=DexClassLoader(dexPath,getDir("app",0).absolutePath,null,classLoader)
val abstractClass=dexLoader.loadClass("demo.apt.dexlib.LibPlugin")

第二步找到要调用的方法:
val TestLibClass = Class.forName("demo.apt.aptyyb.TestLib")
val TestLibObject = TestLibClass.newInstance()
val myAbstractMethod = TestLibClass.getDeclaredMethod("abstractTest",
Class.forName("demo.apt.aptyyb.MyAbstract"))

第三步直接Invoke:

myAbstractMethod.invoke(TestLibObject,abstractClass.newInstance())

好了,到此就完成了我们得反射调用含抽象类参数的方法。
看下输入的结果:

 
 

I/Lib: MyAbstract Main is load
I/LibPlugin: LibPlugin Plugin constructor is executing!
I/TestLib: abstractTest start executing
I/LibPlugin: LibPlugin Plugin doFail!
I/LibPlugin: LibPlugin Plugin doSucc!

 

成功!

 

总结,调用含抽象类或接口参数的方法,需要传入一个对象,这时候就需要实例化类或接口!









转载于:https://www.cnblogs.com/lzh-Linux/p/9149262.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值