java反射机制

本文深入浅出地介绍了Java反射机制的基本概念及其应用场景。通过具体的代码示例解释了如何利用反射加载类、创建对象以及访问类的成员变量和方法。此外还讨论了反射在Spring框架中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

首先我们了解一下JVM,什么是JVM,Java的虚拟机,java之所以能跨平台就是因为这个东西,你可以理解成一个进程,程序,只不过他的作用是用来跑你的代码的。上图是java的内存模型,我们关注的点,一个方法区,一个栈,一个堆,初学的时候老师不深入的话只告诉你java的内存分为堆和栈,易懂点吧!

假如你写了一段代码:Object o=new Object();

运行了起来!

首先JVM会启动,你的代码会编译成一个.class文件,然后被类加载器加载进jvm的内存中,你的类Object加载到方法区中,创建了Object类的class对象到堆中,注意这个不是new出来的对象,而是类的类型对象,每个类只有一个class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否加载,寻找类对应的class对象,若加载好,则为你的对象分配内存,初始化也就是代码:new Object()。

上面的流程就是你自己写好的代码扔给jvm去跑,跑完就over了,jvm关闭,你的程序也停止了。

为什么要讲这个呢?因为要理解反射必须知道它在什么场景下使用。

题主想想上面的程序对象是自己new的,程序相当于写死了给jvm去跑。假如一个服务器上突然遇到某个请求哦要用到某个类,哎呀但没加载进jvm,是不是要停下来自己写段代码,new一下,哦启动一下服务器,(脑残)!

反射是什么呢?当我们的程序在运行时,需要动态的加载一些类这些类可能之前用不到所以不用加载到jvm,而是在运行时根据需要才加载,这样的好处对于服务器来说不言而喻,举个例子我们的项目底层有时是用mysql,有时用oracle,需要动态地根据实际情况加载驱动类,这个时候反射就有用了,假设 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection这两个类我们要用,这时候我们的程序就写得比较动态化,通过Class tc = Class.forName("com.java.dbtest.TestConnection");通过类的全类名让jvm在服务器中找到并加载这个类,而如果是oracle则传入的参数就变成另一个了。这时候就可以看到反射的好处了,这个动态性就体现出java的特性了!举多个例子,大家如果接触过spring,会发现当你配置各种各样的bean时,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就会根据你的需求去动态加载,你的程序就能健壮地运行。

 

 

 

一、反射机制的作用:

              1,反编译:.class-->.java

              2,通过反射机制访问java对象的属性,方法,构造方法等;

             这样好像更容易理解一些,下边我们具体看怎么实现这些功能。

二、在这里先看一下sun为我们提供了那些反射机制中的类:

java.lang.Class;                

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

java.lang.reflect.Method;

java.lang.reflect.Modifier;

 

            很多反射中的方法,属性等操作我们可以从这四个类中查询。还是哪句话要学着不断的查询API,那才是我们最好的老师。

三、具体功能实现:

package com.linksky;


import java.lang.reflect.Field;
import java.lang.reflect.Modifier;


public class Employee {

public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
//第一种方法:
Class classc1 = Class.forName("com.linksky.Employee"); 
System.out.println(classc1);
//第二种方法
Class Classc2 = Employee.class;
System.out.println("2:"+Classc2);

//第三种方式:  
//java语言中任何一个java对象都有getClass 方法  
Employee e = new Employee();  
Class Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)
System.out.println("3:"+Classc3);

Class a =Employee.class; 
 
//创建此Class 对象所表示的类的一个新实例  
Object o = a.newInstance(); //调用了Employee的无参数构造方法.
   System.out.println(o);
  
   
   //获取整个类  
        Class c = Class.forName("java.lang.Integer");  
        //获取所有的属性?  
        Field[] fs = c.getDeclaredFields();  
        //定义可变长的字符串,用来存储属性  
        StringBuffer sb = new StringBuffer();  
        //通过追加的方法,将每个属性拼接到此字符串中  
        //最外边的public定义  
        sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");  
        //里边的每一个属性  
        for(Field field:fs){  
            sb.append("\t");//空格  
            sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  
            sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  
            sb.append(field.getName()+";\n");//属性的名字+回车  
        }  
        sb.append("}");  
        System.out.println(sb);  
        //获取特定的属性,对比着传统的方法来学习
        System.out.println(/* ============================================================================================= */);
        //获取类
        Class u = Class.forName("com.linksky.User"); 
        //获取id属性
        Field idf=u.getDeclaredField("id");
        //实例化这个类赋给o
        Object ob=u.newInstance();
        //打破封装
        idf.setAccessible(true);//使用反射机制可以打破封装性,导致了java对象的属性不安全
        //给o对象的id属性赋值“110”
        idf.set(ob, 110);
        //get
        System.out.println(idf.get(ob));
        
        
}
}

欢迎访问我的网站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值