首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么这个带有有界通配符的Java泛型代码不能编译?

带有有界通配符的Java泛型代码不能编译的原因是由于类型擦除机制导致的。

Java中的泛型是通过类型擦除来实现的,编译器在编译时会将泛型类型擦除为其上界类型(或Object类型)。在使用有界通配符时,编译器无法确定具体的类型,因此无法进行类型检查和类型推断。

例如,考虑以下代码:

代码语言:txt
复制
public class GenericClass<T extends Number> {
    private T value;
    
    public void setValue(T value) {
        this.value = value;
    }
    
    public T getValue() {
        return value;
    }
    
    public static void main(String[] args) {
        GenericClass<?> genericClass = new GenericClass<>();
        genericClass.setValue(10); // 编译错误
        Number value = genericClass.getValue(); // 编译错误
    }
}

在上述代码中,我们定义了一个泛型类GenericClass,其中泛型类型T必须是Number或其子类。在main方法中,我们创建了一个GenericClass<?>对象,表示可以接受任意类型的GenericClass实例。然而,由于类型擦除的影响,编译器无法确定?代表的具体类型,因此无法通过类型检查。

为了解决这个问题,可以使用无界通配符<?>或者具体的类型来替代有界通配符<? extends T>。例如,可以将上述代码中的GenericClass<?>替换为GenericClass<Number>GenericClass<?>,这样就可以编译通过。

总结起来,带有有界通配符的Java泛型代码不能编译是因为类型擦除导致编译器无法确定具体的类型,解决方法是使用无界通配符或具体的类型来替代有界通配符。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

深入理解

这就是为什么在运行时我们不能直接询问一个对象是否是List或是List,因为所有的类型信息在运行时都不可获得。...桥接方法 由于类型擦除,可能会出现子类在继承带有参数父类时方法签名冲突。为了解决这个问题,Java编译器会生成所谓桥接方法。...例如,如果一个类型参数总是用于映射键,使用K比T更清晰。 使用有界通配符 有界通配符增加了灵活性,允许限制未知类型范围。 有界通配符示例 ?...有界通配符好处 使用有界通配符可以编写能够接受更广范围类型参数灵活代码,同时保持类型安全。 避免原始类型 使用原始类型(没有类型)会绕过类型安全检查,应该尽量避免。...类型推断 Java 7引入了钻石操作符,使得编译器可以推断出实例参数类型,简化了使用。 通配符高级用法 使用上限和下限通配符可以编写更加灵活代码,使得方法可以接受更广泛参数类型。

17530

年后跑路第一战,从Java学起!

概述 大家好,我是麦洛,今天来复习一下。JDK 5.0 引入了 Java ,允许设计者详细地描述变量和方法类型要如何变化,使得代码具有更好可读性。...本文章是对 Java快速介绍,包含背后目标以及使用如何提高我们代码质量。 为什么要引入?...在 Java 集合中,我们使用T表示类型,K表示键,V表示值。 有界 类型参数可以有界,我们可以限制方法接受类型。...否则会导致编译时错误。 在中使用通配符Java中,通配符由?表示,我们使用它们来指代未知类型。通配符特别有用,可以用作参数类型。 首先,我们知道Object是所有 Java超类。...例如,以下不能编译: List list = new ArrayList(); list.add(17); 要理解基本类型为什么不起作用,让我们记住是一个编译时特性,这意味着类型参数被删除并且所有类型都实现为类型

69130

更深入地理解Java

引言 jdk5.0中引入了Java,目的是减少错误,并在类型上添加额外抽象层。 本文将简要介绍Java背后目标以及如何使用来提高代码质量。 2....为什么要用 设想一个场景,我们希望用Java创建一个列表来存储Integer;代码可能会写成这样: List list = new LinkedList(); list.add(new Integer...否则,将导致编译时错误。 4. 使用通配符 通配符Java中用问号“?“ 表示,它们是用来指一种未知类型。通配符在使用时特别有用,可以用作参数类型,但首先要考虑是一个重要注释。...和原始数据类型 Java一个限制是类型参数不能是基本类型 例如,以下内容无法编译: List list = new ArrayList(); list.add(17); 复制代码...为了理解原始数据类型为什么不起作用,只需记住 编译时特性,这意味着类型将会被擦除,所有类型都实现为 Object 类。

99330

关于对Java解释和思考

通配符 问号 (?) 是通配符,表示未知类型。通配符可用作参数或局部变量类型,有时还可用作返回类型。但我们不能在调用方法或实例化类时使用通配符。...我们使用带有extends关键字通配符和上限类或接口,这将允许我们传递上限或其子类型参数。...7.3) 下界通配符添加下边界,即传入类型实参必须是指定类型父类型,使用带有super关键字和下界类通配符 (?) 来实现。...而对数组声明进行限制,对于这样情况,可以在编译期提示代码有类型安全问题,比没有任何提示要强很多。...通过上面的例子可以证明,在编译之后程序会采取去措施。也就是说Java,只在编译阶段有效。

