数组返回可以用于赋值,但不能在循环中使用

我我

当我遇到一个小谜团时,我正在发布另一个问题的答案类定义(从原始提问者中稍作修改)在这里:

public class Playground<T>{
    private int pos;
    private final int size;
    private T[] arrayOfItems;
    public Playground(int size){
        this.size = size;
        pos = 0;
        arrayOfItems = (T[]) new Object[size];
    }

    public void addItem(T item) {
        arrayOfItems[pos] = item;
        pos++;
    }

    public void displayItems() {
        for(int i = 0;i<pos;i++){
            System.out.println(arrayOfItems[i]);
        }
    }

    public T[] returnItems() { 
        return (T[]) arrayOfItems;
    }
}

首先,我们创建一个新的Playground,Playground<String> animals = new Playground<String>(5);并在其中放入一些动物弦。(狗,猫等)。

神秘之处在于:

Object[] s = animals.returnItems();
for(int i=0; i < s.length; i++) {
        System.out.println(s[i]);
}

但这会ClassCastException 在for循环声明中创建一个

for(int i=0; i < animals.returnItems().length; i++) {
        System.out.println(animals.returnItems()[i]);
}

两个Object[]S和String[]■找长度变量。为什么在循环声明中使用accessor方法会导致异常?

格特曼

之所以ClassCastException不能-强制转换Object[]String[]-是由于编译器在使用泛型时所做的事情。调用时returnItems(),编译器将强制类型转换为String[],因为会returnItems返回T[]编译时的类型擦除表示它返回Object[],但既然TString这里,编译器就会将强制转换插入String[]但是原始对象arrayOfItems不是String[],而是Object[],因此转换失败。

这应该导致在编译过程中产生一个“ unchecked cast”警告,从Object[]T[]

相反,您需要遵循如何在Java中创建通用数组中的建议在创建通用数组时。

Class<T>在构造函数中接受一个,这样您就可以从一开始就调用Array.newInstance并获取一个T[]

@SuppressWarnings("unchecked")  // This suppression is safe.
public Playground(int size, Class<T> clazz){
    this.size = size;
    pos = 0;
    arrayOfItems = (T[]) Array.newInstance(clazz, size);
}

然后,您可以animals通过String.class以下方式创建

Playground<String> animals = new Playground<String>(5, String.class);

更新

