Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java wildcard generic as return warning in Eclipse and SonarQube

private List gridModel;

public List getGridModel() {
        return gridModel;
}

Eclipse shows a warning:

List is a raw type. References to generic type List should be parameterized.

Changing the code to below will remove the warning

private List<?> gridModel;

public List<?> getGridModel() {
        return gridModel;
}

However the above code shows a Major pitfall error in SonarQube which says:

Remove usage of generic wildcard type. Generic wildcard types should not be used in return parameters

So how can I fix this warning?
I see a similar question here but could not find the solution .

Using Class<? extends Object> did not remove Sonar warning.

like image 263
Alireza Fattahi Avatar asked May 30 '15 07:05

Alireza Fattahi


People also ask

Can return type be wildcard?

Using a wildcard as a return type should be avoided because it forces programmers using the code to deal with wildcards. A list defined by List<? extends ...> can be informally thought of as read-only, but that is not a strict guarantee.

How do you use generic wildcards?

Guidelines for Wildcards. Upper bound wildcard − If a variable is of in category, use extends keyword with wildcard. Lower bound wildcard − If a variable is of out category, use super keyword with wildcard. Unbounded wildcard − If a variable can be accessed using Object class method then use an unbound wildcard.

Do not use bounded wildcard types as return types?

It is highly recommended not to use wildcard types as return types. Because the type inference rules are fairly complex it is unlikely the user of that API will know how to use it correctly. Let's take the example of method returning a "List<? extends Animal>".

What is a generic wildcard?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).


3 Answers

So how can I fix this warning ?

You can use a type parameter for your class :

public class GridModelHolder<T> {
   private List<T>  gridModel;

   public List<T> getGridModel() {
    return gridModel;
   }
}

The client code can then decide what type of List GridModelHolder holds :

GridModelHolder<String> gridModelHolder = new GridModelHolder<String>(new ArrayList<String>);

However, if you insist on using raw types, you can either suppress the warnings or simply have a List of objects (Neither of these are recommended)

@SuppressWarnings("unchecked")
public class GridModelHolder {
   private List  gridModel;

   public List getGridModel() {
    return gridModel;
   }
}

OR

public class GridModelHolder {
   private List<Object>  gridModel;

   public List<Object> getGridModel() {
    return gridModel;
   }
}
like image 151
Chetan Kinger Avatar answered Nov 04 '22 09:11

Chetan Kinger


Make the class take a generic. Apply that generic to the List. Also, the warning is valid (a collection type without a generic is a raw type). Something like,

class MyClass<T> {
    private List<T> gridModel;    
    public List<T> getGridModel() {
            return gridModel;
    }
}

If you really want to disable the type-checking then make the List generic on Object (which is what a raw type is) like

private List<Object> gridModel;    
public List<Object> getGridModel() {
        return gridModel;
}
like image 44
Elliott Frisch Avatar answered Nov 04 '22 09:11

Elliott Frisch


I'm sorry, that doesn't make sense; there's nothing wrong with returning Foo<?> if the API needs to. Even the Object class has a method like that.

Here's the list of public methods in JDK that return with wildcards:

(There are more in javax, but the list is too long to be posted on stackoverflow. See complete list )