60020

Java

Why:为什么要引入Java 集合框架中数据元素,是Object类型,也就是可以是任意类型。 在使用集合数据时,需要显式地调用 强制类型转换。...> c) { for (Object e : c) { System.out.println(e); } } Bounded Wildcards(有界通配符有界通配符是因为什么需求出现呢...在适当代码中,集合总是伴随着类型参数。当使用类似集合类型而不使用类型参数时,它称为原始类型。 原始类型类似于通配符类型,这是一个精心设计决定,允许与预先存在遗留代码进行互操作。...一个主要目标就是提高Java程序类型安全,使用可以使编译器知道变量类型限制,进而可以在更高程度上验证类型假设。...支持Java编译器(例如JDK1.5中Javac)可以用来编译经过扩充Java程序(Generics Java程序),但是现有的没有使用扩充Java程序仍然可以用这些编译器来编译

2.2K51

JAVA回忆录之

为了创建smaeAvg方法,必须使用Java另一个特性:通配符参数。通配符参数是由“?”指定,表示未知类型。...有界通配符(上界) 向上造型一个对象引用 我们可以使用通配符把相关代码转换程:因为Apple是Fruit一个子类,我们使用?...原因非常简单,你可以这样想:这个? extends T 通配符告诉编译器我们在处理一个类型T子类型,但我们不知道这个子类型究竟是什么。...super Integer>,因此你不能保证从中读取到元素类型。 即是生产者,也是消费者 如果一个列表既要生成,又要消费,你不能使用通配符声明列表,比如List。...而从 JDK1.7开始new实例不用制定类型,编译期会默认与声明对象用于相同类型。 擦除 前文中讲过擦除,为什么这里还需要再讲述呢?

50130

Java 中文官方教程 2022 版(六)

完成本课程后,你可能想继续学习 Gilad Bracha 》教程。 为什么使用?...使用代码比不使用代码有许多好处: 编译时进行更强类型检查。 Java 编译器对代码应用强类型检查,如果代码违反类型安全性,则会发出错误。...请注意,这个构造函数包含一个形式类型参数T。编译器为这个构造函数形式类型参数T推断了类型String(因为这个构造函数实际参数是一个String对象)。...为了解决这个问题并在类型擦除后保留类型多态性,Java 编译器生成一个桥接方法来确保子类型化按预期工作。...要有效地使用 Java ,您必须考虑以下限制: 不能用原始类型实例化类型。 不能创建类型参数实例。 不能声明其类型为类型参数静态字段。

11600

Java 示例 - 方法,类,接口

Java通用类型 Java通用类型命名约定可以帮助我们轻松理解代码,并且具有命名约定是Java编程语言最佳实践之一。因此,带有自己命名约定。...Java通用通配符 问号(?)是通配符,表示未知类型。通配符可以用作参数,字段或局部变量类型,有时还可以用作返回类型。在调用通用方法或实例化通用类时,不能使用通配符。...Java类型重构 添加了Java以在编译时提供类型检查,并且在运行时没有使用,因此Java编译器使用类型更改功能删除字节码中所有类型检查代码,并在必要时插入类型转换。...12.1)为什么我们在Java中使用?...12.3)如何在Java中工作? 通用代码可确保类型安全。编译器使用类型预先在编译时删除所有类型参数,以减少运行时重载。 13.

2.6K50

Java中类型参数“”和无界通配符“”区别

