在创建Java的泛型类型的数组 [英] Creating Arrays of Generic Types in Java

查看:102
本文介绍了在创建Java的泛型类型的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我知道你不能轻易创建Java的泛型类型的数组(但你可以创建集合)。我最近碰到地方,我需要的对象的2维数组(即是通用性)的情况下跑了。下面是什么它看起来像一个粗的想法(没有完成,但我想尽可能简短):

 类外< T> {
  私人美孚[] [] foo的;  抽象类Foo就继承了布拉赫< T> {
    公开名单< T> getContents();
  }  抽象类酒吧扩展美孚{
    ...
  }
}

因此​​,在code的地方,我需要一个数组作为这样的:

 富=新富[宽度] [高];

(我们知道这是不可能发生的)。不过,我想这样的:

 富=(富[] [])Array.newInstance(让Foo.class,新的INT [] {的getWidth()的getHeight()});

该编译器所接受,虽然我不得不燮preSS警告。我想我的问题是这会扼杀我在萌芽状态某处行?的成员foo被永远不会暴露在外部(虽然类型Foo和Bar是)。我知道这是丑陋的,但它肯定可行,救了我不必创建一些其他的psedu-杂牌的可能会导致类覆盖外类更多的麻烦。在此先感谢!


这可能使事情更容易显现

这是更接近什么我实际上做;当然意识到有很多支持方法和其他逻辑Map类里面,我已经离开了为简洁。

 进口java.lang.reflect.Array中;
    进口的java.util.ArrayList;
    进口的java.util.List;    接口电池< T> {
        公共无效添加(T T);
        公共布尔删除(T T);
        公开名单< T>得到所有 ();
        公共地图< T>的GetMap();
    }    类地图< T> {
        保护BaseCell地图[] [];        公共抽象类BaseCell实现电池< T> {
            私人列表< T>内容;            公共BaseCell(){
                this.contents =新的ArrayList< T> ();
            }            公共无效添加(T(T)){
                this.contents.add(T);
            }            公共布尔删除(T(T)){
                返回this.contents.remove(T);
            }            公开名单< T>得到所有 () {
                返回this.contents;
            }            公共地图< T>的GetMap(){
                返回Map.this;
            }            抽象的公共布尔测试();
        }        公共类SpecialCell扩展BaseCell {
            @覆盖
            公共布尔测试(){
                返回true;
            }
        }        公共类SpecialCell2扩展BaseCell {
            @覆盖
            公共布尔测试(){
                返回false;
            }
        }        @燮pressWarnings(未登记)
        公共地图(INT宽度,高度INT){
            this.map =(BaseCell [] [])Array.newInstance(BaseCell.class,新的INT [] {宽度,高度});
            对于(INT Y = 0; Y<高度; Y ++){
                为(中间体X = 0; X&下;宽度; X ++){
                    如果(的Math.random()&下; .5){
                        this.map [X] [Y] =新SpecialCell();
                    }其他{
                        this.map [X] [Y] =新SpecialCell2();
                    }
                }
            }
        }        公共BaseCell getCellAt(INT X,int y)对{
            返回this.map [X] [Y]
        }
    }    公共类垃圾{        / **
         * @参数ARGS
         * /
        公共静态无效的主要(字串[] args){
            类乘员{
            }            地图<乘员GT;地图=新地图<乘员GT; (50,50);
            map.getCellAt(10,10)。新增(新乘员());            map.getCellAt(10,10).getMap();            对于(INT Y = 0; Y< 50; Y ++){
                为(中间体X = 0; X&下; 50; X ++){
                    System.out.print(map.getCellAt(X,Y​​).TEST()1:0);
                }
                的System.out.println();
            }
        }
    }


解决方案

因为你控制未曝光的你在做什么是安全的地图。你或许应该将其变为私有,但并没有受到保护,否则扩展类可能会错误操作它。您可以通过铸造成一个运行时检查,这样就摆脱了编译器警告的:

  this.map = BaseCell [] []。class.cast(Array.newInstance(BaseCell.class,
        新的INT [] {宽度,高度}));

那么,如果在以后的某个点code以不兼容的方式改变了潜在的编译器警告会屏蔽掉,它会至少年初运行时异常你的地图。请当然记住泛型是在编译时简单地删除。

So I know that you cannot "easily" create an array of a generic type in Java (but you can create collections). I recently ran across a situation where I needed a 2 dimensional array of objects (that were Generic). Here's a "rough" idea of what it looked like (not complete but I'm trying to be as brief as possible):

class Outer<T> {
  private Foo[][] foo;

  abstract class Foo extends Blah<T> {
    public List<T> getContents ();
  }

  abstract class Bar extends Foo {
    ...
  }
}

So somewhere in the code I needed an array as such:

foo = new Foo[width][height];

(which we know can't happen). However, I tried this:

foo = (Foo[][])Array.newInstance (Foo.class, new int[]{getWidth (), getHeight ()});

which the compiler accepted though I had to suppress warnings. I guess my question is "Is this going to nip me in the bud somewhere down the line? The member "foo" is never exposed to the outside (though the types Foo and Bar are). I know it's ugly but it definitely works and saved me from having to create some other "psedu-kludge" the would probably have caused classes overriding the "Outer" class more headaches. Thanks in advance!


This might make things easier to visualize

This is closer to what I'm actually doing; realizing of course that there are many support methods and other logic inside of the Map class that I've left out for brevity.

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

解决方案

What you're doing is safe because you're controlling the unexposed map. You should probably make it private though and not protected, otherwise extending classes could incorrectly manipulate it. You can get rid of the compiler warning by casting into a runtime check, like this:

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

Then if at some later point the code is potentially changed in an incompatible way that the compiler warning would mask out, it'll at least break early with a runtime exception at the construction of your map. Keep in mind of course that Generics are simply erased at compile time.

这篇关于在创建Java的泛型类型的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