Generic parameter: only diamond operator seems to work - java

Background: the question came up in this answer (the first revision of the answer, to be exact). The code presented in this question is reduced to the bare minimum to explain the problem.
Suppose we have the following code:
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
return new Sample<>();
}
public static void main(String... args) {
Sample<? extends Sample<?>> sample = Sample.get();
}
}
It compiles without warning and executes fine. However, if one tries to somehow define the inferred type of return new Sample<>(); in get() explicitly the compiler complains.
Up until now, I was under the impression that the diamond operator is just some syntactic sugar to not write explicit types and thus could always be replaced with some explicit type. For the given example, I was not able to define any explicit type for the return value to make the code compile. Is it possible to explicitly define the generic type of the return value or is the diamond-operator needed in this case?
Below are some attempts I made to explicitly define the generic type of the returned value with the corresponding compiler errors.
return new Sample<Sample> results in:
Sample.java:6: error: type argument Sample is not within bounds of type-variable T
return new Sample<Sample>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
Sample.java:6: error: incompatible types: Sample<Sample> cannot be converted to Sample<? extends Sample<?>>
return new Sample<Sample>();
^
return new Sample<Sample<?>> results in:
Sample.java:6: error: type argument Sample<?> is not within bounds of type-variable T
return new Sample<Sample<?>>();
^
where T is a type-variable:
T extends Sample<T> declared in class Sample
return new Sample<Sample<>>(); results in:
Sample.java:6: error: illegal start of type
return new Sample<Sample<>>();
^

The JLS simply says:
If the type argument list to the class is empty — the diamond form <> — the type arguments of the class are inferred.
So, is there some inferred X that will satisfy the solution? Yes.
Of course, for you to explicitly define such an X, you'd have to declare it:
public static <X extends Sample<X>> Sample<? extends Sample<?>> get() {
return new Sample<X>();
}
The explicit Sample<X> is compatible with the return type Sample<? extends Sample<?>>, so compiler is happy.
The fact that return type is a messed up Sample<? extends Sample<?>> is an entirely different story.

