Java中:如何合规获取BaseShape及比较无共同父类的同类型孙元素?
问题1解答
- 可以比较,这和父元素是否有共同类/超类无关。
- 孙元素本身是具体的类实例,直接针对孙元素的实例进行类型判断即可:
- 用
obj.getClass() == TargetClass.class判断是否为同一类(严格匹配,不包含子类) - 用
obj instanceof TargetClass判断是否属于该类或其子类
- 用
- 举例:即使
ParentA和ParentB没有共同超类(除了Object),只要它们的孙元素实例是同一个类的对象,就能通过上述方法完成类型比较。
问题2解答
针对你遇到的ShapeSelect场景,推荐以下几种符合SonarQube规范、无需冗长if的方案:
方案1:统一访问接口+适配器模式
通过适配器封装每个形状的访问逻辑,用统一接口抽象行为:
- 定义统一访问接口:
interface ShapeAccessor { boolean hasValidShape(ShapeSelect shapeSelect); BaseShape getBaseShape(ShapeSelect shapeSelect); }
- 为每个形状实现适配器:
class TriangleAccessor implements ShapeAccessor { @Override public boolean hasValidShape(ShapeSelect shapeSelect) { return shapeSelect.getTriangleObject() != null; } @Override public BaseShape getBaseShape(ShapeSelect shapeSelect) { return shapeSelect.getTriangleObject().getBaseShape(); } } // 同理实现SquareAccessor、PentagonAccessor等25个适配器类(IDE可自动生成模板代码)
- 遍历适配器列表获取结果:
private static final List<ShapeAccessor> SHAPE_ACCESSORS = Arrays.asList( new TriangleAccessor(), new SquareAccessor(), new PentagonAccessor() // 补充其他22个适配器 ); public BaseShape extractBaseShape(ShapeSelect shapeSelect) { return SHAPE_ACCESSORS.stream() .filter(accessor -> accessor.hasValidShape(shapeSelect)) .findFirst() .map(accessor -> accessor.getBaseShape(shapeSelect)) .orElseThrow(() -> new IllegalArgumentException("No valid shape found in ShapeSelect")); }
- 优势:类型安全,SonarQube无违规风险,新增形状只需添加适配器并更新列表,扩展性强。
方案2:封装判断逻辑到ShapeSelect(若有权限修改)
如果能修改ShapeSelect类,直接在内部封装获取BaseShape的逻辑:
public class ShapeSelect { // 原有字段、getter方法 public BaseShape getBaseShape() { if (triangleObject != null) return triangleObject.getBaseShape(); if (squareObject != null) return squareObject.getBaseShape(); if (pentagonObject != null) return pentagonObject.getBaseShape(); // 补充其他22个形状的判断 throw new IllegalArgumentException("No valid shape present"); } }
- 优势:实现最简单,外部调用仅需
shapeSelect.getBaseShape(),SonarQube不会判定违规(逻辑集中封装,而非分散在业务代码中的冗余判断)。 - 限制:必须有权限修改ShapeSelect类。
方案3:枚举映射方法引用
用枚举关联每个形状的getter和BaseShape提取逻辑:
- 定义枚举类:
enum ShapeType { TRIANGLE(ShapeSelect::getTriangleObject, obj -> ((TriangleObject) obj).getBaseShape()), SQUARE(ShapeSelect::getSquareObject, obj -> ((SquareObject) obj).getBaseShape()), PENTAGON(ShapeSelect::getPentagonObject, obj -> ((PentagonObject) obj).getBaseShape()); // 补充其他22个枚举项 private final Function<ShapeSelect, Object> shapeGetter; private final Function<Object, BaseShape> baseShapeExtractor; ShapeType(Function<ShapeSelect, Object> shapeGetter, Function<Object, BaseShape> baseShapeExtractor) { this.shapeGetter = shapeGetter; this.baseShapeExtractor = baseShapeExtractor; } public Optional<BaseShape> extract(ShapeSelect shapeSelect) { Object shape = shapeGetter.apply(shapeSelect); return shape != null ? Optional.of(baseShapeExtractor.apply(shape)) : Optional.empty(); } }
- 遍历枚举获取结果:
public BaseShape extractBaseShape(ShapeSelect shapeSelect) { return Arrays.stream(ShapeType.values()) .map(type -> type.extract(shapeSelect)) .filter(Optional::isPresent) .map(Optional::get) .findFirst() .orElseThrow(() -> new IllegalArgumentException("No valid shape found")); }
- 优势:无需额外适配器类,代码紧凑;需确保所有形状都有
getBaseShape()方法(用户已说明满足此条件)。
内容的提问来源于stack exchange,提问作者Wickerbough
相关产品推荐
相关产品推荐

