在泛型类型“T”的对象之间进行投射以及泛型类型的对象“< T extends Comparable< T>>” [英] Casting between an object of generic type "T" and an object of generic type "<T extends Comparable<T>>"

查看:137
本文介绍了在泛型类型“T”的对象之间进行投射以及泛型类型的对象“< T extends Comparable< T>>”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过以下方式实现了一个ArrayLinearList类:

  public class ArrayLinearList< T>实现LinearList< T>,Iterable< T> 

其中包含类成员

  protected T []元素

为了扩展类我创建了一个继承自第一个类的新类

  class SuperList< T extends Comparable< T>>扩展ArrayLinearList< T> 

这里我确保类型T实现了Comparable接口(这是不能更改的)。



在SuperList类中,我有以下方法:

  public void替换(int pedro,T玛丽亚){
元素[pedro] =玛丽亚;

}



生成以下错误:

 线程main中的异常java.lang.ClassCastException:[Ljava.lang.Object;不能转换为[Ljava.lang.Comparable; 

但是,如果我按照以下方式声明该类,则不再存在此问题这种方式我不再能够比较类对象)

  class SuperList< T>扩展ArrayLinearList< T> {

我将不胜感激任何帮助解决此问题。我不允许修改类\ [ArrayLinearList,只是SuperList类。



预先感谢。

解决方案

基于异常,它看起来像是用 new object初始化元素 [someLength ] 并做一个未检查的转换为 T [] 。这可能发生在 ArrayLinearList 中。问题是,在这段代码中:

  element [pedro] = maria; 

元素被视为 Comparable [] 在运行时,并且一个 Object [] 不是 Comparable []

现在有很多与通用数组创建有关的文章,但是你的问题很有趣,因为你已经把继承放到了组合中(缩小一个类型参数的边界)。最好的解决方案似乎只与 ArrayLinearList 类中的元素进行交互。使它 private 并暴露getter和setter。这应该避免像这样的运行时失败(这需要避免在执行未经检查的转换(如(T [])new Object [someLength] )时)。



例如:

  public class ArrayLinearList< T>实现LinearList< T>,Iterable< T> {

private final T []元素;

public ArrayLinearList(final int length){
@SuppressWarnings(unchecked)//不会暴露在这个类之外
final T [] withNarrowedType =(T [ ])new Object [length];
elements = withNarrowedType;


public final void set(final int index,final T element){
elements [index] = element;
}
}

编辑:注意到你的免责声明我不允许修改类 ArrayLinearList 只是类 SuperList 。那很不幸,因为 ArrayLinearList 的作者写了类型不安全的代码。但是问题变成为什么像 SuperList.replace 这样的方法需要直接与数组交互(或根本不存在)。它看起来只是给指定索引分配一个新元素 - 是否没有 ArrayLinearList 方法可以用来做到这一点?



如果一切都失败了,这是最后一个解决方法:

 ((Object [])element)[pedro ] =玛丽亚; 

但这是一个很糟糕的解决方案,它可以解决潜在问题。


I've implemented an ArrayLinearList class on the following way

public class ArrayLinearList<T> implements LinearList<T>, Iterable<T>

which contains the class member

protected T[] element

In order to extend the functionality of the class I create a new class that inherits from the first one

class SuperList<T extends Comparable<T>> extends ArrayLinearList<T>

Here I ensure that the type T implements the Comparable interface (this cannot be changed).

In the SuperList class I have the following method

public void replace( int pedro, T maria ){
   element[ pedro ] = maria;

}

The line of the method generate the following error

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Comparable;

But if I declare the class on the following way I don't have this problem anymore (but in this way I'm no longer able to compare class objects)

class SuperList<T> extends ArrayLinearList<T>{

I would appreciate any help to solve this issue. I'm not allowed to modify the class \ [ ArrayLinearList, just the class SuperList.

Thanks in advance.

解决方案

Based on the exception, it looks like you're initializing element with new Object[someLength] and doing an unchecked cast to T[]. This is likely happening in ArrayLinearList. The problem is that in this code:

element[ pedro ] = maria;

element is treated as a Comparable[] at runtime, and an Object[] isn't a Comparable[].

There are many existing posts related to generic array creation, but your issue is interesting because you've thrown inheritance into the mix (with a narrowing of a type parameter's bounds). The best solution seems to be only interacting with element within the ArrayLinearList class. Make it private and expose getters and setters. This should avoid runtime failures like this (which take some thought to avoid when doing unchecked casts like (T[])new Object[someLength]).

For example:

public class ArrayLinearList<T> implements LinearList<T>, Iterable<T> {

    private final T[] elements;

    public ArrayLinearList(final int length) {
        @SuppressWarnings("unchecked") // won't be exposed outside this class
        final T[] withNarrowedType = (T[])new Object[length];
        elements = withNarrowedType;
    }

    public final void set(final int index, final T element) {
        elements[index] = element;
    }
}

EDIT: I just noticed your disclaimer "I'm not allowed to modify the class ArrayLinearList just the class SuperList." Well that's unfortunate, because the author of ArrayLinearList has written type-unsafe code. But the question becomes why a method like SuperList.replace needs to interact with the array directly (or exist at all). It looks like it's simply assigning a new element to the specified index - is there no ArrayLinearList method you can use to do that?

If all else fails, here's a last-ditch workaround:

((Object[])element)[pedro] = maria;

But that's an awful solution that duct-tapes over the underlying problem.

这篇关于在泛型类型“T”的对象之间进行投射以及泛型类型的对象“&lt; T extends Comparable&lt; T&gt;&gt;”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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