泛型类型参数是否转换为原始类型的对象?

2024-01-30

考虑这段代码:

public class Main {
    public static void main(String[] args) {
        Cat<Integer> cat = new Cat();
        Integer i= cat.meow();
        cat.var = 6;
    }
}
public class Cat<E> {
    public E var;
    public E meow() {
        return null;
    }
}

根据我的理解,因为我没有在 LHS 上指定类型参数,所以它将被视为Object. And Cat应该成为Cat<Object>因为要使变量声明有意义,T 必须转换为类/接口引用。这是对其工作原理的正确理解吗?在原始类型的情况下如何处理类型参数 T?

我在聊天中讨论过这个问题并得到了下列的 https://chat.stackoverflow.com/transcript/message/22993150#22993150这超出了我的理解范围:

泛型之所以有效,是因为类型被删除了。考虑 T 的擦除 #0-捕获对象。当 T 未指定(原始类型)时,它是 #0-capture-of-(nothing)

什么是#0-capture-of-(nothing) mean?

边注:由于泛型类型是作为编译时转换实现的,因此如果可以看到最终翻译的代码,会更容易理解它们。有谁知道如何查看类的翻译代码(而不是字节代码)?


No,

原始类型并不像它们被参数化一样Object,它们也不像通配符类型(<?>).
对于原始类型,泛型是关掉.

此代码已编译(带有警告):

Cat c1 = new Cat<String>();
Cat<Integer> c2 = c1;

这段代码没有:

Cat<? extends Object> c1 = new Cat<String>(); // btw: this is the same as Cat<?>
Cat<Integer> c2 = c1; // error

这也不:

Cat<Object> c1 = new Cat();
Cat<Integer> c2 = c1; // error

至于类型var:

编译后字段的类型是参数的上限(Object如果没有指定)。但是如果我们访问编译器会做什么var?

Cat<String> c1 = ...
String c1Var = c1.var;

这段代码编译没有错误,但编译器实际编译的是:

Cat c1 = ...
String c1Var = (String) c1.var;

如你看到的,var始终被视为类型字段Object, but 对于泛型,编译器会自动插入类型安全的强制转换. 就这样。如果你使用原始类型,你必须自己做。不管怎样,当你把一个Cat将一个整数存储在a中Cat<String>变量,如果您尝试读取,您只会得到运行时异常var.

A quiz

现在看一下声明集合.max http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/Collections.java#Collections.max%28java.util.Collection%29。为什么你认为参数定义为T extends Object & Comparable<? super T>?

答案编码为rot13 http://rot13.com:

Fb 贡 nsgre pbzcvyngvba 古尔盖亚 glcr vfBowrpg, abg Pbzcnenoyr。 Guvf vf arrqrq sbe onpxjneqf pbzcngvovyvgl (gur zrgubq vgfrys vf byqreguna trarevpf)。

Edit:

这是我刚刚偶然发现的另一个很好的例子:

class Foo<T> {
    public <V> V bar(V v) { return v; }
}

//compiles
Foo<Object> foo = new Foo<Object>();
Integer i = foo.bar(1);

//compiles
Foo<?> foo = new Foo<String>();
Integer i = foo.bar(1);

// fails
Foo foo = new Foo();
Integer i = foo.bar(1); // error: Object cannot be converted to Integer

不使用参数会完全禁用泛型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

