
在理解反射的时候,不得不说一下内存。
先理解一下JVM的三个区:堆区,栈区,和方法去(静态区)。
堆区:存放所有的对象,每个对象都有一个与其对应的class信息。在JVM中只有一个堆区,堆区被所有的线程共享。
栈区:存放所有基础数据类型的对象和所有自定义对象的引用,每个线程包含一个栈区。每个栈区中的数据都是私有的,其他栈不能访问。
栈分为三部分:
基本类型变量区、执行环境上下文、 *** 作指令区(存放 *** 作指令)。
方法区:即静态区,被所有的线程共享。方法区包含所有的class和static变量。它们都是唯一的。
在启动一个java虚拟机时,虚拟机要加载你程序里所用到的类 ,这个进程会首先跑到jdk中(在jdk的jre/lib/ext文件夹里找那些jar文件),如果没有找到,会去classpath里设置的路径去找。
在找到要执行的类时:
1首先将找到的类的信息加载到运行时数据区的方法区。这个过程叫做类的加载。所以一下static类型的在类的加载过程中就已经放到了方法区。所以不用实例化就能用一个static类型的方法。
2加载完成后,在new一个类时,首先就是去方法区看看有没有这个类的信息。如果没有这个类的信息,先装载这个类。then,加载完成后,会在堆区为new的这个类分配内存,有了内存就有了实例,而这个实例指向的是方法区的该类信息。其实就是存放了在方法区的地址。而反射就是利用了这一点。
可以实现,很方便。我去找个例子贴给你
Class daoFactoryClass = ClassforName(daoName);
//daoName是DAOFactory实现类的名字
// types of the constructor arguments
Class[] constrArgs = {Propertiesclass};
Object[] args = {daoProps};
//daoProps是Properties类型,它的内容来自一个配置文件
// get Constructor of this class with matching parameter types
Constructor<IDAOFactory> constructor = daoFactoryClassgetConstructor(constrArgs);
thisfactory = constructornewInstance(args);
先通过IO,定位到这个包
通过Filelist得到一个包含这个包下所有class的文件的数组。
循环这个数组,用包名拼接每一个遍历出来的文件的名字,得到每一个完整的类名(即,包名加类名)
通过classforname反射得到每一个类实例
之前看过大神的 美团组件化方案 ,其中提到了通过servicelaoder进行解耦的思路,主要是通过配置接口及其实现类的方式坐到接口隔离作用,本文主要是实现此思路并延伸出通过加载自定义properties文件获取参数配置信息
通过查看ServiceLoader源码可知,ServiceLoader是通过加载META-INF/services/路径下的接口实现类,加载方式是通过读取配置文件并通过反射的方式获取类的实例
1配置文件读取,获取文件流
其中PREFIX = "META-INF/services/";
由此可见加载路径是META-INF文件夹下面的文件
2通过流获取实现类全路径
其中parseLine方法里面是做了类全路径名校验
思路:
1读取配置文件
2获取配置的类全名
3通过反射获取类的实例
我们的配置文件将写在assets文件夹下
通过查看apk包结构可以发现assets文件夹位置是与META-INF平级的,由此我们可以将系统的ServiceLoader加载文件路径改为assets路径
1配置文件读取,获取文件流
2通过流获取接口类与实现类的对应集合
由于接口类与实现类是一对一关系,所以通过Map以键值对的方式存储接口类与实现类,在系统ServiceLoader做简单修改:
3获取实现类
在上一步已经获取了所有接口类和实现类的集合,在此通过接口类全名来获取实现类全名,并通过反射的方式获取实现类实例:
到此我们自定义ServiceLoader已经初步实现,在实际开发中,我们一般只需要一个实例及单利,在此我们可以用Map将类的实例与接口类名绑定起来即可。
使用
加载properties配置参数的思路与ServiceLoader基本一致,只是获取配置参数可以通过java类Properties获取
1获取流
和自定义ServiceLoader获取流一致
2获取Properties实例
3获取value
4使用
1在查看Iterable 接口时无意中发现了default关键字,经查看资料显示为java8新加的,用于在接口中写默认的方法函数体
有兴趣的可以去 >
反射说白了就是可以获得一个类的所有信息,主要包括方法和属性两部分。
1获得方法包括获得方法的名称,方法的返回类型,方法的访问修饰符,以及通过反射执行这个方法。
2获得属性包括属性的名称,类型,访问修饰符,以及这个属性的值。
这些获得都有相应的API提供 *** 作。
举个例子:
先定义一个类,有age这个属性,以及age的get和set方法:
public class TestRflectionFather {
public int age =32;
public int getAge() {
return age;
}
public void setAge(int age) {
thisage = age;
}
}
然后 *** 作获得所有方法:
import javalangreflectMethod;
public class Testmain {
public static void main(String[] args) throws Exception {
Class clazz = ClassforName("TestRflectionFather");
Method[] methods =clazzgetDeclaredMethods();
for(Method me:methods)
{
Systemoutprintln(megetName());
}
}
}
//最后输出
getAge
setAge
以上就是关于请问利用Java反射实现一个类中的接口是如何实现的呢全部的内容,包括:请问利用Java反射实现一个类中的接口是如何实现的呢、如何利用java反射构造一个类,使之实现一个接口和一些功能、java如何通过反射获取包中所有的类等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)