Instantiating Generics with Wildcards
There's a couple problems here, but before delving into them, let me address your actual question:
Is it possible to explicitly define the generic type of the return value or is the diamond-operator needed in this case?
It is not possible to explicitly instantiate a Sample<? extends Sample<?>> (or a Sample<?> for that matter). Wildcards may not be used as type arguments when instantiating a generic type, though they may be nested within type arguments. For example, while it is legal to instantiate an ArrayList<Sample<?>>, you cannot instantiate an ArrayList<?>.
The most obvious workaround would be to simply return some other concrete type that is assignable to Sample<?>. For example:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
public static Sample<? extends Sample<?>> get() {
return new X();
}
}
However, if you specifically want to return a generic instantiation of the Sample<> class containing wildcards, then you must rely on generic inference to work out the type arguments for you. There are a few ways to go about this, but it usually involves one of the following:
Using the diamond operator, as you are doing right now.
Delegating to a generic method that captures your wildcard with a type variable.
While you cannot include a wildcard directly in a generic instantiation, it's perfectly legal to include a type variable, and that's what makes option (2) possible. All we have to do is ensure that the type variable in the delegate method gets bound to a wildcard at the call site. Every mention of the type variable the method's signature and body then gets replaced with a reference to that wildcard. For example:
public class Sample<T extends Sample<T>> {
public static Sample<? extends Sample<?>> get() {
final Sample<?> s = get0();
return s;
}
private static <T extends Sample<T>> Sample<T> get0() {
return new Sample<T>();
}
}
Here, the return type of Sample<T> get0() gets expanded to Sample<WC#1 extends Sample<WC#1>>, where WC#1 represents a captured copy of the wildcard inferred from the assignment target in Sample<?> s = get0().
Multiple Wildcards in a Type Signature
Now, let's address that method signature of yours. It's hard to tell for sure based on what code you've provided, but I would guess that a return type of Sample<? extends Sample<?>> is *not* what you really want. When wildcards appear in a type, each wildcard is distinct from all others. There is no enforcement that the first wildcard and second wildcard refer to the same type.
Let's say get() returns a value of type X. If it was your intention to ensure that X extends Sample<X>, then you have failed. Consider:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
static class Y extends Sample<X> {}
public static Sample<? extends Sample<?>> get() {
return new Y();
}
public static void main(String... args) {
Sample<?> s = Sample.get(); // legal (!)
}
}
In main, variable s holds a value that is a Sample<X> and a Y, but not a Sample<Y>. Is that what you'd intended? If not, I suggest replacing the wildcard in your method signature with a type variable, then letting the caller decide the type argument:
class Sample<T extends Sample<T>> {
static class X extends Sample<X> {}
static class Y extends Sample<X> {}
public static <T extends Sample<T>> Sample<T> get() { /* ... */ }
public static void main(String... args) {
Sample<X> x = Sample.get(); // legal
Sample<Y> y = Sample.get(); // NOT legal
Sample<?> ww = Sample.get(); // legal
Sample<?> wx = Sample.<X>get(); // legal
Sample<?> wy = Sample.<Y>get(); // NOT legal
}
}
The version above effectively guarantees that, for some return value of type A, the returned value extends Sample<A>. In theory, it even works when T is bound to a wildcard. Why? It goes back to wildcard capture:
In your original get method, the two wildcards could end up referring to different types. In effect, your return type was Sample<WC#1 extends Sample<WC#2>, where WC#1 and WC#2 are separate wildcards that are not related in any way. But in the example above, binding T to a wildcard captures it, allowing the same wildcard to appear in more than one spot. Thus, when T is bound to a wildcard WC#1, the return type expands to Sample<WC#1 extends Sample<WC#1>. Remember, there is no way to express that type directly in Java: it can only be done by relying on type inference.
Now, I said this works with wildcards in theory. In practice, you probably won't be able to implement get in such a way that the generic constraints are runtime-enforceable. That's because of type erasure: the compiler can emit a classcast instruction to verify that the returned value is, for example, both an X and a Sample, but it cannot verify that it's actually a Sample<X>, because all generic forms of Sample have the same runtime type. For concrete type arguments, the compiler can usually prevent suspect code from compiling, but when you throw wildcards into the mix, complex generic constraints become difficult or impossible to enforce. Buyer beware :).
Aside
If all this is confusing to you, don't fret: wildcards and wildcard capture are among the most difficult aspects of Java generics to understand. It's also not clear whether understanding these will actually help you with your immediate goal. If you have an API in mind, it might be best to submit it to the Code Review stack exchange and see what kind of feedback you get.

Related

How Automatic Type Inference works if the constructor parameter is not generic

