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

Java原始类型案例中的显式类型转换,java,raw-types,Java,Raw Types,我正在读一本关于OOP模式和Java示例的书。。 本书中的类代码示例: public class Board { private int width, height; private List tiles; ... private void initialize() { tiles = new ArrayList(width); for (int i=0; i<width; i++) { tile

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

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);
    }

}
公共课程委员会{
私人int宽度、高度;
私人名单瓷砖;
...
私有void初始化(){
瓷砖=新阵列列表(宽度);

对于(inti=0;i这是在引入泛型之前较旧的Java代码,因此
List
接口返回
Object
,而不是所需的类型。用现代的说法,他们似乎想要类似于

private List<List<Tile>> tiles;
(我相信原始代码中的
Array
ArrayList
的打字错误)


好像你在读一本古书

为什么在所描述的两种方法中都使用显式类型转换


这是必要的,因为你正在处理

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


如果您利用ArrayList,则无需强制转换。

有两种方法可以声明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
List tiles=new ArrayList();
添加(新的Tile());
Tile Tile=tiles.get(0);
System.out.println(tile.x);//打印123

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

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

我想

tiles = new Array(width);
应该是

tiles = new ArrayList(width);
进一步

 ((ArrayList)tiles.get(i)).add(j, new Tile());
这里tiles.get(i)被类型化为ArrayList,因为tiles是一个列表,每个元素都有自己的ArrayList。(这是一个2D动态数组创建代码)

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

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

但是在这个例子中,我们甚至无法编译代码,因为一个例子说明了原始类型是多么不可靠,编译器在编译时就理解了这一点。我是说这个字符串:
((ArrayList)tiles.get(I)).add(j,new Tile());
-是一个简单的例子,可以说明问题。如果我们删除(ArrayList)和get
(tiles.get(i)).add(j,new Tile());
——为什么Java编译器必须相信我们在
(tiles.get(i))
中有一个列表或某个对象具有
add()
方法?!是的,不是必须的,他没有

为了进行检查,我们可以尝试在case List vars中使用原始类型编译简单的类似示例:

List listOfLists = new ArrayList();
listOfLists.add(0, new ArrayList());
(listOfLists.get(0)).add("something");  // compile error
但是,当我们在
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
List listofList=new ArrayList();//现在列表中只有列表的内部
添加(0,新的ArrayList());
(listOfLists.get(0)).add(“某物”);//无编译错误

编译器知道列表。get(0)
是一个列表,它有
add()
method.

这是必要的,因为您处理的是原始类型。如果您利用泛型,则不必强制转换。这就是为什么在2004年添加泛型以解决此类问题的原因。判断是否需要泛型的最佳方法是在不使用强制转换的情况下尝试此方法,并查看其是否有效。顺便说一句,我认为您正在阅读一篇非常古老的book.Java自从这个例子有意义以来已经发生了相当大的变化。@DawoodibnKareem ibn Kareem代码还没有完成。只是作为示例的部分。我无法检查。如果您想学习设计模式,我建议您使用O'Reilly.Middle!中的头优先设计模式。首先在您的示例(没有泛型)中添加tiles.add(new Tile())将某些特定类型转换为
tiles
!!为什么需要在这里转换它
Tile Tile=((Tile)tiles.get(0));
当您取回它时?!@mature这是一个好问题。这是因为列表(不使用通用标记)接受一个对象。对象是每个其他类的父类/超类。因此,当它存储在列表中时,它将被视为对象而不是平铺。这就是为什么在检索它时需要将其转换回平铺。使用列表时,在存储时强制该类型,并一直将其视为平铺。对不起,你是对的。我的输入错误在示例中。.
new ArrayList
是正确的。是的,你是对的,是我的打字错误。
new ArrayList
是正确的
((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