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调用其他类的setget方法

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中有三种类类加载器。

1Bootstrap ClassLoader此加载器采用c++编写,一般开发中很少见。

2Extension ClassLoader用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类

3AppClassLoader加载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();         }     } }


 

 

原创粉丝点击