【问题标题】:Java Generic Wildcard Constructor not accepting objects?Java通用通配符构造函数不接受对象?
【发布时间】:2021-01-06 21:09:31
【问题描述】:

我有一个 RandomizedWrapper 类。该类包含一个接受列表的构造函数:

public class RandomizedWrapper{

   final int upperBound = 100;
   final List<RandomizerEntry<?>> randomizeList;
   Map<Integer, RandomizerEntry<?>> randomizerMap;

/**
 * Construct a new RandomizedWrapper instance
 * 
 * @param randomizeList - A list containing all randomizable objects
 */
public RandomizedWrapper(final List<RandomizerEntry<?>> randomizeList) {
    
    this.randomizeList = randomizeList;
    this.randomizerMap = new HashMap<>();
   }
}

我想创建这个 RandomizedWrapper 类的新实例。我通过以下代码进行:

    List<RandomizerEntry<ItemStack>> randomizerList = new ArrayList<>();

    //stuff here

    RandomizedWrapper wrapper = new RandomizedWrapper(randomizerList);//error

当我尝试创建这个新对象时,我遇到了以下错误:

The constructor RandomizedWrapper(List<RandomizerEntry<ItemStack>>) is undefined

这毫无意义。我很清楚地在 RandomizedWrapper 类中有一个构造函数,它接受List&lt;RandomizerEntry&lt;?&gt;&gt; 通配符。编译器提出的解决方案是“create a constructor that accepts this argument”。我点击它,只是想看看会发生什么,它告诉我“This constructor already exists”。

有人了解这里发生了什么吗?为什么我不能实例化这个对象?

【问题讨论】:

标签: java generics constructor


【解决方案1】:

这里的问题是List&lt;RandomizerEntry&lt;ItemStack&gt;&gt; 不是 List&lt;RandomizerEntry&lt;?&gt;&gt; 的子类型,因此您的构造函数不适用于您的论点。请参阅this section of the Java tutorial,它专门解决了这种误解。

至于 IDE 建议创建另一个构造函数,这是行不通的,因为在 Java 中不可能“重载一个方法,其中每个重载的形式参数类型都擦除为相同的原始类型”(details) .

解决这个问题的一种方法是让你的局部变量的类型与你的构造函数兼容,尽管这当然会限制你可以用它做什么:

List<RandomizerEntry<?>> randomizerList = new ArrayList<>();

【讨论】:

  • 请注意,鉴于这个“随机化”类的明显目的,它绝对应该是@​​987654326@。
  • 或者将构造函数参数定义为List&lt;? extends RandomizerEntry&lt;?&gt;&gt;。虽然我认为@chrylis 的建议更有意义。
【解决方案2】:

? (wildcars) 主要在通用代码不需要对类型的任何引用并且RandomizedWrapper 不是需要通配符的类类型时使用。在这种情况下,最好使用类型参数&lt;T&gt; (Difference between ? (wildcard) and Type Parameter in Java)

public class RandomizedWrapper<T>{

    final int upperBound = 100;
    final List<RandomizerEntry<T>> randomizeList;
    Map<Integer, RandomizerEntry<T>> randomizerMap;

    /**
     * Construct a new RandomizedWrapper instance
     *
     * @param randomizeList - A list containing all randomizable objects
     */
    public RandomizedWrapper(final List<RandomizerEntry<T>> randomizeList) {

        this.randomizeList = randomizeList;
        this.randomizerMap = new HashMap<>();
    }


    public void create(){
        List<RandomizerEntry<Integer>> randomizerList = new ArrayList<>();
        //stuff here
        RandomizedWrapper wrapper = new RandomizedWrapper(randomizerList);//OK
    }
}

【讨论】:

    猜你喜欢
    • 2016-09-03
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-24
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多