我如何正确使用泛型类型的数组? [英] How do I use arrays of generic types correctly?

查看:214
本文介绍了我如何正确使用泛型类型的数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类将传入消息映射到基于消息类的匹配读取器。所有消息类型都实现接口消息。读卡器在映射程序类中注册,指出它将能够处理的消息类型。这些信息需要以某种方式存储在消息阅读器中,我的方法是从构造函数中设置 private final 数组。



现在,似乎我对泛型和/或数组有些误解,我似乎无法弄清楚,请参阅下面的代码。这是什么?

  public class HttpGetMessageReader实现IMessageReader {
//因为缺少类型参数而给出警告
//另外,我实际上想要比
//
// private final Class [] _rgAccepted;

//在这里工作,但在下面看到
private final Class< ;?扩展IMessage> [] _rgAccepted;

public HttpGetMessageReader()
{
//在这里工作,但在上面看到
// this._rgAccepted = new Class [1];

//给出错误无法创建Class的通用数组< ;? extends IMessage>
this._rgAccepted = new Class <?扩展IMessage> [1];

this._rgAccepted [0] = HttpGetMessage.class;
}
}

ETA
正如Cletus正确指出的那样,最基本的Google搜索表明Java不允许泛型数组。我明确地理解了这个例子(例如 E [] arr = new E [8] ,其中 E 是周围类的类型参数)。但为什么新的Class [n] 允许?那么,什么是正确的(或至少是普通的)方式来做到这一点? 解决方案

不允许通用数组。更多信息请参阅 Java泛型常见问题解答



要回答您的问题,只需使用列表(可能是 ArrayList a>)而不是数组。

更多解释可以在 Java理论与实践:泛型陷阱
$ b


泛型不是covariant



尽管您可能会发现
将集合看作是数组的
抽象,但它们有一些
特殊属性该集合做不
。 Java语言中的数组是
covariant - 这意味着如果
Integer扩展Number(它是
),那么不仅是 Integer
也是数字,但是 Integer []
也是 Number [] 传递或分配一个整数[] ,其中一个
Number [] 被调用。 (如果 Number 是超类型
Integer ,则<$ c $>正式地更多
,然后 Number [] 是一个
的超类型 Integer [] 。)你可能会认为同样是真的的通用
类型 - List< Number>
List< Integer>的超类型
,您可以传递列表<整数>
,其中a 列表< Number> 预计。
不幸的是,它不能用
的方式。

事实证明,
不起作用的一个很好的理由是方式:它会打破
类型安全泛型应该提供
。想象一下,您可以将一个
List< Integer> 分配给 List< Number>
然后下面的代码将允许
把一些不是
Integer 的东西放到 List< ;整数>

  List< Integer> li = new ArrayList< Integer>(); 
列表<号码> ln = li; //非法
ln.add(new Float(3.1415));

由于ln是 List< Number> ,将
a Float 添加到它似乎完全合法。
但是如果ln与li混淆,那么
会破坏类型安全承诺
,隐含在li -
的定义中,它是一个整数列表,
是为什么泛型不能是
协变。



I have a class that maps incoming messages to matching readers based on the message's class. All message types implement the interface message. A reader registers at the mapper class, stating which message types it will be able to handle. This information needs to be stored in the message reader in some way and my approach was to set a private final array from the constructor.

Now, it seems I have some misunderstanding about generics and / or arrays, that I can't seem to figure out, see the code below. What is it?

public class HttpGetMessageReader implements IMessageReader {
    // gives a warning because the type parameter is missing
    // also, I actually want to be more restrictive than that
    // 
    // private final Class[] _rgAccepted;

    // works here, but see below
    private final Class<? extends IMessage>[] _rgAccepted;

    public HttpGetMessageReader()
    {
        // works here, but see above
        // this._rgAccepted = new Class[1];

        // gives the error "Can't create a generic array of Class<? extends IMessage>"
        this._rgAccepted = new Class<? extends IMessage>[1];

        this._rgAccepted[0] = HttpGetMessage.class;
    }
}

ETA: As cletus correctly pointed out, the most basic googling shows that Java does not permit generic arrays. I definitely understand this for the examples given (like E[] arr = new E[8], where E is a type parameter of the surrounding class). But why is new Class[n] allowed? And what then is the "proper" (or at least, common) way to do this?

解决方案

Java does not permit generic arrays. More information in the Java Generics FAQ.

To answer your question, just use a List (probably ArrayList) instead of an array.

Some more explanation can be found in Java theory and practice: Generics gotchas:

Generics are not covariant

While you might find it helpful to think of collections as being an abstraction of arrays, they have some special properties that collections do not. Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List<Number> is a supertype of List<Integer>, and that you can pass a List<Integer> where a List<Number> is expected. Unfortunately, it doesn't work that way.

It turns out there's a good reason it doesn't work that way: It would break the type safety generics were supposed to provide. Imagine you could assign a List<Integer> to a List<Number>. Then the following code would allow you to put something that wasn't an Integer into a List<Integer>:

List<Integer> li = new ArrayList<Integer>();
List<Number> ln = li; // illegal
ln.add(new Float(3.1415));

Because ln is a List<Number>, adding a Float to it seems perfectly legal. But if ln were aliased with li, then it would break the type-safety promise implicit in the definition of li -- that it is a list of integers, which is why generic types cannot be covariant.

这篇关于我如何正确使用泛型类型的数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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