java - 在 Java 中创建泛型数组

标签 java arrays generics

所以我知道您不能“轻松地”在 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 ();
            }
        }
    }

最佳答案

您正在做的事情是安全的,因为您控制着未暴露的 map 。您可能应该将其设为私有(private)而不是 protected ,否则扩展类可能会错误地操作它。您可以通过转换为运行时检查来消除编译器警告,如下所示:

this.map = BaseCell[][].class.cast(Array.newInstance(BaseCell.class,
        new int[] { width, height }));

然后,如果在稍后的某个时间点,代码可能以编译器警告会掩盖的不兼容方式进行更改,它至少会在构建 map 时因运行时异常而提前中断.当然请记住,泛型只是在编译时被删除。

关于java - 在 Java 中创建泛型数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5428145/

相关文章:

java - 服务在 android 8 (oreo) 下意外停止

java - 如何抑制特定函数的 Java 编译器警告

swift - 在 Swift 中创建通用 Realm 存储库

java - 是否可以解决 "A generic array of T is created for a varargs parameter"编译器警告?

Java 泛型、类型删除、通配符和 Function<?...> 产生不兼容的类型

java - 是否可以将 `if` 语句转换为 `switch` 语句?

java - 数据输出流格式不正确

arrays - 在 Ruby 中创建数组

arrays - VBA - 获取数组中第n个最大值的索引

c - 如何在 C 中使用单个 malloc 分配三角数组?