- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
希望在理解了通用边界之后,我试图理解通配符的上下限。我的参考是:https://docs.oracle.com/javase/tutorial/java/generics/wildcards.html
我发现有一个句子我可以理解:“通配符可以在多种情况下使用:作为参数,字段或局部变量的类型;”
字段和局部变量?无法想象。为什么这么重要的资料没有通过简单的例子来强调呢?
我试图理解使用哪个参考Java编译器替换(同时擦除)“?”。也许我有一个很大的误解,并且发生了任何擦除操作(因此,以下所有示例均不相关)。
在以下示例中:
1。
public static void funcA (List<? extends Number>l)
public static void funcB(List<? super Integer>l)
public static <T extends Integer> funcC(List<? extends T>l)
public static <T extends Integer> void funcC(List<T>l)
最佳答案
前言:您已经询问了有关类型擦除的许多问题,包括在聊天室中。尽管此答案将解决此特定问题,但它可能还会回答您的其他一些问题(甚至可能尚未回答)。
警告:这个答案很长,本文中专门提出的问题仅在最后直接解决。
什么是类型擦除?
其他问答中对此进行了很好的介绍,因此我将简单地链接到它们:
Java generics type erasure: when and what happens?
What is the concept of erasure in generics in Java?
What is a raw type and why shouldn't we use it?
类型擦除的规则是什么?
Java语言规范(JLS)的§4.6 Type Erasure中指定了类型擦除的规则:
类型擦除是从类型(可能包括参数化类型和类型变量)到类型(从不参数化类型或类型变量)之间的映射。我们写|T|
来擦除类型T
。擦除映射定义如下:
参数化类型(§4.5)G<T1,...,Tn>
的擦除为|G|
。
嵌套类型T.C
的擦除为|T|.C
。
数组类型T[]
的擦除为|T|[]
。
类型变量(§4.4)的擦除是其最左边界的擦除。
其他所有类型的擦除都是该类型本身。
类型擦除还将映射构造函数或方法的签名(§8.4.2)到没有参数化类型或类型变量的签名。删除构造函数或方法签名s
是由与s
相同的名称以及s
中给出的所有形式参数类型的擦除组成的签名。
如果擦除方法或构造函数的签名,则方法的返回类型(§8.4.5)和通用方法或构造函数的类型参数(§8.4.4,§8.8.4)也将被擦除。
通用方法签名的擦除没有类型参数。
对于这个答案,我们应该关注第一和第四点:
参数化类型(§4.5)G<T1,...,Tn>
的擦除为|G|
。
和:
类型变量(§4.4)的擦除是其最左边界的擦除。
分别。特别要注意的是,第四个要点仅是说明类型变量的擦除。为什么这么重要?我会回到那。
术语
了解术语对于理解规则的应用方式很重要:
通用类
在JLS的§8.1.2 Generic Classes and Type Parameters中指定。
泛型类是声明一个或多个类型变量的类。
通用接口
在JLS的§9.1.2 Generic Interfaces and Type Parameters中指定。
通用接口是声明一个或多个类型变量的接口。
通用方法
在JLS的§8.4.4 Generic Methods中指定。
泛型方法是声明一个或多个类型变量的方法。
通用构造函数
在JLS的§8.8.4 Generic Constructors中指定。
泛型构造函数是声明一个或多个类型变量的构造函数。
类型变量
在JLS的§4.4 Type Variables中指定。
类型变量由在泛型成员上声明的类型参数引入。
类型变量的syntax为:{Annotation} TypeIdentifier
类型参数
在JLS的许多部分中指定。我链接到上述术语的每个部分都提到类型参数。
类型参数是泛型成员上类型变量及其边界的声明。
类型参数的syntax为:{TypeParameterModifier} TypeIdentifier [TypeBound]
其中TypeParameterModifier
扩展为Annotation
。
参数化类型
在JLS的§4.5 Parameterized Types中指定。
参数化类型是带有类型实参的泛型类或泛型接口的实际使用。
类型参数
在JLS的§4.5.1 Type Arguments of Parameterized Types中指定。
类型实参是代替类型实参使用的实际类型或通配符。
请注意,类型形参和类型形参之间的区别类似于Java如何区分方法形参和形参。当将方法声明为void bar(Object obj)
时,Object obj
是参数。但是,当您调用bar(someObjInstance)
之类的方法时,someObjInstance
的值是参数。
术语代码示例
查看代码中的一些示例可以帮助您理解每个术语适用于代码的哪些部分。
具有类型参数的泛型类
public class Foo<T extends CharSequence, U> {
// class body...
}
T extends Charsequence
T
。
extends CharSequence
U
U
extends Object
(隐式定义)
public void <V extends Number> bar(V obj) {
// method body...
}
V extends Number
V
。
extends Number
。
public <E extends Number> void bar(List<E> list) {
// method body...
}
List<E>
E
。
public void bar(List<? extends Number> list) {
// method body...
}
List<? extends Number>
? extends Number
public class Foo<T extend CharSequence, U> {
private List<T> listField;
private U objField;
public void bar(List<? extends T> listParam) {
// method body...
}
public U baz(T objParam) {
// method body...
}
public <V extends Number> V qux(V objParam) {
// method body...
}
}
// the raw type of Foo
public class Foo {
private List listField;
private Object objField;
public void bar(List listParam) {
// method body...
}
public Object baz(CharSequence objParam) {
// method body...
}
public Number qux(Number objParam) {
// method body...
}
}
public static void funcA(List<? extends Number> l)
public static void funcA(List l)
public static void funcB(List<? super Integer> l)
public static void funcB(List l)
void
,则忘记指定有问题的返回类型)
public static <T extends Integer> void funcC(List<? extends T> l)
public static void funcC(List l)
public static <T extends Integer> void funcC(List<T> l)
public static void funcC(List l)
public class Foo<T extends Number> {
public void bar(T obj) {
// method body...
}
public void baz(List<? extends T> list) {
// method body...
}
}
bar
具有类型为
T
的单个参数。该参数直接使用类型变量。类型变量的擦除是其最左边界的擦除,在这种情况下为
Number
。这意味着擦除后,该方法的参数为
Number
。
baz
具有类型为
List<? extends T>
的单个参数。在这里,类型变量
T
用作参数化类型的类型参数的上限。换句话说,尽管使用了类型变量,但此处实际使用的擦除是参数化类型的擦除。这意味着擦除后,该方法的参数仅为
List
。即使type参数是低界通配符(例如
List<? super T>
),无界通配符(例如
List<?>
)或什至是非通配符(例如
List<T>
),也会发生这种情况。
<? super T>
and <? extends T>
in Java [duplicate]
关于java - Java类型删除如何对待'?',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58575372/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!