Java基础之——反射

一、什么是反射

反射就是程序可以访问,检测和修改它本身状态或行为的一种能力,也就是在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展。

二、反射的原理:

下图是类的正常加载过程、反射原理与class对象:

Class对象的由来是将.class文件读入内存,并为之创建一个Class对象。
请添加图片描述

三、哪里用到反射机制?

1.JDBC中,利用反射动态加载了数据库驱动程序。
2.Web服务器中利用反射调用了Sevlet的服务方法。
3.Eclispe等开发工具利用反射动态刨析对象的类型与结构,动态提示对象的属性和方法。
4.很多框架都用到反射机制,注入属性,调用方法,如Spring。

四、反射机制的优缺点?

优点:可以动态执行,在运行期间根据业务功能动态执行方法、访问属性,最大限度发挥了java的灵活性。
缺点:对性能有影响,这类操作总是慢于直接执行java代码。

五、动态代理是什么?有哪些应用?

动态代理是运行时动态生成代理类。
动态代理的应用有 Spring AOP数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。

六、怎么实现动态代理?

JDK 原生动态代理和 cglib 动态代理。
JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。

七、反射具体使用及方法介绍

获取Class类对象的三种方式

  • 类名.class属性
  • 对象名.getClass()方法
  • Class.forName(全类名)方法

示例代码:

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        //使用类的class属性来获取该类对应的Class对象
        Class<Student> c1 = Student.class;
        System.out.println(c1);

        Class<Student> c2 = Student.class;
        System.out.println(c1 == c2);
        System.out.println("--------");

        //调用对象的getClass()方法,返回该对象所属类对应的Class对象
        Student s = new Student();
        Class<? extends Student> c3 = s.getClass();
        System.out.println(c1 == c3);
        System.out.println("--------");

        //使用Class类中的静态方法forName(String className)
        Class<?> c4 = Class.forName("com.itheima_02.Student");
        System.out.println(c1 == c4);
    }
}

获取构造方法

  • Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
  • Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
  • Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
  • Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象

案例需求

  • 通过反射获取公共的构造方法并创建对象
  • 代码实现
//学生类
public class Student {
    //成员变量:一个私有,一个默认,一个公共
    private String name;
    int age;
    public String address;

    //构造方法:一个私有,一个默认,两个公共
    public Student() {
    }

    private Student(String name) {
        this.name = name;
    }

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

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

    //成员方法:一个私有,四个公共
    private void function() {
        System.out.println("function");
    }

    public void method1() {
        System.out.println("method");
    }

    public void method2(String s) {
        System.out.println("method:" + s);
    }

    public String method3(String s, int i) {
        return s + "," + i;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}
//测试类
public class ReflectDemo02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //public Student(String name, int age, String address)
        //Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor<?> con = c.getConstructor(String.class, int.class, String.class);
        //基本数据类型也可以通过.class得到对应的Class类型

        //T newInstance(Object... initargs)
        Object obj = con.newInstance("林青霞", 30, "西安");
        System.out.println(obj);
    }
}

Constructor类创建对象方法

  • T newInstance(Object…initargs)根据指定的构造方法创建对象 获取类的成员方法
  • Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
  • Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
  • Method getMethod(String name, Class<?>… parameterTypes)返回单个公共成员方法对象
  • Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象

Method执行方法的方法

  • Objectinvoke(Object obj,Object… args)调用obj对象的成员方法,参数是args,返回值是Object类型

案例需求

  • 通过反射获取成员方法并调用
  • 代码实现
  • 学生类:参见上方学生类
//测试类
public class ReflectDemo02 {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //Student s = new Student();
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();

        //s.method1();
        Method m1 = c.getMethod("method1");
        m1.invoke(obj);

        //s.method2("林青霞");
        Method m2 = c.getMethod("method2", String.class);
        m2.invoke(obj,"林青霞");

//        String ss = s.method3("林青霞",30);
//        System.out.println(ss);
        Method m3 = c.getMethod("method3", String.class, int.class);
        Object o = m3.invoke(obj, "林青霞", 30);
        System.out.println(o);

        //s.function();
//        Method m4 = c.getMethod("function"); //NoSuchMethodException: com.itheima_02.Student.function()
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }
}

获取类的成员变量

  • Field[] getFields()返回所有公共成员变量对象的数组
  • Field[] getDeclaredFields()返回所有成员变量对象的数组
  • Field getField(Stringname)返回单个公共成员变量对象
  • Field getDeclaredField(String name)返回单个成员变量对象

给成员变量赋值的方法

  • voidset(Object obj,Object value)给obj对象的成员变量赋值为value

案例需求

  • 通过反射获取成员变量并赋值
  • 代码实现
  • 学生类:参见上方学生类
//测试类
public class ReflectDemo02 {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<?> c = Class.forName("com.itheima_02.Student");

        //Student s = new Student();
        Constructor<?> con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        //s.name = "林青霞";
//        Field nameField = c.getField("name"); //NoSuchFieldException: name
        Field nameField = c.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(obj, "林青霞");
        System.out.println(obj);

        //s.age = 30;
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj,30);
        System.out.println(obj);

        //s.address = "西安";
        Field addressField = c.getDeclaredField("address");
        addressField.setAccessible(true);
        addressField.set(obj,"西安");
        System.out.println(obj);
    }
}
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值