学习笔记之 反射实例

来源:互联网 发布:unix环境高级编程第3版 编辑:程序博客网 时间:2024/06/06 14:48

一.Person类

1.1实体

 

public class Person {

    private Stringname;

    private int age;

    public int num;

    public static String country ="cn";

 

    public Person() {

 

    }

 

    public Person(String name,int age) {

 

        this.name = name;

        this.age = age;

        System.out.println("2个参数的构造函数");

    }

 

    private Person(String name) {

        this.name = name;

    }

 

    public String getName() {

        returnname;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public int getAge() {

        returnage;

    }

 

    public void setAge(int age) {

        this.age = age;

    }

 

    public void eat() {

        System.out.println("吃东西");

    }

 

    public void eat(String food) {

        System.out.println(":" + food);

    }

 

    public static void play(String game) {

        System.out.println(":" + game);

    }

 

    private void movie(String name) {

        System.out.println(":" + name);

    }

 

    @Override

    public String toString() {

        return"Person [name=" + name + ", age=" + age + ", num=" + num + "]";

    }

 

}

 

 

二.反射测试

2.1 获取Person 类的字节码对象. Class

    /*

     * 获取Person类的字节码对象. Class

     */

    @Test

    public void testGetPersonClass() throws ClassNotFoundException {

        // 方式一:类名.class

        Class clazz = Person.class;

 

        // 方式二:对象.getClass()

        Person p = new Person();

        Class clazz1 = p.getClass();

 

        // 方式三: Class的静态方法forName加载指定的类的...

        Class clazz2 = Class.forName("cn.itcast.gz.a_reflect.Person");

 

        // 字节码文件只加载一次,所以是Class对象在内存中是唯一的.

        System.out.println(clazz == clazz1);

    }

 

 

2.2 获取Person 类的字节码信息,并分析

    /**

     * 获取Person类的字节码信息,并分析

     *

     * @throws ClassNotFoundException

     * */

    @Test

    public void testGetPersonInfo() throws ClassNotFoundException {

        Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");

        // 获取类的类名 ->获取类的完整的名称...全限定名称(包名+类名)

        String name = clazz.getName();

        /**cn.itcast.gz.a_reflect.Person**/

 

        // 获取类的简单名称只有类名.

        String simpleName = clazz.getSimpleName();

        /**Person**/

 

        // 获取类的修饰符

        // public ->1 default 0 abstract 1024

        int modifiers = clazz.getModifiers();

        /**1**/

 

    }

 

2.3 获取类的成员变量

    /**

     * 获取类的成员变量

     *

     * @throwsClassNotFoundException

     * @throws NoSuchFieldException

     * @throws SecurityException

     *

     *             注意:虽然反射可以获取类中的成员变量,还是面向对象的基本的原则静态成员变量:随着的类的加载而加载.

     *             通过反射机制,给静态的变量赋值和取值时,不需要传递对象,给类的成员取值和赋值.非静态成员:

     *             创建对象,在对象的对内存中依赖于对象存在的.通过反射机制,该非静态的成员变量时,需要指定一个对象.给哪个对象的对象

     *             赋值和取值吧...

     */

    @Test

    public void testGetFields() throws Exception {

        Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");

 

        Object p = clazz.newInstance();

        /** Person [name=null, age=0,num=0] **/

 

        // 获取类中的所有的公有的成员变量

        Field[] fields = clazz.getFields();

        for (Field field : fields) {

            System.out.println(field);

        }

        /**

         * public int cn.itcast.gz.a_reflect.Person.num ;

         * public static java.lang.String cn.itcast.gz.a_reflect.Person.country;

         */

 

        // 获取类中所有的成员变量(包括私有的)

        Field[] declaredFields = clazz.getDeclaredFields();

        for (Field field : declaredFields) {

            System.out.println(field.getName());

        }

        /** name age num country **/

 

        // 获取类中指定的成员变量...指定成员变量的名称

        Field f = clazz.getField("num");

        /**public int cn.itcast.gz.a_reflect.Person.num**/

       

        // 给成员变量赋值

        f.set(p, 100);

        // 成员变量可以存储信息,取出信息...

        System.out.println(f.get(p));

        /**100**/

        System.out.println(p);

        /**Person [name=null, age=0, num=100]**/

       

        // 获取类中指定的成员变量

        Field f1 = clazz.getField("country");

        /**public static java.lang.String cn.itcast.gz.a_reflect.Person.country**/

       

        // 获取成员变量的值.

        System.out.println(f1.get(null));

        /**cn**/

       

        f1.set(null,"us");

        /**us**/

 

        // 获取.私有的成员变量

        Field f2 = clazz.getDeclaredField("name");

        /**private java.lang.String cn.itcast.gz.a_reflect.Person.name**/

 

        // 暴力反射 (打开权限)

        f2.setAccessible(true);

        // 赋值,取值.注意: name 是私有的成员变量... 无法直接赋值的

        f2.set(p, "张三疯");

        /**

         * 张三疯

         * Person [name=张三疯, age=0,num=100]

         */

    }

2.4 获取类中的构造函数 Constructor 对象

