Type mismatch: cannot convert from Class <..> t

2019-08-11 07:58发布

问题:

I've 'inherited' an Eclipse RCP project which seems to work fine with a target platform set based around 3.6. However, moving forward we need to update to the latest version of the platform, but when I change the target platform to 3.7 (or 4.2) I get a handful of errors along the lines of

Type mismatch: cannot convert from Class<capture#1-of ?> to Class<? extends IDatasetProvider>

Can anyone suggest/provide an explanation of why this might work fine in 3.6, but not in 3.7 (and later)? Any ideas as to where I would start in resolving this would also be great!

A snippet of the code causing this error (which appears at the b.loadClass part):

    List<Class<? extends IDatasetProvider>> list = new LinkedList<Class<? extends IDatasetProvider>>();
    ClassMap<IDatasetProvider, List<String>> map = new ClassMap<IDatasetProvider, List<String>>();

    for (IConfigurationElement e : elements)
    {
        try
        {
            Bundle b = Platform.getBundle(e.getContributor().getName());

            String viewId = e.getAttribute("viewId");
            Class<? extends IDatasetProvider> datasetType = b.loadClass(e
                    .getAttribute("datasetProvider"));
            ...
            ...
            ...
        }
     }

There are also 3 (possibly) related warnings

 IDatasetProvider is a raw type. References to generic type IDatasetProvider<T> should be parameterized 

If I change back to our 3.6 platform, it all works again.

EDIT: fixed thanks to the help of Alexy and gzukmin.

I used the following code, specifically casting to Class<? extends IDatasetProvider> rather than just Class:

Class<? extends IDatasetProvider> datasetType = 
    (Class<? extends IDatasetProvider>) b.loadClass(e.getAttribute("datasetProvider"));

If there's any reason I should consider just casting to the more generic Class, please let me know!

回答1:

You can just cast it to raw type like this:

Class<? extends IDatasetProvider> datasetType = 
    (Class) b.loadClass(e.getAttribute("datasetProvider"));

Note this will:

  1. Add more warnings about raw types and unchecked casts.

  2. Blow up at the runtime if your class actually turns out not to extend IDatasetProvider. And not at the cast location, but later when you try to actually use the class. So it might be a good idea to check this with

    IDatasetProvider.class.isAssignableFrom(datasetType)
    

(see Javadoc).