以下是Object[]当第二个示例不起作用(length直接在方法的返回类型上访问字段)时为什么第一个示例起作用(分配给的合理解释returnItems()

第一个例子

Object[] s = animals.returnItems();
for(int i=0; i < s.length;i++) {
        System.out.println(s[i]);
}

JLS,第5.2节,描述了“作业上下文”支配从分配给一个变量的表达式的值时会发生什么。

分配上下文中的转换可能引起的唯一例外是:

  • 如果在应用了上述转换之后,结果值是一个对象,它不是变量类型的Erase(第4.6节)的子类或子接口的实例,则为ClassCastException。

这种情况只能由堆污染引起(第4.12.2节)。实际上,当字段的擦除类型或方法的返回类型与未擦除类型不同时,实现仅在访问参数化类型的对象的字段或方法时执行强制转换。

...

编译器无需在String[]此处插入强制类型转换length以后访问字段时,该变量已经是type Object[],因此这里没有问题。

第二个例子

for(int i=0; i < animals.returnItems().length;i++) {
    System.out.println(animals.returnItems()[i]);
}

ClassCastException这里似乎不是依赖于for循环; 只需简单打印长度,就会出现此错误:

System.out.println(animals.returnItems().length);

这是一个字段访问表达式,在JLS第15.11.1节中介绍

标识符以类型T命名一个可访问的成员字段,并且字段访问表达式的类型是捕获转换后的成员字段的类型(第5.1.10节)。

捕获转换将类型捕获为String[]编译器String[]出于与方法调用插入转换相同的原因,必须将转换插入到此处-字段或方法只能存在于捕获的类型上。

因为的类型arrayOfItems为true Object[],所以强制转换失败。

如上所述,创建通用数组可以Array.newInstance解决此问题,因为String[]正在创建实际数组进行此更改后,插入的演员表仍然存在,但是这次成功了。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么Python中的函数可以在封闭范围内打印变量,但不能在赋值中使用它们?

来自分类Dev

为什么不能在多个foreach循环中使用数组?

来自分类Dev

HTML 可以在 Fiddle 中使用,但不能在本地使用

来自分类Dev

不能在嵌套的for循环中使用特定变量?

来自分类Dev

不能在嵌套的for循环中使用特定变量?

来自分类Dev

不能在循环中使用 FormData.append 吗?

来自分类Dev

为什么我可以在for循环中多次重定义相同的变量,但不能在循环之外?

来自分类Dev

我的Flatten数组方法可以在控制台中使用,但不能在Codewars中使用?

来自分类Dev

可以在结构中返回两个数组,但不能在类 C++ 中返回

来自分类Dev

JavaScript函数有效..但不能在for循环中

来自分类Dev

使用DOMParser解析XML可以在Chrome中使用,但不能在FF中使用

来自分类Dev

$ .ajax帖子可以在Chrome中使用,但不能在Firefox中使用

来自分类Dev

Facebook登录可以在Chrome中使用,但不能在Firefox中使用

来自分类Dev

我的脚本可以在jsFiddle中使用,但不能在我的网页中使用

来自分类Dev

Cookie可以在Chrome中使用,但不能在IE或Safari中使用?

来自分类Dev

jQuery可以在jsFiddle中使用,但不能在Drupal中使用

来自分类Dev

代码可以在jsfiddle中使用,但不能在浏览器中使用

来自分类Dev

可以在Bash中使用,但不能在ZSH中使用?....别名ls ='ls -lh'

来自分类Dev

命令可以在命令行中使用,但不能在Shell脚本中使用

来自分类Dev

字体可以在IE中使用,但不能在Firefox或Chrome中使用

来自分类Dev

插件可以在Linux Unity Editor中使用,但不能在独立的Linux版本中使用

来自分类Dev

查询可以直接在MySQL中使用,也可以在PHP中使用mysqli,但不能在PDO中使用

来自分类Dev

在onclick之后使用.val可以在模拟器中使用,但不能在设备上使用

来自分类Dev

键盘扩展可以在模拟器中使用,但不能在设备上使用

来自分类Dev

音量键可以统一使用,但不能在xfce4中使用

来自分类Dev

网站Favicon可以正常使用,但不能在Chrome书签中使用

来自分类Dev

音量键可以统一使用,但不能在xfce4中使用

来自分类Dev

为什么我不能在匿名方法中的while循环中使用break?

来自分类Dev

为什么我不能在Swift中的for循环中使用i ++

Related 相关文章

  1. 1

    为什么Python中的函数可以在封闭范围内打印变量,但不能在赋值中使用它们?

  2. 2

    为什么不能在多个foreach循环中使用数组?

  3. 3

    HTML 可以在 Fiddle 中使用,但不能在本地使用

  4. 4

    不能在嵌套的for循环中使用特定变量?

  5. 5

    不能在嵌套的for循环中使用特定变量?

  6. 6

    不能在循环中使用 FormData.append 吗?

  7. 7

    为什么我可以在for循环中多次重定义相同的变量,但不能在循环之外?

  8. 8

    我的Flatten数组方法可以在控制台中使用,但不能在Codewars中使用?

  9. 9

    可以在结构中返回两个数组,但不能在类 C++ 中返回

  10. 10

    JavaScript函数有效..但不能在for循环中

  11. 11

    使用DOMParser解析XML可以在Chrome中使用,但不能在FF中使用

  12. 12

    $ .ajax帖子可以在Chrome中使用,但不能在Firefox中使用

  13. 13

    Facebook登录可以在Chrome中使用,但不能在Firefox中使用

  14. 14

    我的脚本可以在jsFiddle中使用,但不能在我的网页中使用

  15. 15

    Cookie可以在Chrome中使用,但不能在IE或Safari中使用?

  16. 16

    jQuery可以在jsFiddle中使用,但不能在Drupal中使用

  17. 17

    代码可以在jsfiddle中使用,但不能在浏览器中使用

  18. 18

    可以在Bash中使用,但不能在ZSH中使用?....别名ls ='ls -lh'

  19. 19

    命令可以在命令行中使用,但不能在Shell脚本中使用

  20. 20

    字体可以在IE中使用,但不能在Firefox或Chrome中使用

  21. 21

    插件可以在Linux Unity Editor中使用,但不能在独立的Linux版本中使用

  22. 22

    查询可以直接在MySQL中使用,也可以在PHP中使用mysqli,但不能在PDO中使用

  23. 23

    在onclick之后使用.val可以在模拟器中使用,但不能在设备上使用

  24. 24

    键盘扩展可以在模拟器中使用,但不能在设备上使用

  25. 25

    音量键可以统一使用,但不能在xfce4中使用

  26. 26

    网站Favicon可以正常使用,但不能在Chrome书签中使用

  27. 27

    音量键可以统一使用,但不能在xfce4中使用

  28. 28

    为什么我不能在匿名方法中的while循环中使用break?

  29. 29

    为什么我不能在Swift中的for循环中使用i ++

热门标签

归档