泛型类型参数是否转换为原始类型的对象? 的相关文章

  • 使用 Maven 生成 Eclipse 项目文件

    当我尝试使用生成 Eclipse 项目文件时mvn eclipse eclipse我收到以下错误 插件管理器执行目标时出现内部错误 org apache maven plugins maven eclipse plugin 2 9 SNAP
  • Java 字符串哈希码缓存

    字符串不变性的优点之一是哈希码缓存以实现更快的访问 在这种情况下 如何处理具有相同哈希码的字符串的缓存 在这种情况下它真的能提高性能吗 在这种情况下 如何处理具有相同哈希码的字符串的缓存 被缓存的是字符串的哈希码 它被缓存在私有的int字符
  • 检查发送到网页的请求数

    我正在编写一个 Java 多线程应用程序 它可以访问不同 Web 服务器的数百万个 有时甚至数十亿个 URL 这个想法是检查这些 URL 是否给出有效的 200OK 响应或 404 其他代码 我如何知道我的程序是否不会在他们的服务器上造成高
  • 通过 html tidy 提供渲染 jsp 页面

    我有一个在 Glassfish 上运行的 Java 项目 它会呈现一些难看的 HTML 这是使用各种内部和外部 JSP 库的副作用 我想设置某种渲染后过滤器 通过 HTMLTidy 提供最终的 HTML 这样源代码就很好且整洁 有助于调试
  • Spring boot 2.0.5.RELEASE和mongo 4.0连接问题

    我正在关注使用 MongoDB 访问数据教程春季网站 https spring io guides gs accessing data mongodb 我将 Mongo DB 服务器版本 4 安装为服务当我使用客户端连接到它时 它的身份验证
  • 如何在Spring Boot中初始化一次MongoClient并使用它的方法?

    您好 我正在尝试导出MongoClient在 Spring Boot 中成功连接后 我尝试在其他文件中使用它 这样我就不必每次需要在 MongoDB 数据库中进行更改时都调用该连接 连接非常简单 但目标是将应用程序连接到我的数据库一次 然后
  • 从字符串生成密钥?

    我需要从字符串生成一个密钥 以便我始终可以从同一字符串创建相同的密钥 具体来说是一个Key对象 这样我就可以用它来创建Cipher进而创建SealedObject 这在 Java 中可行吗 我应该考虑什么类 方法组合才能做到这一点 对于 A
  • 使用 Hibernate Dialect 设置表字符集/排序规则?

    我使用 Hibernate MySQLInnoDB Dialect 来生成 DDL hibernate cfg xml
  • Android 游戏偶尔出现延迟

    我正在用 Java 制作一个简单的 Android 游戏 我注意到每 20 40 秒就会出现一些烦人的延迟 首先 我认为它们是由垃圾收集器引起的 但当我检查 LogCat 时 我发现游戏滞后时没有垃圾收集 每当游戏开始滞后时 我都会标记日志
  • Java 中的 MP4 容器编写器

    我想找到一个免费的 Java MP4 容器 编写器 我不需要编码器 只需要能够根据预期值写入正确原子的编码器 Bonus对于这样一个库 也可以编写 有效 F4V 我更喜欢纯 Java 解决方案 而不是使用 JNI 或外部可执行文件的解决方案
  • 为什么我要使用责任链而不是 switch 语句

    考虑一下您已经获得了多次验证 仅当要检查的对象属于某种类型时 这些验证才应生效 为什么我要使用责任链而不是 switch 语句 责任链示例 public class Executor Inject private ValidatorFact
  • 如何使用 Selenium 中的索引切换到窗口

    由于selenium不提供切换到窗口 多个窗口 的方法 但我想使用index html自定义方法来切换到不同的窗口 但下面的代码没有按预期工作 请建议以下方法的最佳实施 public void switchToWindowIndex int
  • vm 参数中的 -D 是什么,它表示为什么我们必须在 vm 参数中始终指定 -D

    vm 参数中的 D 是什么 它表示为什么我们必须在 vm 参数中始终指定 D 有什么标准吗 如果是 那是什么以及指定的位置 D 设置当前运行的 java 程序可以访问的属性值 它允许程序员设置程序运行所需的值 但程序不知道这些值是什么 因此
  • 两条腿的 OAuth 和 Gmail Atom feed

    我们正在尝试让 2 legged OAuth 与 Gmail Atom feed 一起使用 我们使用 John Kristian Praveen Alavilli 和 Dirk Ba lfanz 贡献的 Java 库 http oauth
  • 使用 JNI 从 Java 代码中检索 String 值的内存泄漏

    我使用 GetStringUTFChars 从使用 JNI 的 java 代码中检索字符串的值 并使用 ReleaseStringUTFChars 释放该字符串 当代码在 JRE 1 4 上运行时 不会出现内存泄漏 但如果相同的代码在 JR
  • 获取包中声明的所有 Java 类的名称

    我正在编写一个功能 它将有助于将类放入我的程序的某个包中 另外 我只想要子类某个类的类 我需要这些类才能调用它们的静态方法 有没有一种自动的方法来做到这一点 如果是的话 速度慢吗 如果我不清楚 我想要的是这样的 ArrayList
  • Java 中更高级的泛型

    假设我有以下课程 public class FixExpr Expr
  • ASTParser:解析绑定后查找声明节点

    我创建了一个启用了绑定的 AST 当我稍后解析绑定时 我得到了一个有效的 ITypeBinding 但是 当我想要获取绑定的声明 Node 时 它 总是返回 null 除非 ITypeBinding 在 sourceFile 中声明 这是我
  • 您可以严格泛型类型或为一个参数指定多个类型吗?

    例如我想指定一个类型可能是Integer or String并将其用作特殊类型func我试过typealias但它不会解决这个问题 因为类型别名不能有or参数作为其唯一用途 因此请考虑下面的情况 typealias alis StringP
  • Java 可变 BigInteger 类

    我正在使用 BigIntegers 进行计算 该计算使用一个调用 multiply 大约 1000 亿次的循环 并且从 BigInteger 创建新对象使其非常慢 我希望有人编写或找到了 MutableBigInteger 类 我在 jav

随机推荐