zoukankan      html  css  js  c++  java
  • 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!

    成功!

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









  • 相关阅读:
    Docker
    Dotted lines by default in ViVA
    8245H(C2)光猫配置方法
    两种将verilog网表转为spice网表的方法
    calibredrv create reference cell
    怎么flatten一个GDS所有层次
    路由器后面访问光猫
    贝尔IPTV
    PDK导出的cdl MOS四端顺序不正确
    如何删除已经存在lib的techfile
  • 原文地址:https://www.cnblogs.com/lzh-Linux/p/9149262.html
Copyright © 2011-2022 走看看