【发布时间】:2011-07-22 15:19:07
【问题描述】:
所以我知道您不能“轻松”在 Java 中创建泛型类型的数组(但您可以创建集合)。我最近遇到了一种情况,我需要一个二维对象数组(即通用)。这是一个“粗略”的想法(不完整,但我试图尽可能简短):
class Outer<T> {
private Foo[][] foo;
abstract class Foo extends Blah<T> {
public List<T> getContents ();
}
abstract class Bar extends Foo {
...
}
}
所以在代码的某个地方我需要一个这样的数组:
foo = new Foo[width][height];
(我们知道这不可能发生)。但是,我尝试了这个:
foo = (Foo[][])Array.newInstance (Foo.class, new int[]{getWidth (), getHeight ()});
尽管我不得不禁止警告,但编译器接受了它。我想我的问题是“这会不会把我扼杀在萌芽状态?成员“foo”从不暴露在外面(尽管 Foo 和 Bar 类型是)。我知道它很丑,但它确实有效并且使我不必创建一些其他“psedu-kludge”,这可能会导致覆盖“外部”类的类更加头痛。提前致谢!
这可能会使事情更容易可视化
这更接近于我实际在做的事情;当然要意识到 Map 类内部有许多支持方法和其他逻辑,我为了简洁而省略了。
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
interface Cell<T> {
public void add (T t);
public boolean remove (T t);
public List<T> getAll ();
public Map<T> getMap ();
}
class Map<T> {
protected BaseCell map[][];
public abstract class BaseCell implements Cell<T> {
private List<T> contents;
public BaseCell () {
this.contents = new ArrayList<T> ();
}
public void add (T t) {
this.contents.add (t);
}
public boolean remove (T t) {
return this.contents.remove (t);
}
public List<T> getAll () {
return this.contents;
}
public Map<T> getMap () {
return Map.this;
}
abstract public boolean test ();
}
public class SpecialCell extends BaseCell {
@Override
public boolean test() {
return true;
}
}
public class SpecialCell2 extends BaseCell {
@Override
public boolean test() {
return false;
}
}
@SuppressWarnings("unchecked")
public Map (int width, int height) {
this.map = (BaseCell[][])Array.newInstance(BaseCell.class, new int[] {width, height});
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (Math.random() < .5) {
this.map[x][y] = new SpecialCell ();
} else {
this.map[x][y] = new SpecialCell2 ();
}
}
}
}
public BaseCell getCellAt (int x, int y) {
return this.map[x][y];
}
}
public class Junk {
/**
* @param args
*/
public static void main(String[] args) {
class Occupant {
}
Map<Occupant> map = new Map<Occupant> (50, 50);
map.getCellAt(10, 10).add(new Occupant ());
map.getCellAt(10, 10).getMap ();
for (int y = 0; y < 50; y++) {
for (int x = 0; x < 50; x++) {
System.out.print (map.getCellAt (x, y).test () ? "1" : "0");
}
System.out.println ();
}
}
}
【问题讨论】:
-
你为什么不能
new Foo[width][height]?你不能这样做new T[width][height] -
我认为这与外部类是通用的(而不是内部类)有很大关系。但我可能是错的。我得写个测试看看。
-
确实,是的。事实上,外部类是通用的,这阻止了只做新的 Foo[width][height]。我也许可以重构 Foo 使其不必是内部类,但它会出现问题并且可能会消耗更多内存。
-
为什么不能用obj.width、obj.height定义一个新的对象,然后把obj的数组或者链表拼起来?你知道什么是链接列表吗?
-
我当然知道链表是什么,但是与简单的二维数组相比,这样做的开销有点过大。我试图想出一个与我正在做的事情更相关的更好的例子(一个 2D 单元格地图,其中单元格可以包含对象列表)。我将更新我的问题以显示“更好”的示例。