《Java-SE-第三十七章》之反射

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


文章目录

  • 反射
    • 定义
    • 基本使用
      • 获取类
      • 获取构造器
      • 获取成员变量
      • 获取成员方法
      • 使用场景


反射

定义

Java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然都可以拿到,我们就可以修改类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

基本使用

获取类

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的。因为对象都是通过类创建而来的,拿到了Class对象,并对其解析就可以获取类的成员属性,成员方法,构造器。Class对象存在的位置具体如下图。

《Java-SE-第三十七章》之反射_第1张图片

获取类有三种方法

  1. 使用 Class.forName(“类的全路径名”); 静态方法。
  2. 使用类名.class
  3. 使用对象.getClass();

使用演示

首先创建一个User类,便于后期使用

@Data
@AllArgsConstructor
@NoArgsConstructor

public class User {
    private String username;
    private String password;
    public int age ;


    public  String pr(String username){
      return username;
    }
}

开始使用上述三种方法获取User的类对象

public class ClassDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> user = Class.forName("org.example.Functional.model.User");
        Class<User> userClass = User.class;
        User user2 = new User("user2", "11");
        Class<? extends User> aClass = user2.getClass();
        System.out.println(user);
        System.out.println(userClass);
        System.out.println(aClass);
    }
}

获取构造器

获取构造器的方法如下

方法 说明
Constructor[] getConstructors() 返回所有构造器对象的数组(只能拿public的)
Constructor[] getDeclaredConstructors() 返回所有构造器对象的数组,存在就能拿到
Constructor getConstructor(Class… parameterTypes) 返回单个构造器对象(只能拿public的)
Constructor getDeclaredConstructor(Class… parameterTypes) 返回单个构造器对象,存在就能拿到

使用演示

import java.lang.reflect.Constructor;

public class ConstructorsDemo {
    public static void main(String[] args) throws NoSuchMethodException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的无参构造
        Constructor<User> declaredConstructor = userClass.getDeclaredConstructor();
        //设置禁止访问权限
        declaredConstructor.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor.getName()+"->"+declaredConstructor.getParameterCount());
        //获取有参构造
        Constructor<User> declaredConstructor1 = userClass.getConstructor(String.class, String.class);
        //设置禁止访问权限
        declaredConstructor1.setAccessible(true);
        //得到类名称和参数个数
        System.out.println(declaredConstructor1.getName()+"->"+declaredConstructor1.getParameterCount());

        Constructor<?>[] constructors = userClass.getConstructors();
        Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
        System.out.println(constructors[1]);
        System.out.println(constructors[0]);
        System.out.println(declaredConstructors[1]);
        System.out.println(declaredConstructors[0]);
    }
}

运行结果:

《Java-SE-第三十七章》之反射_第2张图片

获取构造器的作用依旧是为了初始化对象返回

Constructor类中用于创建对象的方法

方法 说明
T newInstance(Object… initargs) 根据指定的构造器创建对象
public void setAccessible(boolean flag) 设置为true,表示取消访问检查,进行暴力反射

使用演示

将User的有参构造设置为私有,并且不设置访问检查

public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

《Java-SE-第三十七章》之反射_第3张图片

取消访问检查后

public class ConstructorsDemo2 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Constructor<User> declaredConstructor1 = userClass.getDeclaredConstructor(String.class, String.class);
        //设置禁止访问权限
         declaredConstructor1.setAccessible(true);
        User user = declaredConstructor1.newInstance( "sdf","211");
        System.out.println(user.toString());
    }
}

运行结果:

《Java-SE-第三十七章》之反射_第4张图片

如果是非public的构造器,需要打开权限,然后才能创建对象。反射是Java的后门破坏的封装性,私有的也可以构造方法也可以执行了。

获取成员变量

Class类中用于获取成员变量的方法

方法 说明
Field[] getFields() 返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields() 返回所有成员变量对象的数组,存在就能拿到
Field getField(String name) 返回单个成员变量对象(只能拿public的)
Field getDeclaredField(String name) 返回单个成员变量对象,存在就能拿到

使用演示

public class AttributeDemo {
    public static void main(String[] args) throws NoSuchMethodException, NoSuchFieldException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        Field[] fields = userClass.getFields();
        for (Field field : fields) {
            System.out.println(field.getName()+"-->"+field.getType());
        }
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName()+"-->"+declaredField.getType());
        }
        //定位某个变量
        Field age = userClass.getField("age");
        Field username = userClass.getDeclaredField("username");
        Field password = userClass.getDeclaredField("password");
        User user = new User();
        //设置私有变量的访问
        username.setAccessible(true);
        password.setAccessible(true);
        //赋值
        username.set(user,"sdf");
        password.set(user,"ss12");
        age.set(user,90);
        System.out.println(user);
        //取值
        String o = (String)username.get(user);
        System.out.println(o);
    }
}

运行结果:

《Java-SE-第三十七章》之反射_第5张图片

私有的成员变量依旧需要开启访问权限

获取成员方法

Class类中用于获取成员变量的方法、

方法 说明
Method[] getMethods() 返回所有成员方法对象的数组(只能拿public的
Method[] getDeclaredMethods() 返回所有成员方法对象的数组,存在就能拿到
Method getMethod(String name, Class… parameterTypes) 返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod(String name, Class… parameterTypes) 返回单个成员方法对象,存在就能拿到

使用演示

public class MethodDemo {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.反射第一步:获取这个类的Class对象
        Class<User> userClass = User.class;
        //获取类的成员方法
        Method[] methods = userClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName() + " "+method.getParameterCount()
            +method.getReturnType());
        }
        //获取某个对象方法
        Method pr = userClass.getDeclaredMethod("pr",String.class);
        System.out.println(pr.getName() + " "+pr.getParameterCount()+" "
                +pr.getReturnType());
        User user = new User();
        pr.setAccessible(true);
        //调用方法,用user对象
        Object invoke = pr.invoke(user,"java");
        System.out.println(invoke);
    }
}

使用场景

  1. 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统****应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法 。

  2. 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。


各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

《Java-SE-第三十七章》之反射_第6张图片

你可能感兴趣的:(Java,java,开发语言)