Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2397530
  • 博文数量: 328
  • 博客积分: 4302
  • 博客等级: 上校
  • 技术积分: 5486
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-01 11:14
个人简介

悲剧,绝对的悲剧,悲剧中的悲剧。

文章分类

全部博文(328)

文章存档

2017年(6)

2016年(18)

2015年(28)

2014年(73)

2013年(62)

2012年(58)

2011年(55)

2010年(28)

分类: Java

2015-07-14 16:15:43

简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息.
反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。

当程序主动使用某个类时,若该类还没加载到内存中,系统会通过加载,链接,初始化3个操作对类进行初始化。
类字面常量”,class”创建Class对象的引用时,不会自动地初始化该Class对象,准备工作包含3个步骤:
1.加载:由类加载器执行,该步骤查找字节码,并从这些字节码中创建一个Class对象
2.链接:在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。
3.初始化:如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块

类的初始化时机
1.创建类的实例
2.访问类或接口的静态变量(static final常量除外,static final变量可以)
3.调用类的静态方法
4.反射(Class.forName(packageName.className))
5.初始化类的子类(子类初始化问题:满足主动调用,即访问子类中的静态变量、方法,否则仅父类初始化)
6.java虚拟机启动时被标明为启动类的类
注:加载顺序:启动类的static block最先加载
(父类静态成员、静态代码块—>子类静态成员、静态代码块—>父类实例成员、代码块——>父类构造函数—>子类实例成员、代码块—>子类构造函数)

我们需要明白在JAVA中任何class都要装载在虚拟机上才能运行,而forClass就是装载类用的,这是要和new不一样,要分清楚哦。
A a = (A)Class.forName(“package.A”).newInstance();和 A a = new A;是等价的。
记住一个概念,静态代码是和class绑定的,class装载成功就表示执行了你的静态代码,而且以后不会再走这套静态代码了
Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也即是说JVM会执行该类的静态代码段。

JAVA中获取Class对象有3种方式:
1.Class.forName()
2.Object.getClass()
3.类字面常量 xx.class

代码例子:

复制代码
package Reflect; class Demo{ //other codes... } class hello{ public static void main(String[] args) {
        Class<?> demo1=null;
        Class<?> demo2=null;
        Class<?> demo3=null; try{ //一般尽量采用这种形式 demo1=Class.forName("Reflect.Demo");
        }catch(Exception e){
            e.printStackTrace();
        }
        demo2=new Demo().getClass();
        demo3=Demo.class;
         
        System.out.println("类名称   "+demo1.getName());//Reflect.Demo System.out.println("类名称   "+demo2.getName());//Reflect.Demo System.out.println("类名称   "+demo3.getName());//Reflect.Demo   }
}
复制代码

 

从Class中获取信息(可以查看Class的API文档了解):

获取类的构造器 
首先介绍一下Constructor类,这个类用来封装反射得到的构造器,Class有四个方法来获得Constructor对象
public Constructor<?>[] getConstructors() 返回类中所有的public构造器集合,默认构造器的下标为0
public Constructor<T> getConstructor(Class<?>... parameterTypes) 返回指定public构造器,参数为构造器参数类型集合
public Constructor<?>[] getDeclaredConstructors() 返回类中所有的构造器,包括私有
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 返回任意指定的构造器

获取类的成员变量 
成员变量用Field类进行封装,主要的方法非常的类似:
public Field getDeclaredField(String name) 获取任意指定名字的成员
public Field[] getDeclaredFields() 获取所有的成员变量
public Field getField(String name) 获取任意public成员变量
public Field[] getFields() 获取所有的public成员变量

获取类的方法 
public Method[] getMethods() 获取所有的共有方法的集合
public Method getMethod(String name,Class<?>... parameterTypes) 获取指定公有方法 参数1:方法名 参数2:参数类型集合 
public Method[] getDeclaredMethods() 获取所有的方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes) 获取任意指定方法

常用的就这些,知道这些,其他的都好办…… getDeclaredMethod*()获取的是类自身声明的所有方法,包含public、protected和private方法。getMethod*()获取的是类的所有共有方法,这就包括自身的所有public方法,和从基类继承的、从接口实现的所有public方法。

 

获取基本信息的例子:

