学习笔记之 反射实例

一.Person类

1.1实体

 

public class Person {

    private String name;

    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() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    public int getAge() {

        return age;

    }

 

    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) public int

         * 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()

         */

    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值