what is the difference between ? and T in class and method signatures? - java

why does
public interface ArrayOfONEITEMInterface <T extends ONEITEMInterface>{
public List<T> getONEITEM();
}
compile, but not
public interface ArrayOfONEITEMInterface <? extends ONEITEMInterface>{
public List<?> getONEITEM();
}
what is the difference between ? and T in class and method signatures?

? is a wildcard and means any subclass of ONEITEMInterface including itself.
T is a specific implementation of ONEITEMInterface in this case.
Since ? is a wildcard, there is no relation between your ? in the class declaration and the ? in your method declaration hence it won't compile. Just List<?> getONEITEM(); will compile though.
The first scenario means the entire class can handle exactly one type of Bar per instance.
interface Foo<T extends Bar> {
List<T> get();
}
The second scenario allows each instance to operate on any subtype of Bar
interface Foo {
List<? extends Bar> get()
}

T is a placeholder for a type that will be provided by an implementing or instantiating class.
? is a placeholder saying "I don't know or care what the generic type is" generally used when the work you'll do on the container object doesn't need to know the type.
The reason you can't use '?' in the class/interface definition is because there's the value is saying defining the name of the placeholder (and the type will be provided elsewhere). Putting a '?' doesn't make sense.
Furthermore, the placeholder doesn't need to be T, it can any standard Java variable. By convention, it is one capital character, but need not be.

? allows you to have a list of Unknown types, where as T requires a definite type.

The clause <T extends ONEITEMInterface> is declaring a type parameter named T. This allows your generic type, ArrayOfONEITEMInterface, to refer to the parameter elsewhere. For example you can declare a method like void add(T t).
Without naming the type parameter, how would you refer to it? If you never refer to the type parameter, why is your type generic in the first place? For example, you don't need a parameterized type to do something like this:
public interface ArrayOfONEITEMInterface {
List<? extends ONEITEMInterface> getONEITEM();
}
It doesn't make sense to declare an anonymous type parameter, so it is syntactically illegal.

Related

Using a Generic Class as Upper Bound of a Type Parameter

I'm struggling with generic bounds for type parameters in Java. What I want to achieve is the following:
I have a generic class (Generic<> (1) in the sample code)
I have a generic class where the type parameter should scope over types of the first generic class (UsingGeneric<> (2); this is already strange, as it forces me to repeat the Comparable constraint)
I then want to instantiate this second class with a third class (MyGeneric (3)) which extends a concrete application of the first class.
Think of it like this: You have a generic container class where the elements are constrained. You have a generic iterator class that scopes over such containers. Now you want to create a concrete iterator for a concrete container.
The problem: Statement (4) won't compile, complaining:
Type parameter MyGeneric is not within its bound; should extend Generic<MyGeneric>.
The problem seems to be that Java forces me to repeat the type variable in the upper bound - which is kind of nonsensical as, to stay with the container example, I don't want my concrete container to be of a type of "container of container". I still want it to be of type "container of comparable". I.e the UsingGeneric class should have a signature where the primary type variable is decoupled from the type variable of the upper bound, somewhat like UsingGeneric<T extends Generic<S> & Comparable<S>>. Which is not possible, AFAIK.
What am I doing wrong?
Sample code:
class Test {
static class Generic<E extends Comparable<E>> {} // (1)
static class UsingGeneric<T extends Generic<T> & Comparable<T>> {} // (2)
static class MyGeneric extends Generic<Integer> {} // (3)
static UsingGeneric<MyGeneric> myUsingGeneric; // (4) - won't compile
}
The reason your current code doesn't compile is because:
class UsingGeneric<T extends Generic<T> & Comparable<T>> { ... }
Requires that the type argument used must implement both Generic<T> and Comparable<T>. The Integer class may implement the latter but does not implement the former, thus the compilation error. And the reason you have to specify the Comparable bounds again is because UsingGeneric has declared a new type parameter, T, which is being used as the type argument to the Generic bound, which is a parameterized type in this context. Since the type parameter of Generic is bounded by Comparable you must ensure the type parameter of UsingGeneric has compatible bounds.
That said, what you seem to be looking for is a way to specify the Comparable type used with the Generic type, while not requiring that the type implements both interfaces. This will require two type parameters:
class UsingGeneric<T extends Generic<E>, E extends Comparable<E>> { ... }
This may seem redundant at first but all the information is necessary. Now we have E being used as the type argument of the Generic bound of T while allowing E to be a different type than T. But again, since the type parameter of Generic is bounded by Comparable we have to make sure E has compatible bounds.

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!
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.
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.

Clarification about wildcards (Generics) in Java

I have recently started reading Core Java. But I am having a hard time grasping the concept of wildcards.
Specifically, I'm confused about the difference between the following:
public class A<T extends {some_class}> {/*...*/}
and
public class A<? extends {some_class}> {/*...*/}
Can anyone help me understand the difference if there is at all?
The difference is that you cannot use the ? elsewhere while you can use T. For example:
public class Foo<T extends Number> {
T value; // you can declare fields of type T here
int foo() {
// Since you said T extends Number, you can call methods of Number on value
return value.intValue();
}
}
So why would you use ? at all? If you don't need the type. It wouldn't make sense to use it in a class definition any way that I can think of. But you could use it in a method like this:
int getListSize(List<?> list) {
return list.size();
}
Any kind of method where you're more interested in the overall class and it has a method that doesn't involve the paramaterized type would work here. Class.getName() is another example.
They are the same, except with the wildcard you can't refer to the type in the code of your class. Using T names the type.
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). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.
The Type T is a defined type or known type
Hope this helps
? extends some class or T extends some_class
means some_class itself or any of its children and anything that would work with instanceof some_class.
As per conventions T is meant to be a Type and ? is unknown type.

