A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 水煮牛蛙 中级黑马   /  2018-4-23 15:53  /  404 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 小石姐姐 于 2018-4-25 15:55 编辑

Java反射机制概述及应用

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态
调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该象。而解剖使用的就是Class类中的方法.所以先要获
取到每一个字节码类的字节码文件对文件对应的Class类型的对象.

通过反射获取构造方法并使用:
                获取构造方法
                                getConstructors
                                getDeclaredConstructors
                创建对象
                                newInstance()
                                con.newInstance(“zhangsan", 20);

通过反射获取成员变量并使用:
                获取所有成员
                getFields()
                getDeclaredFields()
                获取单个成员
                getField()
                getDeclaredField()

修改成员的值:
                set(Object obj,Object value)
                将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

通过反射获取成员方法并使用:
                获取所有方法
                getMethods
                getDeclaredMethods
                获取单个方法
                getMethod
                getDeclaredMethod
                暴力访问
                method.setAccessible(true);

------------------------------------------------------

package com.jiuye_zikan_day12;
/*
* 反射的前提
*                 要获取类的对象(Class对象)
*
* 三种方式获取的字节码对象是相等的(地址相同)
*                                 clazz==clazz2==clazz3
*
*/
public class 反射概述_字节码对象 {
        public static void main(String[] args) throws ClassNotFoundException {
                //通过Object的getClass()方法获取,必须要有对象
                Student s = new Student ();
                Class clazz = s.getClass();
               
                //通过类名获取字节码对象
                Class clazz2 = Student.class;
               
                //通过类方法
                Class clazz3 = Class.forName("com.jiuye_zikan_day12.Student");
                System.out.println(clazz);
                /*Output:
                        class com.jiuye_zikan_day12.Student
                *///:~
                        
        }
}

class Student{
        
}
----------------------------------
>>>>>>>>  使用反射获取类的构造方法  并创建该类的对象   <<<<<<<<<<

package com.jobday13;
/*
* 通过反射获取构造方法并使用:
*                 1.        Constructor<?>[] getConstructors()  //获取公共的构造函数(public修饰的)
*                         //返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对
*                         //象所表示的类的所有公共构造方法。
*                         (将构造函数以对象的形式返回,只能获取public修饰的构造)
                        
*
*                 2.        Constructor<T> getConstructor(Class<?>...parameterTypes)
*                         //返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
                         //根据参数返回具体的构造
*                 
*                 3.        T newInstance(); //使用无参构造创建对象
*
* Constructor 类的方法:
*                 4. T newInstance(Object... initargs))
*                         // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,
*                         //并用指定的初始化参数初始化该实例。
*                         //(它是一个可变参数,跟据类的构造情况,可以传参,也可以不传参数)
*         
*
*
* 方法  1.2.3.为 Constructor类的方法
* 当我们使用无参构造创建对象时可以使用Class类的newInstance()方法,比较方便
*
*
*
*
* Constructor 类:        
*                 Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

                Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,
                但是如果发生收缩转换,则抛出 IllegalArgumentException。


*/
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class _2_反射获取构造方法_并使用 {

        public static void main(String[] args) throws ReflectiveOperationException {
                //获取Student类的字节码对象
                Class clazz = Class.forName("com.jobday13.Student");
               
                //方法一
                //Constructor<?>[] getConstructor()
//                获取公共构造函数(clazz);
               
                //方法二.1
                //Constructor<T> getConstructor(Class<?>...parameterTypes)
                //不传参数时
//                获取无参构造_1(clazz);
               
                //方法二.2
                //Constructor<T> getConstructor(Class<?>...parameterTypes)
//                使用带参构造创建对象(clazz);
               
               
                //方法三
                //T newInstance();  //使用Class类的方法创建对象
                Object obj = clazz.newInstance();
                System.out.println(obj);
                /*Output:
                        Student [name=null, age=0]
                        //创建了一个Student对象
                *///:~
                                       
        }
        //方法二.2
        private static void 使用带参构造创建对象(Class clazz)
                        throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
               
                //Constructor<T> getConstructor(Class<?>...parameterTypes)
                Constructor c = clazz.getConstructor(String.class,int.class);
                System.out.println(c);
                /*Output:
                        public com.jobday13.Student(java.lang.String,int)
                        //
                *///:~
                //通过 c 这个有参构造创建一个Student对象
                Object obj = c.newInstance("苹果",25);
                //此处必须传入参数,否则报错
                //java.lang.IllegalArgumentException: wrong number of arguments
                // "参数错误"
                System.out.println(obj);
                /*Output:
                        Student [name=苹果, age=25]
                        //创建成功
                *///:~
        }
        //方法二.1
        private static void 获取无参构造_1(Class clazz)
                        throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
                //Constructor<T> getConstructor(Class<?>...parameterTypes)
                Constructor cs = clazz.getConstructor();//它使用的是可变参数,因此先使用无参
                System.out.println(cs);
                /*Output:
                        public com.jobday13.Student()
                        //获取的是无参构造
                *///:~
                //使用获取的无参构造创建对象
                Object obj = cs.newInstance();
                System.out.println(obj);
                /*Output:
                        public com.jobday13.Student()
                        Student [name=null, age=0]
                        //获取了一个Student对象,参数都是默认值
                *///:~
        }
        //方法一:
        private static void 获取公共构造函数(Class clazz) {
                //Constructor<?>[] getConstructor()
                Constructor[]  cs = clazz.getConstructors();
                for(int i=0;i<cs.length;i++){
                        System.out.println(cs
);
                }
                /*Output:
                        public com.jobday13.Student()  //空参构造
                        public com.jobday13.Student(java.lang.String,int)  //带参构造
                        public com.jobday13.Student(java.lang.String)  //带参构造
                        //有参构造内到的 参数类型都是全路径 (java.lang.String)
                *///:~
        }

}
class Student {
        String name;
        int age;
        
