Java原始类型案例中的显式类型转换

时间:2018-12-13 19:12:18

标签: java raw-types

我正在阅读一本有关带有Java示例的OOP模式的书。 书中的类代码示例:

public class Board {

    private int width, height;
    private List tiles;

    ...

    private void initialize() {
        tiles = new ArrayList(width);
        for (int i=0; i<width; i++) {
            tiles.add(i, new ArrayList(height));
            for (int j=0; j<height; j++) {
                ((ArrayList)tiles.get(i)).add(j, new Tile());
            }
        }
    }

    public Tile getTile(int x, int y) {
        return (Tile)((ArrayList)tiles.get(x-1)).get(y-1);
    }

}

问题:

为什么在上述两种方法中都使用了显式类型转换?第一种情况是在第((ArrayList)tiles.get(i)).add(j, new Tile());行中使用 ArrayList ,第二种情况是在return (Tile)((ArrayList)tiles.get(x-1)).get(y-1);行中使用 Tile 。我的意思是,这是脚本作者的观点还是在Java情况下必需的?

5 个答案:

答案 0 :(得分:3)

这是较早的Java代码,在引入泛型之前,因此List接口返回Object而不是所需的类型。用现代的话来说,他们似乎想要

private List<List<Tile>> tiles;

然后initialize(假设我没有打错字)可能像这样:

private void initialize() {
    tiles = new ArrayList<>(width);
    for (int i=0; i<width; i++) {
        tiles.add(i, new ArrayList<>(height));
        for (int j=0; j<height; j++) {
            tiles.get(i)).add(j, new Tile();
        }
    }
}

(我相信原始代码中的ArrayArrayList的错字)

public Tile getTile(int x, int y) {
    return tiles.get(x-1).get(y-1);
}

答案 1 :(得分:1)

好像您正在读一本古籍

  

为什么在上述两种方法中都使用了显式类型转换?

这是必需的,因为您正在处理raw types

  

我的意思是,这是脚本作者的观点还是在Java情况下必需的?

如果您使用generics,则无需投射。

答案 2 :(得分:1)

有两种方法来声明ArrayList。

为使示例更简单,我创建了以下虚拟类

public class Tile {
    int x = 123;
}

您在问题中描述的第一种较旧的方式可能写为

List tiles = new ArrayList();
tiles.add(new Tile());

Tile tile = ((Tile)tiles.get(0));
System.out.println(tile.x); // prints 123

使用泛型可以完成相同的事情。

List<Tile> tiles = new ArrayList<>();
tiles.add(new Tile());

Tile tile = tiles.get(0);
System.out.println(tile.x); // prints 123

使用泛型时,不需要使用强制转换,这是使用列表的首选方式。

答案 3 :(得分:1)

我尝试测试您的代码。我不确定您指定的代码是否完全正确。

我认为

tiles = new Array(width);

应该是

tiles = new ArrayList(width);

更多

 ((ArrayList)tiles.get(i)).add(j, new Tile());

在此处tiles.get(i)被类型转换为ArrayList,因为tiles是一个List,每个元素都拥有自己的ArrayList。 (这是2D动态数组创建代码)

当前tiles.get(i)返回一个Object类型。必须将其类型转换为ArrayList才能使用方法“ add” 在下面类似,对象被类型转换为ArrayList 以使用方法“ get”

答案 4 :(得分:0)

Java是强类型语言。大多数\所有类型错误必须在编译时获得。在泛型之前,您无法控制List中存储的类型。在这种情况下(原始类型),推迟的类型检查将进入运行时。然后最好先将任何原始类型转换为具体类型,以避免运行时错误。

但是在此示例中,我们甚至无法编译代码,因为一个示例说明了Raw类型可能是多么不可靠,并且编译器在编译时就理解了这一点。我的意思是这个字符串:mtcars-是一个不言自明的简单案例。如果我们删除(ArrayList)并得到ggplot(mtcars_plot, aes(x = wt, y = mpg)) + geom_point() + geom_smooth(aes(), method=lm, se=F, fullrange=TRUE) + geom_ribbon(aes(ymin = Low, ymax = High, fill = group), alpha = .25) + labs(fill = "Weight Class") + scale_fill_manual(values = c("red", "orange"), name = "fill") -为什么Java编译器必须相信我们,在((ArrayList)tiles.get(i)).add(j, new Tile());中,我们有一个List或一些带有(tiles.get(i)).add(j, new Tile());方法?是的,不是必须的,他不是。

要进行检查,我们可以尝试使用原始类型编译简单的类似示例,以防List变量:

(tiles.get(i))

但是,当我们说到add()中有关确切类型的编译器时,一切都会好的:

List listOfLists = new ArrayList();
listOfLists.add(0, new ArrayList());
(listOfLists.get(0)).add("something");  // compile error

泛型可以更准确地解决此问题。他们严格固定List变量的类型:

listOfLists.get(0)

编译器知道((ArrayList)listOfLists.get(0)).add("something"); // NO compile error 是一个列表,并且具有List<List> listOfLists = new ArrayList<List>(); // now List only have List's inside listOfLists.add(0, new ArrayList()); (listOfLists.get(0)).add("something"); // NO compile error 方法。