Java反射

1、反射机制有什么用?

通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件。)
通过反射机制可以操作代码片段。(class文件。)

2、反射机制相关的重要的类有哪些?

含义
java.lang.Class代表整个字节码。代表一个类型,代表整个类。
java.lang.reflect.Method代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。

必须先获得Class才能获取Method、Constructor、Field

3.获取Class的三方式


public class Demo06 {
    /**
     * 获取class对象
     * @param args
     */
    public static void main(String[] args) throws ClassNotFoundException {

        /**
         * 方式1:直接通过类名.class获取(最常用的方法)
         */
        Class<Person> personClass = Person.class;
        System.out.println(personClass); //class com.zxb.test10.Person

        /**
         * 方式2: 通过Class.forName(路径)的方式获取(比较灵活,可以传递不同的路径,获取不同的class对象)
         */
        String path = "com.zxb.test10.Person";
        Class<?> aClass = Class.forName(path);
        System.out.println(aClass); //class com.zxb.test10.Person

        /**
         * 这种方式比较好少用
         */
        Class<? extends Person> aClass1 = new Person().getClass();
        System.out.println(aClass1); //class com.zxb.test10.Person


    }
}

5、通过反射实例化对象

package com.zxb.web.test01Lx;

public class Student {
    private String name;
    private Integer age;
    public String sex="男";
    public String character;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void me(){
        System.out.println("我是私有方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", character='" + character + '\'' +
                '}';
    }
}
public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
            InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
        /**
         * 通过反射机制调用构造方法实例化java对象
         */
        /**
         * 方式1:使用newInstance()方法,调用无参构造方法
         */
        Class<Student> sc1 = Student.class;
        Object object1 = sc1.newInstance();

        /**
         * 方式2:调用有参构造方法
         */
        Class<Student> sc2 = Student.class;
        //获取到这个有参数的构造方法,里面传参数的类型
        Constructor<Student> declaredConstructor = sc2.getDeclaredConstructor(String.class, Integer.class);
        //创建有参构造对象
        Object object2 = declaredConstructor.newInstance("蛮族之王", 28);
        System.out.println(object2); //Student{name='蛮族之王', age=28, sex='男', character='null'}

        /**
         * 方式3:调用无参构造方法
         */
        Class<Student> sc3 = Student.class;
        //获取到这个无参数的构造方法,不用传参数的类型
        Constructor<Student> declaredConstructor1 = sc3.getDeclaredConstructor();
        Object object3 = declaredConstructor1.newInstance();
        System.out.println(object3); //Student{name='null', age=null, sex='男', character='null'}
        //给对象赋值
        ((Student) object3).setName("你好呀");
        System.out.println(object3); //Student{name='你好呀', age=null, sex='男', character='null'}
}

5、JDBC重点(Class.forName导致类加载)

如果你只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用: 

Class.forName("完整类名");

 这个方法的执行会导致类加载,类加载时,静态代码块执行。 

6、反射Filed【反射一个类的属性】 

6.1 获取类中所有public修饰的属性

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
            InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException {
       Class<?> ac = Class.forName("com.zxb.web.test01Lx.Student");
          /**
         * 获取类中所有public修饰的属性
         */

        Field[] fields = ac.getFields();
        for (Field i : fields) {
            System.out.println(i.getName());
        }
        /**
         * 获取类中所有私有的属性
         */
        Field[] fields1 = ac.getDeclaredFields();
        for (Field i : fields1) {
            System.out.println("=========================================");
            // 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号
            // 用Modifier类的toString转换成字符串
            System.out.println(Modifier.toString(i.getModifiers())); //private
            System.out.println(i.getType().getSimpleName());// 获取属性的类型  String
            System.out.println(i.getName());// 获取属性的名字  name
        }
}

 6.2  获取类中所有的实例方法

 public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException,
            InstantiationException, NoSuchMethodException, NoSuchFieldException, InvocationTargetException { 
         Class<?> ac = Class.forName("com.zxb.web.test01Lx.Student");  
        /**
         * 获取类中所有私有的属性
         */
        Field[] fields1 = ac.getDeclaredFields();
        for (Field i : fields1) {
            System.out.println("=========================================");
            // 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号
            // 用Modifier类的toString转换成字符串
            System.out.println(Modifier.toString(i.getModifiers())); //private
            System.out.println(i.getType().getSimpleName());// 获取属性的类型  String
            System.out.println(i.getName());// 获取属性的名字  name
        }
}

 6.3  public修饰的属性,给属性设置值 set()、get()

        /**
         * 通过反射操作public修饰的属性,给属性设置值*
         * set()
         * get()
         */
        Object obj1 = ac.newInstance();
        Field getFid = ac.getDeclaredField("character");
        getFid.set(obj1,"张三丰");
        System.out.println(getFid.get(obj1)); //张三丰

  6.4 setAccessible打破封装,给私有属性赋值

        /**
         * setAccessible打破封装,给私有属性赋值
         */
        Class<Student> sc = Student.class;
        Object object = sc.newInstance();
        Field name = sc.getDeclaredField("name");
        //打破封装
        name.setAccessible(true);
        name.set(object, "张三");
        System.out.println(name.get(object)); //张三

 7. Class类方法