        public Student() {
        }

        public Student(String name, int age) {
                super();
                this.name = name;
                this.age = age;
        }
        public Student(String name) {
                super();
                this.name = name;
        }

        @Override
        public String toString() {
                return "Student [name=" + name + ", age=" + age + "]";
        }
        
}
-----------------------------------
>>>>>>>  反射获取 私有成员  <<<<<<<<<<

package com.jobday13;

import java.lang.reflect.Field;

/*
* 通过反射获取私有成员变量并使用:
*                         //只能看见所有个字段,不能访问(想访问的话,就要通过方法取消访问权限)
*                         Field[] getDeclaredFields()  //获取所有的字段(public,private都可以)
*                         Field getDeclaredField(String name) //获取指定的字段
*
* AccessibleObject 类是 Field、Method 和 Constructor 对象的基类.
*
* Field 的父类  AccessibleObject 的方法:
*                                 void setAccessible(boolean flag)
                          //将此对象的 accessible 标志设置为指示的布尔值。 true为取消java默认访问检查
   Field 也可以使用这个方法;
*
*/
public class 通过反射获取私有成员变量_使用_2 {

        public static void main(String[] args) throws ReflectiveOperationException  {
                //获取学生类的字节码对象
                Class clazz = Class.forName("com.jobday13.Student");
                //通过字节码对象创建学生对象
                Object stu = clazz.newInstance();
               
                //获取私有字段对象      
                Field f = clazz.getDeclaredField("name");
                //设置反射式取消java默认的的访问检查,暴力访问
                f.setAccessible(true);
               
                Object name = f.get(stu);
                System.out.println(name);
                /*Output:
                        橘子
                        //访问成功
                *///:~
        }
}
----------------------------------------------
>>>>>>>>  反射获取 成员方法    <<<<<<<<<<<
package com.jobday13;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/*
* 通过反射获取成员方法并使用:
*                 Method getMethod(String name,Class<?>...parameterTypes)
*                //可以传入参数也可以不用参数
*
* Method:
*                 Object invoke(Object obj, Object...args)
*
*
*/
public class 反射_获取成员方法_1 {

        public static void main(String[] args) throws ReflectiveOperationException {
                //获取学生类的字节码对象
                Class clazz = Class.forName("com.jobday13.Student");
                //获取学生对对象
                Object stu = clazz.newInstance();
               
//                获取无返回值的方法(clazz, stu);
//                获取有参无返回值的方法(clazz, stu);
               
//                获取无参有返回值的方法(clazz, stu);
               
        }

        private static void 获取无参有返回值的方法(Class clazz, Object stu)
                        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
                //获取无参有返回值的方法
                Method m = clazz.getMethod("getName");
                Object obj = m.invoke(stu);
                System.out.println(obj);
        }

        private static void 获取有参无返回值的方法(Class clazz, Object stu)
                        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, NoSuchFieldException {
                //获取有参无返回值的方法
                Method m = clazz.getDeclaredMethod("setName",String.class);
                m.setAccessible(true);
                m.invoke(stu, "haha");
                Field f = clazz.getDeclaredField("name");
                Field g = clazz.getDeclaredField("age");
                f.setAccessible(true);
                g.setAccessible(true);
                System.out.println(g.get(stu));
                System.out.println(f.get(stu));
        }

        private static void 获取无返回值的方法(Class clazz, Object stu)
                        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
                //获取无返回值的方法
                Method m = clazz.getMethod("method");
                m.invoke(stu);
                /*Output:
                        我是Student的无参无返回值方法
                        //这个方法是在Student类的method方法中定义的输出语句
                *///:~
               
        }

}

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马