Android开发者必知的Java知识(一):Java反射机制

来源:互联网 发布:python入门经典 下载 编辑:程序博客网 时间:2024/06/08 03:25

Android开发者必知的Java知识(一):Java反射机制

最近重新温习了一下java的反射机制,终结了一些东西,供大家参考

转载请注明出处:http://blog.csdn.net/qinjunni2014/article/details/44106243

1. 获取函数

getMethod

获取所有继承的方法,以及自己声明的public方法,

getDclaredMethod

获取所有自己单独声明的方法,不论处于什么访问状态

代码为证:

class MethodsDisplay {    public static void displayMethods(Class clazz) throws Throwable {        System.out.println("getMethods拿到的方法: ");        Method[] methods = clazz.getMethods();        for (int i = 0; i < methods.length; i++) {            Method method = methods[i];            System.out.println("方法名称 " + method.getName());            // System.out.println("param type " +            // method.getParameterTypes().toString());        }    }    public static void displayDeclaredMethods(Class clazz) throws Throwable {        System.out.println("getDeclaredMethods拿到的方法: ");        Method[] methods = clazz.getDeclaredMethods();        for (int i = 0; i < methods.length; i++) {            Method method = methods[i];            System.out.println("方法名称 " + method.getName());            // System.out.println("param type " +            // method.getParameterTypes().toString());        }    }}
getDeclaredMethods拿到的方法: 方法名称 name方法名称 hello方法名称 printh方法名称 smilegetMethods拿到的方法: 方法名称 smile方法名称 wait方法名称 wait方法名称 wait方法名称 equals方法名称 toString方法名称 hashCode方法名称 getClass方法名称 notify方法名称 notifyAll

调用私有函数

调用私有函数必须先调用getDeclaredMethod拿到函数, 而且必须在调用前,设置函数accessible

        MyObject myObject = new MyObject();        Method method = MyObject.class.getDeclaredMethod("printh");        method.setAccessible(true);        method.invoke(myObject);

调用构造函数

调用构造函数较为特殊,必须使用getDelcaredConstructor获得 一个类型为Constructor的实例,并调用newInstance构造对象

class Person {    private String name;    private int age;    public Person() {        System.out.println("default constructor");    }    public Person(String _name, int _age) {        name = _name;        age = _age;        System.out.println("Constructor with two int params");    }    private void printh() {        System.out.println("invoke private method");    }    protected void name() {        System.out.println(name);    }    void hello(){        System.out.println("hello");    }    public void smile() {        System.out.println("Smiling...");    }}
try {    Class[] paramTypes = {String.class, int.class};    Constructor con = Person.class.getDeclaredConstructor(paramTypes);    Person person = (Person) con.newInstance("LiLi",18);    person.name();} catch (InstantiationException e) {    // TODO Auto-generated catch block    e.printStackTrace();}

Class.newInstance

创建对象,除了使用Constructor.newInstance方法外,还可使用Class.newInstance方法,但只限于无参默认构造函数:

Person p = Person.class.newInstance();p.smile();

如果我们注释掉Person中得无参构造函数, 则在运行上述代码时,会抛出Exception:

Exception in thread "main" java.lang.InstantiationException: Person    at java.lang.Class.newInstance(Class.java:364)    at ReflectMain.main(ReflectMain.java:47)

2. 获取变量

对于Field, 同样有两种获取的函数,getDeclaredField, getField…, 与获取函数一样,两种函数的区别在于 是否包含 继承的field以及private field

  1. getField: 获取继承的field以及声明的public field
  2. getDeclaredField: 获取自身声明的field

代码为证:

class Person {    public static final String FEMALE = "female";    public static final String MALE = "male";    private String gender;    public String name;    private int age;}class Student extends Person{    public int level;    private int score;}class FieldDisplay{    public static void displayFields(Class clazz) throws Throwable{        System.out.println("display getFields:");        Field[] fields = clazz.getFields();        for(int i=0;i< fields.length;i++){            Field field = fields[i];            System.out.println(field.getType()+ ": "+field.getName());        }    }    public static void displayDeclaredFields(Class clazz) throws Throwable{        System.out.println("display getDeclaredFields:");        Field[] fields = clazz.getDeclaredFields();        for(int i=0;i< fields.length;i++){            Field field = fields[i];            System.out.println(field.getType()+ ": "+field.getName());        }    }}FieldDisplay.displayFields(Student.class);FieldDisplay.displayDeclaredFields(Student.class);

输出为:

display getFields:int: levelclass java.lang.String: FEMALEclass java.lang.String: MALEclass java.lang.String: namedisplay getDeclaredFields:int: levelint: score

访问私有变量只需对Field调用setAccessible(true)

获取Class

获取Class对象,有两种方法:

  1. 当我们能访问到该类时,例如Person类,我们可以直接调用Person.class 或者 Person类的对象person的getClass 方法
  2. 但我们无法访问该类时,我们如果知道该类的完整名称(包括包名),可以直接调用Class.forName进行类的加载

Class.forName

Class.forName有两种重载形式:

  1. Class.forName(String className)
  2. forName(String name, boolean initialize, ClassLoader loader) loader指定使用某个类加载器,initialize决定是否初始化

关于类加载器,我们在此不深究,有兴趣的可以参考Java官方文档.

好了,讲了这些Java 反射中最常用到的API,其实只是在为下一步讲解Java 中得annotation作铺垫,小哥即将下篇关于Annotation的介绍,敬请期待。

0 0
原创粉丝点击