Java 反射机制,零基础入门到精通,收藏这篇就够了

目录

一、反射的核心概念

二、反射基础API

2.1 获取Class对象的四种方式

2.2 访问私有字段

2.3 动态创建对象

2.4 获取所有字段信息

2.5 调用方法(Method)

三、反射的实战场景

3.1 案例 1:XML 配置 + 反射实现 “可配置” 工厂

3.2 案例 2:依赖注入(DI)的简单实现


一、反射的核心概念

    Java反射(Reflection)是Java语言的一个重要特性,是 Java 的一种**运行时机制**,通过`java.lang.reflect`包中的 API,程序可以在运行时动态地获取类的信息、创建对象、调用方法和访问字段。反射机制打破了Java的封装性,同时提供了极大的灵活性。

核心特点:

  • 运行时类型检查:在运行时获取类的完整结构信息

  • 动态操作:动态创建对象、调用方法、访问字段

  • 突破封装:可以访问私有成员(通过setAccessible(true))

二、反射基础API

2.1 获取Class对象的四种方式

  • 类名.class 和 ClassLoader加载 不会触发类的初始化(静态代码块、构造函数不执行)。

  • 对象.getClass 会触发类的初始化(如Stu的静态代码块、构造函数会执行)。

  • Class.forName("类的全路径”) 会执行静态代码块

package com.demo1;

public class Stu {

	private int age = 100;
	
	static {
		System.out.println("Stu的静态块执行");
	}
	
	public Stu() {
        System.out.println("Stu的无参构造函数被调用");
    }

}

package com.demo1;

//import com.sun.org.apache.bcel.internal.util.ClassLoader;

public class Test {

	public static void main(String[] args) {
		
		// 获取Stu类的变量,构造函数、方法
		// 反射的四个入口方式,加载这个类的Class类型
		
		// 1. 类名.class   (不会触发初始化)
//		Class c1 = Stu.class;
//		System.out.println(c1);
		
		
		// 2. 对象.getClass    (执行静态块和无参构造函数)
//		Class c2 = new Stu().getClass();
		
		
		// 3.Class.forName("类的全路径”)    (执行静态块)
//		try {
//			Class c3 = Class.forName("com.demo1.Stu");
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		
		// 4. 通过类的加载器ClassLoader   (不会触发初始化)
//		Class c4 = null;
//		try {
//			c4 = ClassLoader.getSystemClassLoader().loadClass("com.demo1.Stu");
//		} catch (ClassNotFoundException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		
	}
}

2.2 访问私有字段

  • 反射可以访问类的所有字段(包括私有字段)
  • 方法newInstance()调用默认无参构造函数
package com.demo1;

public class User {

	private int a = 10;		// 私有字段
	
	public User() {
		System.out.println("调用User的无参构造函数");
	}
}

package com.demo1;

import java.lang.reflect.Field;

public class Test {
	
	public static void main(String[] args) {
		
		//传统的面向对象的思想
//		User  u  = new User();
//		System.out.println(u.a);
		
		//反射API
		//获取User这个类的Class对象
		Class  targetClass = User.class;
		
		try {
			// 创建这个类的对象,基于反射机制,newInstance()调用默认无参构造函数
			Object  obj = targetClass.newInstance();
			
			// 获取这个类的属性变量a的Field类型。获取名为"a"的字段(包括私有字段)
			Field f = targetClass.getDeclaredField("a");
			
			// 设置暴力访问
			f.setAccessible(true);
			
			// 通过Field对象的get()方法获取指定对象的字段值。
			Object aValue = f.get(obj);
			
			System.out.println(aValue);
			
			
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

运行结果:

2.3 动态创建对象

    通过`Class`对象,可以动态创建类的实例:
package com.demo4;

public class User {

	public int id;
	
	public String name;

	public User() {
		this.name = "六神";
	}

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

}

package com.demo4;

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

public class Test {

	public static void main(String[] args) throws Exception {

		Class userClass = User.class;

		// 方式1:调用无参构造函数(需类有无参构造)
		Object user1 = userClass.newInstance();

		Field f1 = userClass.getDeclaredField("name");

		Object obj1 = f1.get(user1);

		System.out.println("user1的姓名为:  " + obj1);

		// 方式2:通过Constructor调用指定构造函数
		// 获取带参数的构造函数
		Constructor constructor = userClass.getConstructor(int.class, String.class);
		// 创建实例并传入参数
		Object user2 = constructor.newInstance(9, "花露水");

		Field f2 = userClass.getDeclaredField("name");

		Object obj2 = f2.get(user2);

		System.out.println("user2的姓名为:  " + obj2);
	}

}

运行结果:

2.4 获取所有字段信息

package com.demo2;

public class User {

	private int a = 10;

	public String name = "QQ";

	protected int count = 100;
}

package com.demo2;

import java.lang.reflect.Field;

public class Test {

	public static void main(String[] args) {

		try {
			Class c = Class.forName("com.demo2.User");

			Object newObj = c.newInstance();

			// 获取这个类中所有定义的变量(加了s)
			Field[] fs = c.getDeclaredFields();

			// 只能获取类的public字段
//			Field[]  fs=  c.getFields();

			for (Field f : fs) {
				f.setAccessible(true);

				System.out.println("变量名为: " + f.getName() + "  值为:" + f.get(newObj));
			}

		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

运行结果:

2.5 调用方法(Method)

    反射可以调用类的所有方法(包括私有方法):
public static void main(String[] args) throws Exception {

		System.out.println("请问你要执行哪个类?");
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String name = br.readLine();

		Config config = maps.get(name); // 获取配置

		if (null == config) {
			throw new ActionException("没有匹配的执行类");
		}

		Class c = Class.forName(config.getPath()); // 加载类
		Method m = c.getDeclaredMethod(config.getMname(), null); // 获取方法
		m.invoke(c.newInstance(), null);		// 反射的执行方法

	}

三、反射的实战场景

3.1 案例 1:XML 配置 + 反射实现 “可配置” 工厂

    通过 XML 配置类的全限定名,动态创建对象,实现 “新增类无需修改代码,只需修改配置文件里的内容”。

工程目录结构

XML 配置文件(application.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean name="dog"  		path="com.demo8.Dog" ></bean> 
    <bean name="cat" 		path="com.demo8.Cat"></bean>
    <bean name="person" 	path="com.demo8.Person"></bean>
</beans>

接口与实现类

// 接口
package com.demo8;

public interface  Animal {
	
	public  void  eat();

}

// 实现类
package com.demo8;

public class Cat   implements  Animal{

	public void eat() {
		// TODO Auto-generated method stub
		System.out.println("猫吃鱼");
	}

}


package com.demo8;

public class Dog   implements Animal{

	public void eat() {
		// TODO Auto-generated method stub
		System.out.println("狗吃骨头");
	}

}


package com.demo8;

public class Person  implements Animal{

	public void eat() {
		// TODO Auto-generated method stub
		System.out.println("人吃米饭");
		
	}

}




解析 XML + 反射创建对象

package com.demo8;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ParseXML {

	private static ParseXML px;  	// 单例实例

	private static Hashtable<String, String> tabs = new Hashtable<String, String>(); 	// 配置缓存

	// 私有构造函数 - 读取配置
	private ParseXML() {

		Properties p = new Properties();
		try {
			p.load(new FileInputStream("./config.properties"));

			String xmlPath = p.getProperty("xmlPath");		// 获取XML路径(application.xml)

			System.out.println("XML路径: " + xmlPath);

			SAXReader saxReader = new SAXReader();
			Document doc = saxReader.read(new File(xmlPath));

			// 方案1:绝对路径
//			List<Element> lists =(List<Element>) doc.selectNodes("/beans/bean");
			
			// 方案2:相对路径(从根节点开始)
			List<Element> lists = doc.getRootElement().elements("bean");

			for (Element currentElement : lists) {
				// System.out.println(currentElement.getName());
				String name = currentElement.attributeValue("name");
				String path = currentElement.attributeValue("path");

				tabs.put(name, path); 		// 存入缓存

			}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// 单例获取方法
	public synchronized static ParseXML getInstance() {
		if (null == px) {
			px = new ParseXML();
		}
		return px;
	}


	public static Hashtable<String, String> getTabs() {
		return tabs;
	}

	public static void setTabs(Hashtable<String, String> tabs) {
		ParseXML.tabs = tabs;
	}

}



package com.demo8;

import java.util.Hashtable;

public class AnimalFactory {

	private static Animal an;

	public static Animal getAnimal(String name) {

		// 配置文件+反射机制 an = 容器类.getBean(name)

		Hashtable<String, String> tabs = ParseXML.getInstance().getTabs();

		String path = tabs.get(name);		// 根据名称获取类路径

		if (path == null || "".equals(path)) {

			throw new PathException("没有匹配的值");
		}
		
		try {
			Class c = Class.forName(path);
			an = (Animal)c.newInstance();		// 反射创建实例
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return an;

	}

}

自定义异常

package com.demo8;

public class PathException   extends RuntimeException {
	
	public PathException(String msg)
	{
		super(msg);
	}

}

测试类

package com.demo8;

import java.util.Scanner;

public class Test {
	
	public static void main(String[] args) {
		
		System.out.println("请用户输入需要的类型:");
		
		Scanner  s   = new Scanner(System.in);
		
		String name  =s.next();
		
		Animal  an = AnimalFactory.getAnimal(name);
		an.eat();
	}

}



运行结果:

3.2 案例 2:依赖注入(DI)的简单实现

    通过反射实现 “构造器注入”,动态为对象注入依赖。

工程目录结构

XML 配置文件(app.xml

<?xml version="1.0" encoding="UTF-8"?>
<app>
  <class name="user" path="com.demo3.User"  ref="dao"  method="actionUser"></class>
  
  <class  name="dao" path="com.demo3.UserDao"></class>

</app>

容器核心类(App

package com.demo3;

import java.io.File;
import java.util.Hashtable;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class App {

	private static App app;		// 单例实例

	private static Hashtable<String, ClassBean> tabs = new Hashtable<String, ClassBean>(); 	// 配置缓存

	// 静态块:启动时加载配置
	static {

		SAXReader saxReader = new SAXReader();
		
		try {
			Document doc = saxReader.read(new File("./app.xml"));

			List<Element> lists = doc.selectNodes("./app/class");

			for (Element e : lists) {

				ClassBean cbean = new ClassBean();
				String name = e.attributeValue("name");
				String path = e.attributeValue("path");
				String ref = e.attributeValue("ref"); 		 // 依赖引用
				String method = e.attributeValue("method");

				//System.out.println(path + "," + ref + "," + method);

				cbean.setPath(path);

				if (null != ref || "" != ref) {
					cbean.setRef(ref);
				}

				if (null != method || "" != method) {
					cbean.setMethod(method);
				}

				tabs.put(name, cbean);		// 存入缓存

			}

		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static App getInstance() {
		if (null == app) {
			app = new App();
		}

		return app;

	}
	
	// 获取配置Bean
	public static Object getApplicationBean(String name)
	{
		 return tabs.get(name);
	}

	public static void main(String[] args) {

		ClassBean cbean =  (ClassBean)App.getApplicationBean("user");
		System.out.println(cbean.getPath()+","+cbean.getRef()+","+cbean.getMethod());
		
		ClassBean cbean1 =  (ClassBean)App.getApplicationBean(cbean.getRef());
		System.out.println(cbean1.getPath());
		
	}

}


配置信息封装类(ClassBean

package com.demo3;

public class ClassBean {
	
	private String path; // 类全限定名
	
	private String  ref; // 依赖的Bean名称
	
	private String method;// 默认调用方法

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getRef() {
		return ref;
	}

	public void setRef(String ref) {
		this.ref = ref;
	}

	public String getMethod() {
		return method;
	}

	public void setMethod(String method) {
		this.method = method;
	}

}


接口与实现类

// 数据访问接口
package com.demo3;

public interface IDao {
	
	public String execDao();

	
	public String addDao();

}


// Dao实现类1
package com.demo3;

public class Dao implements IDao{
	
	public String execDao()
	{
		return  "查询获取的数据";
	}
	
	public String addDao()
	{
		return "添加用户";
	}

}


// Dao实现类2
package com.demo3;

public class UserDao implements IDao{
	
	public String execDao()
	{
		return  "超快查询获取的数据";
	}
	
	public String addDao()
	{
		return "超快添加用户";
	}

}

业务类(User

    依赖`IDao`接口,通过**构造器注入**获取实现类:
package com.demo3;

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

public class User {

	IDao dao;		// 依赖接口,而不是具体实现,便于动态绑定

	public User() {
		
	}
	
	// 构造注入
	public User(IDao dao) {
		this.dao = dao;
}
	
	// Set注入
//	public void setUser(IDao dao) {
//		this.dao = dao;
//	}

	public String actionUser() {
		//dao = new Dao();
		return dao.execDao();
	}

	public String addUser() {
		//dao = new Dao();
		return dao.addDao();
	}

	public static void main(String[] args) {

		// 面向对象的方式去调用
//		User u = new User();
//		String  r1 = u.actionUser();
//		System.out.println(r1);
//		String  r2 = u.addUser();
//		System.out.println(r2);

		try {

			ClassBean cbean = (ClassBean) App.getApplicationBean("user");
			Class c = Class.forName(cbean.getPath());
			System.out.println(cbean.getPath());		// com.demo3.User

			// (参数对象的实例化):Dao类/UserDao类的对象通过反射实例化
			ClassBean cbean1 = (ClassBean) App.getApplicationBean(cbean.getRef());
			System.out.println(cbean1.getPath());		// com.demo3.Dao
			Class cdao = Class.forName(cbean1.getPath());

			
//			Object obj = c.newInstance();  //下面用到两次的obj来自于这里new的同一个实例对象

			
			// Setter注入的实例化
			// c.getName()得到的是类的全路径,用substring截取类名再和set拼接,得到Set注入的方法名(总体就是通过反射得到setUser方法完成dao的实例化)
//			String cname = c.getName().substring(c.getName().lastIndexOf(".") + 1, c.getName().length());
//			System.out.println(cname);  // cname为User
//			String mname = "set" + cname;
//			Method daoMethod = c.getDeclaredMethod(mname, IDao.class);
//			Object resultObj = daoMethod.invoke(obj, cdao.newInstance()); //(当前类的对象,Dao类/UserDao类的对象)
//			System.out.println("已完成实例化");

			
			
			// 构造器注入
			// 获取带参数的构造函数
			Constructor constructor = c.getConstructor(IDao.class);
			// 使用构造函数创建实例(直接注入依赖)
			Object	obj = constructor.newInstance(cdao.newInstance());
			System.out.println("已完成实例化");
			
			
			
			Method m = c.getDeclaredMethod(cbean.getMethod(), null);   // 得到actionUser方法
			Object result = m.invoke(obj, null);

			System.out.println("返回值为:" + result);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}


运行结果:

这是小红书上一位Java工程师辞职两次的真实经历

可以看出Java如今的就业大环境确实差强人意,那如何拯救现在的Java行业呢?

当然是与新兴技术结合起来,发挥Java最大的作用,提升自己的优势,现如今发展最好的趋势莫过于今年deepseek带火的大模型技术,

Java与大模型结合的技术优势

  • 推理环节的核心地位
    大模型训练依赖Python生态的高性能计算资源,而Java在推理阶段(模型部署、性能优化、系统集成)具有独特优势。其“编写一次,处处运行”的特性,使其能无缝集成到微服务、分布式系统等企业级架构中,高效处理高并发请求。例如,某电商平台通过Java构建的大模型API网关,支撑每日千万级请求的稳定运行,响应时间缩短50%。

  • 生态成熟与性能稳定
    Java拥有Spring Boot、Spring Cloud等成熟框架,可快速实现服务注册、负载均衡、熔断降级等生产级能力。JVM的垃圾回收机制和即时编译技术,使其在长连接、高并发场景下表现优于脚本语言。例如,某金融系统采用Java实现大模型推理服务,系统可用率长期保持99.99%以上。

  • 兼容性与工程化能力
    Java与现有业务系统的兼容性极强,可降低大模型落地的集成成本。例如,某制造企业通过Java将大模型与ERP系统对接,实现生产流程的智能优化,故障率降低30%。同时,Java在代码规范、测试流程、版本管理等方面的积累,能大幅降低大模型项目的研发成本和维护难度。

因此捕获AI,掌握技术是关键,让AI成为我们最便利的工具.

一定要把现有的技术和大模型结合起来,而不是抛弃你们现有技术!掌握AI能力的Java工程师比纯Java岗要吃香的多。

即使现在裁员、降薪、团队解散的比比皆是……但后续的趋势一定是AI应用落地!大模型方向才是实现职业升级、提升薪资待遇的绝佳机遇!

如何学习AGI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享**

一、2025最新大模型学习路线

一个明确的学习路线可以帮助新人了解从哪里开始,按照什么顺序学习,以及需要掌握哪些知识点。大模型领域涉及的知识点非常广泛,没有明确的学习路线可能会导致新人感到迷茫,不知道应该专注于哪些内容。

我们把学习路线分成L1到L4四个阶段,一步步带你从入门到进阶,从理论到实战。

L1级别:AI大模型时代的华丽登场

L1阶段:我们会去了解大模型的基础知识,以及大模型在各个行业的应用和分析;学习理解大模型的核心原理,关键技术,以及大模型应用场景;通过理论原理结合多个项目实战,从提示工程基础到提示工程进阶,掌握Prompt提示工程。

L2级别:AI大模型RAG应用开发工程

L2阶段是我们的AI大模型RAG应用开发工程,我们会去学习RAG检索增强生成:包括Naive RAG、Advanced-RAG以及RAG性能评估,还有GraphRAG在内的多个RAG热门项目的分析。

L3级别:大模型Agent应用架构进阶实践

L3阶段:大模型Agent应用架构进阶实现,我们会去学习LangChain、 LIamaIndex框架,也会学习到AutoGPT、 MetaGPT等多Agent系统,打造我们自己的Agent智能体;同时还可以学习到包括Coze、Dify在内的可视化工具的使用。

L4级别:大模型微调与私有化部署

L4阶段:大模型的微调和私有化部署,我们会更加深入的探讨Transformer架构,学习大模型的微调技术,利用DeepSpeed、Lamam Factory等工具快速进行模型微调;并通过Ollama、vLLM等推理部署框架,实现模型的快速部署。

整个大模型学习路线L1主要是对大模型的理论基础、生态以及提示词他的一个学习掌握;而L3 L4更多的是通过项目实战来掌握大模型的应用开发,针对以上大模型的学习路线我们也整理了对应的学习视频教程,和配套的学习资料。

二、大模型经典PDF书籍

书籍和学习文档资料是学习大模型过程中必不可少的,我们精选了一系列深入探讨大模型技术的书籍和学习文档,它们由领域内的顶尖专家撰写,内容全面、深入、详尽,为你学习大模型提供坚实的理论基础(书籍含电子版PDF)

三、大模型视频教程

对于很多自学或者没有基础的同学来说,书籍这些纯文字类的学习教材会觉得比较晦涩难以理解,因此,我们提供了丰富的大模型视频教程,以动态、形象的方式展示技术概念,帮助你更快、更轻松地掌握核心知识

四、大模型项目实战

学以致用 ,当你的理论知识积累到一定程度,就需要通过项目实战,在实际操作中检验和巩固你所学到的知识,同时为你找工作和职业发展打下坚实的基础。

五、大模型面试题

面试不仅是技术的较量,更需要充分的准备。

在你已经掌握了大模型技术之后,就需要开始准备面试,我们将提供精心整理的大模型面试题库,涵盖当前面试中可能遇到的各种技术问题,让你在面试中游刃有余。


因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值