I just saw this C# question and wondered, if something similar could happen in Java. It can, with
class A<T> {
A(Integer o) {...}
A(T o) {...}
}
the call
new A<Integer>(43);
is ambiguous and I see no way how to resolve it. Is there any?
You can drop the generics during construction (and suppress a warning):
A<Integer> a = new A(42);
or, less preferably use reflection (where again you'd have to suppress warnings)
Constructor<A> c = A.class.getDeclaredConstructor(Integer.class);
A<Integer> a = c.newInstance(42);
Yes, members of a parameterized type JLS3#4.5.2 can end up in conflicts that are precluded in a normal class declaration(#8.4.8). It's pretty easy to come up with many examples of this kind.
And in Java, neither constructor in your example is more specific than the other, because there is no subtyping relation between T and Integer. see also Reference is ambiguous with generics
If method overloading creates this kind of ambiguity, we can usually choose to use distinct method names. But constructors cannot be renamed.
More sophistries:
If <T extends Integer>, then indeed T is a subtype of Integer, then the 2nd constructor is more specific than the 1st one, and the 2nd one would be chosen.
Actually javac wouldn't allow these two constructors to co-exist. There is nothing in the current Java language specification that forbids them, but a limitation in the bytecode forces javac to forbid them. see Type Erasure and Overloading in Java: Why does this work?
Another point: If <T extends Integer>, since Integer is final, T can only be Integer, so Integer must also be a subtype of T, therefore isn't the 2nd constructor also more specific than the 1st?
No. final isn't considered in subtyping relations. It is actually possible to drop final from Integer one day, and Java even specifies that removing final does not break binary compatibility.
Indeed, it is ambiguous, and so doesn't compile if you try new A<Integer>(new Integer(0)).
Related
I am trying to write a method in Java that uses a generic parameter and which I want to restrict to being exclusively either one of three possible classes (either Field, Method, or Constructor).
I've tried the following header:
private static <T extends Field,Method,Constructor> T[] sort(T[] anArray)
But this way it ignores generic parameters of type Method or Constructor. Using the following also produces an error:
private static <T extends Field | Method | Constructor> T[] sort(T[] anArray)
Is it possible to do such a thing in Java?
For your particular case (If you are talking about the Reflection specific classes), you are in luck.
You can use the AccessibleObject class.
private static <T extends AccessibleObject> T[] sort(T[] anArray)
You may also be interested in Member interface depending on your requirement.
Type-parameter bound cannot be defined using the or operator (|).
It's only possible to restrict a type-parameter T to extend a class and multiple interfaces, though, by using the & operator:
<T extends SomeClass & FirstInterface & SecondInterface>
No, but you could use a common interface/super class, just use Object and check inside the method or provide separate overloads.
Note that A & B would be possible, i.e. require that a generic type implements both types. You can't use or (i.e. A | B) because the compiler can't/won't determine a common super type - if it even exists besides Object - and thus your implementation can't work on any of the types because when in doubt you'll get passed the wrong type.
Think about it: if you were allowed to declare T as T extends Field | Method, how would you use it inside the code? All you'd really know is that both types provide the methods of Object.
Generics are meant to remove the need for (potentially failing) casts in order to access a specific type's methods (i.e. the generic type's upper bound). Restricting parameter types comes as a consequence of this but is not a primary objective the way you seem to want to use it. That's what method overloads are for.
Edit: I just read Codebender's answer and that's what I mentioned in my first sentence: use a common interface or, as is the case here, super class. That's probably the best way to go.
Field, Constructor and Method each inherit from Member. You could just do:
private static <T extends Member> T[] sort(T[] anArray)
It wouldn't make sense to specify a type bound which could match one of several unrelated types. The whole point of generics is to give the compiler enough information to determine what methods would be available to the type T given that we don't know exactly what T will actually be. If it can be one of three things, how can the compiler possibly know which methods should be allowed?
Referring to : Wildcard Capture Helper Methods
It says to create a helper method to capture the wild card.
public void foo(List<?> i) {
fooHelper(i);
}
private <T> void fooHelper(List<T> l) {
l.set(0, l.get(0));
}
Just using this function below alone doesn't produce any compilation errors, and seems to work the same way. What I don't understand is: why wouldn't you just use this and avoid using a helper?
public <T> void foo(List<T> l) {
l.set(0, l.get(0));
}
I thought that this question would really boil down to: what's the difference between wildcard and generics? So, I went to this: difference between wildcard and generics.
It says to use type parameters:
1) If you want to enforce some relationship on the different types of method arguments, you can't do that with wildcards, you have to use type parameters.
But, isn't that exactly what the wildcard with helper function is actually doing? Is it not enforcing a relationship on different types of method arguments with its setting and getting of unknown values?
My question is: If you have to define something that requires a relationship on different types of method args, then why use wildcards in the first place and then use a helper function for it?
It seems like a hacky way to incorporate wildcards.
In this particular case it's because the List.set(int, E) method requires the type to be the same as the type in the list.
If you don't have the helper method, the compiler doesn't know if ? is the same for List<?> and the return from get(int) so you get a compiler error:
The method set(int, capture#1-of ?) in the type List<capture#1-of ?> is not applicable for the arguments (int, capture#2-of ?)
With the helper method, you are telling the compiler, the type is the same, I just don't know what the type is.
So why have the non-helper method?
Generics weren't introduced until Java 5 so there is a lot of code out there that predates generics. A pre-Java 5 List is now a List<?> so if you were trying to compile old code in a generic aware compiler, you would have to add these helper methods if you couldn't change the method signatures.
I agree: Delete the helper method and type the public API. There's no reason not to, and every reason to.
Just to summarise the need for the helper with the wildcard version: Although it's obvious to us as humans, the compiler doesn't know that the unknown type returned from l.get(0) is the same unknown type of the list itself. ie it doesn't factor in that the parameter of the set() call comes from the same list object as the target, so it must be a safe operation. It only notices that the type returned from get() is unknown and the type of the target list is unknown, and two unknowns are not guaranteed to be the same type.
You are correct that we don't have to use the wildcard version.
It comes down to which API looks/feels "better", which is subjective
void foo(List<?> i)
<T> void foo(List<T> i)
I'll say the 1st version is better.
If there are bounds
void foo(List<? extends Number> i)
<T extends Number> void foo(List<T> i)
The 1st version looks even more compact; the type information are all in one place.
At this point of time, the wildcard version is the idiomatic way, and it's more familiar to programmers.
There are a lot of wildcards in JDK method definitions, particularly after java8's introduction of lambda/Stream. They are very ugly, admittedly, because we don't have variance types. But think how much uglier it'll be if we expand all wildcards to type vars.
The Java 14 Language Specification, Section 5.1.10 (PDF) devotes some paragraphs to why one would prefer providing the wildcard method publicly, while using the generic method privately. Specifically, they say (of the public generic method):
This is undesirable, as it exposes implementation information to the caller.
What do they mean by this? What exactly is getting exposed in one and not the other?
Did you know you can pass type parameters directly to a method? If you have a static method <T> Foo<T> create() on a Foo class -- yes, this has been most useful to me for static factory methods -- then you can invoke it as Foo.<String>create(). You normally don't need -- or want -- to do this, since Java can sometimes infer those types from any provided arguments. But the fact remains that you can provide those types explicitly.
So the generic <T> void foo(List<T> i) really takes two parameters at the language level: the element type of the list, and the list itself. We've modified the method contract just to save ourselves some time on the implementation side!
It's easy to think that <?> is just shorthand for the more explicit generic syntax, but I think Java's notation actually obscures what's really going on here. Let's translate into the language of type theory for a moment:
/* Java *//* Type theory */
List<?> ~~ ∃T. List<T>
void foo(List<?> l) ~~ (∃T. List<T>) -> ()
<T> void foo(List<T> l) ~~ ∀T.(List<T> -> ()
A type like List<?> is called an existential type. The ? means that there is some type that goes there, but we don't know what it is. On the type theory side, ∃T. means "there exists some T", which is essentially what I said in the previous sentence -- we've just given that type a name, even though we still don't know what it is.
In type theory, functions have type A -> B, where A is the input type and B is the return type. (We write void as () for silly reasons.) Notice that on the second line, our input type is the same existential list we've been discussing.
Something strange happens on the third line! On the Java side, it looks like we've simply named the wildcard (which isn't a bad intuition for it). On the type theory side we've said something _superficially very similar to the previous line: for any type of the caller's choice, we will accept a list of that type. (∀T. is, indeed, read as "for all T".) But the scope of T is now totally different -- the brackets have moved to include the output type! That's critical: we couldn't write something like <T> List<T> reverse(List<T> l) without that wider scope.
But if we don't need that wider scope to describe the function's contract, then reducing the scope of our variables (yes, even type-level variables) makes it easier to reason about those variables. The existential form of the method makes it abundantly clear to the caller that the relevance of the list's element type extends no further than the list itself.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?
Java Generics — Assigning a list of subclass to a list of superclass
With raw types you can easily say something like this.
[...] // MyClass is generic with upper bound of Object
MyClass c = new MyClass<Double>();
[...]
But this isn't allowed
MyClass<Number> c = new MyClass<Double>()
I don't understand why this is. My book tells me why the second doesn't work, because you can't add a Integer to a MyClass<Double>. What it doesn't explains is why MyClass<Double> is a subclass of MyClass<Object> (or the equivalent raw type form), since double is subclass of object.
So why is the first allowed if the second form isn't. Please realize I am new to this.
Edit: Taking it a step further what would happen in the first example if Number was the upper bound?
You can see here the effects of type erasure
class Untitled {
public static void main(String[] args) {
}
public static<T> void c(T t)
{
t.SubClassMethod();// this won't work because class Object has no such method. But if I change the upperbound to SubClass it will.
t.toString() // this will because class Object has such a method
}
}
My point is that why should it matter what the Generic is declared as if it ultimately becomes treated as the upper bound anyway?
Try this:
MyClass<? extends Number> c = new MyClass<Double>();
The first thing to eliminate your confusion is to understand that the Raw Type is not part of the generics system at all. It is in no way equivalent to Something<Object>. Basically, the reason the Raw Type exists at all is just for backward compatibility. When Generics were introduced in Java 5, some existing classes and interfaces were retroactively made generic. In order for old code that didn't have generic declarations to compile in the Java 5 or later compiler, the Raw Declarations are legal.
Any comparison between the way the Raw Type behaves and the way the Parameterized type behaves is in a way a bit fundamentally spurious. The intent of the design is not that the Raw Type be considered an 'alternative' to declaring a parameter. New code that uses the Raw Type is incorrect code. It's legal to compile it so that old code still works.
My point is that why should it matter what the Generic is declared as
if it ultimately becomes treated as the upper bound anyway?
Because the entire point of the generics is to prevent ClassCastException. It will be treated as the actual declared type when someone, for example, someone takes the object back out of the list and assigns it to the specific type they're expecting. The compiler is making a promise that it guarantees this will succeed, so it has to restrict what goes in and out.
Suppose that MyClass is like this:
public class MyClass<T>{
T value;
public void foo(T arg){
value = arg;
}
}
and then those two other classes:
class A{ }
class B extends A { }
now imagine what happens if you do:
MyClass<A> container = new MyClass<B>();
container.foo(new A());
you'd try to put an A into a field of type B. The restriction you are facing is thought to prevent such things. C# has a nifty solution in terms of in and out parameters to generics...
Any MyClass<XXX> is a MyClass, but contrary to what you are saying, MyClass<Double> is not a subclass of MyClass<Object>.
You can find more about it if you search for erasure, like here.
If I declare a Class as a field:
Class fooClass;
Eclipse gives me the warning:
Class is a raw type. References to
generic type Class should be
parametrized
What does this mean in practice? and why am I urged to do it? If I ask Eclipse for a "quick fix" it gives me:
Class<?> fooClass;
which doesn't seem to add much value but no longer gives a warning.
EDIT: Why is Class generic? Could you please give an example of parameterization, i.e. could there be a valid use of something other than <?> ?
EDIT: WOW! I had not realized the depths of this. I have also watched the Java Puzzler and it's certainly scared me about the bear traps. So I will always use
Class<MyString> myStringClass = MyString.class;
rather than
Class myStringClass = MyString.class;
(But having used Java from day one, I didn't really notice when Class became generic);
NOTE: I have accepted #oxbow_lakes as this makes sense to me, but it is clearly a very complicated area. I would urge all programmers to use the specific Class<MyString> rather than Class. And Class<?> is much safer than Class.
Raw Types and Unbounded Wildcards
None of the previous answers have really addressed why you should prefer Class<?> over Class, as on the face of it, the former seems to offer no more information than the latter.
The reason is that, the raw type, i.e. Class, prevents the compiler from making generic type checks. That is, if you use raw types, you subvert the type-system. For example:
public void foo(Class<String> c) { System.out.println(c); }
Can be called thusly (it will both compile and run):
Class r = Integer.class
foo(r); //THIS IS OK (BUT SHOULDN'T BE)
But not by:
Class<?> w = Integer.class
foo(w); //WILL NOT COMPILE (RIGHTLY SO!)
By always using the non-raw form, even when you must use ? because you cannot know what the type parameter is (or is bounded by), you allow the compiler to reason about the correctness of your program more fully than if you used raw types.
Why have Raw Types at all?
The Java Language Specification says:
The use of raw types is allowed only as a concession to compatibility of legacy code
You should always avoid them. The unbounded wildcard ? is probably best described elsewhere but essentially means "this is parameterized on some type, but I do not know (or care) what it is". This is not the same as raw types, which are an abomination and do not exist in other languages with generics, like Scala.
Why is Class Parameterized?
Well, here is a use-case. Suppose I have some service interface:
public interface FooService
And I want to inject an implementation of it, using a system property to define the class to be used.
Class<?> c = Class.forName(System.getProperty("foo.service"));
I do not know at this point that my class, is of the correct type:
//next line throws ClassCastException if c is not of a compatible type
Class<? extends FooService> f = c.asSubclass(FooService.class);
Now I can instantiate a FooService:
FooService s = f.newInstance(); //no cast
which doesn't seem to add much value
but no longer gives a warning.
You're right. But this might add value:
Class<FooClass> fooClass;
or, if more appropriate:
Class<? extends FooClass> fooClass;
or
Class<FooInterface> fooClass;
As with generics in general, you can improve type safety by specifying what kind of class you want the variable to hold. The warning against raw types is just meant to catch pieces of code where this potential is not used. By declaring Class<?> you're basically saying "this is meant to hold any kind of class".
Because, since JDK 5, Class has now have parameterized type, which makes Class a generic object. This is necessary (since the introduction of Generics) for the compiler to do type checking (at compile time, of course).
Class<?> means a "class of unknown" where ? is a generics wildcard. It means a that fooClass of type Class<?> accepts a Class whose type matches anything.
Typical example:
Class<?> classUnknown = null;
classUnknown = ArrayList.class; //This compiles.
You can, effectively, provided a Parameterized Type to be more specific, e.g.:
Class<ArrayList> = ArrayList.class;
PS Bear in mind, that Class<List> listClass = ArrayList.class; won't compile (even though ArrayList is of List) but (as Mark Peters mentioned on the comment) Class<? extends List> listClass = ArrayList.class; does compile (thanks to the wildcard).
The Javadoc of the Class class does give some idea about why type parameters exist for this class:
T - the type of the class modeled by
this Class object. For example, the
type of String.class is Class<String>.
Use Class<?> if the class being
modeled is unknown.
The use of this type parameter is not so obvious, but a cursory look at the source code of the class, indicates why the type parameter is sometimes necessary. Consider the implementation of the newInstance method:
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
checkMemberAccess(Member.PUBLIC, ClassLoader.getCallerClassLoader());
}
return newInstance0();
}
If one hasn't noticed, the type of the object returned by this method is that of the type parameter. This is useful in code that utilizes a lot of reflection, and where one would like to be extra careful to ensure that objects of the right type are being instantiated.
Considering the example in the question, if the class instance was instead declared as:
Class<String> fooClass;
Class<Integer> barClass;
String aString;
then, it is next to impossible to have the following code to compile:
aString = barClass.newInstance();
In short, if you're going to be working with class hierarchies and you wish to impose strict compile time checks to ensure that your code does not need to perform a lot of instanceof checks, then you're better off specifying the type of the class that you wish to utilize. Specifying ? allows all types, but there would be cases when you'll need to be more specific.
Because using raw types instead of parameterized types has many pitfalls.
One of which is that if a raw type is used, all generics on the class are lost. Even those defined per-method.
There are methods like these which require Class literals as argument.
Collection<EmpInfo> emps =
SomeSqlUtil.select(
EmpInfo.class,
"select * from emps");
or
GWT.create(Razmataz.class);
The problem presents itself when I need to supply generic specific classes like
EmpInfo<String>
Razmataz<Integer>
The following would be wrong syntax
Collection<EmpInfo<String>> emps =
SomeSqlUtil.select(
EmpInfo<String>.class,
"select * from emps");
or
GWT.create(Razmataz<Integer>.class);
Because you cannot do syntax like
Razmataz<Integer>.class
So, how would I be able to squeeze a class literal out of
EmpInfo<String>
Razmataz<Integer>
so that I could feed them as arguments to methods requiring Class literals?
Further info
Okay, I confess that I am asking this primarily for GWT.
I have a pair of GWT RPC interface Razmataz. (FYI, GWT RPC interface has to be defined in server-client pairs). I plan to use the same interface pair for communicating whether it be String, Integer, Boolean, etc.
GWT.create(Razmataz) for Razmataz<T>
complains that, since I did not specify T, GWT compiler treated it as Object. Then GWT compiler would not accept Object class. It needs to be more specific than being an Object.
So, it seems there is no way for me to tell GWT.create what T is because a Class literal is a runtime concept while generics is a compile time concept, Right?
Quote from Java Generics and Collections, section 7.2:
Class literals are also restricted; it is not even syntactically valid to supply a type parameter to the type in a class literal. Thus, the following fragment is illegal:
class ClassLiteral {
public Class<?> k = List<Integer>.class; // syntax error
}
Indeed, Java's grammar makes a phrase such as the preceding one difficult to parse, and it may trigger a cascade of syntax errors [...]
This syntax problem leads to an irregularity. Everywhere else that a reifiable type is required, you may supply either a raw type (such as List) or a parameterized type with unbounded wildcards (such as List<?>). However, for class tokens, you must supply a raw type; not even unbounded wildcards may appear. Replacing List<Integer> with List<?> in the preceding code leads to a similar error cascade.
So, you have no choice but use only raw types in class tokens, like
GWT.create(Razmataz.class);
You can't.
Use an unsafe cast:
Collection<EmpInfo<String>> emps =
(Collection<EmpInfo<String>>) someMethod(EmpInfo.class);
Someone left a short but concise answer here, which I was about to choose as the answer. Unfortunately, that person deleted that answer. If that person would be so kind to re-post that answer for me to select. In the mean time, let me state that answer and how I made use of it.
This is what I should have thought of,
Interface RazmatazString extends Razmataz<String>{}
GWT.create(RazmatazString.class);
Basing on the answer that was deleted,
I would have a basic Razmataz interface pair the does a lot of stuffs, which I am too lazy to repeat.
Abstract class Razmatazer{
.....
Interface Razmataz<T>{
// does a lot of RPC stuffs
}
Interface RazmatazAsync<T>{
// does a lot of RPC stuffs
}
RazmatazAsync<?> razmatazAsyncRPC;
}
The concept is not to instantiate razmatazAsyncRPC handle at the base class but at the derived class.
For T = String
StringRazmatazer extends Razmatazer{
Interface RazmatazStringAsync extends RazmatazAsync<String>{}
Interface RazmatazString extends Razmataz<String>{}
razmatazAsyncRPC = GWT.create(RazmatazString.class);
}
Otherwise I would have to repeat ~100 lines of code, ~50 each for Razmataz and RazmatazAsync, over various T parametric values of String, Map, Boolean, Integer, etc.
The basic premise for overcoming this hurdle was - I am lazy to repeat those lines.