Capturing method argument type and ask for corresponding class object

Given the following scenario
class Base { }
class Extended extends Base {}
I can easily ask for a class object in a generic class's constructor that is some subclass of the generic type.
class Test<T extends Base> {
Test(Class<? extends T> test) { }
}
This way I can do all of the following
new Test<Base>(Base.class);
new Test<Base>(Extended.class);
new Test<Extended>(Base.class); // This is not allowed by the compiler
new Test<Extended>(Extended.class);
what is exactly what I want. However, I cannot figure out how I can achieve the same constraint when using a generic methods like this:
<T extends Base> void test(T x, Class<? extends T> test) { }
With this definition, all of the following are permitted by the compiler:
test(new Base(), Base.class);
test(new Base(), Extended.class);
test(new Extended(), Base.class); // even though Base is not a subclass of Extended
test(new Extended, Extended.class);
I figure this is because of type inference and Java determining
<Base>test(new Extended(), Base.class)
instead of
<Extended>test(new Extended(), Base.class)
But how can I enforce the latter inference method?
Thanks for help!
For future readers: In the first version of this question I called Base A and Extended B. I later clarified this notation. This notation is however used in the answers.
This is a problem in computer science, and as such, can be solved by another level of indirection:
<T extends A, U extends T> void test(T x, Class<U> test) {}
In this case, we use one type variable (bounded to A) to capture the type of the object parameter, and a second one (bounded to the first) to constrain the type of the class parameter.
If i write this example out and feed it to javac (1.6.0_26), it duly tells me:
Test.java:14: cannot find symbol
symbol : method test(B,java.lang.Class<A>)
location: class Test<T>
test(b, A.class);
^
1 error
As #JohnB intimates in his comment, you can defeat this by writing:
this.<A, A>test(b, A.class);
Or by using raw types.
OK, I will try this in two parts. First, I don't think you can do what you want because the caller could always specify the super class as the generic and then pass a subclass as the first argument.
Second, I think trying to make this a compile-time check is the wrong approach because the user could always just choose to use a raw type and ignore all the generics. You should just make this a run-time check and provide appropriate documentation.
Generics are not for imposing arbitrary "restrictions". Generics are only for type safety, i.e. avoiding unsafe casts. There is no type-safety reason to have the restriction that you present. There is no function test in which test(new Base(), Base.class); would be type-safe, but test(new Extended(), Base.class); would not be.
I believe the answer is that in the first case you specify the generic type: new Test<B>(...). Notice the <B>. However in the second case you do not specify the generic type: test(a, A.class) therefore you allow the compiler to see if it can determine a generic type that works. In the case of test(b, A.class), <A> works because b is an instance of A.
Try something like: myInstance.<B>test(b, A.class)

Method type parameter only used once in the signature - is there a point?

The Generic Methods tutorial has this helpful example:
public <T extends E> boolean addAll(Collection<T> c);
However, [...] the type parameter T is used only once. The return type
doesn't depend on the type parameter, nor does any other argument to
the method (in this case, there simply is only one argument). [...]
If that is the case, one should use wildcards.
The codebase of the project I am working on has a few methods like this:
public <T extends Something> T getThing();
and (not in the same interface)
public <D> void storeData(int id, D data);
Is there any point in having the method type parameter instead of using the bound (Something above, Object below) directly?
(Note that in the former case, all of the few implementations are annotated with #SuppressWarnings("unchecked") and the point could be to hide this warning from the user of the method, but I am not sure this is a laudable achievement.
In the latter case, some implementations use reflection to store instances of different classes differently, but I do not see how this is facilitated by the type parameter.)
There are five different cases of a type parameter appearing only once to consider.
1) Once in return type position:
1.a) Return type is the type variable
public <T extends Something> T getThing();
This should be a red flag: The caller can arbitrarily choose an expected return type and the callee has no way of knowing the chosen type. In other words the implementation can't guarantee the returned value will be of the specified return type unless it (a) never returns, (b) always throws an exception or (c) always returns null. In all of these cases the return type happens to be irrelevant altogether.
(Personally I don't mind methods like these if the code is very "dynamic". I.e. you're running the risk of a class cast exception anyway and the method boundary is still early enough for the exception to be raised. A good example is deserialzation. All parties calling the method have to know and understand this though..)
1.b) Type variable is contained in return type, but not the return type itself
Very common and valid. Examples are the various factory methods in guava, like Lists.newArrayList().
2) Once in parameter type position:
2.a) Simple type parameter
public static <E> void shuffle(List<E> list);
Note that the implementation actually needs the type parameter in order to shuffle the elements. Nonetheless, the caller should not have to be bothered with it. You can write an internal helper method that "captures" the wildcard:
public static void shuffle(List<?> list) {
shuffleWithCapture(list);
}
private static <E> void shuffleWithCapture(List<E> list) {
// implementation
}
2.b) Type parameter with multiple bounds
public static <T extends Foo & Bar> void foo(T);
public static <E extends Foo & Bar> void foo(List<E>);
Since Java does not allow intersection types anywhere but in type parameter bounds, this is the only way to express these signatures.
2.c) Type parameter bound contains the type parameter variable
public static <T extends Comparable<? super T>> void sort(List<T> list);
To express that the elements of the list must be comparable with each other, one needs a name for their type. There is no way to eliminate such type parameters.
The first one -
public <T extends Something> T getThing();
will cast the return type to the assigned one and generally not safe (compiler warns you about it) and so may throw ClassCastException. but since it doesn't take any parameter I assume it will always return SomeThing and generic type over there is useless.
The second one I think is also useless as it will allow any type, so better to use Object instead
Such declarations make code less readable and doesn't provide any benefit as well, I'll recommend to use -
public Something getThing();
and
public static void storeData(int id, Object data);

Categories