Java中的反射
来源:互联网 发布:淘宝图片很不清楚 编辑:程序博客网 时间:2024/04/30 15:10
Java中的反射
如果要用到反射,肯定要用到java.lang.Class类型,下面就先介绍一下在Java中获取java.lang.Class。
获取Class对象的方法:
1、 对象.getClass()。比如:Class<?> c = obj.getClass();
2、 Class.forName(“要反射对象的全路径名”)。比如:Class<?> c = Class.forName(“Reflect.Demo”);
3
、类型
.class
。如比:
Class<Boolean> c = Boolean.class;
获取该类型实例的方法:
1、 newInstance()方式:使用这种方式的时候,一定要定义类型的无参构造函数,否则,将出现java.lang.InstantiationException异常。
package Reflect; class Person{ public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString(){ return "["+this.name+" "+this.age+"]"; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.Person"); }catch (Exception e) { e.printStackTrace(); } Person per=null; try { per=(Person)demo.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } per.setName("Rollen"); per.setAge(20); System.out.println(per); } }
2、通过调用类型的构造函数的方式:
package Reflect; import java.lang.reflect.Constructor; class Person{ 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; } @Override public String toString(){ return "["+this.name+" "+this.age+"]"; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.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("Rollen"); per3=(Person)cons[2].newInstance(20); per4=(Person)cons[3].newInstance("Rollen",20); }catch(Exception e){ e.printStackTrace(); } System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); } }
好了,现在我们已经可以很容易地得到指定类型的Class,并从容的从该Class创建出对应的类型实例。下面介绍一些反射中的常用操作。
1、返回一个类实现的接口:
package Reflect; interface China{ public static final String name="Rollen"; public static int age=20; public void sayChina(); public void sayHello(String name, int age); } class Person implements China{ public Person() { } public Person(String sex){ this.sex=sex; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } @Override public void sayChina(){ System.out.println("hello ,china"); } @Override public void sayHello(String name, int age){ System.out.println(name+" "+age); } private String sex; } class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.Person"); }catch (Exception e) { e.printStackTrace(); } //保存所有的接口 Class<?> intes[]=demo.getInterfaces(); for (int i = 0; i < intes.length; i++) { System.out.println("实现的接口 "+intes[i].getName()); } } }
【运行结果】:
实现的接口 Reflect.China
2、取得其他类中的父类
class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.Person"); }catch (Exception e) { e.printStackTrace(); } //取得父类 Class<?> temp=demo.getSuperclass(); System.out.println("继承的父类为: "+temp.getName()); } }
【运行结果】
继承的父类为: java.lang.Object
3、获得其他类中的全部构造函数
class hello{ public static void main(String[] args) { Class<?> demo=null; try{ demo=Class.forName("Reflect.Person"); }catch (Exception e) { e.printStackTrace(); } Constructor<?>cons[]=demo.getConstructors(); for (int i = 0; i < cons.length; i++) { Class<?> p[]=cons[i].getParameterTypes(); System.out.print("构造方法: "); int mo=cons[i].getModifiers(); System.out.print(Modifier.toString(mo)+" "); System.out.print(cons[i].getName()); System.out.print("("); for(int j=0;j<p.length;++j){ System.out.print(p[j].getName()+" arg"+i); if(j<p.length-1){ System.out.print(","); } } System.out.println("){}"); } } }
【运行结果】:
构造方法: public Reflect.Person(){}
构造方法: public Reflect.Person(java.lang.String arg1){}
4、反射调用其他类中的方法
class hello { public static void main(String[] args) { Class<?> demo = null; try { demo = Class.forName("Reflect.Person"); } catch (Exception e) { e.printStackTrace(); } try{ //调用Person类中的sayChina方法 Method method=demo.getMethod("sayChina"); method.invoke(demo.newInstance()); //调用Person的sayHello方法 method=demo.getMethod("sayHello", String.class,int.class); method.invoke(demo.newInstance(),"Rollen",20); }catch (Exception e) { e.printStackTrace(); } } }
【运行结果】:
hello ,china
Rollen 20
5、调用其他类的set和get方法
class hello { public static void main(String[] args) { Class<?> demo = null; Object obj=null; try { demo = Class.forName("Reflect.Person"); } catch (Exception e) { e.printStackTrace(); } try{ obj=demo.newInstance(); }catch (Exception e) { e.printStackTrace(); } setter(obj,"Sex","男",String.class); getter(obj,"Sex"); } /** * @param obj * 操作的对象 * @param att * 操作的属性 * */ public static void getter(Object obj, String att) { try { Method method = obj.getClass().getMethod("get" + att); System.out.println(method.invoke(obj)); } catch (Exception e) { e.printStackTrace(); } } /** * @param obj * 操作的对象 * @param att * 操作的属性 * @param value * 设置的值 * @param type * 参数的属性 * */ public static void setter(Object obj, String att, Object value, Class<?> type) { try { Method method = obj.getClass().getMethod("set" + att, type); method.invoke(obj, value); } catch (Exception e) { e.printStackTrace(); } } }// end class
6、通过反射操作属性
class hello { public static void main(String[] args) throws Exception { Class<?> demo = null; Object obj = null; demo = Class.forName("Reflect.Person"); obj = demo.newInstance(); Field field = demo.getDeclaredField("sex"); field.setAccessible(true); field.set(obj, "男"); System.out.println(field.get(obj)); } }// end class
7、通过反射取得并修改数组的信息
import java.lang.reflect.*; class hello{ public static void main(String[] args) { int[] temp={1,2,3,4,5}; Class<?>demo=temp.getClass().getComponentType(); System.out.println("数组类型: "+demo.getName()); System.out.println("数组长度 "+Array.getLength(temp)); System.out.println("数组的第一个元素: "+Array.get(temp, 0)); Array.set(temp, 0, 100); System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0)); } }
【运行结果】:
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100
8、通过反射修改数组大小
class hello{ public static void main(String[] args) { int[] temp={1,2,3,4,5,6,7,8,9}; int[] newTemp=(int[])arrayInc(temp,15); print(newTemp); System.out.println("====================="); String[] atr={"a","b","c"}; String[] str1=(String[])arrayInc(atr,8); print(str1); } /** * 修改数组大小 * */ public static Object arrayInc(Object obj,int len){ Class<?>arr=obj.getClass().getComponentType(); Object newArr=Array.newInstance(arr, len); int co=Array.getLength(obj); System.arraycopy(obj, 0, newArr, 0, co); return newArr; } /** * 打印 * */ public static void print(Object obj){ Class<?>c=obj.getClass(); if(!c.isArray()){ return; } System.out.println("数组长度为: "+Array.getLength(obj)); for (int i = 0; i < Array.getLength(obj); i++) { System.out.print(Array.get(obj, i)+" "); } } }
【运行结果】:
数组长度为: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 =====================
数组长度为: 8
a b c null null null null null
9、反射用于动态代理
首先来看看如何获得类加载器
class test{ } class hello{ public static void main(String[] args) { test t=new test(); System.out.println("类加载器 "+t.getClass().getClassLoader().getClass().getName()); } }
【程序输出】:
类加载器 sun.misc.Launcher$AppClassLoader
其实在java中有三种类类加载器。
1)Bootstrap ClassLoader此加载器采用c++编写,一般开发中很少见。
2)Extension ClassLoader用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
3)AppClassLoader加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
package Reflect; import java.lang.reflect.*; //定义项目接口 interface Subject { public String say(String name, int age); } // 定义真实项目 class RealSubject implements Subject { @Override public String say(String name, int age) { return name + " " + age; } } class MyInvocationHandler implements InvocationHandler { private Object obj = null; public Object bind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke(this.obj, args); return temp; } } class hello { public static void main(String[] args) { MyInvocationHandler demo = new MyInvocationHandler(); Subject sub = (Subject) demo.bind(new RealSubject()); String info = sub.say("Rollen", 20); System.out.println(info); } }
【运行结果】:
Rollen 20
10、反射用于工厂模式
先来看看,如果不用反射的时候,的工厂模式吧:
/** * @author Rollen-Holt 设计模式之 工厂模式 */ interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } // 构造工厂类 // 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了 class Factory{ public static fruit getInstance(String fruitName){ fruit f=null; if("Apple".equals(fruitName)){ f=new Apple(); } if("Orange".equals(fruitName)){ f=new Orange(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance("Orange"); f.eat(); } }
这样,当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。
现在我们看看利用反射机制:
package Reflect; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } class Factory{ public static fruit getInstance(String ClassName){ fruit f=null; try{ f=(fruit)Class.forName(ClassName).newInstance(); }catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a){ fruit f=Factory.getInstance("Reflect.Apple"); if(f!=null){ f.eat(); } } }
现在就算我们添加任意多个子类的时候,工厂类就不需要修改。
上面的代码虽然可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。
下面我们来看看:结合属性文件的工厂模式
首先创建一个fruit.properties的资源文件,
内容为:
apple=Reflect.Apple
orange=Reflect.Orange
package Reflect; import java.io.*; import java.util.*; interface fruit{ public abstract void eat(); } class Apple implements fruit{ public void eat(){ System.out.println("Apple"); } } class Orange implements fruit{ public void eat(){ System.out.println("Orange"); } } //操作属性文件类 class init{ public static Properties getPro() throws FileNotFoundException, IOException{ Properties pro=new Properties(); File f=new File("fruit.properties"); if(f.exists()){ pro.load(new FileInputStream(f)); }else{ pro.setProperty("apple", "Reflect.Apple"); pro.setProperty("orange", "Reflect.Orange"); pro.store(new FileOutputStream(f), "FRUIT CLASS"); } return pro; } } class Factory{ public static fruit getInstance(String ClassName){ fruit f=null; try{ f=(fruit)Class.forName(ClassName).newInstance(); }catch (Exception e) { e.printStackTrace(); } return f; } } class hello{ public static void main(String[] a) throws FileNotFoundException, IOException{ Properties pro=init.getPro(); fruit f=Factory.getInstance(pro.getProperty("apple")); if(f!=null){ f.eat(); } } }
- JAVA中的类反射
- Java中的反射
- Java中的类反射
- Java中的反射机制
- JAVA中的反射机制
- java 中的反射
- Java中的反射机制
- java中的反射机制
- JAVA中的反射机制
- Java中的反射机制
- java中的反射应用
- java中的反射
- Java中的反射
- Java中的反射机制
- java中的反射
- java中的反射
- java中的反射机制
- java中的反射问题
- VXLAN标准初探:扩展VLAN 支持远距离VM迁移
- 第13周任务2.1
- 今天开始在办公室上班了。
- 国外主要通用网络管理软件
- Netbeans7.0.1下使用JDBC连接MSSQL2008
- Java中的反射
- SQL Server自定义函数
- JNI:Java调用C/C++-传递空值(null)的处理方法
- Web2.0十大安全威胁
- CSS 与 javascript 属性对照
- web浏览器兼容性测试
- 2012C++程序设计实验报告[13.4]
- 什么是kinect
- JQuery相关的资料汇总