Case 1:
class Gen3<T extends Number> {
T val;
<T extends String> Gen3(String ob){
}
}
Here compiler doesn't give any error, but it should give right? Because here are two contradicting bounds for T. Please help me in understanding this.
Case 2:
class Gen3<T extends Number> {
T val;
<T extends String> Gen3(String ob) {
}
}
Suppose if I write following to test the above class
Gen<Integer> a = new Gen<>("r");
Now how automatic type inference would work here?
Please help in understanding this.
There are no two contradicting bounds of T. There are two type variables that happen to have the same name. In the constructor, the type parameter T hides the type parameter of the class level.
Note that the issue is not with the different type bounds. If you actually try to do something with the type parameter, such as:
class Gen3<T extends Number> {
T val;
<T extends Number> Gen3(T ob) {
val = ob;
}
}
This won't pass compilation even if both Ts have the same type bound, since the type parameter of ob is different than the type parameter of val.
"Because here are two contradicting bounds for T" - no. There simply a two separate definitions of T that have nothing to with each other. The T on the constructor hides the T of the class, same with local variables vs. fields of the same name. A "proper" IDE will tell you that the inner T hides the outer T and is unused.
This "use case" of Generics doesn't make sense in multiple aspects. With the <T extends String> clause you introduce a type variable that you don't use and don't give the compiler a chance to replace it with a concrete type in a given call situation.
Your definition is equivalent to the following (I just renamed the two different type variables to have different names, making the discussion easier):
class Gen3<T extends Number> {
T val;
<U extends String> Gen3(String ob) {
}
}
The <U extends String> clause tells the compiler: "The following constructor will use a type parameter U, and I only allow U to be String or a subclass of String". As others already said, String is final, so U can only be String, so it isn't really a variable type, and declaring a variable type that can't vary doesn't make sense. I'll continue with a modified version:
class Gen3<T extends Number> {
T val;
<U extends Collection> Gen3(String ob) {
}
}
If you do Gen<Integer> a=new Gen<Integer>("r");, how should the compiler find out the concrete class to replace U with? The <Integer> part applies to the T variable, so it doesn't help for U. As you don't refer to U in any of the arguments, there's no hint for the compiler.
The idea of Generics is that a class has some elements where you want to allow for varying types, and allow the compiler to flag misuse, e.g. add an Integer to a List<String>:
List<String> myList = new ArrayList<String>();
myList.add(new Integer(12345));
Here, the compiler can match the generic List<E> type parameter E to be a String (from the List<String> declaration). In this context, the gegeric List.add(E e) method declaration becomes an add(String e), and doesn't match the usage with new Integer(12345), which isn't a String, allowing the compiler to flag the error.
Summary:
Introduce a type parameter only if you give the compiler a chance to deduce it from the call arguments.

How to use type parameter correctly

