java的反射机制

什么是反射?

反射就是程序在运行时能够获取自身的信息。只要知道类的名字,就可以通过反射机制来获取类的所有信息。通过反射可以实现动态创建对象和编译,体现出很大的灵活性。举个例子来说,在学jdbc时用过一行代码,

1
Class.forName("com.mysql.jdbc.Driver.class").newInstance()

这就是反射,现在很多开框架都用到反射机制,hibernate、struts都是用反射机制实现的。

反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!

反射机制的作用:

  1. 反编译:.class—>.java,
  2. 通过反射机制访问java对象的属性,方法,构造方法等。

    Class类

    Class类:类本身就是对象,类是java.long.Class类的实例对象。
    注意不可以直接用
    1
    Class a = new Class();

创建对象,Class对象会由java虚拟机去创建
但有三种其他的表达方式:

1
Class c1 = A.class();

1
Class c2 = a.getClass();
1
Class c3 = Class.forName("className"); //className必须为全名,也就是得包含包名,

并且c1 = c2 =c3
通过c1.newInstance();去创建对象的实例

编译时加载类是静态加载类、用new创建对象时就是静态加载类
运行时加载类是动态加载类。

反射例子

采用例子来帮助理解Java反射机制

通过一个对象获得完整的包名和类名

1
2
3
4
5
6
7
8
9
10
11
12
package zju;

class Demo{
//other codes...
}

class test{
public static void main(String[] args) {
Demo demo=new Demo();
System.out.println(demo.getClass().getName());
}
}

【运行结果】:zju.Demo

实例化Class类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package zju;
class Demo{
//other codes...
}

class test{
public static void main(String[] args) {
Class<?> demo1=null;
Class<?> demo2=null;
Class<?> demo3=null;
try{
//一般尽量采用这种形式
demo1=Class.forName("zju.Demo");//必须为全名,也就是包名+类名
}catch(Exception e){
e.printStackTrace();
}
demo2=new Demo().getClass();
demo3=Demo.class;

System.out.println("类名称:"+demo1.getName());
System.out.println("类名称:"+demo2.getName());
System.out.println("类名称:"+demo3.getName());

}
}

运行结果】:
类名称:zju.Demo

类名称:zju.Demo

类名称:zju.Demo

通过Class调用其他类中的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package zju;

import java.lang.zju.Constructor;

class Person{

private String name;
private int age;

public Person() {

}
public Person(String name){
this.name=name;
}
public Person(int age){
this.age=age;
}
public Person(String name, int age) {
this.age=age;
this.name=name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}

public void sayHello(){
System.out.println("hello");
}

public void sayHello(String name, int age){
System.out.println(name+" "+age);
}

}

class hello{
public static void main(String[] args) {
Class<?> demo=null;
try{
demo=Class.forName("zju.Person");
}catch (Exception e) {
e.printStackTrace();
}
Person per1=null;
Person per2=null;
Person per3=null;
Person per4=null;
//取得全部的构造函数
Constructor<?> cons[]=demo.getConstructors();
try{
per1=(Person)cons[0].newInstance();
per2=(Person)cons[1].newInstance("Tom");
per3=(Person)cons[2].newInstance(20);
per4=(Person)cons[3].newInstance("Tom",20);
}catch(Exception e){
e.printStackTrace();
}
System.out.println(per1);
System.out.println(per2);
System.out.println(per3);
System.out.println(per4);
}
}

【运行结果】:
[null 0]

[Tom 0]

[null 20]

[Tom 20]

通过反射调用其他类中的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class hello {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("zju.Person");
} catch (Exception e) {
e.printStackTrace();
}
try{
//调用Person类中的sayChina方法
Method method=demo.getMethod("sayHello");
method.invoke(demo.newInstance());
//调用Person的sayHello方法
method=demo.getMethod("sayHello", String.class,int.class);
method.invoke(demo.newInstance(),"Tom",20);

}catch (Exception e) {
e.printStackTrace();
}
}
}

【运行结果】:

hello

Tom 20

一些常用的方法:

获得构造函数的方法

1
2
3
4
Constructor getConstructor(Class[] params)//根据指定参数获得public构造器
Constructor[] getConstructors()//获得public的所有构造器
Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器
Constructor[] getDeclaredConstructors()//获得public的所有构造器

获得类方法的方法

1
2
3
4
Method getMethod(String name, Class[] params)//根据方法名,参数类型获得方法
Method[] getMethods()//获得所有的public方法,包括从父类继承而来的
Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法
Method[] getDeclaredMethods()//获得所以的public和非public方法

获得类中属性的方法

1
2
3
4
5
Field getField(String name)//根据变量名得到相应的public变量
Field[] getFields()//获得类中所有的变量
Field getDeclaredField(String name)//根据方法名获得public和非public变量
Field[] getDeclaredFields()//获得类中所有的public和非public变量
String getName()//获得该对象的名字

举例

1
2
3
4
5
6
7
8
9
10
public class ReflectPoint{
private int x;
public int y;

public ReflectPoint(int x,int y){
super();
this.x = x;
this.y = y;
}
}
1
2
3
4
5
6
7
8
//开始对ReflectPoint进行反射
ReflectPoint pt1 = new ReflectPoint(3,5);
Field fieldY = pt1.getClass.getField("y"); //注意:fieldY不是对象身上的变量,而是类上的,需要用fieldY.get(Object)来取某一个对象身上对应的值
System.out.println(fieldY.get(pt1));

Field fieldX = pt1.getClass.getDeclaredField("x"); //注意:x是私有的,需要使用getDeclaredField来获得
fieldX.setAccessible(true); //暴力反射,设置fieldX可以访问
System.out.println(fieldX.get(pt1));

总结

java反射机制是一个很好用的东西,用它可以解决很多死的东西,因为反射机制的灵活行很大。可以很大的减少开发时间,而且代码的可读性好。



http://longliqiang88.github.io/2015/07/12/Java%E5%AD%A6%E4%B9%A0-%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/

original link: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值