Java Reflection 学习笔记

来源:互联网 发布:淘宝网规则全文 编辑:程序博客网 时间:2024/06/06 12:49
1.什么是Java的反射机制

Java反射机制是在运行过程中,对于任意一个类,知道其所以的属性和方法。对于任意一个对象,能够调用其方法。这种动态调用信息,动态调用方法的功能称为Java的反射机制。
总而言之,Java反射机制主要提供了以下功能:
      1.在运行时判断任意一个对象所属的类
      2.在运行时构造任意一个类的对象
      3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
      4.在运行时调用任意一个对象的方法(注意:前提都是在运行时,而不是在编译时)


2.Java 反射相关的API简介:
      位于java。lang。reflect包中
        --Class类:代表一个类
        --Filed类:代表类的成员变量
        --Method类:代表类的方法
        --Constructor类:代表类的构造方法
        --Array类:提供了动态创建数组,以及访问数组的元素的静态方法。该类中的所有方法都是静态方法

3. Class类
Class类十分的特殊,它和一般的类一样继承自Object,其实体用以表达java程序运行时的 class和 interface,也用来表达 enum,array,primitive,Java Types 以及关键字void,当加载一个类,或者当加载器(class loader)的defineClass()被JVM调用,便产生一个Class对象, Class是Reflection起源,针对任何你想探勘的class(类),唯有现为他产生一个Class的对象,接下来才能经由后者唤起为数十多个的反射API。

Java允许我们从多种途径为一个类class生成对应的Class对象。
         --运用 getClass():Object类中的方法,每个类都拥有此方法

String str="abc";Class cl=str.getClass();

   --运用 Class。getSuperclass():Class类中的方法,返回该Class的父类的Class
         --运用 Class。forName()静态方法:
         --运用 ,Class:类名.class
         --运用primitive wrapper classes的TYPE语法: 基本类型包装类的TYPE,如:Integer.TYPE
         注意:TYPE的使用,只适合原生(基本)数据类型

光说不练假把式,下面用几个小例子来说明Java反射的用法:
一、通过Class.forName方法来获取类,并创建对象,再使用此对象调用相应的方法。
package domain;public interface Fruit {    public abstract void eat();}
package domain;public class Apple implements Fruit{    @Override    public void eat() {        System.out.println("Alan Turing died eating an poisoned apple");    }}
package domain;public class Banana implements Fruit{    @Override    public void eat() {        System.out.println("banaba is very nice");    }}
package reflect;import domain.Fruit;public class FruitReflection {    public void printer(String classPath) throws ClassNotFoundException, IllegalAccessException, InstantiationException {        Class<?> fruit = Class.forName(classPath);        Fruit ck = (Fruit) fruit.newInstance();        ck.eat();    }    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {        new FruitReflection().printer("domain.Banana");        new FruitReflection().printer("domain.Apple");    }}

运行结果:
banaba is very niceAlan Turing died eating an poisoned apple