java.awt.Font#getAttributes -> java.util.Map<java.awt.font.TextAttribute, ?>
java.awt.Toolkit#mapInputMethodHighlight -> java.util.Map<java.awt.font.TextAttribute, ?>
java.awt.datatransfer.DataFlavor#getDefaultRepresentationClass -> java.lang.Class<?>
java.awt.datatransfer.DataFlavor#getRepresentationClass -> java.lang.Class<?>
java.awt.im.InputMethodHighlight#getStyle -> java.util.Map<java.awt.font.TextAttribute, ?>
java.beans.BeanDescriptor#getBeanClass -> java.lang.Class<?>
java.beans.BeanDescriptor#getCustomizerClass -> java.lang.Class<?>
java.beans.EventSetDescriptor#getListenerType -> java.lang.Class<?>
java.beans.IndexedPropertyDescriptor#getIndexedPropertyType -> java.lang.Class<?>
java.beans.PropertyDescriptor#getPropertyEditorClass -> java.lang.Class<?>
java.beans.PropertyDescriptor#getPropertyType -> java.lang.Class<?>
java.io.ObjectStreamClass#forClass -> java.lang.Class<?>
java.io.ObjectStreamField#getType -> java.lang.Class<?>
java.lang.Class#asSubclass -> java.lang.Class<? extends U>
java.lang.Class#forName -> java.lang.Class<?>
java.lang.Class#getComponentType -> java.lang.Class<?>
java.lang.Class#getDeclaringClass -> java.lang.Class<?>
java.lang.Class#getEnclosingClass -> java.lang.Class<?>
java.lang.Class#getEnclosingConstructor -> java.lang.reflect.Constructor<?>
java.lang.Class#getSuperclass -> java.lang.Class<? super T>
java.lang.ClassLoader#loadClass -> java.lang.Class<?>
java.lang.EnumConstantNotPresentException#enumType -> java.lang.Class<? extends java.lang.Enum>
java.lang.Object#getClass -> java.lang.Class<?>
java.lang.annotation.Annotation#annotationType -> java.lang.Class<? extends java.lang.annotation.Annotation>
java.lang.annotation.IncompleteAnnotationException#annotationType -> java.lang.Class<? extends java.lang.annotation.Annotation>
java.lang.annotation.Repeatable#value -> java.lang.Class<? extends java.lang.annotation.Annotation>
java.lang.instrument.ClassDefinition#getDefinitionClass -> java.lang.Class<?>
java.lang.invoke.MethodHandleInfo#getDeclaringClass -> java.lang.Class<?>
java.lang.invoke.MethodHandleProxies#wrapperInstanceType -> java.lang.Class<?>
java.lang.invoke.MethodHandles$Lookup#lookupClass -> java.lang.Class<?>
java.lang.invoke.MethodType#parameterType -> java.lang.Class<?>
java.lang.invoke.MethodType#returnType -> java.lang.Class<?>
java.lang.ref.ReferenceQueue#poll -> java.lang.ref.Reference<? extends T>
java.lang.ref.ReferenceQueue#remove -> java.lang.ref.Reference<? extends T>
java.lang.reflect.Executable#getDeclaringClass -> java.lang.Class<?>
java.lang.reflect.Field#getDeclaringClass -> java.lang.Class<?>
java.lang.reflect.Field#getType -> java.lang.Class<?>
java.lang.reflect.Member#getDeclaringClass -> java.lang.Class<?>
java.lang.reflect.Method#getDeclaringClass -> java.lang.Class<?>
java.lang.reflect.Method#getReturnType -> java.lang.Class<?>
java.lang.reflect.Parameter#getType -> java.lang.Class<?>
java.lang.reflect.Proxy#getProxyClass -> java.lang.Class<?>
java.rmi.activation.ActivationDesc#getData -> java.rmi.MarshalledObject<?>
java.rmi.activation.ActivationGroupDesc#getData -> java.rmi.MarshalledObject<?>
java.rmi.activation.ActivationInstantiator#newInstance -> java.rmi.MarshalledObject<? extends java.rmi.Remote>
java.rmi.activation.Activator#activate -> java.rmi.MarshalledObject<? extends java.rmi.Remote>
java.rmi.server.LoaderHandler#loadClass -> java.lang.Class<?>
java.rmi.server.RMIClassLoader#loadClass -> java.lang.Class<?>
java.rmi.server.RMIClassLoader#loadProxyClass -> java.lang.Class<?>
java.rmi.server.RMIClassLoaderSpi#loadClass -> java.lang.Class<?>
java.rmi.server.RMIClassLoaderSpi#loadProxyClass -> java.lang.Class<?>
java.security.acl.Group#members -> java.util.Enumeration<? extends java.security.Principal>
java.security.cert.CertPath#getCertificates -> java.util.List<? extends java.security.cert.Certificate>
java.security.cert.CertStore#getCRLs -> java.util.Collection<? extends java.security.cert.CRL>
java.security.cert.CertStore#getCertificates -> java.util.Collection<? extends java.security.cert.Certificate>
java.security.cert.CertStoreSpi#engineGetCRLs -> java.util.Collection<? extends java.security.cert.CRL>
java.security.cert.CertStoreSpi#engineGetCertificates -> java.util.Collection<? extends java.security.cert.Certificate>
java.security.cert.CertificateFactory#generateCRLs -> java.util.Collection<? extends java.security.cert.CRL>
java.security.cert.CertificateFactory#generateCertificates -> java.util.Collection<? extends java.security.cert.Certificate>
java.security.cert.CertificateFactorySpi#engineGenerateCRLs -> java.util.Collection<? extends java.security.cert.CRL>
java.security.cert.CertificateFactorySpi#engineGenerateCertificates -> java.util.Collection<? extends java.security.cert.Certificate>
java.security.cert.CollectionCertStoreParameters#getCollection -> java.util.Collection<?>
java.security.cert.PolicyNode#getChildren -> java.util.Iterator<? extends java.security.cert.PolicyNode>
java.security.cert.PolicyNode#getPolicyQualifiers -> java.util.Set<? extends java.security.cert.PolicyQualifierInfo>
java.security.cert.X509CRL#getRevokedCertificates -> java.util.Set<? extends java.security.cert.X509CRLEntry>
java.time.chrono.ChronoLocalDate#atTime -> java.time.chrono.ChronoLocalDateTime<?>
java.time.chrono.ChronoLocalDateTime#from -> java.time.chrono.ChronoLocalDateTime<?>
java.time.chrono.ChronoZonedDateTime#from -> java.time.chrono.ChronoZonedDateTime<?>
java.time.chrono.Chronology#localDateTime -> java.time.chrono.ChronoLocalDateTime<? extends java.time.chrono.ChronoLocalDate>
java.time.chrono.Chronology#zonedDateTime -> java.time.chrono.ChronoZonedDateTime<? extends java.time.chrono.ChronoLocalDate>
java.util.IllegalFormatConversionException#getArgumentClass -> java.lang.Class<?>
java.util.PriorityQueue#comparator -> java.util.Comparator<? super E>
java.util.Properties#propertyNames -> java.util.Enumeration<?>
java.util.SortedMap#comparator -> java.util.Comparator<? super K>
java.util.SortedSet#comparator -> java.util.Comparator<? super E>
java.util.Spliterator#getComparator -> java.util.Comparator<? super T>
java.util.TreeMap#comparator -> java.util.Comparator<? super K>
java.util.TreeSet#comparator -> java.util.Comparator<? super E>
java.util.concurrent.AbstractExecutorService#submit -> java.util.concurrent.Future<?>
java.util.concurrent.ConcurrentSkipListMap#comparator -> java.util.Comparator<? super K>
java.util.concurrent.ConcurrentSkipListSet#comparator -> java.util.Comparator<? super E>
java.util.concurrent.CountedCompleter#firstComplete -> java.util.concurrent.CountedCompleter<?>
java.util.concurrent.CountedCompleter#getCompleter -> java.util.concurrent.CountedCompleter<?>
java.util.concurrent.CountedCompleter#getRoot -> java.util.concurrent.CountedCompleter<?>
java.util.concurrent.CountedCompleter#nextComplete -> java.util.concurrent.CountedCompleter<?>
java.util.concurrent.ExecutorService#submit -> java.util.concurrent.Future<?>
java.util.concurrent.ForkJoinPool#submit -> java.util.concurrent.ForkJoinTask<?>
java.util.concurrent.ForkJoinTask#adapt -> java.util.concurrent.ForkJoinTask<?>
java.util.concurrent.PriorityBlockingQueue#comparator -> java.util.Comparator<? super E>
java.util.concurrent.ScheduledExecutorService#schedule -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledExecutorService#scheduleWithFixedDelay -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledThreadPoolExecutor#schedule -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledThreadPoolExecutor#scheduleAtFixedRate -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledThreadPoolExecutor#scheduleWithFixedDelay -> java.util.concurrent.ScheduledFuture<?>
java.util.concurrent.ScheduledThreadPoolExecutor#submit -> java.util.concurrent.Future<?>
java.util.stream.Collectors#averagingDouble -> java.util.stream.Collector<T, ?, java.lang.Double>
java.util.stream.Collectors#averagingInt -> java.util.stream.Collector<T, ?, java.lang.Double>
java.util.stream.Collectors#averagingLong -> java.util.stream.Collector<T, ?, java.lang.Double>
java.util.stream.Collectors#counting -> java.util.stream.Collector<T, ?, java.lang.Long>
java.util.stream.Collectors#groupingBy -> java.util.stream.Collector<T, ?, M>
java.util.stream.Collectors#groupingBy -> java.util.stream.Collector<T, ?, java.util.Map<K, D>>
java.util.stream.Collectors#groupingBy -> java.util.stream.Collector<T, ?, java.util.Map<K, java.util.List<T>>>
java.util.stream.Collectors#groupingByConcurrent -> java.util.stream.Collector<T, ?, M>
java.util.stream.Collectors#groupingByConcurrent -> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, D>>
java.util.stream.Collectors#groupingByConcurrent -> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, java.util.List<T>>>
java.util.stream.Collectors#joining -> java.util.stream.Collector<java.lang.CharSequence, ?, java.lang.String>
java.util.stream.Collectors#mapping -> java.util.stream.Collector<T, ?, R>
java.util.stream.Collectors#maxBy -> java.util.stream.Collector<T, ?, java.util.Optional<T>>
java.util.stream.Collectors#minBy -> java.util.stream.Collector<T, ?, java.util.Optional<T>>
java.util.stream.Collectors#partitioningBy -> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, D>>
java.util.stream.Collectors#partitioningBy -> java.util.stream.Collector<T, ?, java.util.Map<java.lang.Boolean, java.util.List<T>>>
java.util.stream.Collectors#reducing -> java.util.stream.Collector<T, ?, T>
java.util.stream.Collectors#reducing -> java.util.stream.Collector<T, ?, U>
java.util.stream.Collectors#reducing -> java.util.stream.Collector<T, ?, java.util.Optional<T>>
java.util.stream.Collectors#summarizingDouble -> java.util.stream.Collector<T, ?, java.util.DoubleSummaryStatistics>
java.util.stream.Collectors#summarizingInt -> java.util.stream.Collector<T, ?, java.util.IntSummaryStatistics>
java.util.stream.Collectors#summarizingLong -> java.util.stream.Collector<T, ?, java.util.LongSummaryStatistics>
java.util.stream.Collectors#summingDouble -> java.util.stream.Collector<T, ?, java.lang.Double>
java.util.stream.Collectors#summingInt -> java.util.stream.Collector<T, ?, java.lang.Integer>
java.util.stream.Collectors#summingLong -> java.util.stream.Collector<T, ?, java.lang.Long>
java.util.stream.Collectors#toCollection -> java.util.stream.Collector<T, ?, C>
java.util.stream.Collectors#toConcurrentMap -> java.util.stream.Collector<T, ?, M>
java.util.stream.Collectors#toConcurrentMap -> java.util.stream.Collector<T, ?, java.util.concurrent.ConcurrentMap<K, U>>
java.util.stream.Collectors#toList -> java.util.stream.Collector<T, ?, java.util.List<T>>
java.util.stream.Collectors#toMap -> java.util.stream.Collector<T, ?, M>
java.util.stream.Collectors#toMap -> java.util.stream.Collector<T, ?, java.util.Map<K, U>>
java.util.stream.Collectors#toSet -> java.util.stream.Collector<T, ?, java.util.Set<T>>
java.util.zip.ZipFile#entries -> java.util.Enumeration<? extends java.util.zip.ZipEntry>
java.util.zip.ZipFile#stream -> java.util.stream.Stream<? extends java.util.zip.ZipEntry>
like image 35
ZhongYu Avatar answered Nov 04 '22 09:11

ZhongYu