Java基础-反射

本文深入浅出地介绍了Java反射机制的基础概念与应用,包括如何获取类的对象、使用属性及调用方法等。通过实例演示了反射的具体操作步骤。

1.反射是什么?

我们将从 .java到.calss的过程叫做编译,那么从.class到.java便是反编译,也就是反射.

反射简单的概括就是将java类中的所有成分映射成独立的对象.

2.反射的使用(这里只是简单的写了几个基础的使用,以后会补全所有使用方法)

这里我们以Person类作为演示,类中只定义了两个参数

    private String name;
    private int age;

  • 获取类的对象(这里我们只介绍几个经常用到的)

1. Class.forName("全限定名");

Class c=Class.forName("com.zking.entity.Person");//全限定名也可以理解为类的真实路径,就是带包名的类路径,如包名.类名
System.out.println(c);//输出获取到的值

这样我们就可以得到一个Class的对象了,下面的所有操作都是依靠这个对象来完成的.

2. C lass class=类名.class;

   Class c= Person.class;
	System.out.println(c);//输出获取到的值

 这样我们也可以得到一个对象.

  • 属性的使用(这里我们也只介绍几个常用的)

这里我们要使用到一个类: Field 类,我们通过这个类来获取对象的属性;

在获取属性之前,我们需要想设置一下Person类中属性的访问权限

setAccessible(true);

通过这行代码,我们可以将Person类中的private属性设置为能够访问,不然是访问不到这个属性的

1.  根据属性名获取属性

Field f=c.getDeclaredField("name");	

这样我们就获取到了Person类中name的属性了,然后我们就可以使用set和get的方法来对这个属性进行修改或赋值了

   Class c= Person.class;   //获得Class对象
	System.out.println(c);  //输出
	Object obj=c.newInstance();   //这个方法是将Person实例化了
	Field f=c.getDeclaredField("name");	//获取person中属性名为name的属性
	f.setAccessible(true);   //设置访问权限
	f.set(obj, "张三");   //修改name的值
	System.out.println(f.get(obj));  //输出

最后我们控制台可以得到的是

class com.zking.entity.Person

张三

这两条结果

2.  获取全部属性

        Field[] field=c.getDeclaredFields();
这里我们注意,获取到的是一个数组

然后循环输出一下

        for (Field f : field) {
			f.setAccessible(true);
			System.out.println(f.getName());  //这里只是简单的输出了一下属性名,并没有进行操作
		}

  • 方法的使用

其实方法的使用和属性的使用非常相似

1. 得到类的所有方法

Method [] method=c.getDeclaredMethods();
根据这个方法我们可以获得所有的方法,这里只是获取到了方法名,接下来就是使用这些方法
		for (Method mm : method) {   //用foreach来循环获取到的方法
			Object obj=c.newInstance();  //实例化对象
			if("m1".equals(mm.getName())) {   //我在Person类中定义了4个方法.m1,m2,m3,m4;分别为无参无返,无参有返,有参无返和有参有返
				mm.invoke(obj, null);   //invoke是执行方法的操作 后面传的null值是我们要传的参数,因为m1和m2没有定义参数,所以我们不需要传值进去
			}else if("m2".equals(mm.getName())) {
				System.out.println(mm.invoke(obj, null)); 
			}else if("m3".equals(mm.getName())) {
				mm.invoke(obj, 1);
			}else if("m4".equals(mm.getName())) {
				System.out.println(mm.invoke(obj, 2));
			}
		}
以下是我在Person类中定义的方法
public void m1() {
		System.out.println("无参无返");
	}
	
	
	public String m2() {
		return "无参有返";
	}
	
	public void m3(int a) {
		System.out.println("有参无返");
	}
	
	public String m4(int a) {
		return "有参有返";
	}

                                                  