I'm confused about type parameter.In the following code, types inside CollectionData angle bracket can be called type parameter. Types inside ArrayList and Generator are not type parameter and should be the same in CollectionData. How to understand it?
//correct
public class CollectionData<T> extends ArrayList<T> {
CollectionData(Generator<T> generator) {
}
}
interface Generator<E> {
E next();
}
Following is wrong. But I can't helping writing this sometimes.
// wrong
public class CollectionData<T> extends ArrayList<E> {
CollectionData(Generator<W> generator) {
}
}
interface Generator<E> {
E next();
}
Added: In the example above, can type variables be only defined in angle bracket of CollectionData, rather than ArrayList or Generator ? Then ArrayList and CollectionData use these types. Right?
These generic types are just type variables.
Writing
public class CollectionData<T> extends ArrayList<E> {
is similar to writing
public int func(int x) {
return y;
}
If there is no variable y, then this code is wrong.
But because you declared x, you can use x where appropriate:
public int func(int x) {
return x;
}
The same is true for generic types.
When you write
public class CollectionData<T> extends ArrayList<T>
you are saying that the T inside ArrayList<T> is the identical T as given by the generic type argument to your class.
The same is true for the constructors's parameter type.
So, to help you knowing when to write the "correct" code: if you require that both generic types are the same (e.g. the generic type given to your class, and the generic type of your base class or a function's argument), then you have to use the same type variable.
This is the same as you would use the same variable inside a function when you need the exact value that is stored in that variable.
Edit for your addendum:
The generic types can only be declared on the class name:
public class CollectionData<T> extends ArrayList<E>
Declares T, but only uses E. This, of course, requires that E has been declared as a generic type (or class, for the fact) somewhere. (When E is a generic type, this should only be valid when CollectionData<T> is inside an outer class which declares E.)
Of course, generic types can also be declared for every function:
public <T> void foo(T x) { x.baz(); }
This declares T and shadows any definition of T.
For example, in this context
public class Foo<T> {
public <T> void foo(T x) { x.baz(); }
}
The T inside the foo method is not the T declared by the class Foo.
This works—again—like shadowing variables:
public class Foo {
int x;
public int foo(int x) {
// returns x from argument, not the field of the class
return x;
}
}
I will assume that you are trying to fill your CollectionData instances with the content passed-in by the Generator in the constructor.
You need to use the same type parameter when you require a match. In your first example, all of the type parameters in CollectionData are T. Since they have the same identifier, the compiler knows that they must match.
In the second example, you have type parameters T, W and E. This does not work because you cannot necessarily fill a list of E or T with instances of W. The compiler has no way of knowing that the instance types are compatible.
I think what's causing your confision is the difference between defining a generic type and using one.
Defining a generic type is basically like defining a function - you define it's parameters and how it uses it's parameters.
Using a generic type means it has to be fully understandable by the compiler - it cannot depend on a yet to be defined type.
Here, in your example, the definition ends with the word extends. Everything that follows is using generic types and so cannot use types that are not known, except for the type parameters from the definition header. The analogy to function definitions should help clear the confusion.

Java Self-Referential Generics With Wildcards

Is it possible to specify that an unknown generic type is self-referential?
A failed attempt:
import java.util.*;
class Generics {
public enum A { A1, A2 }
public enum B { B1, B2 }
public static List<? extends Enum<?>> listFactory(String[] args) {
if (args.length == 0) {
return new ArrayList<A>(Arrays.asList(A.A1, A.A2));
} else {
return new ArrayList<B>(Arrays.asList(B.B1, B.B2));
}
}
public static void main(String[] args) {
List<? extends Enum<?>> lst = listFactory(args);
dblList(lst);
System.out.println(lst);
}
public static <EType extends Enum<EType>> void dblList(List<EType> lst) {
int size = lst.size();
for (int i = 0; i < size; i++) {
lst.add(lst.get(i));
}
}
}
This results in a compilation error:
Generics.java:17: error: method dblList in class Generics cannot be applied to given types;
dblList(lst);
^
required: List<EType>
found: List<CAP#1>
reason: inferred type does not conform to declared bound(s)
inferred: CAP#1
bound(s): Enum<CAP#1>
where EType is a type-variable:
EType extends Enum<EType> declared in method <EType>dblList(List<EType>)
where CAP#1 is a fresh type-variable:
CAP#1 extends Enum<?> from capture of ? extends Enum<?>
1 error
Ideally, the return type of listFactory() would signal that the list contains self-referential generic types (whose exact type is unknown).
Is this possible? If so, what should the types of listFactory() and lst be?
Effective Java Item 28 discourages using wildcards in return types:
Do not use wildcard types as return types. Rather than providing additional flexibility for your users, it would force them to use wildcard types in client code.
Properly used, wildcard types are nearly invisible to users of a class. They cause methods to accept the parameters they should accept and reject those they should reject. If the user of a class has to think about wildcard types, there is probably something wrong with the class's API.
This is a good example of exactly the issues EJ describes. listFactory() is really just returning a List<Enum<?>> but by declaring a wildcard return type you have to jump through hoops to accomplish seemingly simple tasks.
If you instead give listFactory() a signature like so:
public static List<Enum<?>> listFactory(String[] args)
You can clean up the signature of dblList() too:
public static <E> void dblList(List<E> lst)
In Java, a type argument is either a concrete type, a wildcard type, or a type variable. A concrete type is not flexible enough for your use case, and wildcards can not be constrained to be self referential (because each occurrence of a wildcard can stand for a different type).
This leaves type variables, which can be constrained to be self referential, but are provided by the caller of the constructor or method, not the callee, so we can't just do:
<E extends Enum<E>> List<E> listFactory(String[] args);
because somebody might invoke this with an incorrect type argument.
One way to work around this is to decorate the return type:
interface EnumList<E extends Enum<E>> extends List<E> {
}
EnumList<?> listFactory(String[] args);
A caller can then do:
EnumList<?> x = listFactory(args);
dblList(x);
where dblList uses wildcard capture to manipulate the list:
<E extends Enum<E>> void dblList(List<E> list);
It is worth noting that this makes the method signatures quite a bit harder to write, so you should only do this if the method in question actually needs to know that the type is self referential. I mention this because your dblList method does not, and could simply be written as:
<E> void dblList(List<E> list);
instead.

Discrepancy in Generic parametric polymorphism

public class Foo<T extends Bar>{
private Class<T> _type;
public Foo( Class<T> _type ){
this._type = _type;
}
public Collection<T> hypothetical( List<T> items ){ //PROBLEMATIC
return dostuffWithItems( items );
}
}
Usage:
Foo<? extends ChildBar> foo = new Foo<ChildBar>( ChildBar.class );
List<ChildBar> items = ( List<ChildBar> ) foo.hypothetical( new ArrayList<ChildBar>() ); //COMPILER ERROR: The method hypothetical(List<capture#2-of ?>) in the type Foo<capture#2-of ?> is not applicable for the arguments (List<ChildBar>)
The compiler would either accept
casting List<ChildBar> items argument to List<?>
or changing the hypothetical( List<T> items ) signature to either
a) hypothetical( List<ChildBar> items ) or
b) hypothetical( List<? extends Bar> items )
However, none of the alternatives assure that the hypothetical method's List items argument T type is the equivalent runtime type of the Foo class T parametric type. I am currently using an extra method to verify the parametric types at the moment.
Is there a better way within Java generics constructs to achieve this automatically without the extra logic? Or better yet, why can I not declare foo as Foo<? extends Bar> and then fill in the actual type parameter at runtime?
I edited your code and added the missing stuff to make it compilable, and I can confirm that the only problematic parts are:
The missing dostuffWithItems method.
The typos with the hypothetical method name.
Assigning a Collection<ChildBar> to a List<ChildBar>.
The first two are easy to fix.
The last one requires you to either change the change the API method, or change the code where you are calling it. Neither of these is (IMO) problematic. Furthermore, the
It is worth noting that you would get all of these errors if the types were non-generic. You can't assign a Collection to a List without a typecast.
Here's my code for you to play with. (Copy and paste into appropriately named files ...)
public class Bar {
}
public class ChildBar extends Bar {
}
import java.util.*;
public class Foo<T extends Bar> {
private Class<T> _type;
public Foo( Class<T> _type ) {
this._type = _type;
}
public Collection<T> hypothetical( List<T> items ) {
return items; // dummy implementation ...
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Foo<ChildBar> foo = new Foo<ChildBar>( ChildBar.class );
Collection<ChildBar> items =
foo.hypothetical( new ArrayList<ChildBar>() );
}
}
The accepted answer doesn't precisely explain why the snippet in the question (after edits) is rejected by the compiler.
We start from the observation that the snippet from #Stephen C's answer is accepted, while revision 8 of the question is rejected. The difference is: in the latter version the variable foo is declared with a wildcard-parameterized type Foo<? extends ChildBar>, while Stephen C had copied Foo<ChildBar> from an earlier revision (we all seem to agree that this is a suitable way to resolve the compile error).
To understand why this difference is crucial please see that with Foo<? extends ChildBar> foo this wildcard propagates as a capture into the signature for the invocation of foo.hypothetical, so this invocation is rendered as hypothetical(List<capture#2-of ?>), meaning that the parameter has an unknown (upper-bounded) type parameter. List<ChildBar> is not compatible to that type, hence the compile error.
Also note that all mentions of "runtime" in this thread are inappropriate, all this is statically resolved at compile time. Perhaps you meant invocation type, or type of the actual argument, as opposed to the declared type (of the formal parameter). The actual runtime type is unknown to the compiler.
This seems to be currently impossible in Java.
Foo<? extends ChildBar> foo = new Foo<ChildBar>( ChildBar.class );
This leave foo with an ambiguous parametric type. It is obvious that ChildBar would become the true de facto parametric type. The call to the foo.hypothetical() method with the List<ChildBar> exposes this assumption to be untrue. Although foo.hypothetical only accepts a List<> argument containing elements of the foo parametric type, it still fails to recognize that the argument was a list of ChildBar objects.
For this use case, the object parametric type must be specified during foo declaration in order make it a part and parcel of the foo runtime reference.
Foo<ChildBar> foo = new Foo<ChildBar>( ChildBar.class );
All conforming List<ChildBar> arguments of the foo.hypothetical method will now correctly be accepted as carrying elements of the foo's declared parametric type.

What is the meaning of the <?> token in Java?

What is the meaning of the <?> token in this code copied from www.JavaPractices.com? When I replace it with the more conventional looking <T> used for generic types, it fails to compile. (Error: T cannot be resolved to a type.) Why?
// <?> occurs 3 times in the entire program. When it is replaced with <T> the
// program no longer compiles.
void activateAlarmThenStop()
{
Runnable myPeriodicTask = new PeriodicTask();
ScheduledFuture<?> soundAlarmFuture =
this.executorService.scheduleWithFixedDelay(myPeriodicTask,
startT,
period,
TimeUnit.SECONDS
);
Runnable stopAlarm = new StopAlarmTask(soundAlarmFuture);
this.executorService.schedule(stopAlarm, stopT, TimeUnit.SECONDS);
}
private final class StopAlarmTask implements Runnable
{
StopAlarmTask(ScheduledFuture<?> aSchedFuture)
{
fSchedFuture = aSchedFuture;
}
public void run()
{
CConsole.pw.println("Stopping alarm.");
fSchedFuture.cancel(doNotInterruptIfRunningFlag);
executorService.shutdown();
}
private ScheduledFuture<?> fSchedFuture;
}
Edit: Of course when we use generic type tokens like <T>, it has to appear in the class declaration. Here there is no <T> nor <?> in the class declaration but it still compiles and runs properly.
It fails to compile, because your class is not generic (nor any of your methods). In this particular example joker (?) means that ScheduledFuture may be parametrized by anything.
Sometimes, there is no sense to make the whole class generic if you use another generic class inside and you don't know the exact type that will be used.
In this example you had three options:
make StopAlarmTask generic (there is no sense in this case)
use concrete type in ScheduledFuture, but then it would be only one possible result type, for example String or Integer
use wildcard (< ? >) - it allows to retrieve anything as a result of FutureResult (String, Integer, your custom class). You can also narrow the scope of a possible generic type into some subclasses, for example ScheduledGeneric< ? extends MyObject > or into superclasses: ScheduledGeneric< ? super MyObject >
This is an example of using wildcard in a type argument. i.e. a generic type.
A wildcard parameterized type is an instantiation of a generic type where at least one type argument is a wildcard. Examples of wildcard parameterized types are Collection<?> , List<? extends Number> , Comparator<? super String> and Pair<String,?> .
A wildcard parameterized type denotes a family of types comprising concrete instantiations of a generic type. The kind of the wildcard being used determines which concrete parameterized types belong to the family.
Assuming this.executorService is a subtype of ScheduledExecutorService (available since Java 1.5), the return type of scheduleWithFixedDelay() is ScheduledFuture<?>. You can't change the return type from ScheduledFuture<?> to ScheduledFuture<T>, ScheduledFuture<Integer> or anything else for that matter. You could, however, change it to just ScheduledFuture since <?> is a wildcard generic type parameter that approximates a raw type for backward compatibility.
See What is a raw type and why shouldn't we use it? for a good discussion on raw types and generics.
That is Generic Type... usually we set String, Object, or any other objects as generic types... but here they make it general. and generic type stands for the value it can store or hold. its generally used in Collections..
well there is no much diff between the both.. - takes all kind of objects
<T>-is also called `formal type parameter` makes use of what ever type of object you pass in .. for instance you can do this with <T> and not with <?>
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
for more see http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf and http://download.oracle.com/javase/tutorial/java/generics/gentypes.html
A letter in brackets like <T> would be a type parameter. You would say class StopAlarmTask<T> to mean that you are parameterizing the type StopAlarmTask with the type T. The type parameter T would become a part of the type, sort of like a constructor argument becomes part of a new instance.
Then, whenever you declared a StopAlarmTask, you would provide a type, e.g. String, to fill in the type parameter T. You could then refer to that type parameter within the class body. For example, you could define methods which take a T or return a T, or parameterize member variables like fSchedFuture with T. For example, if you parameterized a declaration of StopAlarmTask<T> as StopAlarmTask<String>, then String would be captured as T and wherever you used T within that StopAlarmTask it would act as String.
However, in the code you have listed, StopAlarmTask does not have a type parameter and cannot be parameterized with any type. There is no captured type to refer to as T within the class body.
On the other hand, <?> means "I don't know which type it will be; I don't even know that it will be the type that someone has used to parameterize StopAlarmTask."
You could have parameterized StopAlarmTask<T>, and in that case you could have two variables:
private ScheduledFuture<T> fSchedFuture1;
private ScheduledFuture<?> fSchedFuture2;
The first declaration says that the type parameter of the ScheduledFuture is the same as the type parameter of the enclosing StopAlarmTask. E.g. StopAlarmTask<String> would make fSchedFuture1 into a ScheduledFuture<String>. The second declaration says that we don't know what the type parameter of the ScheduledFuture is, even if we know the type parameter of the enclosing StopAlarmTask.
The joker ? can hold any type. If you want to use the same type for all methods/members you can make the whole class generic. By writing StopAlarmTask<T> you define the type T in the whole class.
private final class StopAlarmTask<T> implements Runnable
{
StopAlarmTask(ScheduledFuture<T> aSchedFuture)
{
fSchedFuture = aSchedFuture;
}
public void run()
{ /* */ }
private ScheduledFuture<T> fSchedFuture;
}
It can take any parameter like Object,String,Integer.... and so on
Now when you plan to use generics then you have to provide the type inside the angel bracket.
EDIT:
<?> is strictly appliable to Collections.
<T> used as type or template for your normal class
StopAlarmTask is not a generic type.
In the following example, you would not think Foo is a generic type.
class Foo
{
Foo(int i)
{ }
doStuff(List<Integer> numbers)
{ }
}
The fact that the constructor of StopAlarmTask uses a generic parameter does not make the class generic any more than doStuff() makes Foo generic.
Use <?> to "refer to" the the declaration of a generic type in a generic way, that is, without specificity. In StopAlarmTask it just happens to be a constructor parameter. It is an "employment of" a generic type and not a declaration of a generic type because it is "merely" a parameter declaration.
In other words, the short answer is that the parameter in the method
StopAlarmTask(ScheduledFuture<?> aSchedFuture)
{ ... }
is applicable for all objects that are instances of ScheduledFuture<T> for all T.
The following is further background on generics.
Use <T> or <E> or whatever to declare the generic type ScheduledFuture<T>. Specifically, <?> would not be used in the declaration of ScheduledFuture<> because the convention is to use a single uppercase letter.
Note that the following test code, if fed to a compiler, will show that the first class compiles but the second does not, so to say that there is a convention to use a letter would actually be an understatement.
class TGeneric1<E> {
List<E> list = new ArrayList<E>();
TGeneric1(E value) {
this.list.add(value);
}
E getHead() {
return this.list.get(0);
}
}
class TGeneric2<?> {
List<?> list = new ArrayList<?>();
TGeneric2(? value) {
this.list.add(value);
}
? getHead() {
return this.list.get(0);
}
}
Illustrated in the following test code, there is no single letter constraint, so the following is also correct.
class TGeneric1<EE> {
List<EE> list = new ArrayList<EE>();
TGeneric1(EE value) {
this.list.add(value);
}
EE getHead() {
return this.list.get(0);
}
}

Categories

Resources