Java Generics:如何避免在这个java 2D泛型数组的例子中进行转换?

时间:2017-11-30 01:08:59

标签: java generics

我正在为一块电路板建模,我想尽可能地使它变得通用,我也想不惜一切代价避免投射,因为它是一种不好的做法!

此外,我的代码现在完全正常工作,但我知道,一旦我开始使用Cell类并扩展它,它就会出现问题!

Cell.java

public class Cell<T> {
    private t value;

    public Cell(T value) {
        this.value = value;
    }

    // setters and getters
}

Board.java

import java.lang.reflect.Array;

public abstract class Board<T, E extends Cell<T>> {
    protected E[][] cells;

    protected Board(Class<? extends E> c) {
        cells = (E[][])Array.newInstance(c, 6, 7);
    }

    protected void resetBoard(T resteVal) {
        for (int i = 0; i < cells.length; i++)
            for (int j = 0; j < cells[i].length; j++)
                cells[i][j]= (E) new Cell<T>(); //HERE IS THE QUESTION
    }
}

Game.java

public interface Game {
    boolean islegalMove();
    boolean isWin();
    void move();
    void resetGame();
    void getScore();
}

Connect4.java

public class Connect4<E extends Cell<Integer>> extends Board<Integer,E> implements Game {
    public Connect4(Class<? extends E> c) {
        super(c);
    }

    // override methods
}

2 个答案:

答案 0 :(得分:1)

将此protected E[][] cells;替换为protected Cell<T>[][] cells;

public abstract class Board<T, E extends Cell<T>> {
    protected Cell<T>[][] cells;
    @SuppressWarnings("unchecked")
    public Board(Class<? extends E> c) {
        cells = (E[][])Array.newInstance(c, 6, 7);
    }

    protected void resetBoard(T resteVal) {
        for (int i = 0; i < cells.length; i++) {
            for (int j = 0; j < cells[i].length; j++) {
                Cell<T> cell =  new Cell<T>();
                cell.setValue(resteVal);
                cells[i][j] = cell; //HERE IS MY REPLACEMENT
            }
        }
    }
}

答案 1 :(得分:1)

我认为问题出在架构上。

您已定义Board类(例如,它可以是可扩展的)。

然后定义一个抽象Cell,它可以使用自定义public abstract class Board<T, E extends Cell<T>> { // why do not use T[][] cells instead? protected final E[][] cells; protected Board(E[][] cells) { this.cells = cells; } // we hole Cell instances inside this class, so no need to create new ones protected void resetBoard(T resetVal) { for (int i = 0; i < cells.length; i++) for (int j = 0; j < cells[i].length; j++) cells[i][j].setValue(resetVal); } }

public final class MagicBoard<T> extends Board<T, MagicBoard.MagicCell<T>> {

    public MagicBoard(Supplier<MagicCell<T>> supplier) {
        //noinspection rawtypes,unchecked
        super(new MagicCell[6][7]);
    }

    public static final class MagicCell<T> extends Cell<T> { }
}

最后,我们可以使用具体的单元格实例来打击具体主板

Board

恢复:

  1. 抽象类Supplier不应该关于具体的单元格实例创建。最大值,它可以接受来自子类的Cell将此工作委托给具体的类'MagicBoard'(只有这个类知道应该创建什么类型的Cell。)

  2. 尽量避免无用的Board实例创建。如果您将其保留在Cell内并且不在其外部共享,则重复使用它。只需重置该值。

  3. 问题!我不知道整个代码,但如果您的Cell只包含一个值,则可以避免使用protected final T[][] cells;并使用{{1}相反(我认为,Board应包含使用Cell的所有逻辑,但单元本身不应该非常聪明 - 只需保持简单的值)。但这只是我的意见。