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!

成功!

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





Java 实例化接口或抽象类的更多相关文章

  1. Java中接口和抽象类的比較

    Java中接口和抽象类的比較-2013年5月写的读书笔记摘要 1. 概述 接口(Interface)和抽象类(abstract class)是 Java 语言中支持抽象类的两种机制,是Java程序设计 ...

  2. 慢慢人生路,学点Jakarta基础-深入剖析Java的接口和抽象类

    在java面向对象编程的,抽象类和接口始终存在有疑问的地方,因为两者太多相似有太多不同,在刚开始学习的时候经常弄的不对,使用情景搞混,今天来总结之前学习Java中接口和抽象类的问题. 抽象类 了解:只 ...

  3. 深入理解Java的接口和抽象类(转)

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  4. 深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  5. [转载]深入理解JAVA的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  6. 深入理解Java的接口和抽象类 _摘抄

    http://www.cnblogs.com/dolphin0520/p/3811437.html 原文 深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可 ...

  7. Java进阶(三十六)深入理解Java的接口和抽象类

    Java进阶(三十六)深入理解Java的接口和抽象类 前言 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太 ...

  8. 【转】深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

  9. 33、深入理解Java的接口和抽象类

    深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...

随机推荐

  1. MySQL:SELECT COUNT 小结

    MySQL:SELECT COUNT 小结 背景 今天团队在做线下代码评审的时候,发现同学们在代码中出现了select count(1) . select count(*),和具体的select co ...

  2. [leetcode] 周赛 211

    比赛题目:https://leetcode-cn.com/circle/discuss/luvHfG/ 两个相同字符之间的最长子字符串 题目:5543. 两个相同字符之间的最长子字符串. 开始理解错题 ...

  3. 第二十章 nginx常见问题

    一.Nginx常见问题 一.nginx多server优先级 在开始处理一个http请求时,nginx会取出header头中的Host变量,与nginx.conf中的每个server_name进行匹配, ...

  4. Lambda表达式(一)

    Lambda表达式其实就是实现SAM接口的语法糖,作用就是简化代码的冗余,同时可读性也好过匿名内部类. 以下先一步步演示是如何把大段的代码变成一句代码的,加强理解! 第一种正常的写法 1 public ...

  5. pyqt5安装报错解决办法

    用国内快速的镜像源即可 pip install PyQt5 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

  6. 腾讯云大学 x CODING | 知识分享月直播预告

    经历十年的发展,DevOps 已经变成被广泛认知的研发效能方法论.DevOps 工具链作为 DevOps 落地的核心技术实践之一,在自动化和质量方面使得开发团队可以更快更好地交付产品,提高其竞争力. ...

  7. Spring学习-Bean的基本概念知识

    4月份开始复习一遍spring相关知识.让自己巩固一下spring大法的深奥益处,所以就看了大佬的博客,转载留下来日后继续研读.认为重点的标记为红色 转载自:http://www.cnblogs.co ...

  8. C2. Pokémon Army (hard version) 解析(思維)

    Codeforce 1420 C2. Pokémon Army (hard version) 解析(思維) 今天我們來看看CF1420C2 題目連結 題目 略,請直接看原題. 前言 根本想不到這個等價 ...

  9. LuoguP4704 太极剑

    题面 测试要求 Bob 尽可能快地切断 n 根绳子. 所有绳子的端点两两不同,所以共有 2n 个端点.这些端点被捆在一个圆上,等距离分布.我们把这些端点按顺时针方向编号为 1 到 2n. Bob 每次 ...

  10. CodeForces 1408G Clusterization Counting

    题意 给定 \(n\) 个点的无向带权完全图,边权为 \(1\sim\frac{n(n-1)}{2}\).对于满足 \(1\leq k\leq n\) 的每个 \(k\) 求出将原图划分成 \(k\) ...