Java反射机制

本文详细介绍了Java反射机制的概念、作用,通过多个示例展示了如何获取和使用Class对象,包括通过不同方式创建对象、调用方法、操作属性等。同时,文章探讨了反射的优缺点,提醒在实际应用中注意性能和安全性问题。
摘要由CSDN通过智能技术生成

一、什么是反射

        Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。

二、反射的作用

        我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!

        反射机制主要提供以下功能:

①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理。

三、反射案例

1、反射中的常用类

java.lang.Class;                
java.lang.reflect.Constructor; java.lang.reflect.Field;        
java.lang.reflect.Method;
java.lang.reflect.Modifier;

2、得到Class对象的各种方式

package Study.Reflection_Study;

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-12 19:13
 * @Description 得到Class对象的各种方式
 */
public class GetClass {
    public static void main(String[] args) throws Exception {
        //1.Class.forName();多用于配置文件,读取类全路径,加载类
        String classAllPath = "Study.Reflection_Study.Cat";
        Class<?> aClass = Class.forName(classAllPath);
        System.out.println(aClass);

        //2.类名.class();多用于参数传递
        Class<Cat> aClass1 = Cat.class;
        System.out.println(aClass1);

        //3.对象.getClass();适用于有对象实例的情况
        Cat cat = new Cat();
        Class<? extends Cat> aClass2 = cat.getClass();
        System.out.println(aClass2);

        //4.classLoader.loadClass();类加载器[4种]
        //(1)得到类加载器
        ClassLoader classLoader = cat.getClass().getClassLoader();
        //(2)通过类加载器得到Class对象
        Class<?> aClass3 = classLoader.loadClass(classAllPath);
        System.out.println(aClass3);

        System.out.println(aClass.hashCode());
        System.out.println(aClass1.hashCode());
        System.out.println(aClass2.hashCode());
        System.out.println(aClass3.hashCode());

        //5.基本数据类型.class
        Class<Integer> integerClass = int.class;
        Class<Character> characterClass = char.class;
        System.out.println(integerClass + "   " + characterClass);

        //6.基本数据类型包装类.TYPE
        Class<Integer> type = Integer.TYPE;
        System.out.println(type);

        System.out.println(integerClass.hashCode());
        System.out.println(type.hashCode());
    }
}

运行结果: 

class Study.Reflection_Study.Cat
class Study.Reflection_Study.Cat
class Study.Reflection_Study.Cat
class Study.Reflection_Study.Cat
1828972342
1828972342
1828972342
1828972342
int   char
int
460141958
460141958

3、演示哪些类型有Class对象

package Study.Reflection_Study;

import java.io.Serializable;

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-12 19:29
 * @Description 演示哪些类型有Class对象
 */
public class AllTypeClass {
    public static void main(String[] args) {
        Class<String> aClass1 = String.class;//外部类
        Class<Serializable> aClass2 = Serializable.class;//接口
        Class<Integer[]> aClass3 = Integer[].class;//数组
        Class<char[][]> aClass4 = char[][].class;
        Class<Override> aClass5 = Override.class;//注解
        Class<Thread.State> aClass6 = Thread.State.class;//枚举
        Class<Integer> aClass7 = int.class;//基本数据类型
        Class<Void> aClass8 = void.class;//void类型
        Class<Class> aClass9 = Class.class;//Class类
        System.out.println(aClass1);
        System.out.println(aClass2);
        System.out.println(aClass3);
        System.out.println(aClass4);
        System.out.println(aClass5);
        System.out.println(aClass6);
        System.out.println(aClass7);
        System.out.println(aClass8);
        System.out.println(aClass9);
    }
}

运行结果:

