反射获取对象成员的字段值,getFields()和getDeclaredFields()用法区别

本文介绍了使用Java反射机制获取内部类属性的过程及遇到的问题。通过对比getFields()和getDeclaredFields()的区别,解决了因属性访问级别导致无法获取的问题。

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

  用反射获取内部类的属性其实很简单。。我弄了半天才弄好,由于很弱智的原因啊,写此博文已吸取教训。
  虽简单,但是太坑爹了,getFields()只能获取public的字段,包括父类的。
  而getDeclaredFields()只能获取自己声明的各种字段,包括public,protected,private。
  而我写的Characters类中的属性是在继承父类的,父类中是protected的,所以获取不到,这个弄了我半天!最后只要把父类的protected属性全改成public的就ok了啊。。

  还有getFields()和getDeclaredFields(),返回的都是Field对象,获取名称直接field.getName(),但是属性值则是field.get(Object),这个object是该field所属的!!!

  太坑爹了,绕了好多弯啊!!!不过这样却对反射获得字段有了深刻的理解。
  具体代码如下:
/**
	 * 生成java实体类的核心方法
	 * @param clazz
	 * @param targetDir
	 * @throws Exception 
	 */
	private void genFileHandler(Class<?> clazz, String targetDir) throws Exception {
		/* 1,获取模板 */
		Template temp = configuration.getTemplate("testEntity.ftl", pageEncoding);
		temp.setEncoding(pageEncoding);
		
		/* 2,设置模板的数据内容Map */
		// 获取相关名称
		String entityName = getEntityName(clazz);
		String enumName = clazz.getSimpleName();
		String tableName = getTableName(clazz);
		
		// 填充Map
		Map<String, Object> targetClazz = new HashMap<String, Object>();
		Map<String, Map<String, String>> fields = new HashMap<String, Map<String, String>>();
		targetClazz.put("entityName", entityName);
		targetClazz.put("enumName", enumName);
		targetClazz.put("tableName", tableName);
		targetClazz.put("fields", fields);
		
		// 获得所有枚举字段成员(id, account, name, profession...),
		// 遍历每个枚举成员,获取属性,放入Map中
		Object[] enums = clazz.getEnumConstants();
		for (Object e : enums) {
			Map<String, String> field = new HashMap<String, String>();
			String name = e.toString();
			Class<?> type = (Class<?>) getFieldValue(clazz, e, "type");
			
			field.put("name", name);
			field.put("type", type.getSimpleName());
			fields.put(e.toString() + "field", field);
		}
		
		// 判断目标文件夹不存在,则新建文件夹
		File dir = new File(targetDir);
		if(!dir.exists())	dir.mkdirs();
		
		/* 3,将模板和数据合并,并生成文件 */
		String fileName = targetDir + entityName + ".java";
		System.out.println("-------开始生成" + fileName + "文件......------");
		
		File target = new File(fileName);
		Writer out = new OutputStreamWriter(new FileOutputStream(target), pageEncoding);
		temp.process(targetClazz, out);
		out.flush();
		out.close();

		System.out.println("-------" + fileName + "文件生成完毕!-------");
	}




还有其父类部分代码改过之后是:
public abstract class EntityConfCommon {
	public Class<?> type;
	public int length;
	public String index;
	public String defaults;
	public boolean isNull;

main方法是:
	public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, InstantiationException {
		Class<Character> c = Character.class;

		FreemarkerGenEntity generator = new FreemarkerGenEntity();
		generator.init();
		generator.genFile(c, "d:\\test\\");
		
	}

这样就没问题了!
### 使用Java反射机制获取类的成员变量 在Java中,通过`java.lang.reflect.Field`类可以访问并操作对象字段。为了获取特定实例中的字段,需先获得该字段对应的`Field`对象,再调用其`get(Object obj)`方法传入目标对象。 对于公共字段而言,可以直接利用`Class.getFields()`来检索所有可访问(即public修饰符定义)的字段列表[^1]: ```java // 获取Bird类的所有公共字段 Class<?> birdClass = Class.forName("com.chimo.reflection.Bird"); Field[] fields = birdClass.getFields(); for (Field field : fields) { System.out.println(field.getName()); } ``` 然而,在实际开发过程中更常见的是处理私有或其他非公开级别的字段。此时应采用`Class.getDeclaredFields()`代替,并设置字段为可访问状态以便读取或修改其[^3]: ```java import java.lang.reflect.Field; public class ReflectionExample { static class Point { private int x; private int y; public Point(int x, int y){ this.x=x; this.y=y; } } public static void main(String args[]) throws Exception{ // 创建Point实例 Object pointInstance = new Point(10, 20); // 获得Point.class Class<?> clazz = pointInstance.getClass(); // 遍历所有声明的字段 Field[] declaredFields = clazz.getDeclaredFields(); for(Field f : declaredFields){ // 设置字段为可访问 f.setAccessible(true); // 打印字段名及其对应于pointInstance上的 String fieldName = f.getName(); Object fieldValue = f.get(pointInstance); System.out.printf("%s field value: %s\n", fieldName, fieldValue.toString()); } } } ``` 上述代码展示了如何遍历指定类型的全部字段,并打印出给定对象上这些字段的具体数得注意的是,这里使用了`setAccessible(true)`绕过了Java的语言级安全性检查,允许程序访问即使是private修饰的成员变量[^4]。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值