Java中通过反射获得对象的属性信息

本文介绍如何在Java中创建一个类,包含多种基本数据类型的属性,并通过自定义方法实现打印对象属性名称、值及类型的功能。

先建立一个类,有四种属性:

private int id;

private String name;

private byte by;

private short st;

 

以下方法,创建一个对象,然后打印该对象的属性名字,属性值,和属性的类型:

public class T {
	public static void main(String[] args) throws Exception {
		User u = new User();
		u.setId(1);
		u.setName("cc");
		u.setBy((byte)1);
		u.setSt((short)2);
		getProperty(u);
	}
	/**
	 * 获得一个对象各个属性的字节流
	 */
	@SuppressWarnings("unchecked")
	public static void getProperty(Object entityName) throws Exception {
		Class c = entityName.getClass();
		Field field[] = c.getDeclaredFields();
		for (Field f : field) {
			Object v = invokeMethod(entityName, f.getName(), null);
			System.out.println(f.getName() + "\t" + v + "\t" + f.getType());
		}
	}
	/**
	 * 获得对象属性的值
	 */
	@SuppressWarnings("unchecked")
	private static Object invokeMethod(Object owner, String methodName,
			Object[] args) throws Exception {
		Class ownerClass = owner.getClass();
		methodName = methodName.substring(0, 1).toUpperCase()
				+ methodName.substring(1);
		Method method = null;
		try {
			method = ownerClass.getMethod("get" + methodName);
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
			return " can't find 'get" + methodName + "' method";
		}
		return method.invoke(owner);
	}
}

 

打印结果如下:

id	1	int
name	cc	class java.lang.String
by	1	byte
st	2	short

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com

 

