I have a class called Piece, and many many subclasses of Piece. I want to add an instance of every single subclass of Piece (under the pieces package) to my JTree. Currently, I have this class with a huge function (well, 57 lines, but still) that increases in size every time I add functionality to my program. My initial approach to this was Hey, let's just use reflection or something to find out all of the classes under the package pieces and add them to the tree! but this SO question shot that down. My second, working approach is to add them all manually by hand. This seems like too much work though and it seems like there would be a better way to do this.As always, miscellaneous comments on my code are very welcome.initTree() private void initTree(final UserInterface userInterface) {    tree = new JTree(createTree());    tree.setRootVisible(false);    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);    tree.addTreeSelectionListener(new TreeSelectionListener(){        @Override        public void valueChanged(TreeSelectionEvent e) {             DefaultMutableTreeNode node = (DefaultMutableTreeNode)                       tree.getLastSelectedPathComponent();             if (node == null){                 return;             }             if (node.isLeaf() && node.getUserObject() instanceof Piece) {                 Piece pieceCreated = (Piece) ((Piece)node.getUserObject()).getInstance();                 userInterface.space.addPiece(pieceCreated);             }        }    });    add( new JScrollPane(tree), BorderLayout.CENTER );}createTree()private DefaultMutableTreeNode createTree(){    //create the root node    DefaultMutableTreeNode root = new DefaultMutableTreeNode(Root);    //create the child nodes    DefaultMutableTreeNode gatesNode = new DefaultMutableTreeNode(Gates);        DefaultMutableTreeNode arithmeticNode = new DefaultMutableTreeNode(Arithmetic);        arithmeticNode.add(new DefaultMutableTreeNode(new Add(0,0)));        arithmeticNode.add(new DefaultMutableTreeNode(new Subtract(0,0)));        arithmeticNode.add(new DefaultMutableTreeNode(new Multiply(0,0)));        arithmeticNode.add(new DefaultMutableTreeNode(new Divide(0,0)));        arithmeticNode.add(new DefaultMutableTreeNode(new Modulo(0,0)));        arithmeticNode.add(new DefaultMutableTreeNode(new Random(0,0)));        gatesNode.add(arithmeticNode);        DefaultMutableTreeNode bitwiseNode = new DefaultMutableTreeNode(Bitwise);        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseAnd(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNand(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNor(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseNot(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseOr(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseXor(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseXnor(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseLeftshift(0,0)));        bitwiseNode.add(new DefaultMutableTreeNode(new BitwiseRightshift(0,0)));        gatesNode.add(bitwiseNode);        //etc with more subclasses of Piece    return root;}Piece.javapublic abstract class Piece implements Serializable{    private static final long serialVersionUID = 2022414861350098747L;    private static final Color BACKGROUND_COLOR = new Color(200,200,200);    static final BasicStroke PORT_STROKE = new BasicStroke(1);    protected int x, y, width, height;    protected Input input;    protected Output output;    public Piece(int x, int y, int width, int height, int inputs, int outputs){       this.x = x;       this.y = y;       this.width = width;       this.height = height;       this.input = new Input(inputs, this);       this.output = new Output(outputs, this);    }    public abstract void draw(Graphics2D g);    public void drawBackground(Graphics2D g){        g.setColor(BACKGROUND_COLOR);        g.fillRoundRect(x, y, width, height,10,10);        input.draw(g);        output.draw(g);    }    public void drawConnections(Graphics2D g){        output.drawConnections(g);    }    public void connect(Piece other, int outputPort, int inputPort){        output.connect(other, outputPort, inputPort);        update();    }    public void disconnect(final int outputPort){        output.disconnect(outputPort);        update();    }    public void update(){        output.update();    }    public abstract Value send(int outputPort);    public abstract void recieve(int inputPort, Value v);    public abstract void doubleClicked();    public abstract Piece getInstance();    public String toString(){        return this.getClass().getSimpleName();    }    public void setPosition(final Point point) {        x = point.x;        y = point.y;    }    public boolean contains(final Point p){        return  x < p.getX() &&                 y < p.getY() &&                x + width > p.getX()  &&                y + height > p.getY();    }    public Integer getOutputPortFromPoint(final Point p){        if(output.contains(p)){            if(output.getConnections().length == 0)                return null;            return output.getOuputFromY(p.y);        }        return null;    }    public Integer getInputPortFromPoint(final Point p){        if(input.contains(p)){            if(input.getConnections().length == 0){                return null;            }            return input.getInputFromY(p.y);        }        return null;    }    public int getX() {        return x;    }    public int getY() {        return y;    }    public int getWidth(){        return width;    }    public int getHeight(){        return height;    }    public Point getPointFromOutputPort(int portSelected) {        return output.getPointFromPort(portSelected);    }}Add.java (Example subclass of Piece)public class Add extends Piece{    private static final long serialVersionUID = -1786155220275379870L;    //v1 + v2 = v    private ValueInteger param1;    private ValueInteger param2;    private ValueInteger result;    private Title title;    public Add(int x, int y) {        super(x,y,150,75, 2, 1);        title = new Title(Add, this);        param1 = new ValueInteger(0);        result = new ValueInteger(0);        param2 = new ValueInteger(0);    }    @Override    public void draw(Graphics2D g) {        drawBackground(g);        title.draw(g);        g.setColor(Color.BLUE);        if(result != null)            g.drawString(result.toString(), x + 10, y + 20);    }    @Override    public Value send(int outputPort) {        return result;    }    @Override    public void recieve(int inputPort, Value v) {        if(inputPort == 0)            param1 = (ValueInteger) v;        else if (inputPort == 1)            param2 = (ValueInteger) v;        this.result = new ValueInteger(param1.add(param2));    }    @Override    public void doubleClicked() {        // TODO Auto-generated method stub    }    @Override    public Piece getInstance() {        return new Add(10,10);    }}
Initializing JTree
java;tree;inheritance;reflection
public enum PieceGroups{    BITWISE(BitwiseAnd.class, BitwiseNand.class, BitwiseNor.class, BitwiseNot.class,            BitwiseOr.class, BitwiseXor.class, BitwiseXnor.class, BitwiseLeftshift.class,            BitwiseRightshift.class),    ARITHMETIC(Add.class, Substract.class, Multiply.class, Divide.class, Modulo.class, Random.class);    private Set<Piece> classSet = new HashSet<Piece>();    private PieceGroups(Class... classes) {        for (Class theClass : classes) {            try {                Constructor construtor = theClass.getDeclaredConstructor(int.class, int.class);                classSet.add((Piece) construtor.newInstance(0, 0));            } catch (NoSuchMethodException ex) {                processException();            } catch (SecurityException ex) {                processException();            } catch (InstantiationException ex) {                processException();            } catch (IllegalAccessException ex) {                processException();            } catch (IllegalArgumentException ex) {                processException();            } catch (InvocationTargetException ex) {                 processException();            }        }    }    public Set<Piece> getClasses () {        return classSet;    }    private void processException () {        throw new IllegalArgumentException(Something went wrong with the init of the Enum);    }}Explication :We create an enum, still the best singleton what there is.Then the states of the enum are grouping where the Piece (sub)class can have, like the Bitwise and Arithmetic you showed.Constructor of the enum is vararg, so you can give up as many classes as you want with one group.We create an instance of the class in the constructor with reflection.At the moment I saw that all your classes have an constructor with 2 ints, so I rely that is for all the implementations of like that.An IllegalArgumentException is thrown when your enum can't be created by an fault (class not found, constructor not present,...)You can also just skip that class at instanciation but then you never know when something went wrong.At last, just ask PieceGroups.BITWISE.getClasses() and you will have a set of the corresponding group.