简体   繁体   中英

Java Generic Wildcard Constructor not accepting objects?

I have a RandomizedWrapper class. This class contains a constructor that accepts a list:

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<>();
   }
}

I want to create a new instance of this RandomizedWrapper class. I do via the following code:

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

    //stuff here

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

When I attempt to create this new object, I run into the following error:

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

This makes no sense. I very clearly have a constructor in the RandomizedWrapper class that accepts a List<RandomizerEntry<?>> wildcards. A proposed solution by the compiler says " create a constructor that accepts this argument ". I click that, just to see what happens, and it tells me " This constructor already exists ".

Does anyone understand whats going on here? Why can't I instantiate this object?

The issue here is that List<RandomizerEntry<ItemStack>> is not a subtype of List<RandomizerEntry<?>> so your constructor is not applicable to your argument. See this section of the Java tutorial which specifically addresses this misunderstanding.

As for the IDE suggestion to create another constructor, this won't work because in Java it is not possible to "overload a method where the formal parameter types of each overload erase to the same raw type" ( details ).

To solve the issue one way is simply to make the type of your local variable compatible with your constructor, although this will of course limit what you can do with it:

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

? (wildcars) ? (wildcars) mostly used when the generic code doesn't require any reference to a type and RandomizedWrapper isn't type of class where wildcards are needed. In this case its preferable to use Type Parameter <T> ( 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
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM