Android 反射机制的理解

2017-01-14 15:49:14来源:http://www.jianshu.com/p/7fdb8c828602作者:Lipt0n人点击

之前在网上找有关反射机制的资料发现网上关于这块的资料不多,而且不太容易懂,所以试着写一篇我自己所理解的反射机制希望能多你有所帮助.


首先来看看用反射机制和用以前的方法新建对象实例有什么不同


第一步新建一个Person对象
用以前的方法是:

Person p = new Person();


在内存中新建一个Person的实例,对象p对这块内存地址进行引用


用反射机制实现 (有三种方法):
第一种:

Class<?> cls=Class.forName("com.fanshe.Person"); //forName(包名.类名)
Person p=(Person)cls.newInstance();


1.通过JVM查找并加载指定的类(上面的代码指定加载了com.fanshe包中的Person类)
2.调用newInstance()方法让加载完的类在内存中创建对应的实例,并把实例赋值给p


第二种:

Person p = new Person();
Class<?> cls=p.getClass();
Person p2=(Person)cls.newInstance();


1.在内存中新建一个Person的实例,对象p对这个内存地址进行引用
2.对象p调用getClass()返回对象p所对应的Class对象
3.调用newInstance()方法让Class对象在内存中创建对应的实例,并且让p2引用实例的内存地址


第三种:

Class<?> cls=Person.Class();
Person p=(Person)cls.newInstance();


1.获取指定类型的Class对象,这里是Person
2.调用newInstance()方法在让Class对象在内存中创建对应的实例,并且让p引用实例的内存地址


注意:
cls.newInstance()方法返回的是一个泛型T,我们要强转成Person类
cls.newInstance()默认返回的是Person类的无参数构造对象
被反射机制加载的类必须有无参数构造方法,否者运行会抛出异常


先来看看反射的好处
可能有人会有疑问,明明直接new对象就好了,为什么非要用反射呢?代码量不是反而增加了?

其实反射的初衷不是方便你去创建一个对象,而是让你在写代码的时候可以更加灵活,降低耦合,提高代码的自适应能力.


怎么样降低耦合度,提高代码的自适应能力?

通过接口实现,但是接口如果需要用到new关键字,这时候耦合问题又会出现
举个栗子:


public static void main(String[] args) {
HeroFacrty facrty =new HeroFacrty();
hero iroman= facrty.CreateHero("IronMan");
iroman.attach();
}
public hero CreateHero(String name) {
if ((name).equals("IronMan")) {
return new IronMan();
}
if ((name).equals("Hulk")) {
return new Hulk();
}
return null;
}
interface hero {
public void attach();
}
class IronMan implements hero {
@Override
public void attach() {
System.out.println("Laser Light");
}
}
class Hulk implements hero {
@Override
public void attach() {
System.out.println("fist");
}
}

假设有1000个不同Hero需要创建,那你打算写1000个 if语句来返回不同的Hero对象?


如果使用反射机制呢?
public static void main(String[] args) {
HeroFacrty facrty = new HeroFacrty();
Hero hero=facrty.CreateHero("test.IroMan");
hero.attack();
}
public Hero CreateHero(String name) {
try {
Class<?> cls = Class.forName(name);
Hero hero = (Hero) cls.newInstance();
return hero;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
class IroMan implements Hero {
@Override
public void attack() {
System.out.println("Laser Light");
}
}
class Hulk implements Hero {
@Override
public void attack() {
System.out.println("Fist");
}
}
interface Hero {
public void attack();
}

利用反射机制进行解耦的原理就是利用反射机制"动态"的创建对象:向CreateHero()方法传入Hero类的包名.类名 通过加载指定的类,然后再实例化对象.


对于反射机制举个不太严谨的栗子:

当你电脑需要使用鼠标时,你向电脑USB接口插入鼠标,鼠标向电脑发送驱动请求,驱动的型号为NFTW-2196的驱动.这时候电脑在驱动集合中查找驱动,找到后运行驱动鼠标能用了,插入键盘同理.


说完了反射机制如何生成类对象,那生成了对象以后当然要开始调用类的方法了

在调用方法前先了解Class<?> cls=Class.forName("fanshe.Person");cls内部有哪些方法供我们使用.









































































方法关键字含义
getDeclareMethods()获取所有的方法
getReturnType()获取方法的返回值类型
getParameterTypes()获取方法的传入参数类型
getDeclareMethod("方法名,参数类型.class,....")获得特定的方法
-
构造方法关键字含义
getDeclaredConstructors()获取所有的构造方法
getDeclaredConstructors(参数类型.class,....)获取特定的构造方法
-
成员变量含义
getDeclaredFields获取所有成员变量
getDeclaredField(参数类型.class,....)获取特定的成员变量
-
父类和父接口含义
getSuperclass()获取某类的父类
getInterfaces()获取某类实现的接口

以下面的Person来做讲解,稍后我们会用反射实现下面的代码:


public class fanshe03 {
public static void main(String[] args) {
Person person=new Person();
person.setName("Lipt0n");
System.out.print(person.getName);
}
}
class Person {
String name;
public Person() {
}
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

很简单步骤分为三步:


实例化一个Person类对象
调用Person.setName("name")设置名字
在控制台打印Person.getName()的值
现在我们用反射机制来实现上面的代码:
public static void main(String[] args) {
try {
Class<?> cls=Class.forName("test.Person");//加载Person类
Object object=(Object) cls.newInstance();//实例化Person
Method setname=cls.getDeclaredMethod("setName", String.class);//获取setName()方法
setname.invoke(object, "Lipt0n");//设置调用setName的对象和传入setName的值
Method getname=cls.getDeclaredMethod("getName");//获取getName方法
System.out.print(getname(object, null));//设置调用getName方法的对象.把值打印到控制台
} catch (Exception e) {
e.printStackTrace();
}
}

Java程序可以加载一个运行时才得知名称的class,获悉其完整构造,并生成其对象实体、或对其成员变量赋值、或调用其方法。这种“看透class”的能力称为反射.--(摘自网上的一段话,具体出处忘记了)



写到这里反射机制的基本用法和好处都基本讲完了.以上就是我对反射机制的理解,希望写出来的东西能对你有所帮助.如果你发现文章有错误的地方希望可以指出,以免误导他人 : )


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台