Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic type in class declaration

I have

1) a basic interface,

2) a few classes that implement this interface,

3) and a generic class that I want to accept, as a parameter, any of the implementing classes

I have tried the following:

public class Foo extends Bar<? extends SomeInterface> {

    public Foo(List<? extends SomeInterface> someInterfaceList) {
        super(someInterfaceList);
    }

    ...
}

I receive the error No Wildcard Expected. Elsewhere in my code I have statements such as List<? extends SomeInterface> and I receive no errors, so why am I running into problems here? How can I fix this problem and still get the desired results?

I have tried search 'No Wildcard Expected' and 'wildcard in class declaration' to no avail. Thanks in advance!

like image 591
Daiwik Daarun Avatar asked Aug 25 '14 02:08

Daiwik Daarun


People also ask

What is a generic declaration?

A generic class declaration looks like a non-generic class declaration, except that the class name is followed by a type parameter section. As with generic methods, the type parameter section of a generic class can have one or more type parameters separated by commas.

What is generic type?

Definition: “A generic type is a generic class or interface that is parameterized over types.” Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.

How do you define a generic class in Java?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.


Video Answer


2 Answers

It sounds like you want to declare a generic type argument that you will reference elsewhere. Wildcards only make sense when the type is used only once, and when declaring a generic type parameter for a class this doesn't make any sense.

Try this instead:

public class Foo<T extends SomeInterface> extends Bar<T> {

    public Foo(List<T> someInterfaceList) {
        super(someInterfaceList);
    }

    ...
}

As your code was written, there was no way for the user of your class to specify the generic type argument for Bar<>, since Foo wasn't itself a generic type.

Further, if this were possible, it would have been possible for the generic argument to Bar<> to be different than the generic argument to List<> -- as long as both types implemented SomeInterface there would not be a compile-time issue with these definitions, but there could have been a much more confusing error message later when you incorrectly assumed that both types must be the same.

So, declare the generic type once as a generic argument to the Foo class, and then use that type (T in my example) elsewhere to refer to that type instead of accepting some new generic type argument that may not refer to the same type.

like image 200
cdhowie Avatar answered Oct 07 '22 10:10

cdhowie


I'm not exactly sure what you're looking for, so it might help if you could provide a little more detail. Perhaps you could be a little more specific about how you're planning to instantiate and use these objects?

Anyways, I think you might be looking for something like this:

import java.util.List;

public class Foo<T extends SomeInterface> {
  public Foo(List<T> someInterfaceList) {
    for (T item : someInterfaceList) {
      // do something with each item
    }
  }
}

class Bar<T> {}

interface SomeInterface<T> {
  T x(T y);
}

Or, alternatively, you could just use the following for the constructor:

public Foo(List someInterfaceList) {

but you wouldn't have an easy way of getting the type T of the items in the list.

like image 22
blevinstein Avatar answered Oct 07 '22 10:10

blevinstein