list){ //...do something } } 3 声明不能用无界通配符,首先要明确通配符不能拿来声明 像下面这样用通配符"?"来表示类型参数约束是不行 ? Error Example 通配符是拿来使用定义好 比如用<?...因为,这时候通配符会捕获具体String类型,但编译器不叫它String,而是起个临时代号,比如”capture#1“ 所以以后再也不能往list里存任何元素,包括String,唯一能存就是null...>.set()参数类型被编译器捕获,命名为capture#1,和box.get()返回Object对象无法匹配 解决方法,是要给getSet()方法写一个辅助函数 ? 5. 有界通配符 实际更常用是或者两种,带有上下界通配符

2.1K10

深入理解

(几乎)不需要 JVM 或类文件更改 所有工作都在编译器中完成 编译器生成代码跟不使用(和强制类型转换)时所写代码几乎一致,只是更能确保类型安全而已 使用   本质是参数化类型,也就是说所操作数据类型被指定为一个参数...中可以使用 E 方法,要不然还得强转成 E 才能使用。 : 在类型参数中使用 super 表示这个参数必须是 E 或者 E 父类。 小结: 无限制通配符<?...当编译器对带有java代码进行编译时,它会去执行类型检查和类型推断,然后生成普通不带字节码,这种普通字节码可以被一般 Java 虚拟机接收并执行,这在就叫做 类型擦除(type erasure...参数类型可以使用 extends 语句,习惯上称为“有界类型”。 参数类型还可以是通配符类型,例如 Class。...你可以把任何带参数类型传递给原始类型 List,但却不能把List 传递给接受List方法,因为不可变性,会产生编译错误。

43010

Java核心技术之什么是

我们在工程代码中一定看过T,K,V等等,这个就是了,那我们看看官网是怎么说这个@(Generic) When you take an element out of a Collection...五、掌握在中间件或者开源框架里应用 下面我们对这几个问题一一探讨 规则 JDK5.0之前是没有这个概念,那么当时是怎么写代码 import java.io.File; import...为了防止子类型化混乱,有了通配符概念 通配符 无界通配符 在上述示例中,我们都是指定了特定类型,至少也是 Object,假设有一种场景,你不知道这个类型是啥,它可以是 Object...> col){ ... } 上界通配符 基于上述场景,加入我想限制这个类型为 Person 子类,只要是 Person 子类就都可以,如果写成 那么只能强转如下所示,那么就失去了意义...public void print(Set strSet) { } public void print(Set intSet) { } } 总结: 代码演变过程和使用及为什么使用是基础算是会用

64520

十问,你能扛住吗?

问题一:为什么需要?...问题二:从ArrayList角度说一下为什么要用? 答: 在Java增加机制之前就已经有一个ArrayList类,这个ArrayList类概念是使用继承来实现。...带有超类型限定通配符行为与子类型限定通配符行为完全相反,可以为方法提供参数,但是却不能获取具体值,即访问器是不安全,而更改器方法是安全编译器无法知道setOne方法具体类型,因此调用这个方法时不能接收类型为...总结一下: 带有超类型限定通配符可以向对象写入,带有子类型限定通配符可以从对象读取。 问题九:在虚拟机中是什么样呢? 答: 虚拟机没有类型对象,所有的对象都属于普通类。...这样做目的是为了让非Java程序在后续支持 jvm 上还可以运行(向后兼容) 当程序调用方法时,如果擦除返回类型,编译器插入强制类型转换。

1K10

重学Java基本使用

我一开始用是JDK 8,在使用这个版本时候,已经进入Java十年了,对于我来说是很理所当然,就像鱼习惯了水一样。那Java为什么要引入呢?...这里来讲下我理解,一般方法需要参数,调用方没有提供,编译不通过。为什么没有引入此设计呢,不传递类型参数,那不通过编译不是更好嘛。那让我们回忆一下,是从JDK哪个版本开始引入?...《Java Tutorial》 其实看到这块时候,我对这个通配符是有点不了解,我将这个符号理解为和T、V一样参数名,但是我用?去取代T时候,发现IDEA里面出现了错误提示。那代表?...总结一下Java为什么要引入呢,原因大致有这么几个: 增强代码复用性、让错误在编译时候就显现出来。...为了保持向后兼容,Java选择了擦除来实现,这一实现机制在早期我来看,这种实现并不好,我认为这种实现影响了Java性能,我甚至认为这不能称之为真正, 比不上C#,但是在重学过程中

33710

Java基础系列(三十七):继承,通配符反射