    /**

     * 获取类中的构造函数 Constructor对象: 该对象提供了一个核心方法: newInstance();可以根据指定的构造函数,创建对象.

     * 反射用在以后的框架中...配置文件.

     *

     * @throws Exception

     */

    @Test

    public void testConstructor() throws Exception {

        Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");

       

        // 获取所有的公有的构造函数...

        Constructor[] constructors = clazz.getConstructors();

 

        // 获取类中所有的构造函数(包含私有的)

        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();

        for (Constructor constructor : declaredConstructors) {

            System.out.println(constructor);

        }

        /**

         * public cn.itcast.gz.a_reflect.Person()

         * public cn.itcast.gz.a_reflect.Person(java.lang.String,int)

         * private cn.itcast.gz.a_reflect.Person(java.lang.String)

         */

       

        // 获取指定的构造函数...一个类中存在多个构造函数,是以重载的形式存在(函数名相同,参数列表不同).

        Constructor c1 = clazz.getConstructor(String.class,int.class);

        /**public cn.itcast.gz.a_reflect.Person(java.lang.String,int)**/

       

        // 创建对象->获取的构造函数.该构造函数需要2个参数.

        Person p = (Person) c1.newInstance("张无忌", 18);

        /**Person [name=张无忌, age=18,num=0]**/

 

        // 获取无参数的构造函数.

        Constructor c2 = clazz.getConstructor(null);

        /**public cn.itcast.gz.a_reflect.Person()**/

 

        // 根据获取的无参数构造创建对象.

        Person p1 = (Person) c2.newInstance(null);

        /**Person [name=null, age=0, num=0]**/

 

        // 普通创建对象方式...普通用法

        Person person = new Person();

    }

2.4.1 私有构造函数用法

    /**

     * 私有构造函数无法直接获取.需要特殊的方法. 注意: 破坏了面向对象封装的基本原则...不要随便使用...

     *

     * @throws Exception

     */

    @Test

    public void getPrivateCon() throws Exception {

        Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");

        // 获取私有的

        Constructor c1 = clazz.getDeclaredConstructor(String.class);

        /**private cn.itcast.gz.a_reflect.Person(java.lang.String)**/

 

        // 创建对象.注意: 构造函数私有,所以使用时需要设置权限(暴力反射)

        c1.setAccessible(true);

       

        Object p = c1.newInstance("赵敏");

        /**Person [name=赵敏, age=0,num=0]**/

    }

2.5 获取类的方法.

    /**

     * 获取类的方法.

     *

     * @throws Exception

     */

    @Test

    public void testMehtod() throws Exception {

        Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");

 

        Object p = clazz.newInstance();

 

        // 获取所有的公有方法,包含父类的.

        Method[] methods = clazz.getMethods();

 

        // 获取所有的构造函数.包含私有的.

        Method[] declaredMethods = clazz.getDeclaredMethods();

 

        // 获取指定的方法.

        // 需要指定函数名,

        Method m1 = clazz.getMethod("eat",null);

        /**public void cn.itcast.gz.a_reflect.Person.eat()**/

       

        // Method 对象的 invoke方法. 执行方法...

        // 注意:获取的eat 方法是非静态的, Java中非静态的方法,必须依赖于对象调用的.

        m1.invoke(p, null);

 

        // 获取有参数的eat方法.

        Method m2 = clazz.getMethod("eat", String.class);

        m2.invoke(p, "馒头");

 

        // 获取静态方法.

        // 注意:执行静态方法时, 静态方法不需要创建对象就可以执行, 本例无需指定对象.

        Method m3 = clazz.getMethod("play", String.class);

        m3.invoke(null,"lol");

 

        // 获取私有方法.

        Method m4 = clazz.getDeclaredMethod("movie", String.class);

        /**private void cn.itcast.gz.a_reflect.Person.movie(java.lang.String)**/

       

        m4.setAccessible(true);

        m4.invoke(p, "c老师");

 

        /**

         * public java.lang.String cn.itcast.gz.a_reflect.Person.toString()

         * public java.lang.String cn.itcast.gz.a_reflect.Person.getName()

         * public void cn.itcast.gz.a_reflect.Person.setName(java.lang.String)

         * public void cn.itcast.gz.a_reflect.Person.eat() public void

         * cn.itcast.gz.a_reflect.Person.eat(java.lang.String) public static

         * void cn.itcast.gz.a_reflect.Person.play(java.lang.String) private

         * void cn.itcast.gz.a_reflect.Person.movie(java.lang.String) publicint

         * cn.itcast.gz.a_reflect.Person.getAge() public void

         * cn.itcast.gz.a_reflect.Person.setAge(int) public void

         * cn.itcast.gz.a_reflect.Person.eat()

         */

    }

 

0 0
原创粉丝点击