复制代码
import java.lang.reflect.*; import java.lang.annotation.*; //使用2个注释修饰该类 @SuppressWarnings(value="unchecked")
@Deprecated public class ClassTest
{ //为该类定义一个私有的构造器 private ClassTest(){
    } //定义一个有参数的构造器 public ClassTest(String name){
        System.out.println("执行有参数的构造器");
    } //定义一个无参数的info方法 public void info(){
        System.out.println("执行无参数的info方法");
    } //定义一个有参数的info方法 public void info(String str){
        System.out.println("执行有参数的info方法"
            + ",其实str参数值:" + str);
    } //定义一个测试用的内部类 class Inner{
    } public static void main(String[] args) throws Exception{ //下面代码可以获取ClassTest对应的Class Class<ClassTest> clazz = ClassTest.class; //获取该Class对象所对应类的全部构造器 Constructor[] ctors = clazz.getDeclaredConstructors();
        System.out.println("ClassTest的全部构造器如下:"); for (Constructor c : ctors)
        {
            System.out.println(c); //private ClassTest() //public ClassTest(java.lang.String)  } //获取该Class对象所对应类的全部public构造器 Constructor[] publicCtors = clazz.getConstructors();
        System.out.println("ClassTest的全部public构造器如下:"); for (Constructor c : publicCtors)
        {
            System.out.println(c); //public ClassTest(java.lang.String)  } //获取该Class对象所对应类的全部public方法 Method[] mtds = clazz.getMethods();
        System.out.println("ClassTest的全部public方法如下:"); for (Method md : mtds)
        {
            System.out.println(md); //public static void ClassTest.main(java.lang.String[]) throws java.lang.Exception //public void ClassTest.info() //public void ClassTest.info(java.lang.String) //public final void java.lang.Object.wait() throws java.lang.InterruptedException //public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException //public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException //public native int java.lang.Object.hashCode() //public final native java.lang.Class java.lang.Object.getClass() //public boolean java.lang.Object.equals(java.lang.Object) //public java.lang.String java.lang.Object.toString() //public final native void java.lang.Object.notify() //public final native void java.lang.Object.notifyAll()  } //获取该Class对象所对应类的指定方法 System.out.println("ClassTest里带一个字符串参数的info方法为:"
            + clazz.getMethod("info" , String.class)); //public void ClassTest.info(java.lang.String) //获取该Class对象所对应类的上的全部注释 Annotation[] anns = clazz.getAnnotations();
        System.out.println("ClassTest的全部Annotattion如下:"); for (Annotation an : anns)
        {
            System.out.println(an);
        }
        
        System.out.println("该Class元素上的@SuppressWarnings注释为:"
            + clazz.getAnnotation(SuppressWarnings.class)); //获取该Class对象所对应类的全部内部类 Class<?>[] inners = clazz.getDeclaredClasses();
        System.out.println("ClassTest的全部内部类如下:"); for (Class c : inners)
        {
            System.out.println(c); //class ClassTest$Inner  } //使用Class.forName方法加载ClassTest的Inner内部类 Class inClazz = Class.forName("ClassTest$Inner"); //通过getDeclaringClass()访问该类所在的外部类 System.out.println("inClazz对应类的外部类为:" + inClazz.getDeclaringClass()); //class ClassTest System.out.println("ClassTest的包为:" + clazz.getPackage()); //null System.out.println("ClassTest的父类为:" + clazz.getSuperclass()); //class java.lang.Object  }
}
复制代码

 

通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)

复制代码
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);//[null  0] System.out.println(per2);//[Rollen  0] System.out.println(per3);//[null  20] System.out.println(per4);//[Rollen  20]  }
}
复制代码
复制代码
综合例子: 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  } //获得其他类中的全部构造函数 Constructor<?>cons[]=demo.getConstructors(); for (int i = 0; i < cons.length; i++) {
            System.out.println("构造方法:  "+cons[i]); //public Reflect.Person() /public Reflect.Person(java.lang.String)
        } 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){} //通过反射调用其他类中的方法 try{ //调用Person类中的sayChina方法 Method method=demo.getMethod("sayChina");
            method.invoke(demo.newInstance());//hello ,china //调用Person的sayHello方法 method=demo.getMethod("sayHello", String.class,int.class);
            method.invoke(demo.newInstance(),"Rollen",20);//Rollen  20  }catch (Exception e) {
            e.printStackTrace();
        }
        
        
        System.out.println("===============本类属性========================"); // 取得本类的全部属性 Field[] field = demo.getDeclaredFields(); for (int i = 0; i < field.length; i++) { // 权限修饰符 int mo = field[i].getModifiers();
            String priv = Modifier.toString(mo); // 属性类型 Class<?> type = field[i].getType();
            System.out.println(priv + " " + type.getName() + " "
                    + field[i].getName() + ";"); //private java.lang.String sex;   }
        System.out.println("===============实现的接口或者父类的属性========================"); // 取得实现的接口或者父类的属性 Field[] filed1 = demo.getFields(); for (int j = 0; j < filed1.length; j++) { // 权限修饰符 int mo = filed1[j].getModifiers();
            String priv = Modifier.toString(mo); // 属性类型 Class<?> type = filed1[j].getType();
            System.out.println(priv + " " + type.getName() + " "
                    + filed1[j].getName() + ";");
        } //public static final java.lang.String name; //public static final int age;  Object obj = null; try{
         obj=demo.newInstance();
        }catch (Exception e) {
            e.printStackTrace();
        } //通过反射操作属性 Field field = demo.getDeclaredField("sex");
        field.setAccessible(true);
        field.set(obj, "男"); //通过反射取得并修改数组的信息: int[] temp={1,2,3,4,5};
        Class<?>demo=temp.getClass().getComponentType();
        System.out.println("数组类型: "+demo.getName());// int System.out.println("数组长度  "+Array.getLength(temp));//5 System.out.println("数组的第一个元素: "+Array.get(temp, 0));//1 Array.set(temp, 0, 100);
        System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0));//100  }
}
复制代码

 

将反射用于工厂模式(结合属性文件的工厂模式):

首先创建一个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();//Apple  }
    }
}
复制代码

 
如果从静态函数中调用的话,要用
        Method mtd = UniEntrance.class.getMethod(query , Session.class, JsonObject.class);
        mtd.invoke(null,session,parameter);

 

参考:
参考sina博文<<forName和类字面常量.class>>
参考<<疯狂JAVA编程>>第18章
java反射详解 (各个例子写的还是挺不错的)
http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html


另可参考Java反射与内省(Introspector beans)

转载自:http://www.cnblogs.com/lijunamneg/archive/2013/03/25/2980991.html
阅读(1563) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~