通配符限定与类型变量限定非常相似,但是通配符类型还有一个附加能力,即可以指定一个超类型限定: ? super Apple 这个通配符限制为 Apple所有父类,为什么要这么做呢?...带有超类型限定通配符行为与子类型限定通配符行为完全相反,可以为方法提供参数,但是却不能获取具体值,即访问器是不安全,而更改器方法是安全: ?...extends Fruit); 编译器无法知道 setFirst方法具体类型,因此调用这个方法时不能接收类型为 Fruit或 Object参数。...总结一下,带有超类型限定通配符可以想对象写入,带有子类型限定通配符可以从对象读取。 还可以使用无限定通配符,例如, Pair。...为了表达类型声明,使用 java.lang.reflect包中提供接口 Type,这个接口包含下列子类型: Class类,描述具体类型 TypeVariable接口,描述类型变量(如 TextendsComparable

59630

深入理解 Java

,支持(几乎)不需要 JVM 或类文件更改 所有工作都在编译器中完成 编译器生成代码跟不使用(和强制类型转换)时所写代码几乎一致,只是更能确保类型安全而已 使用方式 本质是参数化类型...当编译器对带有java代码进行编译时,它会去执行类型检查和类型推断,然后生成普通不带字节码,这种普通字节码可以被一般 Java 虚拟机接收并执行,这在就叫做 类型擦除(type erasure...类型参数可以有多个 参数类型可以使用 extends 语句,习惯上称为“有界类型” 参数类型还可以是通配符类型,例如 Class 使用场景 当类中要操作引用数据类型不确定时候...因此只在编译时强化它类型信息,而在运行时丢弃(或者擦除)它元素类型信息。擦除使得使用代码可以和没有使用代码随意互用。 3.如果类型参数在方法声明中只出现一次,可以用通配符代替它。...4.数组中不能使用 这可能是 Java 面试题中最简单一个了,当然前提是你要知道 Array 事实上并不支持,这也是为什么 Joshua Bloch 在 《Effective Java》一书中建议使用

2.1K111

java边界

参考链接: Java中具有有界类型 在网上发现这篇文章写得不错,地址:http://build.cthuwork.com:8081/wordpress/category/java教程/java再谈...需要注意一点是,不支持协变(Covariant),协变需使用通配符为什么不支持协变呢。我们先从支持协变数组开始考虑。...所以,吸取了这个教训,本身就是为了提高类型安全性而设计不能犯这样低级错误。...四、编译前后比较  系统是作为Java 5一套增强类型安全及减少显式类型转换系统出现。...在虚拟机看来,List这个类型只是普通类型List而已,这种行为叫擦除(Type Erasure)。   那么在Java是如何如何实现其目的呢?Java充分利用了多态性。

2K10

游刃有余:玩转Java

上界通配符允许作为指定类型子类型任何类型,而下界通配符允许作为指定类型超类型任何类型。 方法:除了类和接口之外,Java 还支持方法。...它们使您能够编写更通用算法和数据结构,可以处理多种类型,同时保持了编译类型检查。借助,您能够创建更为健壮且易于维护 Java 代码。...Java 优点 Java 提供了多个优点,有助于编写更安全、更灵活和更可重用代码。以下是 Java 一些主要优点: 类型安全:主要好处之一是提高类型安全性。...性能优化:Java是使用类型擦除来实现。这意味着类型信息在运行时被删除,编译代码可以使用原始类型。因此,不会因而产生运行时开销。这允许编写通用代码而不牺牲性能。...这些示例演示了 Java多功能性,允许您以和类型安全方式处理不同类型。 Java 通配符 Java通配符提供了一种指定未知类型或一系列类型方法。

12410

就这么简单

二、为什么需要 早期Java是使用Object来代表任意类型,但是向下转型有强转问题,这样程序就不太安全 首先,我们来试想一下:没有,集合会怎么样 Collection、Map集合对元素类型是没有任何限制...前面我们已经定义了类,类是拥有这个特性类,它本质上还是一个Java类,那么它就可以被继承 那它是怎么被继承呢??...那么就使用方法 如果没有依赖关系,就使用通配符通配符会灵活一些. ---- 3.6擦除 是提供给javac编译器使用,它用于限定集合输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据...但编译编译带有java程序后,生成class文件中将不再带有形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。...3.6.1兼容性 JDK5提出了这个概念,但是JDK5以前是没有。也就是是需要兼容JDK5以下集合。 当把带有特性集合赋值给老版本集合时候,会把给擦除了。

51140

Java详解,史上最全图文详解「建议收藏」

一:本质 Java (generics)是 JDK 5 中引入一个新特性, 提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法类型。...二:为什么使用 好处是在编译时候检查类型安全,并且所有的强制转换都是自动和隐式,提高代码重用率。 (1)保证了类型安全性。...四:通配符 Java通配符是用于解决之间引用传递问题特殊语法, 主要有以下三类: //表示类型参数可以是任何类型 public class Apple<?...: 表示不确定java类型 六:实现原理 本质是将数据类型参数化,它通过擦除方式来实现,即编译器会在编译期间「擦除」语法并相应做出一些类型转换动作。...但是除此之外是,如果构建实例时使用了语法,那么编译器将标记该实例并关注该实例后续所有方法调用,每次调用前都进行安全检查,非指定类型方法都不能调用成功。

71230

类、方法、类型通配符使用

类、方法、类型通配符使用 一.类        声明和非声明类似,除了在类名后面添加了类型参数声明部分...根据传递给方法参数类型,编译器适当地处理每一个方法调用。...注意类型参数只能代表引用类型,不能是原始类型(像int,double,char等) 1 public class GenericMethodTest 2 { 3 // 方法 printArray...List类型,所以name,age,number都可以作为这个方法实参,这就是通配符作用 2、类型通配符上限通过形如List来定义,如此定义就是通配符值接受Number及其下层子类类型。...Number,所以为String是不在这个范围之内,所以会报错 3、类型通配符下限通过形如 List<?

3.7K40
领券