How can I iterate over a wildcard generic? Basically I would like to inline the following method:
private <T extends Fact> void iterateFacts(FactManager<T> factManager) {
for (T fact : factManager) {
factManager.doSomething(fact);
}
}
If this code is in a separate method as shown, it works because the generic method context allows to define a wildcard type (here T) over which one can iterate. If one tries to inline this method, the method context is gone and one cannot iterate over a wildcard type anymore. Even doing this automatically in Eclipse fails with the following (uncompilable) code:
...
for (FactManager<?> factManager : factManagers) {
...
for ( fact : factManager) {
factManager.doSomething(fact);
}
...
}
...
My question is simply: Is there a way to put some wildcard type one can iterate over, or is this a limitation of generics (meaning it is impossible to do so)?
No. In situation like this, the workaround is to create a helper method.
The JLS has this example http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.10
public static void reverse(List<?> list) { rev(list);}
private static <T> void rev(List<T> list) { ... }
The issue is, we have a List<?> object. We know it must be a List<X> of some X, and we'd like to write code using X. Internally compiler does convert the wildcard to a type variable X, but Java language does not offer programmers a direct way to access it. But if there's a method accepting List<T>, we can pass the object to the method. Compiler infers that T=X and the call is good.
If there's no type erasure, X can be known at runtime, then Java would definitely give us a way to access X. However as of today since X isn't available at runtime, there's not much point. A purely synthetic way could be provided, which is unlikely to be simpler than the helper method workaround.
Type parameters can only defined on
types (i.e. classes/interfaces),
methods, and
constructors.
You would need a type parameter for a local block, which is not possible.
Yeah, I missed something like this sometimes, too.
But there is not really a problem with having the method non-inlined here - if it presents a performance bottleneck where inlining would help, Hotspot will inline it again (not caring about the type).
Additionally, having a separate method allows giving it a descriptive name.
Just an idea, if you need this often:
interface DoWithFM {
void <T> run(FactManager<T> t);
}
...
for (FactManager<?> factManager : factManagers) {
...
new DoWithFM() { public <T> run(FactManager<T> factManager) {
for (T fact : factManager) {
factManager.doSomething(fact);
}
}.run(factManager);
...
}
...
You can always fall back to Object
for (FactManager<?> factManager : factManagers) {
...
for ( Object fact : factManager) {
factManager.doSomething(fact);
}
...
}
This, of course, is subject to what is the actual declaration of doSomething.
If doSomething is declared as this void doSomething( T fact ), then your recourse here would be to use a raw type and swallow unchecked warnings. If you can guarantee that FactManager can only have homogeneous Facts inserted, then that may be an OK solution.
for (FactManager factManager : factManagers) { // unchecked warning on this line
...
for ( Object fact : factManager) {
factManager.doSomething(fact);
}
...
}
Well, I can think of a way to do it using inner classes, because the inner class shares the type parameter with its enclosing type. Also, even using wildcards you could still process your collections thanks to wildcard capture conversion.
Let me create an example. This code compiles and runs fine. But I cannot be certain if the use of inner classes would be an issue for you.
//as you can see type parameter belongs to the enclosing class
public class FactManager<T> implements Iterable<FactManager<T>.Fact> {
private Collection<Fact> items = new ArrayList<Fact>();
public void doSomething(Fact fact) {
System.out.println(fact.getValue());
}
public void addFact(T value) {
this.items.add(new Fact(value));
}
#Override
public Iterator<Fact> iterator() {
return items.iterator();
}
public class Fact {
//inner class share its enclosing class type parameter
private T value;
public Fact(T value) {
this.value = value;
}
public T getValue() {
return this.value;
}
public void setValue(T value) {
this.value = value;
}
}
public static void main(String[] args) {
List<FactManager<String>> factManagers = new ArrayList<FactManager<String>>();
factManagers.add(new FactManager<String>());
factManagers.get(0).addFact("Obi-wan");
factManagers.get(0).addFact("Skywalker");
for(FactManager<? extends CharSequence> factManager : factManagers){
//process thanks to wildcard capture conversion
procesFactManager(factManager);
}
}
//Wildcard capture conversion can be used to process wildcard-based collections
public static <T> void procesFactManager(FactManager<T> factManager){
for(FactManager<T>.Fact fact : factManager){
factManager.doSomething(fact);
}
}
}
This is more precisely matched to the method you defined (that is, if you can call iterateFacts() with the FactManagers in factManagers, you know that the FactManager contain items that are some subclass of Fact).
for (FactManager<? extends Fact> factManager : factManagers) {
for (Fact fact : factManager) {
factManager.doSomething(fact);
}
}
I would tend to think, however, that you would declare FactManager to be generic for subtypes of Fact (just given the name of the class), e.g.
class FactManager<T extends Fact> implements Iterable<T> {
...
}
The Eclipse refactoring fails because it cannot infer the type of an object contained by FactManager<?>.
Related
I had an interview test and saw the following code:
EDIT:
public class TestValue {
private Value<SomeValue> defaultValue;
#Test
public void Empty_Value_Has_No_Value() {
Assert.assertFalse(Value.<SomeValue> createEmptyValue()
.hasValue());
}
#Test
public void Default_Value_IsEmpty() {
Assert.assertEquals(Value.<SomeValue> createEmptyValue(),
defaultValue);
}
#Test
public void Non_Empty_Value_Has_Value() {
Assert.assertTrue(new Value<SomeValue>(true, new SomeValue())
.hasValue());
}
}
I had never seen Java generic like
Value.<SomeValue>
The test is to implement Value class with the given unit test code above.
I tried to figure out the Value method signature below (need implementation):
public interface Value<T> {
public boolean hasValue();
public Value<T> createEmptyValue();
}
Any one know, please help?
Thank you
EDIT: Should be like this according to answers below #marlon
public class Value<T> {
public boolean hasValue(){}
public static <M> Value<M> createEmptyValue(){}; //need <M>
}
The key syntax to know:
Value.<SomeValue> //ClassName.<Type>method
is way to invoke static method of a class with parameterized argument.
EDIT: according to #snipes83, syntax to invoke non-static method of a class with parameterized argument.
SomeObject.<Type>method
Value.<SomeValue> it's the way generics are represented for methods.
Using Google Guava's Optional as an example:
Optional<String> email = Optional.<String>of(strEmail);
See Generic Types - Invoking generic methods
Since interfaces cannot declare static methods (shame on you java), just declare your method as static and forget about the interface, like this:
class Value<T> {
public static <T> Value<T> createEmptyValue(){
return null;
}
}
Look at the class Test with the method getEmptyList below:
public class Test {
public <T> List<T> getEmptyList() {
return new ArrayList<T>();
}
}
It returns an empty List containing objects of type T.
If you use Test like this
Test t = new Test();
List<Integer> list = t.getEmptyList();
Then the type inference mechanism is able to infer the type parameter based on the variable type.
However if you need to use the return value of getEmptyList within a method invocation expression like in the following example where the method printList expects a single argument of type List<Integer>, then the type can not be infered from any variable type.
public void printList(List<Integer> list) {
for (int i : list) {
System.out.print(i);
}
}
printList(t.getEmptyList()); // This will FAIL.
In this case you need to specify the type using the following:
printList(t.<Integer>getEmptyList());
1) This is how generic methods are invoked. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/methods.html
2) <SomeValue> in Value.<SomeValue> is optional. Compiler can infer the type. This is called TypeInference. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
Answer Updated:
3) Value.<SomeValue> createEmptyValue() is right and Value.<SomeValue>createEmptyValue() is right too. Both ways are legal. Just tested it. Didn't notice before.
Although Value is itself obviously typed ( based on the instance variable type of Value<SomeValue>), the static createEmptyValue() method is also typed.
A reasonable assumption, if naming conventions have been adhered to, is that SomeValue extends (or implements) Value.
Although there us no one correct answer, a likely possibility for the signature of Value is:
public class Value<T extend Value> {
public static <V extends Value> V createEmptyValue() {
// some impl
}
}
I don't understand why this confuses the compiler. I'm using the generic type T to hold an object that's not related to the put and get methods. I always thought GenericClass and GenericClass<Object> were functionally identical, but I must be mistaken. When compiling the DoesntWork class I get incompatible types - required: String - found: Object. The Works class does what I expect. What's going on here?
public class GenericClass<T> {
public <V> void put(Class<V> key, V value) {
// put into map
}
public <V> V get(Class<V> key) {
// get from map
return null;
}
public static class DoesntWork {
public DoesntWork() {
GenericClass genericClass = new GenericClass();
String s = genericClass.get(String.class);
}
}
public static class Works {
public Works() {
GenericClass<Object> genericClass = new GenericClass<Object>();
String s = genericClass.get(String.class);
}
}
}
The thing about how raw types work -- generic types that you've left out the arguments for -- is that all generics for them and their methods are erased as well. So for a raw GenericClass, the get and put methods also lose their generics.
This is because when you work with a generic class without the extra type information you work with what is sometimes called the degenerate form of the class. The degenerate form has ALL generic type information removed.
Essentially - your class becomes something like:
public class GenericClass {
public void put(Class key, Object value) {
// put into map
}
public Object get(Class key) {
// get from map
return null;
}
...
}
The compiler response you are seeing is therefore expected behaviour.
It's mentioned in a Java Puzzlers.
I'm stuck trying to translate some Java code that uses (bounded) wildcard generics to C#. My problem is, Java seems to allow a generic type to be both covariant and contravariant when used with a wildcard.
[This is a spin-off from a previous question dealing with a simpler case of bounded-wildcards]
Java - works:
class Impl { }
interface IGeneric1<T extends Impl> {
void method1(IGeneric2<?> val);
T method1WithParam(T val);
}
interface IGeneric2<T extends Impl> {
void method2(IGeneric1<?> val);
}
abstract class Generic2<T extends Impl> implements IGeneric2<T> {
// !! field using wildcard
protected IGeneric1<?> elem;
public void method2(IGeneric1<?> val1) {
val1.method1(this);
//assignment from wildcard to wildcard
elem = val1;
}
}
abstract class Generic<T extends Impl> implements IGeneric1<T>, IGeneric2<T> {
public void method1(IGeneric2<?> val2) {
val2.method2(this);
}
}
C# - doesn't compile...
class Impl { }
interface IGeneric1<T> where T:Impl {
//in Java:
//void method1(IGeneric2<?> val);
void method1<U>(IGeneric2<U> val) where U : Impl; //see this Q for 'why'
// https://stackoverflow.com/a/14277742/11545
T method1WithParam(T to);
}
interface IGeneric2<T>where T:Impl {
void method2<U>(IGeneric1<U> val) where U : Impl;
}
abstract class Generic2<T, TU>: IGeneric2<T> //added new type TU
where T : Impl
where TU : Impl
{
//in Java:
//protected IGeneric1<?> elem;
protected IGeneric1<TU> elem;
//in Java:
//public void method2(IGeneric1<?> val1)
public void method2<U>(IGeneric1<U> val)
where U : TU //using TU as constraint
{
elem = val; //Cannot convert source type 'IGeneric1<U>'
//to target type 'IGeneric1<TU>'
}
public abstract void method1WithParam(T to);
}
abstract class Generic<T> : IGeneric1<T>, IGeneric2<T> where T : Impl
{
//in Java:
//public void method1(IGeneric2<?> val2)
public void method1<U>(IGeneric2<U> val2) where U : Impl
{
val2.method2(this);
}
public abstract T method1WithParam(T to);
public abstract void method2<U>(IGeneric1<U> val) where U : Impl;
public abstract void nonGenericMethod();
}
If I change interface IGeneric1<T> to interface IGeneric1<out T> the above error goes away, but method1WithParam(T) complains about variance:
Parameter must be input-safe. Invalid variance: The type parameter 'T' must be
contravariantly valid on 'IGeneric1<out T>'.
Let me start by saying that is definitely starting to look like a design review is in order. The original Java class aggregates an IGeneric1<?> member, but without knowing its type argument there's no possibility to call method1WithParam on it in a type-safe manner.
This means that elem can be used only to call its method1 member, whose signature does not depend on the type parameter of IGeneric1. It follows that method1 can be broken out into a non-generic interface:
// C# code:
interface INotGeneric1 {
void method1<T>(IGeneric2<T> val) where T : Impl;
}
interface IGeneric1<T> : INotGeneric1 where T : Impl {
T method1WithParam(T to);
}
After this, class Generic2 can aggregate an INotGeneric1 member instead:
abstract class Generic2<T>: IGeneric2<T> where T : Impl
{
protected INotGeneric1 elem;
// It's highly likely that you would want to change the type of val
// to INotGeneric1 as well, there's no obvious reason to require an
// IGeneric1<U>
public void method2<U>(IGeneric1<U> val) where U : Impl
{
elem = val; // this is now OK
}
}
Of course now you cannot call elem.method1WithParam unless you resort to casts or reflection, even though it is known that such a method exists and it is generic with some unknown type X as a type argument. However, that is the same restriction as the Java code has; it's just that the C# compiler will not accept this code while Java will only complain if you do try to call method1WithParam1.
Java doesn't allow a type to be both variant and covariant. What you have is an illusion stemming from the fact that while you are declaring IGeneric1<?> elem in the class Generic2, you don't use its method T method1WithParam(T val);; therefore Java don't see any problem with this declaration. It will however flag an error as soon as you will try to use it through elem.
To illustrate this, the following add a function test() to the Generic2 class which will try to call the elem.method1WithParam() function but this leads to a compilator error. The offensive line has been commented out, so you need to re-install it in order to reproduce the error:
abstract class Generic2<T extends Impl> implements IGeneric2<T> {
// !! field using wildcard
protected IGeneric1<?> elem;
public void method2(IGeneric1<?> val1) {
val1.method1(this);
//assignment from wildcard to wildcard
elem = val1;
}
public void test() {
Impl i = new Impl();
// The following line will generate a compiler error:
// Impl i2 = elem.method1WithParam(i); // Error!
}
}
This error from the Java compiler proves that we cannot use a generic type as both covariant and contravariant and this; even if some declaration seems to prove the contrary. With the C# compiler, you don't even have a chance to get that close before getting a compilation error: if you try to declare the interface IGeneric1<T extends Impl> to be variant with IGeneric1<out T extends Impl>; you automatically get a compilation error for T method1WithoutParam();
Second, I took a look at the reference .NET equivalent for Java wildcard generics <?> with co- and contra- variance? but I must admit that I don't understand why this can be seen as a solution. Type restriction such as <T extends Impl> has nothing to do with unbounded wildcard parameterized type (<?>) or variance (<? extends Impl>) and I don't see how replacing the seconds with the first could be seen as a general solution. However, on some occasions, if you don't really need to use a wildcard parameterized type (<?>) or a variance type than yes, you can make this conversion. However, if you don't really use them in your Java code, this one should also be corrected, too.
With Java generics, you can introduce a lot of imprecision but you won't get that chance with the C# compiler. This is especially true considering that in C#, classes and structs are fully reifiable and therefore, do not support variance (both covariance and contravariance). You can use that only for the declaration of an interface and for delegates; if I remember correctly.
Finally, when polymorphism is involved, there is often a bad tendency to use unnecessary generic types; with or without wildcard parameterized types and variance. This often lead to a long and complex code; hard to read and use and even harder to write. I will strongly suggest you to look at all this Java code and see if it's really necessary to have all this stuff instead of a much simpler code with only polymorphism or a combination of polymorphism with generic but without variance or wildcard parameterized type.
I've decided to use generics in my design, which works fine. Only when I get to abstraction, I got stuck. I'm collecting different instances implementing the same interface with a different generics. To save those in a list, I need to use wildcards, as far as I know. So my current code is like this:
import java.util.List;
import java.util.ArrayList;
public class Main {
private List<IView<?>> views = new ArrayList<IView<?>>();
public void addView(IView<?> view)
{
this.views.add(view);
}
public void handle()
{
for (IView<?> view : this.views)
{
// ## ERROR ##
view.render(
view.cast(new Object())
);
}
}
}
public interface IView<T> {
public T cast(Object entity);
public void render(T entity);
}
public class FirstView implements IView<One> {
// .. Added to Main-collection views
}
public class SecondView implements IView<Two> {
// .. Added to Main-collection views
}
I also tried an alternative approach returning a Class from the IView which I then use to call the class.cast. Same problem.
This is NOT accepted by the compiler
- The method Render(Capture#2-of ?) in the type IView(Capture#2-of ?) is not applicable for the arguments (Capture#3-of ?).
I partially think to understand the problem, but I see no way of solving it. It would be very much appriciated if someone could help me getting going again.
I don't believe you can assign a value to an ? "typed" variable. An unbounded "?" means "the original type of the variable is unknown", which means there is no known type it's safe to assign to it. It doesn't mean that the actual value of the type parameter is retrieved at runtime.
The entire idea of using a generic method to do a cast doesn't make sense in Java generics. The only way to do a cast of an unknown type object in a type-safe way is with an actual cast.
The only solution is to get rid of the cast() method, and use raw types:
public void handle()
{
for (IView view : this.views)
{
view.render(new Object());
}
}
Assuming the cast() method is only doing casting and not type conversion. If the implementing method that ends up being called is FirstView.render(One object), I believe Java will actually cast the parameter to One. (This can also cause amusing bugs where a ClassCastException is thrown on a line of code with no casts.)
If cast() can do a type conversion (in which case, "cast" is a bad name for the operation), that means that every IView must be able to accept Object, in which case it doesn't make much sense have the parameter of render() be the generic type to begin with. The design I would use is something like the following:
interface IView<T> {
void renderObject(Object o);
void render(T);
T coerce(Object o);
}
abstract class ViewBase<T> implements IView<T> {
void renderObject(Object o) {
render(coerce(o));
}
}
class FirstView extends ViewBase<One> {
// …
}
encapsulating the "cast" operation.
There is no statically typesafe way to work with a collection of objects of different types - in Java, IView<One> and IView<Two> are types as different as String and Integer and there are no safe conversions between the two.
Since I was wondering about the two captures in code view.render(view.cast(new Object());,
I read the appropriate section in Angelika Langer's Generics FAQ. It states that:
We cannot call methods through an unbounded wildcard parameterized
type that take arguments of the "unknown" type.
PERIOD.
So using a wildcard declaration prevents the use of parameterized arguments, even if type inference were simple, as in your case :( Hence view.cast(new Object(); is allowed, but view.render(view.cast(new Object()); isn't.
Just for clarification via an example, Angelika gives the following:
Box<?> box = new Box<String>("abc");
box.contains("abc"); // error
where contains takes as argument the parameterized type of Box. She states:
The invocation is illegal if performed through a reference variable of
type Box<?> . [Defining the contains method as taking an argument of
type Object , instead of T , would avoid this effect. In this case
the contains method would not take an object of "unknown", but an
object of "any" type, and it would be permitted to invoke it through a
reference variable of type Box<?> .]
So she suggests retrieting back to Object (similarly to the suggestion in my other answer). Btw, she discourages using raw types, as does Josh Bloch in Effective Java's item 23, "Don’t use raw types in new code".
I do not understand the compiler error, i.e. why view.render(view.cast(new Object()); produces two captures. (I've tried this code with view being final, and the same error message shows).
But since IView<One> and IView<Two> only have Object as common type, the way of solving it is using List<IView<Object>>.
I sort of replaced the casting by returning a typed object (and I slightly changed the example by replacing the new Object with IEntity);
public class Main {
public static List<IView<? extends IEntity<?>>> views = new ArrayList<IView<? extends IEntity<?>>>();
public static <T extends IEntity<T>> void register(IView<T> view)
{
Main.views.add(view);
}
public static void handle()
{
for (IView<? extends IEntity<?>> view : Main.views)
{
// ## Error ##
/* Bound mismatch: The generic method view(IView<T>) of the type Main
* is not applicable for the arguments (IView<capture#1-of ? extends IEntity<?>>).
* The inferred type capture#1-of ? extends IEntity<?> is not a valid
* substitute for the bounded parameter <T extends IEntity<T>>
*/
Main.view(view);
}
}
public static <T extends IEntity<T>> void view(IView<T> view)
{
IKey<T> key = view.getKey(/* Some arg */);
T entity = key.getEntity();
view.render(entity);
}
}
public interface IView<T> {
public IKey<T> getKey(/* Some args */);
public void render(T entity);
}
public interface IKey<T> {
public T getEntity();
}
The wildcard is someway bounded, but then it creates another problem (which may actually be the same): Is there a way to check that two wildcards match, i.e.:
for (IView<? extends IEntity<?>> view : Main.views)
Where ? can only be one (=the same) (generic)type?
What is the rationale behind not providing / providing before return type of a method/constructor in Java for Generic classes?
I cannot get my head around it.
Sometimes it wants it and sometimes not. Do we ever need it for constructors?
The rules seem to be random and cannot find a logical explanation for it.
<T> in the method definition means that the type is defined in the method signature, and used only within that method.
Put <T> before the return type of a method when you want a generic associated with that method, instead of the containing class.
class Foo {
// T is associated with the method
<T> T stuff(T x) ...
}
class Bar<T> {
// T is associated with the class
T stuff(T x) ...
}
class Baz<T> {
// S is associated with the method, T with the class
<S> T stuff(S x) ...
<S> S otherStuff(T x) ...
}
class WTF<T> {
// Legal, but redundant
<T> T stuff(T x) ...
}
Constructors are no different. It is possible to put generics in constructors, as in
class Weird {
// T is associated with the constructor only
<T> Weird(T arg) ...
}
This would be unusual, though. It is much more common to see constructors use class-level generics, as in
class Normal<T> {
// T is associated with the class, as usual
Normal(T arg) ...
}
Sometimes it wants it and sometimes
not.
In the following case, it is not necessary, because the generic type is declared/defined as part of the class definition:
public class Example<T> {
public T generateItem() { return null; };
}
In the following case, it is necessary, because the generic type is NOT declared/defined as part of the class definition (or elsewhere):
public class Example {
public <T> T generateItem() { return null; };
}
The rule is: is it declared somewhere in the context or not? That's it!