Java中取得Bean的所有Field(包括SuperClass中的fields)

本文介绍如何使用Java反射API遍历类及其父类的所有字段,包括私有字段,并提供了一个具体的实现示例。
      前些日子在用Annotation的时候,发现了一个问题,就是使用下面的代码可以获取到当前类中的Fields,但是不能得到superclass中的fields。
Class类是Reflection API 中的核心类,它有以下方法
 getName():获得类的完整名字。
 getFields():获得类的public类型的属性。
 getDeclaredFields():获得类的所有属性。  这里应该是当前类的所有属性
 getMethods():获得类的public类型的方法。
 getDeclaredMethods():获得类的所有方法。
 getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
 getConstructors():获得类的public类型的构造方法。
 getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
 newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
java 代码
 
  1. package study;  
  2.   
  3. import java.lang.reflect.Field;  
  4.   
  5. public class MyBean extends BaseBean {  
  6.   
  7.     /** 
  8.      * @param args 
  9.      */  
  10.     public static void main(String[] args) {  
  11.         try {  
  12.             Class cls=Class.forName(MyBean.class.getName());  
  13.             Field[] fields=cls.getDeclaredFields();  
  14.             System.out.println("==================");  
  15.             for(Field f:fields){  
  16.                 System.out.println("field:"+f.getName());  
  17.             }  
  18.             System.out.println("==================");  
  19.         } catch (ClassNotFoundException e) {  
  20.             // TODO Auto-generated catch block  
  21.             e.printStackTrace();  
  22.         }  
  23.     }  
  24.   
  25.     private String porp1;  
  26.     private String prop2;  
  27.     private String prop3;  
  28.     public String getPorp1() {  
  29.         return porp1;  
  30.     }  
  31.     public void setPorp1(String porp1) {  
  32.         this.porp1 = porp1;  
  33.     }  
  34.     public String getProp2() {  
  35.         return prop2;  
  36.     }  
  37.     public void setProp2(String prop2) {  
  38.         this.prop2 = prop2;  
  39.     }  
  40.     public String getProp3() {  
  41.         return prop3;  
  42.     }  
  43.     public void setProp3(String prop3) {  
  44.         this.prop3 = prop3;  
  45.     }  
  46. }  
BaseBean的代码是:
java 代码
 
  1. package study;  
  2.   
  3. public class BaseBean {  
  4.     private int id;  
  5.     private String remark;  
  6.     public int getId() {  
  7.         return id;  
  8.     }  
  9.     public void setId(int id) {  
  10.         this.id = id;  
  11.     }  
  12.     public String getRemark() {  
  13.         return remark;  
  14.     }  
  15.     public void setRemark(String remark) {  
  16.         this.remark = remark;  
  17.     }  
  18. }  

运行的结果是:
java 代码
  1. ==================  
  2. field:porp1  
  3. field:prop2  
  4. field:prop3  
  5. ==================  
