【框架基础】:Java反射机制详解(二)

来源:互联网 发布:hashcode源码 编辑:程序博客网 时间:2024/05/18 03:06

        一、Class类

        要正确使用Java反射机制就得使用java.lang.Class这个类。它是Java反射机制的起源。当一个类被加载以后,

Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方

法、成员以及构造方法的声明和定义等信息。

       反射机制获取类有三种方法,我们来获取Foo类类型:

//第一种方式:  Class clazz1 = Class.forName("com.demo.reflect.Foo");  //第二种方式:  //Java中每个类型都有class 属性.  Class clazz2 = Foo.class;     //第三种方式:  //Java语言中任何一个Java对象都有getClass()方法  Foo foo = new Foo();  Class clazz3 = foo.getClass(); //clazz3是运行时类(foo的运行时类是Foo)  

       创建对象:获取类以后我们来创建它的对象,利用newInstance()方法:

Class clazz =Class.forName("com.demo.reflect.Foo");    //创建此Class 对象所表示的类的一个新实例  Object object = clazz.newInstance(); //调用了Foo的无参构造方法

       示例代码:

package com.demo.reflect;public class ClassDemo1 {public static void main(String[] args) {//Foo的实例对象如何表示Foo foo1 = new Foo();//foo就表示出来了。//Foo这个类也是一个实例对象,Class类的实例对象,如何表示呢//任何一个类都是Class的实例对象,这个实例对象有三种表示方式//第一种表示方式--->实际在告诉我们任何一个类都有一个隐含的静态成员变量classClass<?> clazz1 = Foo.class;//第二中表达方式  已经知道该类的对象通过getClass()方法Class<?> clazz2 = foo1.getClass();/* * 官网 clazz1 ,clazz2 表示了Foo类的类类型(class type) * 万事万物皆对象, * 类也是对象,是Class类的实例对象 * 这个对象我们称为该类的类类型 *///不管clazz1  or clazz2都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象System.out.println(clazz1 == clazz2);//第三种表达方式Class<?> clazz3 = null;try {clazz3 = Class.forName("com.demo.reflect.Foo");} catch (ClassNotFoundException e) {e.printStackTrace();}System.out.println(clazz2==clazz3);//我们完全可以通过类的类类型创建该类的对象实例---->通过clazz1 or clazz2 or clazz3创建Foo的实例对象try {/* * clazz1.newInstance()这个方法的返回值是Object类型,所以需要进行强制类型转换。 * newInstance()是实现虚拟构造器的一种方法,(虚拟构造器:允许你不知道确切类型, * 但是你必须要正确的创造自己)而clazz1,clazz2,clazz3仅仅只是Class类的引用, * 编译器不具备任何更多信息,只有在创建新实例的时候会得到Object引用(注意是Object引用), * 你要想用这个引用那你必须要向下转型啦,就是这里的强制类型转换。 */Foo foo = (Foo)clazz1.newInstance();//需要有无参数的构造方法foo.print();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}class Foo{//打印输出方法void print(){System.out.println("foo");}}

       运行结果:

       

       对于基本的数据类型和其对应的包装类也有类类型:

package com.demo.reflect;public class ClassDemo2 {public static void main(String[] args) {Class<?> clazz1 = int.class;//int 的类类型Class<?> clazz2 = String.class;//String类的类类型   String类字节码(自己发明的)Class<?> clazz3 = double.class;//double的类类型Class<?> clazz4 = Double.class;//Double类的类类型Class<?> clazz5 = void.class;//void关键字的类类型System.out.println(clazz1.getName());System.out.println(clazz2.getName());System.out.println(clazz2.getSimpleName());//不包含包名的类的名称System.out.println(clazz3.getName());System.out.println(clazz4.getName());System.out.println(clazz4.getSimpleName());//不包含包名的类的名称System.out.println(clazz5.getName());}}

       运行结果:

       

       二、反射机制的相关API

       通过一个对象获得完整的包名和类名:

package com.demo.reflect;public class TestReflect {    public static void main(String[] args) throws Exception {        TestReflect testReflect = new TestReflect();        System.out.println(testReflect.getClass().getName());// 结果是com.demo.reflect.TestReflect    }}

       实例化Class类对象:

package com.demo.reflect;public class TestReflect {    public static void main(String[] args) throws Exception {        Class<?> clazz1 = null;        Class<?> clazz2 = null;        Class<?> clazz3 = null;        // 一般采用这种形式        clazz1 = Class.forName("com.demo.reflec.TestReflect");        clazz2 = new TestReflect().getClass();        clazz3 = TestReflect.class;        System.out.println("类名称   " + clazz1.getName());//结果是com.demo.reflect.TestReflect        System.out.println("类名称   " + clazz2.getName());//结果是com.demo.reflect.TestReflect        System.out.println("类名称   " + clazz3.getName());//结果是com.demo.reflect.TestReflect    }}

       获取一个对象的父类与实现的接口:

package com.demo.reflect;import java.io.Serializable;public class TestReflect implements Serializable {    public static void main(String[] args) throws Exception {        Class<?> clazz = Class.forName("com.demo.reflect.TestReflect");        // 取得父类        Class<?> parentClass = clazz.getSuperclass();        System.out.println("clazz的父类为:" + parentClass.getName());        // clazz的父类为: java.lang.Object        // 获取所有的接口        Class<?> intes[] = clazz.getInterfaces();        System.out.println("clazz实现的接口有:");        for (int i = 0; i < intes.length; i++) {            System.out.println((i + 1) + ":" + intes[i].getName());        }        // clazz实现的接口有:        // 1:java.io.Serializable    }}

       获取某个类中的全部构造函数 - 详见下例

       通过反射机制实例化一个类的对象:

package com.demo.reflect;import java.lang.reflect.Constructor;public class TestReflect {    public static void main(String[] args) throws Exception {        Class<?> class1 = null;        class1 = Class.forName("net.xsoftlab.baike.User");        // 第一种方法,实例化默认构造方法,调用set赋值        User user = (User) class1.newInstance();        user.setAge(20);        user.setName("Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]        // 第二种方法 取得全部的构造函数 使用构造函数赋值        Constructor<?> cons[] = class1.getConstructors();        // 查看每个构造方法需要的参数        for (int i = 0; i < cons.length; i++) {            Class<?> clazzs[] = cons[i].getParameterTypes();            System.out.print("cons[" + i + "] (");            for (int j = 0; j < clazzs.length; j++) {                if (j == clazzs.length - 1)                    System.out.print(clazzs[j].getName());                else                    System.out.print(clazzs[j].getName() + ",");            }            System.out.println(")");        }        // 结果        // cons[0] (java.lang.String)        // cons[1] (int,java.lang.String)        // cons[2] ()        user = (User) cons[0].newInstance("Rollen");        System.out.println(user);        // 结果 User [age=0, name=Rollen]        user = (User) cons[1].newInstance(20, "Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]    }}class User {    private int age;    private String name;    public User() {        super();    }    public User(String name) {        super();        this.name = name;    }    public User(int age, String name) {        super();        this.age = age;        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "User [age=" + age + ", name=" + name + "]";    }}

       获取某个类的全部属性:

package com.demo.reflect;import java.io.Serializable;import java.lang.reflect.Field;import java.lang.reflect.Modifier;public class TestReflect implements Serializable {    public static void main(String[] args) throws Exception {        Class<?> clazz = Class.forName("com.demo.reflect.TestReflect");        System.out.println("===============本类属性===============");        // 取得本类的全部属性        Field[] field = clazz.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() + ";");        }                 System.out.println("==========实现的接口或者父类的属性==========");        // 取得实现的接口或者父类的属性        Field[] filed1 = clazz.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() + ";");        }    }}

       获取某个类的全部方法:

package com.demo.reflect;import java.io.Serializable;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class TestReflect implements Serializable {    public static void main(String[] args) throws Exception {        Class<?> clazz = Class.forName("com.demo.reflect.TestReflect");        Method method[] = clazz.getMethods();        for (int i = 0; i < method.length; ++i) {            Class<?> returnType = method[i].getReturnType();            Class<?> para[] = method[i].getParameterTypes();            int temp = method[i].getModifiers();            System.out.print(Modifier.toString(temp) + " ");            System.out.print(returnType.getName() + "  ");            System.out.print(method[i].getName() + " ");            System.out.print("(");            for (int j = 0; j < para.length; ++j) {                System.out.print(para[j].getName() + " " + "arg" + j);                if (j < para.length - 1) {                    System.out.print(",");                }            }            Class<?> exce[] = method[i].getExceptionTypes();            if (exce.length > 0) {                System.out.print(") throws ");                for (int k = 0; k < exce.length; ++k) {                    System.out.print(exce[k].getName() + " ");                    if (k < exce.length - 1) {                        System.out.print(",");                    }                }            } else {                System.out.print(")");            }            System.out.println();        }    }}

       通过反射机制调用某个类的方法:

package com.demo.reflect;import java.lang.reflect.Method;public class TestReflect {    public static void main(String[] args) throws Exception {        Class<?> clazz = Class.forName("com.demo.reflect.TestReflect");        // 调用TestReflect类中的reflect1方法        Method method = clazz.getMethod("reflect1");        method.invoke(clazz.newInstance());        // Java 反射机制 - 调用某个类的方法1.        // 调用TestReflect的reflect2方法        method = clazz.getMethod("reflect2", int.class, String.class);        method.invoke(clazz.newInstance(), 20, "张三");        // Java 反射机制 - 调用某个类的方法2.        // age -> 20. name -> 张三    }    public void reflect1() {        System.out.println("Java 反射机制 - 调用某个类的方法1.");    }    public void reflect2(int age, String name) {        System.out.println("Java 反射机制 - 调用某个类的方法2.");        System.out.println("age -> " + age + ". name -> " + name);    }}

       通过反射机制操作某个类的属性:

package com.demo.reflect;import java.lang.reflect.Field;public class TestReflect {    private String proprety = null;    public static void main(String[] args) throws Exception {        Class<?> clazz = Class.forName("com.demo.reflect.TestReflect");        Object obj = clazz.newInstance();        // 可以直接对 private 的属性赋值        Field field = clazz.getDeclaredField("proprety");        field.setAccessible(true);        field.set(obj, "Java反射机制");        System.out.println(field.get(obj));    }}

       反射机制的动态代理:

package com.demo.reflect;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;//定义项目接口interface Subject {    public String say(String name, int age);}// 定义真实项目class RealSubject implements Subject {    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);    }    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Object temp = method.invoke(this.obj, args);        return temp;    }}/** * 在java中有三种类类加载器。 *  * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 *  * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类 *  * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 *  * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。 */public class TestReflect {    public static void main(String[] args) throws Exception {        MyInvocationHandler demo = new MyInvocationHandler();        Subject sub = (Subject) demo.bind(new RealSubject());        String info = sub.say("Rollen", 20);        System.out.println(info);    }}



1 0