Java反射机制

来源:互联网 发布:北京美工集团礼品 编辑:程序博客网 时间:2024/05/16 10:21

通过反射获取类

Java中,类也是对象,是java.lang.Class类的实例对象

任何一个类都是Class类的实例对象,这个实例对象有三种表达方式:

class Foo{    void info(){System.out.println("-------");}}public class ClassDemo01 {    public static void main(String[] args) throws Exception {        Foo foo1 = new Foo();        //Foo本身也是Class类的实例对象        //第一种表达方式-->根据类的class静态变量        Class c1 = Foo.class;        //第二种表达方式-->该类的对象通过getClass方法        Class c2 = foo1.getClass();        System.out.println(c1==c2); //true,一个类只可能是Class的一个实例对象        //第三种表达方式-->根据类名        Class c3 = null;        c3 = Class.forName("reflection.Foo");        System.out.println(c3==c2); //true        //我们完全可以通过该类的类类型创建该类的实例对象,通过c1或c2、c3创建Foo的实例对象        Foo foo2 = (Foo) c1.newInstance();  //要求需要有无参数的构造方法        foo2.info();    }}/*output:    true    true    -------*/  * /

基础类也一样:

public class ClassDemo02 {    public static void main(String[] args){        Class[] c = {int.class,double.class,Double.class,                String.class,void.class};        for(Class s:c){            System.out.println(s);        }    }}/** *output: intdoubleclass java.lang.Doubleclass java.lang.Stringvoid */

new 创建对象 是静态加载类:在编译时就加载所有需要的的类(包)
Class.forName()可以动态加载类:在运行时加载:

package reflection;class Base{    static int i = 2;    static{        System.out.println("Base->static");    }    {        System.out.println("Base->Initialize");    }    Base(){        System.out.println("Base->Constructor");    }}public class NewClass {    //静态加载类    public static void staticLoading(){        System.out.println(Base.i);        Base base = new Base();    }    //动态加载类    public static void dynamicLoading(){        try {            Class c = Class.forName("reflection.Base");            c.newInstance();        } catch (Exception e) {            e.printStackTrace();        }    }    public static void main(String[] args) {        System.out.println("static Loading");        staticLoading();        System.out.println("dynamic Loading");        dynamicLoading();    }}

这里为了显示编译的问题,把Base类注释掉,静态加载的部分因为找不到Base类出现报错,但是动态加载的类不会出现问题。

我们可以生成对应的类:

package reflection;interface A{    void info();}class NewA implements A{    public void info(){        System.out.println("New A");    }}class OldA implements A{    public void info(){        System.out.println("Old A");    }}public class ClassDemo_New {    public static void main(String[] args){        try {            Class c = Class.forName(args[0]);            A a = (A) c.newInstance();  //通过类类型,创建该对象            a.info();        } catch (Exception e) {            e.printStackTrace();        }    }}/** * input value:reflection.NewA * output:New A */

用反射理解泛型:

 编译之后集合的泛型是去泛型化的,Java中集合的泛型,是防止错误输入的,只在编译阶段有效。

之前也说过反射是一种动态加载的机制,利用这一点可以绕过泛型的检查。

package reflection;import java.lang.reflect.Method;import java.util.*;public class MethodDemo {    public static void main(String[] args) {        List<String> strlist = new ArrayList<String>();        List<Integer> numlist = new ArrayList<Integer>();        strlist.add("str");//      The method add(Integer) in the type List<Integer> is not applicable for the arguments (String)//      numlist.add("sd");        Class strclazz = strlist.getClass();        Class numclazz = numlist.getClass();        System.out.println("尽管这里泛型不同,但是这是得到的类还是相同的" + (strclazz == numclazz));        //通过反射的方式绕过检查        try {            Method m = numclazz.getMethod("add", Object.class);            //这里绕过了检查            m.invoke(numlist, "src");            //显示:[src]还是把数据放进去了            System.out.println(numlist);        } catch (Exception e) {        }    }}

通过反射来调用私有构造器

package reflection;import java.lang.reflect.Constructor;class Own {    private Own() {        System.out.println("private constructor---");    }    public void info() {        System.out.println("Own.info()---");    }}public class GetPrivateClass {    public static void main(String[] args) throws Exception{        //获取类        Class clazz = Own.class;        //获取构造器        Constructor con = clazz.getDeclaredConstructor();        //设定访问权限        con.setAccessible(true);        //通过构造器来创建类        Own own = (Own) con.newInstance();        own.info();    }}/** * result:private constructor---Own.info()--- */