你会发现父类中的field id、remark 并没有打印出来。
怎么样得到他们呢?
首先将main函数改为如下:
java 代码
 
  1.     public static void main(String[] args) {
            try {
                Class cls = Class.forName(MyBean.class.getName());
                for (;!cls.equals(Object.class); cls = cls
                        .getSuperclass()) {
                    Field[] field = cls.getDeclaredFields();
                    for(Field f : field){
                        System.out.println(f.getName());
                    }
                }
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
运行结果:
java 代码
  1. porp1  
  2. prop2  
  3. prop3  
  4. id  
  5. remark  
最主要的一段代码就是这里
java 代码
 
  1. for (;!cls.equals(Object.class); cls = cls  
  2.                     .getSuperclass()) {  
  3.                 Field[] field = cls.getDeclaredFields();  
  4. ....................... 
  5. }
巧妙的运用了for循环语句。如果还有其它的条件要加进来的话,就写在!cls.equals(Object.class);这段里,比如
java 代码
 
  1. for (; field == null && !cls.equals(Object.class); cls = cls  
  2.                     .getSuperclass()) {  
  3. .......................  
  4. }  
package com.kucun.dto.validation; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import org.springframework.beans.factory.annotation.Autowired; import com.kucun.Service.DynamicRepositoryService; import com.kucun.entity.EntityBasis; /** * 实体唯一性验证器 * <p> * 用于验证实体字段的唯一性约束,支持单字段或多字段组合的唯一性验证。 * 可以处理关联对象字段,并在更新操作时排除当前实体。 * </p> * * @author KuCun System * @version 1.0 * @since 1.0 */ public class UniqueEntityValidator implements ConstraintValidator<UniqueEntity, Object> { @Autowired private DynamicRepositoryService repositoryService; @Autowired private EntityManager entityManager; /** 仓储名称 */ private String repositoryName; /** 需要验证唯一性的字段名数组 */ private String[] fields; /** * 初始化验证器 * * @param constraintAnnotation 唯一性约束注解 */ @Override public void initialize(UniqueEntity constraintAnnotation) { this.repositoryName = constraintAnnotation.repositoryName(); this.fields = constraintAnnotation.fields(); } /** * 验证实体的唯一性 * * @param entity 待验证的实体对象 * @param context 验证上下文 * @return true表示验证通过,false表示验证失败 */ @Override public boolean isValid(Object entity, ConstraintValidatorContext context) { if (entity == null) { return true; } try { Class<?> entityClass = entity.getClass(); Map<String, Object> fieldValues = new HashMap<>(); // 收集字段值(处理关联对象) for (String fieldName : fields) { Field field = getField(entityClass, fieldName); field.setAccessible(true); Object value = field.get(entity); if (value instanceof EntityBasis) { // 获取关联对象的ID Field idField = getField(value.getClass(), "id"); idField.setAccessible(true); fieldValues.put(fieldName, idField.get(value)); } else { fieldValues.put(fieldName, value); } } // 构建JPQL查询 StringBuilder jpql = new StringBuilder("SELECT COUNT(e) FROM ") .append(entityClass.getSimpleName()).append(" e WHERE "); int index = 0; for (String fieldName : fields) { if (fieldValues.get(fieldName) == null) { jpql.append("e.").append(fieldName).append(" IS NULL"); } else { jpql.append("e.").append(fieldName); // 处理关联字段的特殊情况 if (isAssociationField(entityClass, fieldName)) { jpql.append(".id = :").append(fieldName); } else { jpql.append(" = :").append(fieldName); } } if (++index < fields.length) { jpql.append(" AND "); } } // 排除自身(更新操作) Field idField = getField(entityClass, "id"); idField.setAccessible(true); Object idValue = idField.get(entity); if (idValue != null) { jpql.append(" AND e.id <> :id"); } // 执行查询 Query query = entityManager.createQuery(jpql.toString()); for (String fieldName : fields) { if (fieldValues.get(fieldName) != null) { query.setParameter(fieldName, fieldValues.get(fieldName)); } } if (idValue != null) { query.setParameter("id", idValue); } Long count = (Long) query.getSingleResult(); return count == 0; } catch (Exception e) { // 记录异常信息,在生产环境中应使用日志框架 e.printStackTrace(); return false; } } /** * 检查字段是否是关联字段 * * @param entityClass 实体类 * @param fieldName 字段名 * @return true表示是关联字段,false表示不是 * @throws NoSuchFieldException 当字段不存在时抛出 */ private boolean isAssociationField(Class<?> entityClass, String fieldName) throws NoSuchFieldException { Field field = getField(entityClass, fieldName); return EntityBasis.class.isAssignableFrom(field.getType()); } /** * 递归获取字段(包括父类) * * @param clazz 类对象 * @param fieldName 字段名 * @return 字段对象 * @throws NoSuchFieldException 当字段不存在时抛出 */ private Field getField(Class<?> clazz, String fieldName) throws NoSuchFieldException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { Class<?> superClass = clazz.getSuperclass(); if (superClass == null) { throw e; } return getField(superClass, fieldName); } } }------------------- : Request Parameters: {"requestBody":"{\"number\":\"7777776999\",\"xiadan\":\"2025-09-18\",\"jiaohuo\":\"\"}"} java.lang.NullPointerException: Cannot invoke "jakarta.persistence.EntityManager.createQuery(String)" because "this.entityManager" is null at com.kucun.dto.validation.UniqueEntityValidator.isValid(UniqueEntityValidator.java:120) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:180) at org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints(SimpleConstraintTree.java:66) at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:75) at org.hibernate.validator.internal.metadata.core.MetaConstraint.doValidateConstraint(MetaConstraint.java:130) at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:123) at org.hibernate.validator.internal.engine.ValidatorImpl.validateMetaConstraint(ValidatorImpl.java:555) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForSingleDefaultGroupElement(ValidatorImpl.java:518) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:488) at org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:450) at org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:400) at org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:172) at org.hibernate.boot.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:128) at org.hibernate.boot.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:81) at org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:186) at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:75) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:676) at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:291) at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:272) at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:322) at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:363) at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:277) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:140) at org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:314) at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:233) at org.hibernate.event.internal.DefaultMergeEventListener.merge(DefaultMergeEventListener.java:152) at org.hibernate.event.internal.DefaultMergeEventListener.doMerge(DefaultMergeEventListener.java:142) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:126) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:80) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:848) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:834) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:360) at jdk.proxy2/jdk.proxy2.$Proxy138.merge(Unknown Source) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:312) at jdk.proxy2/jdk.proxy2.$Proxy138.merge(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:621) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244) at jdk.proxy2/jdk.proxy2.$Proxy157.save(Unknown Source) at com.kucun.Service.AppService.addEntity(AppService.java:124) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:699) at com.kucun.Service.AppService$$SpringCGLIB$$0.addEntity(<generated>) at com.kucun.controller.AppController.handleEntityOperation(AppController.java:172) at com.kucun.controller.AppController.addEntity(AppController.java:104) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) at com.kucun.aspect.LoggingAspect.logAround(LoggingAspect.java:65) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:751) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703) at com.kucun.controller.AppController$$SpringCGLIB$$0.addEntity(<generated>) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAcce
最新发布
09-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值