<think>在Java中,通过反射得到的属性值可以是引用类型,也可以是基本类型。但是,在反射中,基本类型会被自动装箱为对应的包装类(如int会被装箱为Integer),因此当你通过反射获取属性值时,你得到的是一个Object对象。如果原始属性是基本类型,那么你得到的是其包装类的实例;如果是引用类型,那么直接得到该类型的实例。 具体来说,使用`Field.get(Object obj)`方法获取属性值时,返回的是`Object`类型。这个对象可能是: - 引用类型的实例(包括包装类) - 数组(数组也是对象) 因此,我们可以说通过反射得到的属性值总是以对象的形式呈现(即引用类型),即使它原本是基本类型,因为基本类型会被自动装箱。 下面是一个代码示例,展示如何使用反射获取属性值,并判断其类型: ```java import java.lang.reflect.Field; public class ReflectionExample { private int primitiveInt = 42; private String referenceType = "Hello, Reflection!"; public static void main(String[] args) throws Exception { ReflectionExample example = new ReflectionExample(); Class<?> clazz = example.getClass(); // 获取primitiveInt字段并获取其值 Field primitiveIntField = clazz.getDeclaredField("primitiveInt"); primitiveIntField.setAccessible(true); Object primitiveIntValue = primitiveIntField.get(example); System.out.println("primitiveInt value: " + primitiveIntValue); System.out.println("primitiveInt value type: " + primitiveIntValue.getClass().getName()); System.out.println("Is primitiveIntValue an Integer? " + (primitiveIntValue instanceof Integer)); // 获取referenceType字段并获取其值 Field referenceTypeField = clazz.getDeclaredField("referenceType"); referenceTypeField.setAccessible(true); Object referenceTypeValue = referenceTypeField.get(example); System.out.println("referenceType value: " + referenceTypeValue); System.out.println("referenceType value type: " + referenceTypeValue.getClass().getName()); System.out.println("Is referenceTypeValue a String? " + (referenceTypeValue instanceof String)); } } ``` 运行上述代码,输出如下: ``` primitiveInt value: 42 primitiveInt value type: java.lang.Integer Is primitiveIntValue an Integer? true referenceType value: Hello, Reflection! referenceType value type: java.lang.String Is referenceTypeValue a String? true ``` 解释: 1. 我们定义了一个类`ReflectionExample`,其中包含一个基本类型字段`primitiveInt`和一个引用类型字段`referenceType`。 2. 在`main`方法中,我们通过反射获取这两个字段的值。 3. 对于基本类型字段`primitiveInt`,我们通过`Field.get`方法得到的是一个`Integer`对象(自动装箱)。 4. 对于引用类型字段`referenceType`,我们得到的是`String`对象。 因此,通过反射获取属性值时,总是得到一个对象(引用类型)。如果原始属性是基本类型,那么返回的是对应的包装类对象。 **注意事项**: - 如果字段是静态的,那么`Field.get`方法的参数可以传入`null`。 - 如果字段是私有的,需要先调用`setAccessible(true)`来访问。 §§相关问题§§: 1. Java反射中如何修改一个私有字段的值? 2. 反射获取基本类型字段时,如何避免自动装箱? 3. 如何通过反射调用一个方法? 4. 反射中`Field`类的`get`方法在获取静态字段时应该传入什么参数?</think>在 Java 中,通过反射获取属性值**总是以对象形式(引用类型)返回**,无论原始属性是基本类型还是引用类型。这是因为反射 API 统一使用 `Object` 类型作为返回值,基本类型会被自动装箱为对应的包装类对象。 ### 关键点说明: 1. **基本类型的处理**: - 基本类型(如 `int`, `double` 等)会被装箱为对应的包装类(`Integer`, `Double` 等) - 获取的值是包装类对象(引用类型),不是原始基本类型 2. **引用类型的处理**: - 对象类型(如 `String`, 自定义类等)直接返回原对象的引用 - 数组类型也按引用返回 3. **反射 API 行为**: - `Field.get(Object)` 方法返回 `Object` 类型 - 实际类型需要通过 `getClass()` 或 `instanceof` 判断 ### 代码示例: ```java import java.lang.reflect.Field; public class ReflectionExample { private int primitiveValue = 42; // 基本类型 private String referenceValue = "Hello"; // 引用类型 public static void main(String[] args) throws Exception { ReflectionExample obj = new ReflectionExample(); Class<?> clazz = obj.getClass(); // 获取基本类型字段 Field primitiveField = clazz.getDeclaredField("primitiveValue"); primitiveField.setAccessible(true); Object primitiveResult = primitiveField.get(obj); // 获取引用类型字段 Field referenceField = clazz.getDeclaredField("referenceValue"); referenceField.setAccessible(true); Object referenceResult = referenceField.get(obj); // 验证类型 System.out.println("基本类型字段实际类型: " + primitiveResult.getClass()); // java.lang.Integer System.out.println("是Integer吗? " + (primitiveResult instanceof Integer)); // true System.out.println("是int吗? " + (primitiveResult instanceof int.class)); // 编译错误 System.out.println("引用类型字段实际类型: " + referenceResult.getClass()); // java.lang.String System.out.println("是String吗? " + (referenceResult instanceof String)); // true } } ``` ### 输出结果: ``` 基本类型字段实际类型: class java.lang.Integer 是Integer吗? true 引用类型字段实际类型: class java.lang.String 是String吗? true ``` ### 关键解释: 1. **装箱机制**: - `int` 字段的值 `42` 被装箱为 `Integer` 对象 - 反射系统自动处理了装箱过程 2. **类型安全**: - 返回值总是 `Object`,需要开发者自行转换类型 - 转换前应使用 `instanceof` 检查类型安全 3. **特殊类型处理**: - 数组类型:返回数组对象引用 - `null` 值:当字段值为 `null` 时直接返回 `null` - 静态字段:获取静态字段时传入 `null` 作为对象参数 ### 注意事项: 1. **类型转换风险**: ```java // 不安全的转换(可能导致ClassCastException) String badCast = (String) primitiveField.get(obj); // 安全做法 if (primitiveResult instanceof Integer) { int value = (Integer) primitiveResult; // 自动拆箱 } ``` 2. **性能考虑**: - 反射操作比直接访问慢 10-100 倍 - 频繁操作应考虑缓存 `Field` 对象 3. **封装破坏**: - 使用 `setAccessible(true)` 可以访问私有字段 - 违反封装原则,应谨慎使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值