java反射机制

Java反射机制允许在运行时动态获取类的信息并调用其方法。它涉及Class类、Field、Method和Constructor等,常用于框架开发和处理注解。反射提供了访问私有属性和方法的能力,但这也可能导致安全问题。文章通过示例展示了如何获取和使用Class对象,以及如何创建对象、访问私有构造器、字段和方法。
摘要由CSDN通过智能技术生成

反射定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制。
总结 : 反射就是通过非常规手段 ,拿到一个类不提供给你的属性或方法 - 是一把双刃剑

反射获取对象的过程

反射怎样获取一个类的属性与方法 :
Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是 java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类 .

反射的用途

  1. 在开发中, 获取类的私有属性或方法
  2. 开发各种框架
  3. 实现自定义注解

反射相关的类(重要)

①java.lang.Class.java : 代表类的实体,在运行的Java应用程序中表示类和接口
②java.lang.reflect.Field.java :代表类的成员变量/类的属性
③java.lang.reflect.Method.java : 代表类的方法
④ java.lang.reflect.Constructor.java : 代表类的构造方法
注:所有和反射相关的包都在 import java.lang.reflect 包下面。

反射的优缺点

优点 : 不受类的访问权限限制 , 随心所欲访问
缺点 : 随心所欲的访问在计算机中可不是好词 -会造成安全性的问题

Class类(反射机制的起源 )

Class帮助文档代表类的实体,在运行的Java应用程序中表示类和接口 .

  • getClassLoader() 获得类的加载器
  • getDeclaredClasses() 返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)
  • forName(String className) 根据类名返回类的对象
  • newInstance() 创建类的实例
  • getName() 获得类的完整路径名字

常用获得类中属性相关的方法

  • getField(String name) 获得某个公有的属性对象
  • getFields() 获得所有公有的属性对象
  • getDeclaredField(String name) 获得某个属性对象
  • getDeclaredFields() 获得所有属性对象

获得类中注解相关的方法

  • getAnnotation(Class annotationClass) 返回该类中与参数类型匹配的公有注解对象
  • getAnnotations() 返回该类所有的公有注解对象
  • getDeclaredAnnotation(Class annotationClass) 返回该类中与参数类型匹配的所有注解对象
  • getDeclaredAnnotations() 返回该类所有的注解对象.

获得类中构造器相关的方法

  • getConstructor(Class…<?> parameterTypes) 获得该类中与参数类型匹配的公有构造方法
  • getConstructors() 获得该类的所有公有构造方法
  • getDeclaredConstructor(Class…<?> parameterTypes) 获得该类中与参数类型匹配的构造方法
  • getDeclaredConstructors() 获得该类所有构造方法

获得类中方法相关的方法

  • getMethod(String name, Class…<?> parameterTypes) 获得该类某个公有的方法
  • getMethods() 获得该类所有公有的方法
  • getDeclaredMethod(String name, Class…<?> parameterTypes) 获得该类某个方法
  • getDeclaredMethods() 获得该类所有方法

反射示例

获得Class对象的三种方式

  1. 使用 Class.forName(“类的全路径名”); 静态方法。常用

前提:已明确类的全路径名。

  1. 第二种,使用 .class 方法。

说明:仅适合在编译前就已经明确要操作的 Class

  1. 第三种,使用类对象的 getClass() 方法

示例:

class Student{
	//私有属性name
	private String name = "zhangsan";
	//公有属性age
	public int age = 2;
	//不带参数的构造方法
	public Student(){
		System.out.println("Student()");
	}
	private Student(String name,int age) {
		this.name = name;
		this.age = age;
		System.out.println("Student()");
	}
	
	private void function(String str) {
		System.out.println(str);
	} 
	@Override
	public String toString() {
		return "Student{" +
		"name='" + name + '\'' +
		", age=" + age +
		'}';
	}
}

反射的使用

反射的测试类

package Reflect;

class Student{
    //私有属性name
    private String name = "sss";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }

    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }

    private void eat(){
        System.out.println("i am big");
    }

    public void sleep(){
        System.out.println("i am pig");
    }

    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Test2 {
    //一个类 只能拥有一个class对象
    public static void main(String[] args) throws ClassNotFoundException {
        Class<?> c1 = Class.forName("Student");

        Class<?> c2 = Student.class;

        Student student = new Student();
        Class<?> c3 = student.getClass();

        System.out.println(c1==c2);
        System.out.println(c3==c2);
        System.out.println(c1==c3);
    }
}

反射的测试

package Reflect;

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


public class ReflectClassDemo {

    public static void reflectNewInstance() {
        try {
            Class<?> c1 = Class.forName("Student");
            Student student = (Student)c1.newInstance();
            System.out.println("学生对象:"+student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateConstructor() {
        try {
            Class<?> c1 = Class.forName("Student");
            Constructor<?> constructor =  c1.getDeclaredConstructor(String.class,int.class);

            constructor.setAccessible(true);

            Student student = (Student)constructor.newInstance("sss",19);

            System.out.println(student);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateField() {
        try {
            Class<?> c1 = Class.forName("Student");
            Field field = c1.getDeclaredField("name");

            field.setAccessible(true);

            Student student = (Student)c1.newInstance();
            field.set(student,"唐老鸭");

            System.out.println(student);

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    public static void reflectPrivateMethod() {
        try {
            Class<?> c1 = Class.forName("Student");
            Method method = c1.getDeclaredMethod("function",String.class);

            method.setAccessible(true);

            Student student = (Student)c1.newInstance();

            method.invoke(student,"我是一个参数!");
            //System.out.println(student);

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }  catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }


    public static void main(String[] args) {
        //reflectNewInstance();
        //reflectPrivateConstructor();
        //reflectPrivateField();
        reflectPrivateMethod();
    }
}

四大测试结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值