7.1  getMethods获取类中public修饰的方法

        Method[] methods = ac.getMethods();
        for (Method i:methods) {
            System.out.println(i.getName());
        }

7.2  getDeclaredMethods获取类中所有的实例方法

        Method[] methods1 = ac.getDeclaredMethods();
        for (Method i : methods1) {
            System.out.println(i.getName());
        }

 7.3 通过反射调用public修饰的方法

    public static void main(String[] args) {
        /**
         * 通过反射调用public修饰的方法
         */
        Class<?> studentClass = Student.class;
        //实例化一个对象
        Object o = studentClass.newInstance();
        //通过getMethod方法取得setName这个方法的实例化对象,方法名称与参数类型(String.class)
        Method setName = studentClass.getMethod("setName", String.class);
        //调用invoke方法,调用setName方法。invoke方法中需要你指定给那个对象的那个方法进行传参
        setName.invoke(o,"娜美");
        //通过getMethod方法取得getName这个方法的实例化对象,方法名称与参数类型,如果没有参数可以不用传参数类型
        Method getName = studentClass.getMethod("getName");
        //调用invoke方法,调用getName方法
        Object result = getName.invoke(o);
        System.out.println(result); // 娜美
    }

7.4  通过反射机制调用构造方法实例化java对象

    public static void main(String[] args) {
        /**
         * 方式1:使用newInstance()方法,调用无参构造方法
         */
        Class<Student> sc1 = Student.class;
        Object object1 = sc1.newInstance();

        /**
         * 方式2:调用有参构造方法
         */
        Class<Student> sc2 = Student.class;
        //获取到这个有参数的构造方法,里面传参数的类型
        Constructor<Student> declaredConstructor = sc2.getDeclaredConstructor(String.class, Integer.class);
        //创建有参构造对象
        Object object2 = declaredConstructor.newInstance("蛮族之王", 28);
        System.out.println(object2); //Student{name='蛮族之王', age=28, sex='男', character='null'}

        /**
         * 方式3:调用无参构造方法
         */
        Class<Student> sc3 = Student.class;
        //获取到这个无参数的构造方法,不用传参数的类型
        Constructor<Student> declaredConstructor1 = sc3.getDeclaredConstructor();
        Object object3 = declaredConstructor1.newInstance();
        System.out.println(object3); //Student{name='null', age=null, sex='男', character='null'}
        //给对象赋值
        ((Student) object3).setName("你好呀");
        System.out.println(object3); //Student{name='你好呀', age=null, sex='男', character='null'}

    }

 8. 获取一个类的父类以及实现的接口

    public static void main(String[] args) {
        /**
         * 获取一个类的父类以及实现的接口
         * 重点:给你一个类,怎么获取这个类的父类,已经实现了哪些接口?
         * 以String举例
         */
        //获取String的反射对象
        Class<String> sc4 = String.class;
        //获取String类的父类
        Class<? super String> sc5 = sc4.getSuperclass();
        System.out.println(sc5); //class java.lang.Object
        //获取String类实现的所有接口
        Class<?>[] interfaces = sc4.getInterfaces();
        System.out.println(Arrays.toString(interfaces)); //[interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence]
        for (Class i:interfaces) {
            System.out.println(i.getName()); //java.io.Serializable、java.lang.Comparable、java.lang.CharSequence
        }

    }
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值