如何在Java中从泛型类型参数T获取静态MovementType值?
解决方案
方案一:反射读取RobotState子类的静态常量
这是最贴合需求的实现方式,无需额外传递参数,仅通过泛型类型自动推导:
- 在每个RobotState子类中定义公开静态常量:
public class TranslationState extends RobotState { public static final MovementType MOVEMENT_TYPE = MovementType.TRANSLATION; // 子类其他逻辑 } public class RotationState extends RobotState { public static final MovementType MOVEMENT_TYPE = MovementType.ROTATION; // 子类其他逻辑 }
- 修改Plan类构造方法,通过反射获取泛型参数对应的RobotState子类并读取静态常量:
public abstract class Plan<T extends RobotState> { protected MovementType movementType; protected Movement[] movements; public Plan(Movement... movements) { // 获取当前Plan子类的泛型父类信息 ParameterizedType superType = (ParameterizedType) getClass().getGenericSuperclass(); // 提取泛型参数T对应的Class对象 Class<T> stateClass = (Class<T>) superType.getActualTypeArguments()[0]; try { // 读取子类的MOVEMENT_TYPE静态字段 Field typeField = stateClass.getField("MOVEMENT_TYPE"); this.movementType = (MovementType) typeField.get(null); } catch (NoSuchFieldException | IllegalAccessException e) { throw new IllegalArgumentException("所有RobotState子类必须定义公开的MOVEMENT_TYPE静态常量", e); } this.movements = movements; } // 其他方法逻辑 }
ExamplePlan继承后,构造时会自动从TranslationState获取对应MovementType,无需额外代码。
方案二:运行时注解绑定类型关系
如果不想用静态常量,可以通过注解标记RobotState子类与MovementType的对应关系:
- 定义运行时注解:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface BindMovementType { MovementType value(); }
- 在RobotState子类上标注注解:
@BindMovementType(MovementType.TRANSLATION) public class TranslationState extends RobotState { // 子类其他逻辑 } @BindMovementType(MovementType.ROTATION) public class RotationState extends RobotState { // 子类其他逻辑 }
- 修改Plan构造方法读取注解:
public abstract class Plan<T extends RobotState> { protected MovementType movementType; protected Movement[] movements; public Plan(Movement... movements) { ParameterizedType superType = (ParameterizedType) getClass().getGenericSuperclass(); Class<T> stateClass = (Class<T>) superType.getActualTypeArguments()[0]; BindMovementType annotation = stateClass.getAnnotation(BindMovementType.class); if (annotation == null) { throw new IllegalArgumentException("所有RobotState子类必须标注@BindMovementType注解"); } this.movementType = annotation.value(); this.movements = movements; } // 其他方法逻辑 }
方案三:抽象方法+集中类型映射(无反射,更安全)
如果不想依赖反射,可以通过Plan子类实现抽象方法,结合集中管理的类型映射表避免代码冗余:
- 建立类型映射工具类:
public class RobotStateTypeMapper { private static final Map<Class<? extends RobotState>, MovementType> TYPE_MAP = new HashMap<>(); static { TYPE_MAP.put(TranslationState.class, MovementType.TRANSLATION); TYPE_MAP.put(RotationState.class, MovementType.ROTATION); } public static MovementType getMovementType(Class<? extends RobotState> stateClass) { MovementType type = TYPE_MAP.get(stateClass); if (type == null) { throw new IllegalArgumentException("未注册的RobotState类型: " + stateClass.getName()); } return type; } }
- 修改Plan类,定义抽象方法获取RobotState的Class:
public abstract class Plan<T extends RobotState> { protected MovementType movementType; protected Movement[] movements; public Plan(Movement... movements) { this.movementType = RobotStateTypeMapper.getMovementType(getStateClass()); this.movements = movements; } // 让子类返回对应的RobotState子类Class protected abstract Class<T> getStateClass(); // 其他方法逻辑 }
- 子类实现抽象方法:
public class ExamplePlan extends Plan<TranslationState> { @Override protected Class<TranslationState> getStateClass() { return TranslationState.class; } }
这种方式完全避免反射,类型映射集中管理,后续新增RobotState子类只需在TYPE_MAP中添加条目即可。
内容的提问来源于stack exchange,提问作者stephen cai
相关产品推荐
相关产品推荐