二、通过反射调用接口、构造函数及父类
package domain;public interface China {    public static final String name = "Alex";    public static final int age = 23;    public void sayChina();    public void sayHello(String name, int age);}
package domain;public class ChinaImp implements China {    private String name;    public void setName(String name) {        this.name = name;    }    public String getName() {        return name;    }    public ChinaImp() {    }    public ChinaImp(String name) {        this.name = name;    }    @Override    public void sayChina() {        System.out.println("Say hello China");    }    @Override    public void sayHello(String name, int age) {        System.out.println(name + " " + age);    }}
package reflect;import java.lang.reflect.Constructor;public class ChinaReflection {    public static void main(String args[]) {        Class c = null;        try {            c = Class.forName("domain.ChinaImp");  //domain is the package of ChinaImp.java        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        Class interfaces[] = c.getInterfaces();        Class superClass = c.getSuperclass();        Constructor[] cons = c.getConstructors();        for (int i = 0; i < interfaces.length; i++) {            System.out.println("interface -- >" + interfaces[i].getName());        }        System.out.println("SuperClass -- >" + superClass.getName());        for (int i = 0; i < cons.length; i++){            System.out.println("constructor name -- >" + cons[i]);        }    }}

运行结果:
interface -- >domain.ChinaSuperClass -- >java.lang.Objectconstructor name -- >public domain.ChinaImp(java.lang.String)constructor name -- >public domain.ChinaImp()

三、通过反射获得定义的字段、方法、方法参数、方法修饰符、返回类型、以及特定类的方法的调用。
package reflect;import domain.ChinaImp;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Modifier;public class ChinaReflection_2 {    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {        Class ci = null;        try {            ci = Class.forName("domain.ChinaImp");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        Field[] fields = ci.getFields();        Field[] declaredFields = ci.getDeclaredFields();        Method methods[] = ci.getMethods();        Class<?>[] para = null;        for (int i = 0; i < fields.length; i++) {            System.out.println("all fields -- > " + fields[i].getName());        }        System.out.println("****************************************");        for (int i = 0; i < declaredFields.length; i++) {            System.out.println("declared fields -- > " + declaredFields[i].getName());        }        System.out.println("****************************************");        for (int i = 0; i < methods.length; i++) {            System.out.println("method name  -- > " + methods[i].getName());            para = methods[i].getParameterTypes();            for (int j = 0; j < para.length; j++) {                System.out.println("paramater -- > " + para[j].getName());            }            int modifier = methods[i].getModifiers();            System.out.println("Modifiers -- > " + Modifier.toString(modifier));            Class<?> returnType = methods[i].getReturnType();            System.out.println("return type -- > " + returnType.getName());            System.out.println(" --------------------------------------- ");        }        System.out.println("invoke method");        Method invokeMethods = ci.getMethod("sayChina");        invokeMethods.invoke(ci.newInstance());        invokeMethods = ci.getMethod("sayHello", String.class, int.class);        invokeMethods.invoke(ci.newInstance(), "David Beckham", 37); //函数调用会隐含地把调用该函数的对象传到函数的第一个函数,        //所以此处需要把该函数的对象传到invoke中去        System.out.println("invoke setter and getter");        ChinaImp obj = (ChinaImp) ci.newInstance();        setter(ci, "Name", obj);        getter(ci, "Name", obj);    }    private static void setter(Class ci, String name, ChinaImp chinaImp) throws InstantiationException {        Method method = null;        try {            method = ci.getMethod("set" + name, String.class);        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        try {            System.out.println("call setter method");            method.invoke(chinaImp, "Robin Van Persie");        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        }    }    public static void getter(Class clazz, String attr, ChinaImp chinaImp) {        Method method = null;        try {            method = clazz.getMethod("get" + attr);        } catch (NoSuchMethodException e) {            e.printStackTrace();        }        try {            System.out.println("getter value : " + method.invoke(chinaImp));        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        }    }}
四、通过反射构造出的对象去调用相应类的方法
package domain;public class Person {    private String name;    private int age;    public Person() {    }    public Person(int age) {        this.age = age;    }    public Person(String name) {        this.name = name;    }    public Person(String name, int age) {        this.age = age;        this.name = name;    }    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.getName() + " : " + this.getAge() + "]";    }}
package reflect;import domain.Person;public class PersonReflection {    public static void main(String[] args) {        Class person1 = null;        try {            person1 = Class.forName("domain.Person");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        Person person2 = null;        try {            person2 = (Person) person1.newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }        person2.setName("David Beckham");        person2.setAge(37);        System.out.println(person2);    }}
运行结果:
[David Beckham : 37]

五、同上,但是通过传入不同的参数调用相应的函数
package reflect;import domain.Person;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;public class PersonReflection_2 {    public static void main(String args[]) {        Class per = null;        try {            per = Class.forName("domain.Person");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        Constructor<?> cons[] = per.getConstructors();        Person person1 = null;        Person person2 = null;        Person person3 = null;        Person person4 = null;        try {            person1 = (Person) cons[0].newInstance();            person2 = (Person) cons[3].newInstance(37);            person3 = (Person) cons[2].newInstance("David Beckham");            person4 = (Person) cons[1].newInstance("David Beckham", 37);        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        }        System.out.println(person1);        System.out.println(person2);        System.out.println(person3);        System.out.println(person4);    }}
运行结果:
[null : 0][null : 37][David Beckham : 0][David Beckham : 37]

六、通过反射查看类加载器
package domain;public class ClassLoader_model {}
package reflect;import domain.ClassLoader_model;public class ClassLoaderReflection {    public static void main(String args[]){        ClassLoader_model classLoader_model = new ClassLoader_model();        System.out.println("ClassLoader Name : " + classLoader_model.getClass().getClassLoader().getClass().getName());    }}
运行结果:
ClassLoader Name : sun.misc.Launcher$AppClassLoader

其实在java中有三种类类加载器。

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

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

3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。


七、通过反射为类的特定字段赋值
package domain;public class RVP {    public String name;    int age;    String height;}
package reflect;import domain.RVP;import java.lang.reflect.Field;public class RVPReflection {    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {        Class<?> cl = Class.forName("domain.RVP");        Field field = cl.getDeclaredField("name");        RVP rvp = (RVP) cl.newInstance();        field.setAccessible(true);        field.set(rvp, "Van Persie");        System.out.println(field.get(rvp));    }}
运行结果:
Van Persie


原创粉丝点击