我有一个T类型的泛型类,它使用T读写方法.让我们在列表中加以说明.

当我将其与通配符类型一起使用时,我会遇到一个特定的问题:

List<?> list = ...
list.add(list.get(0)); //here I get a compiler error

据我所知,Java编译器应该在内部将类型存储为"capture of?"它应该认识到,add/get中使用的类型是匹配的.

如果这是不可能做到的,那么"最好"的解决方法是什么?我的 idea :

  1. Helper methods

    private <S> void aaa(List<S> list) {
        list.add(list.get(0));
    }
    

    这是可行的,但将这些方法用于所有可能的组合是不切实际的.

  2. Casting

    List<?> list;
    
    private <S> void aaa() {
        List<S> list = (List<S>)this.list
        list.add(list.get(0));
    }
    

    这同样有效,但我也不喜欢,而且我收到了unchecked cast条警告.

  3. Creating type

    class Foo<T> {
        List<T> list;
    
        private void aaa() {
            list.add(list.get(0));
        }
    }
    

    这也行得通,但仅仅为了这个目的定义一个类型似乎太过分了.

谢谢你的 idea !

推荐答案

据我所知,Java编译器应该在内部将类型存储为"capture of?"它应该认识到,add/get中使用的类型是匹配的.

这不是捕获系统所做的.不幸地

这是可行的,但将这些方法用于所有可能的组合是不切实际的

"所有可能的组合"?只有一个组合,真的.或者更确切地说,您执行此类交互的次数(将调用thing上的方法的结果直接作为参数提供给thing上的另一个方法)并不完全是一项常见任务.每次它发生时,你都必须编写一个方法,但是,考虑到它很罕见,我不认为这是不切实际的.请注意,如果您愿意,当然可以将0设为参数.

正在创建类型

这真是个坏主意.不是因为它杀伤力过大.因为它漏水.你的泛型是public.你会希望隐藏它的这一方面.或者更确切地说,类型的语义,无论它可能是什么,要么包括类型,要么不包括类型,"我需要将列表中的一个元素复制到该列表的末尾",在您的设计决策中,对于类型本身是否应该有泛型来表示您得到的这个列表字段/参数的类型,绝对不应该起任何作用.

"最好"的解决方法是什么?

我认为这基本上是一种辅助方法.请注意,如果你真的想这样做,你可以将其推到本地:

import java.util.*;

class Test {
  public static void main(String[] args) {
    List<String> a = new ArrayList<String>();
    a.add("Hello"); a.add("World");
    copyFirstToEnd(a);
    System.out.println(a);
  }

  private static void copyFirstToEnd(List<?> in) {
    class Helper {
      <S> void help(List<S> a) { a.add(a.get(0)); }
    }

    new Helper().help(in);
  }
}

效果很好.笨手笨脚的代码有点难看.但是,除了你自己的眼球之外,绝对没有任何东西可以"看到"这一点,只有当你明确地看到为这种方法提供动力的code时.你不会在大纲中看到它.你不会在javadoc中看到它.你不会在自动完成对话框中看到它(除了编辑代码inside copyFirstToEnd时,这是一件好事),当然,任何处理不是这Test.java本身的源文件的人甚至都不知道你已经为此创建了一个类型,即使他们try 使用反射*.

*)他们可以四处搜索,找到Test$Helper.class件艺术品,但在这一点上,这感觉很学术.该类以各种可能的方式发出尖叫,您不应该首先将其视为存在,而工具和IDE确实是这样做的(将其完全排除在类型查找对话框等之外).

遗憾的是,您得到了一个对象alloc,但最坏的情况是它只有一个ref字段,并且是线程本地化的快速垃圾.这是一种尽可能便宜的alloc,因此考虑到java的代垃圾收集系统,以及对支持"许多小的不可变对象"作为编码模型的明确关注,成本可能实际上为零.

Java相关问答推荐

Spring安全实现多个SQL表身份验证

从技术上讲,OPC UA客户端是否可以通过转发代理将请求通过 tunel 发送到OPC UA服务器?

多个Java线程和TreeMap.put()的非预期行为

如何配置ActiveMQ Artemis以使用AMQP 1.0和其他协议与Java

';com.itextpdf.ext.html.WebColors已弃用

滚动视图&不能在alert 对话框中工作(&Q;&Q;)

连接Quarkus中的两个异步操作

对Java中的通配符参数的混淆

自定义批注的外推属性值

如何从日期中截取时间并将其传递给组件?

使用存储在字符串变量中的路径目录打开.pdf文件

如何集成语义发布和BitBucket(Java项目)

为什么同步数据块无效?

JNI:将代码打包成自包含的二进制文件

在使用具有不同成本的谓词调用allMatch之前对Java流进行排序会带来什么好处吗?

如何从命令行编译包中的所有类?

如何通过用户ID向用户发送私信

如何从指定某些字段的父对象创建子对象

在对象列表上调用提取后,如何判断没有值为空?

Keycloak + Spring Boot 角色认证不起作用