You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现可指定成员变量与对应值的setPartProperties方法?

Solution: Implementing Pair-Based Dynamic Property Setting for Java Abstract Class

Got it, let's work through this problem step by step. The main goals here are replacing that unsuitable Parameter type with a proper key-value pair structure, and using reflection to dynamically set your Part class's member variables without needing a HashMap. Here's how to do it:


Step 1: Create a Reusable Pair Class

First, we need a simple way to pass field-name and value pairs. We'll make a generic Pair class (either as a static inner class in Part or a top-level class) to hold these pairs. A static factory method will make the calling syntax clean, matching your desired (x, 100) style.

// Add this inside the Part class (or as a separate top-level class)
public static class Pair<K, V> {
    private final K key;
    private final V value;

    // Private constructor to enforce using the factory method
    private Pair(K key, V value) {
        this.key = key;
        this.value = value;
    }

    // Clean factory method for creating pairs
    public static <K, V> Pair<K, V> of(K key, V value) {
        return new Pair<>(key, value);
    }

    // Getters to access the key/value
    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

Step 2: Refactor the setPartProperties Method

Replace the Parameter... parameter with our Pair<String, Object>... (since field names are strings, and values can be any type matching your member variables). We'll use reflection to iterate over each pair and set the corresponding field:

public void setPartProperties(Pair<String, Object>... properties) {
    for (Pair<String, Object> property : properties) {
        String fieldName = property.getKey();
        Object value = property.getValue();

        try {
            // Get the field from the current class (supports subclasses too)
            Field field = this.getClass().getDeclaredField(fieldName);
            // Allow access to package-private fields like your x/y/width/etc.
            field.setAccessible(true);
            // Set the field value for this instance
            field.set(this, value);
        } catch (NoSuchFieldException e) {
            throw new IllegalArgumentException("Field '" + fieldName + "' doesn't exist in " + this.getClass().getSimpleName(), e);
        } catch (IllegalAccessException e) {
            throw new IllegalArgumentException("Can't access field '" + fieldName + "'", e);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("Value type doesn't match field '" + fieldName + "'", e);
        }
    }
}

Step 3: Update the Wheel Subclass Constructor

Now we can call the method with the clean Pair.of() syntax, which aligns with your desired input style:

public Wheel(double x, double y, double width, double height, double angle) {
    super(x, y, width, height, angle);
    // Pass key-value pairs using our Pair factory method
    setPartProperties(
        Pair.of("x", 100.0),
        Pair.of("y", 100.0),
        Pair.of("width", 50.0),
        Pair.of("height", 40.0),
        Pair.of("angle", 0.0)
    );
}

Full Modified Code

Updated Part Class

import com.sun.javafx.geom.Shape;
import javafx.scene.Group;
import java.lang.reflect.Field;

public abstract class Part {
    double x;
    double y;
    double width;
    double height;
    double angle;

    // Generic Pair class for key-value property pairs
    public static class Pair<K, V> {
        private final K key;
        private final V value;

        private Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public static <K, V> Pair<K, V> of(K key, V value) {
            return new Pair<>(key, value);
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }
    }

    public Part(double x, double y, double width, double height, double angle) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.angle = angle;
        Group group = new Group();
        group.getChildren().addAll();
    }

    abstract void createPart(Shape shape);
    abstract void addPart(Group group);

    public void setPartProperties(Pair<String, Object>... properties) {
        for (Pair<String, Object> property : properties) {
            String fieldName = property.getKey();
            Object value = property.getValue();

            try {
                Field field = this.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(this, value);
            } catch (NoSuchFieldException e) {
                throw new IllegalArgumentException("Field '" + fieldName + "' not found in " + getClass().getSimpleName(), e);
            } catch (IllegalAccessException e) {
                throw new IllegalArgumentException("Cannot access field '" + fieldName + "'", e);
            } catch (ClassCastException e) {
                throw new IllegalArgumentException("Value type mismatch for field '" + fieldName + "'", e);
            }
        }
    }
}

Updated Wheel Class

import com.sun.javafx.geom.Shape;
import javafx.scene.Group;

public class Wheel extends Part {
    public Wheel(double x, double y, double width, double height, double angle) {
        super(x, y, width, height, angle);
        setPartProperties(
            Pair.of("x", 100.0),
            Pair.of("y", 100.0),
            Pair.of("width", 50.0),
            Pair.of("height", 40.0),
            Pair.of("angle", 0.0)
        );
    }

    @Override
    public void createPart(Shape shape) {
        // Implement your JavaFX circle creation logic here
    }

    @Override
    public void addPart(Group group) {
        // Implement adding your shape to the group here
    }
}

Key Notes

  • Reflection Usage: We use reflection to dynamically access fields by name, which lets us modify any member variable without writing separate setters for each.
  • Error Handling: Wrapping reflection exceptions in IllegalArgumentException gives clear, actionable error messages if a field doesn't exist, can't be accessed, or the value type is wrong.
  • Clean Syntax: The Pair.of() method keeps the method call concise, just like your original desired (x, 100) format.

内容的提问来源于stack exchange,提问作者KNOB Personal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:11:47