class java.lang.String
interface java.io.Serializable
class [Ljava.lang.Integer;
class [[C
interface java.lang.Override
class java.lang.Thread$State
int
void
class java.lang.Class

4、 演示Class类常用方法

package Study.Reflection_Study;

import java.lang.reflect.Field;

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-12 18:58
 * @Description 演示Class类常用方法
 */
public class Class02 {
    public static void main(String[] args) throws Exception {
        String classAllPath = "Study.Reflection_Study.Cat";
        //1.获取Class对象
        Class<?> cls = Class.forName(classAllPath);//<?>表示不确定Java类型,可去掉
        //2.输出Class
        System.out.println(cls);//哪个类的class对象
        System.out.println(cls.getClass());//运行类型
        //3.得到包名
        System.out.println(cls.getPackage().getName());
        //4.得到类名
        System.out.println(cls.getName());
        //5.生成对象实例
        Object o = cls.getDeclaredConstructor().newInstance();
        //6.通过反射获取属性
        Field age = cls.getField("age");//公有属性
        System.out.println(age);
        //7.给属性设置值
        age.set(o,10);
        System.out.println(age.get(o));
        //8.得到所有公有属性
        Field[] fields = cls.getFields();
        for (Field f: fields) {
            System.out.println(f);
        }
    }
}

运行结果:

class Study.Reflection_Study.Cat
class java.lang.Class
Study.Reflection_Study
Study.Reflection_Study.Cat
public int Study.Reflection_Study.Cat.age
10
public int Study.Reflection_Study.Cat.age
public java.lang.String Study.Reflection_Study.Cat.sex

5、通过反射机制创建实例

package Study.Reflection_Study;

import java.lang.reflect.Constructor;

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-14 18:57
 * @Description 通过反射机制创建实例
 */
public class ReflectCreateInstance {
    public static void main(String[] args) throws Exception {
        //获取User类的Class对象
        Class<?> userClass = Class.forName("Study.Reflection_Study.User");
        //通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
        //通过public的有参构造器创建实例
        Constructor<?> constructor = userClass.getConstructor(String.class);
        Object o1 = constructor.newInstance("猪头");
        System.out.println(o1);
        //通过非public的有参构造器创建实例☆☆☆
        Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(int.class, String.class);
        declaredConstructor.setAccessible(true);//暴破,使用反射访问private构造器
        Object o2 = declaredConstructor.newInstance(1000,"呆子");
        System.out.println(o2);
    }
}

class User {
    private int age=10;
    private String name="猫";

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

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

    public String toString() {
        return "User[age=" + age + ", name=" + name + "]";
    }
}

 运行结果:

User[age=10, name=猫]
User[age=10, name=猪头]
User[age=1000, name=呆子]

 6、演示通过反射调用方法

package Study.Reflection_Study;

import java.lang.reflect.Method;

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-14 19:40
 * @Description 演示通过反射调用方法
 */
public class ReflectAccessMethod {
    public static void main(String[] args) throws Exception {
        Class<?> bossClass = Class.forName("Study.Reflection_Study.Boss");
        Object o = bossClass.newInstance();
        //调用hi方法
        Method hi = bossClass.getDeclaredMethod("hi", String.class);
        hi.invoke(o, "呆子");
        //调用say方法
        Method say = bossClass.getDeclaredMethod("say", int.class, String.class, char.class);
        say.setAccessible(true);//暴破
        System.out.println(say.invoke(o, 100, "狗头", 'a'));
        System.out.println(say.invoke(null, 200, "猫头", 'b'));
        //在反射中,如果方法有返回值,统一返回Object
        Object returnValue = say.invoke(o, 20, "猪头", 'c');
        System.out.println("运行类型为" + returnValue.getClass());


    }
}

class Boss {
    public int age;
    private static String name;

    public Boss() {
    }

    private static String say(int n, String s, char c) {
        return n + " " + s + " " + c;
    }

    public void hi(String s) {
        System.out.println("hi," + s);
    }
}

 运行结果:

hi,呆子
100 狗头 a
200 猫头 b
运行类型为class java.lang.String

7、演示反射操作属性

package Study.Reflection_Study;

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

/**
 * @author NJUPT_MR.Z
 * @create 2022-05-14 19:27
 * @Description 演示反射操作属性
 */
public class ReflectAccessProperty {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class<?> stuClass = Class.forName("Study.Reflection_Study.Student");
        //创建对象
        Constructor<?> constructor = stuClass.getConstructor();
        Object o = constructor.newInstance();
        System.out.println(o);
        //反射得到age属性对象
        Field age = stuClass.getField("age");
        age.set(o,88);//通过反射操作属性
        System.out.println(age.get(o));
        System.out.println(o);
        //反射操作name属性
        Field name = stuClass.getDeclaredField("name");
        name.setAccessible(true);//暴破获取private属性
        name.set(o,"猪头");//或者name.set(null,"猪头"),因为name是static的
        System.out.println(name.get(o));//或者name.get(null)
        System.out.println(o);
    }
}

class Student {
    public int age;
    private static String name;

    public Student() {
    }

    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
}

运行结果:

Student [age=0, name=null]
88
Student [age=88, name=null]
猪头
Student [age=88, name=猪头]

四、反射机制利弊 

        反射虽然很灵活,能够使得写的代码,变的大幅精简,所以在用的时候,一定要注意具体的应用场景,反射的优缺点如下: 

优点: 
(1)能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。 
(2)与Java动态编译相结合,可以实现无比强大的功能 
缺点: 
(1)使用反射的性能较低 
(2)使用反射相对来说不安全 
(3)破坏了类的封装性,可以通过反射获取这个类的私有方法和属性 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值