什么是反射?
反射就是程序在运行时能够获取自身的信息。只要知道类的名字,就可以通过反射机制来获取类的所有信息。通过反射可以实现动态创建对象和编译,体现出很大的灵活性。举个例子来说,在学jdbc时用过一行代码,
1
| Class.forName("com.mysql.jdbc.Driver.class").newInstance()
|
这就是反射,现在很多开框架都用到反射机制,hibernate、struts都是用反射机制实现的。
反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
反射机制的作用:
- 反编译:.class—>.java,
- 通过反射机制访问java对象的属性,方法,构造方法等。
Class类
Class类:类本身就是对象,类是java.long.Class类的实例对象。
注意不可以直接用
创建对象,Class对象会由java虚拟机去创建
但有三种其他的表达方式:
1
| Class c2 = a.getClass();
|
1
| Class c3 = Class.forName("className");
|
并且c1 = c2 =c3
通过c1.newInstance();去创建对象的实例
编译时加载类是静态加载类、用new创建对象时就是静态加载类
运行时加载类是动态加载类。
反射例子
采用例子来帮助理解Java反射机制
通过一个对象获得完整的包名和类名
1 2 3 4 5 6 7 8 9 10 11 12
| package zju;
class Demo{ } 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{ } 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{ Method method=demo.getMethod("sayHello"); method.invoke(demo.newInstance()); 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) Constructor[] getConstructors() Constructor getDeclaredConstructor(Class[] params) Constructor[] getDeclaredConstructors()
|
获得类方法的方法
1 2 3 4
| Method getMethod(String name, Class[] params) Method[] getMethods() Method getDeclaredMethod(String name, Class[] params) Method[] getDeclaredMethods()
|
获得类中属性的方法
1 2 3 4 5
| Field getField(String name) Field[] getFields() Field getDeclaredField(String name) Field[] getDeclaredFields() 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 pt1 = new ReflectPoint(3,5); Field fieldY = pt1.getClass.getField("y"); System.out.println(fieldY.get(pt1));
Field fieldX = pt1.getClass.getDeclaredField("x"); fieldX.setAccessible(true); System.out.println(fieldX.get(pt1));
|
总结
java反射机制是一个很好用的东西,用它可以解决很多死的东西,因为反射机制的灵活行很大。可以很大的减少开发时间,而且代码的可读性好。