精华内容
下载资源
问答
  • 那么为什么不能创建泛型数组呢,如果想要使用该怎么办呢????? 首先,java中我们不能实例化一个泛型数组,但是确实可以定义一个这样的变量 这是因为,泛型具有擦除机制,在运行时的类型会被擦除为了与之前版本类库的融合...

    今天敲代码的时候,想到创建一个set数组,结果不假思索的就写了下面这行代码在这里插入图片描述
    结果编译器报错:“不能创建泛型数组”

    那么为什么不能创建泛型数组呢,如果想要使用该怎么办呢?😕

    1. 首先,java中我们不能实例化一个泛型数组,但是确实可以定义一个这样的变量
      这是因为,泛型具有擦除机制,在运行时的类型会被擦除为了与之前版本类库的融合(不重写之前的类库),所以目前采用了类型擦除这种方法.
      比如:
    class Pair<T> {
        private T value;
        public T getValue() {
            return value;
        }
        public void setValue(T  value) {
            this.value = value;
        }
    }
    擦除后
    class Pair {
    	private Object value;
    	public Object getValue() {
    		return value;
    	}
    	public void setValue(Object  value) {
    		this.value = value;
    	}
    }
    //当然擦除后的类型不一定是Object还有可能是它的最近的父类型
    
    1. (Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。)
      因此jvm只知道存储的是一个object类的对象,并且会在编译的时候也就是擦除之前判断操作的数据类型是否一致,

    2. 类型检查就是针对引用的
      其实下面的第二了例子算是上转型对象,还是属于父类对象,所以都可以接收.

    ArrayList<String> arrayList1=new ArrayList();
    		arrayList1.add("1");//编译通过
    		arrayList1.add(1);//编译错误
    		String str1=arrayList1.get(0);//返回类型就是String
    		
    		ArrayList arrayList2=new ArrayList<String>();
    		arrayList2.add("1");//编译通过
    		arrayList2.add(1);//编译通过
    		Object object=arrayList2.get(0);//返回类型就是Object
    
    

    知道了这些,我们再来看看为什么不能创建泛型数组

    由于泛型具有擦除机制,在运行时的类型参数会被擦除,Java只知道存储的对象是一个Object而已,而对于Java的数组来说,他必须知道它持有的所有对象的具体类型,而泛型的这种运行时擦除机制违反了数组安全检查的原则。

    如果想使用泛型数组该这么办呢?

    1. 直接去掉实例化里的泛型

    在这里插入图片描述
    2. 或者直接使用List<List<Integer>>,用list代替数组,这种方式比较推荐不容易出错

    展开全文
  • 之前只是知道在 Java 中不能创建泛型数组 现在我们假设在 Java 中可以创建泛型数组,看看可能会发生什么情况: // 假设可以创建泛型数组 List<String>[] stringLists = new ArrayList<String>[1]...

     

    之前只是知道在 Java 中不能创建泛型数组

     

    现在我们假设在 Java 中可以创建泛型数组,看看可能会发生什么情况:

    复制代码

    // 假设可以创建泛型数组
    List<String>[] stringLists = new ArrayList<String>[1];
    List<Integer> intList = Arrays.asList(42);
    // 泛型擦除,List 继承自 Object,所以可以如此赋值
    // 在数组中,子类数组 是 父类数组 的子类,Object[] o = new ArrayList[1];
    Object[] objects = stringLists;
    // 同理,泛型擦除后,List 类型变量赋值给 Object 类型变量
    // 但此时出现问题了,**** List<Integer> 实例添加到了声明为 List<String>[] 类型的数组中了 ******
    objects[0] = intList;
    String s = stringLists[0].get(0);

    复制代码

    由于泛型擦除,结果就是泛型的检查作用失效,可以将 List<Integer> 类型的值添加到 List<String>[] 类型的数组中。

    而这类问题在编译时无法发现,只能在运行时出现问题

     

    所以如果禁止创建泛型数组,就可以避免此类问题

    展开全文
  • Java为什么不能创建泛型数组

    万次阅读 热门讨论 2015-12-03 18:06:25
    Java为什么不允许创建泛型数组

    近期看《Java核心技术 卷I》,看到其中有一页说不能创建泛型数组。情形如下:

    public class Pair<T> {
    	public void info( )
    	{
    		System.out.println("I am Pair");
    	}
    }
    
    
    Pair<String>[] p=new Pair<String>[10];//该句编程环境eclipse会提示错误,连编译都不能通过

    为什么Java不允许创建泛型数组?看核心技术里的讲解看不懂,又翻开《疯狂Java讲义》,两本书拼凑,终于看懂了。也曾查阅网上资料,但大都抄来抄去,也是说不明白。

    首先,从一个问题讲起——Java为什么使用泛型?引入泛型的目的之一就是为了提高程序的安全性,减少错误发生,还是用一段更形象的代码来讲吧。请看下面代码

    public class Test {
    	
    	public static void main(String[] args) {
    		
    		ArrayList list=new ArrayList();
    		list.add(new Pair());
    		//list.add(5);
    		Pair p=(Pair)list.get(0);
    		p.info(); 
    	}
    }


    
    运行上面代码是不会有任何问题的,但是我们稍加改动,即放开被注释掉的那行代码,并将索引改为1,即变为如下代码
    

    public class Test {
    	
    	public static void main(String[] args) {
    		
    		ArrayList list=new ArrayList();
    		list.add(new Pair());
    		list.add(5);
    		Pair p=(Pair)list.get(1);
    		p.info(); 
    	}
    }


    
    程序将发生java.lang.ClassCastException,很显然,是因为我们把int类型强制转为Pair类型发生的。以上代码是用引入泛型代码之前的方式写的,在引入泛型后,java集合都已经重写以迎合泛型。引入泛型的目的之一就是为了消除这种隐患,于是,泛型的一个原则被引了出来——如果一段代码在编译时没有提出“未经检查的转换”警告,则程序在运行时不会引发ClasscastException异常。
    

    我们再用泛型的方式来重写一遍上面的代码,如下

    编译环境会提示错误,编译都通不过,于是这便在编译阶段就避免了这种隐患的发生。泛型能够保证类型的统一。

    接下来讲本篇博客的重点——为什么不能创建泛型数组?

    这跟数组的一个特点有关,看代码

    public class Father {
    
    }

    public class Son extends Father{
    
    }
    

    public class Test {
    	
    	public static void main(String[] args) {
    		
    		Father[] son=new Son[10];
    	}
    }
    
    数组是允许把一个子类数组赋给一个父类数组变量的!这会发生什么!?

    public class Test {
    	
    	public static void main(String[] args) {
    		
    		Pair<String>[] p=new Pair<String>[10];//实际这句是不能通过编译的,eclipse会提示错误
    		Object[] oj=p;
    	}
    }
    如果允许创建泛型数组,将能在数组p里存放任何类的对象,并且能够通过编译,因为在编译阶段p被认为是一个Object[ ],也就是p里面可以放一个int,也可以放一个Pair,当我们取出里面的int,并强制转换为Pair,调用它的info()时会怎样?java.lang.ClassCastException!这就违反了泛型引入的原则。所以,Java不允许创建泛型数组。

    有人可能会说,即使我用泛型ArrayList<Pair> list=new ArrayList<Pair>( ),我不是照样可以取出里面的对象,使用显式的强制类型转换吗?比如,Father f=(Father)list.get(0),实际操作你将会发现,你依旧会被提示错误,编译不过,这并不违背泛型引入的原则。


    最后,感谢《Java核心技术 卷I》和《疯狂Java讲义》。

    展开全文
  • 上面的这段代码是可以正常编译的,但在运行这段代码的时候会报异常java.lang.ArrayStoreException这是因为数组创建的时候就确定了元素的类型,并且会记住该类型,每次向数组中添加值的时候,都会做类型检...

    首先我们来看一个简单的例子

    Integer[] intArr = new Integer[1];

    Object[] objArr = intArr;

    objArr[0] = "xxx";

    上面的这段代码是可以正常编译的,但在运行这段代码的时候会报异常java.lang.ArrayStoreException

    这是因为数组在创建的时候就确定了元素的类型,并且会记住该类型,每次向数组中添加值的时候,都会做类型检查,类型不匹配时就会抛异常java.lang.ArrayStoreException

    知道了这个数组类型检查机制后,我们来看看创建泛型类的数组会有什么问题,首先我们创建一个泛型类:

    public class A{

    private T value;

    public A(T value) {

    this.value = value;

    }

    // 省略 get 和 set 方法

    // ...

    }

    我们尝试来创建一个 A 类的数组:

    A[] arr = new A[1]; // 编译错误

    上面的这行代码根本不能通过编译,也就是不允许我们创建泛型数组

    为了解释为什么不能创建泛型数组,这样会带来什么问题,我们假如上面的代码可以通过编译,接着看:

    A[] arr = new A[1];

    Object[] objArr = arr;

    objArr[0] = new A();

    类似我们前面说的那样,我们把 arr 赋给一个 Object[],然后我们往数组中加入 A 类型的值,这样做是可以的,在编译和运行期间都不会报错。因为泛型类型会被擦除,A 和 A 的类型其实是一样的:

    System.out.println(new A().getClass() == new A().getClass());

    // 输出:true

    这样就逃过了数组的类型检查机制,在我们使用中就会造成类型转换错误。

    所以,Java 中不允许创建泛型的数组。

    注意

    有一种绕过“不能创建泛型数组”限制的方法,就是使用强制类型装换:

    A[] arr = (A[]) new A[1];

    当然,这么做是不安全的,当我们向数组中放入一个 A,然后以 String 类型取出时会报异常java.lang.ClassCastException,如下代码所示:

    A[] arr = (A[]) new A[1];

    Object[] objArr = arr;

    objArr[0] = new A(1);

    A a = arr[0];

    String s = a.getValue();

    // java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

    展开全文
  • 首先我们来看一个简单的例子 Integer[] intArr = new Integer[1]; Object[] objArr = intArr; objArr[0] = "xxx";...这是因为数组创建的时候就确定了元素的类型,并且会记住该类型,每次向数组中添加值的时候,...
  • Java 为什么不能创建泛型数组?

    千次阅读 2018-09-23 20:53:03
    泛型是 JDK 1.5 中引入的新特性, 首先我们来思考下 java 为什么要引入泛型, 我们看如下代码: List list = new ArrayList(); list.add(55); list.add("dd"); System.out.println(((Integer) list.get...
  • 为什么在java中不能创建泛型数组

    千次阅读 2017-10-23 22:40:32
    前段时间在上国外某教授的algorithm课程,提到在java中不能创建泛型数组,课后也有这个思考题,自己百思不得其解,于是翻开了《think in java》这本书,在书的第15章,写到。这是由于擦除机制。(尽管通读了第15章,...
  • 复制代码  Java数组为什么是协变的?在Java的早期版本中,由于没有泛型,而为了能够复用数组的实现,就将数组设计为协变的。但是,如果将数组设计为协变,可能会引发一个问题:类型安全性,例如: Number[] ...
  • 没事的时候在书中翻了下泛型相关的知识,注意到一个比较有意思的问题:Java 不能创建泛型数组。比如像下面这样就是不允许的: // 创建一个泛型类 public class Generic<T> { } // 测试类 public ...
  • 在java泛型中是不能实例化参数化类型的数组的,例如: Pair<String>[] table = new Pair<String>[10]; //Error 这是为什么呢?其实主要是为了避免数组里出现类型不一致的元素。 我们先看一下,数组是否...
  • 为什么下面的代码不能编译通过 [code="java"]Class[] claszz = new Class[]{ B.class, C.class };[/code] 假如不使用泛型则可以编译通过 [code="java"]Class[] claszz = new Class[]{ B.class, C.class };[/code]...
  • java泛型数组问题

    2010-05-20 18:57:52
    为什么我这样写老提示 不能创建泛型数组? Latte, Mocha, Cappuccino,Americano, Breve 均是Coffee的子类 [code="java"] Class[] types = { Latte.class, Mocha.class, Cappuccino.class, Americano.class, ...
  • <<thinking in java>>中代码 ``` class Generic<T>{} class ArrayofGenericReference{ static Generic[] gia;...虽然书上说不能创建泛型数组,但是Generic[] gia = new Generic[1];却可以正常编译运行。请问为什么
  • 本人是小菜一枚,在上的算法课要用到JAVA实现。 其中讲到栈的时候,用到了泛型编程,代码如下 public class raStack<Item>...这里,为什么不能直接用 s = new Item[1]; ? 求大神讲解。
  • // Cannot create a generic array of GenericClass.MyClass } } 这不是创建通用数组.编译器应该没有理解/确定MyClass的问题,不是吗? 解决方法: 内部类“知道”封闭类的哪个实例创建它们,并且可以访问该实例的字段...
  • 4. 不能创建泛型数组 一.泛型擦除是什么 java泛型是编译期的泛型,不是运行时的泛型 java语言是跨平台的,每个平台都有对应的JVM(java虚拟机),编写的java源码不能直接在JVM中运行,能在...
  • Java泛型

    2020-10-25 16:31:53
    限定类型变量泛型使用中的约束和局限性不能用基本类型实例化类型参数运行时类型查询只适用于原始类型泛型类的静态上下文中类型变量失效不能创建参数化类型的数组不能实例化类型变量不能捕获泛型类的实例泛型类型能...
  • java泛型—擦除的补偿

    2018-11-19 21:24:23
    1、为什么需要补偿 由于擦除,我们无法直接得到泛型参数的类型信息。所以任何运行时需要类型信息的操作都...(3)无法创建泛型数组 public class Erase&lt;T&gt;{ public static void f(Object arg){ ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 102
精华内容 40
关键字:

为什么不能创建泛型数组