<think>嗯,用户之前问过关于`int``integer`的区别,现在转向Java基础中的反射。可能用户正在学习Java,之前的问题涉及基本数据类型包装类,现在深入到了更高级的主题。我需要先确定用户对Java基础掌握程度,反射通常是面向对象之后的内容,所以用户可能已经有一定的Java基础。 用户的需求是了解Java反射基础知识,可能需要知道反射是什么、为什么用它、以及如何使用。深层需求可能包括实际应用场景或常见问题,比如性能影响或者安全性考虑。需要结构清晰,分点解释,帮助用户逐步理解。 首先,反射的定义,必须用简单明了的语言,避免术语过多。然后核心类,比如Class、Constructor、Method、Field,这些是反射的关键类,需要举例说明。应用场景部分,用户可能想知道反射的实际用途,比如框架开发或动态加载,要举常见的例子如Spring的IoC。 接下来要讲实现步骤,获取Class对象的三种方式,实例化对象的方法,访问字段调用方法。每个步骤都需要代码示例,但用户可能对代码的细节不太清楚,所以需要解释每个步骤的作用。例如,`Class.forName`可能会抛出异常,需要提及异常处理,但可能不需要深入,保持基础知识的介绍。 优缺点部分需要平衡,用户可能想知道为什么有时候不推荐使用反射,所以性能安全问题是重点。最后,实际案例,比如动态加载类,或者简单的框架应用,帮助用户将理论联系实际。 还要注意用户可能存在的误区,比如滥用反射导致代码难以维护,或者性能问题。需要提醒在必要时使用,并遵循最佳实践。此外,检查是否需要提到Java版本的变化对反射的影响,比如模块化系统带来的访问限制,但可能用户刚入门,暂时不需要深入。 最后总结,强调反射的灵活性代价,帮助用户权衡使用场景。整体结构需要逻辑清晰,从定义到实现再到应用,逐步深入,确保用户能够跟随思路,逐步掌握反射基础知识。</think>好的!以下是关于 **Java反射(Reflection)** 的基础知识介绍,以逐步分析的方式展开: --- ### 一、反射的定义 **反射(Reflection)** 是Java提供的一种**运行时动态机制**,允许程序在**不预先知道类结构**的情况下,通过`Class`对象获取类的信息(如字段、方法、构造器等),并操作这些成员。简单来说:**通过反射,程序可以“观察”修改自身的行为**。 --- ### 二、反射的核心类 Java反射通过以下核心类实现: 1. **`Class`**:表示类或接口的元数据。 2. **`Constructor`**:表示类的构造方法。 3. **`Method`**:表示类的方法。 4. **`Field`**:表示类的字段(属性)。 5. **`Modifier`**:解析成员的修饰符(如`public`、`private`)。 --- ### 三、反射的核心用途 1. **动态获取类信息** 例如:获取类名、父类、接口、注解等。 ```java Class<?> clazz = String.class; System.out.println("类名:" + clazz.getName()); // 输出:java.lang.String ``` 2. **动态创建对象** 即使没有显式定义构造方法,也可以通过反射实例化对象。 ```java Class<?> clazz = Class.forName("java.util.ArrayList"); Object list = clazz.newInstance(); // 创建ArrayList实例(已过时,推荐用构造器) ``` 3. **动态调用方法/访问字段** 可以绕过访问权限(如调用私有方法)。 ```java Method method = clazz.getDeclaredMethod("privateMethod"); method.setAccessible(true); // 突破private限制 method.invoke(obj); ``` 4. **实现通用框架** 如Spring的依赖注入(IoC)、MyBatis的ORM映射等。 --- ### 四、反射的实现步骤(以调用方法为例) 1. **获取`Class`对象** 三种方式: ```java Class<?> clazz1 = Class.forName("全限定类名"); // 通过类路径加载 Class<?> clazz2 = Object.class; // 通过类字面量 Class<?> clazz3 = obj.getClass(); // 通过对象实例 ``` 2. **获取方法或字段** ```java Method method = clazz.getDeclaredMethod("方法名", 参数类型.class); // 包括私有方法 Field field = clazz.getDeclaredField("字段名"); // 包括私有字段 ``` 3. **设置访问权限(可选)** ```java method.setAccessible(true); // 突破private限制 ``` 4. **执行操作** ```java Object result = method.invoke(对象实例, 参数值); // 调用方法 field.set(对象实例, 值); // 修改字段值 ``` --- ### 五、反射的优缺点 | **优点** | **缺点** | |------------------------------|-----------------------------------| | 动态性高(如插件化开发) | 性能较差(比直接调用慢约10-100倍)| | 可访问私有成员(灵活性强) | 代码可读性降低 | | 通用性高(框架开发必备) | 绕过类型安全检查,可能引发异常 | --- ### 六、实际应用案例 1. **动态加载类**(如插件机制): ```java Class<?> pluginClass = Class.forName("com.example.Plugin"); Object plugin = pluginClass.newInstance(); Method runMethod = pluginClass.getMethod("run"); runMethod.invoke(plugin); ``` 2. **Spring框架的依赖注入**: ```java // 通过反射创建Bean并注入属性 Class<?> beanClass = Class.forName("com.example.UserService"); Object bean = beanClass.newInstance(); Field daoField = beanClass.getDeclaredField("userDao"); daoField.setAccessible(true); daoField.set(bean, new UserDaoImpl()); // 注入依赖 ``` --- ### 七、注意事项 1. **性能优化**:避免在频繁调用的代码中使用反射。 2. **安全限制**:Java 9+的模块系统可能限制反射访问(需在`module-info.java`中声明`opens`)。 3. **代码健壮性**:反射调用需处理大量异常(如`ClassNotFoundException`、`NoSuchMethodException`)。 --- ### 总结 反射Java中强大的动态编程工具,**核心价值是灵活性**,但需谨慎使用。掌握反射后,可以深入理解框架设计原理(如Spring、Hibernate),但日常开发中应优先考虑直接调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值