Java Generics - explanation needed - java

I have a question about Java Generics. In code below we have interface B parametrized by another type that must implement interface A.
This code is correct.
Question is: why it does not work with following list() method declaration?
private <X extends A, Y extends B<X>> List<Y> list()
Working code:
public interface A {
}
public interface B<T extends A> {
}
public class Test {
private static class AA implements A {}
private static class BB implements B<AA> {}
private <R extends A, X extends R, Y extends B<X>> List<Y> list() {
return null;
}
private void test() {
List<BB> l = list();
}
}
EDIT:
I've reworked the code. Now we have bird paremetrized by sound it can make. Question is why useless_t is necessary?
public class Test {
public interface Sound {
}
public interface Bird<T extends Sound> {
}
private static class Quack implements Sound {}
private static class Duck implements Bird<Quack> {}
private <useless_t extends Sound, sound_t extends useless_t, bird_t extends Bird<sound_t>> List<bird_t> list() {
return null;
}
private void test() {
List<Duck> l = list();
}
}

My Eclipse IDE does not compile any of your code examples as is. But they do compile when given additional type hints. In the second example, with or without the type parameter useless_t, the following line does not compile for me:
List<Duck> l = list();
But the following does compile for me:
List<Duck> l = this.<Sound, Quack, Duck> list();
With the useless_t factored out, the following compiles, too:
List<Duck> l = this.<Quack, Duck> list();
So it is basically a matter of the compiler not getting the type parameters right, and you need to give the types explicitly.
UPDATE : If you really came across a program where adding the useless_t made a difference, you are on unsafe terrain, and rely on unspecified compiler behaviour.
You ran into an issue where different compilers behave differently, namely Type Inference. The JLS is not entirely clear on where a compiler must infer types, and where it must refuse to infer, so there is wiggle room here. Different versions of the Eclipse compiler and different versions of javac differ in where they do infer types. For javac, this is true even when comparing different 1.5.0_x versions, and the Eclipse compiler usually can infer more than javac.
You should only rely on type inference where all common compilers succeed, and otherwise give type hints. Sometimes, that is as easy as introducing a temporary variable, but sometimes (as in your example) you must use the var.<Types>method() syntax.
Regarding the comment: what if i want method Duck.getSound() to return Quack, not Sound using generics?
Assume the Bird interface had the following method:
public interface Bird<T extends Sound> {
T getSound();
}
Then you could implement it like so:
private static class Duck implements Bird<Quack> {
public Quack getSound() { return new Quack(); }
}
This is one use case for generics - allow implementations to specify concrete types, so that even the superclass can use that type. (The Bird interface could have a setSound(T), or do other stuff with T, without knowing the concrete type of T.)
If a caller only knew that an instance was of type Bird<? extends Sound>, he would have to call getSound like so:
Sound birdSound = bird.getSound();
If the caller knew about Quack, he could perform an instanceof test. But if the caller knew that the bird was really a Bird<Quack>, or even that is was a Duck, then he can write this and it compiles as desired:
Quack birdSound = bird.getSound();
But beware: Generifying too many types used in the interface or superclass brings the risk of overcomplicating the system. As Slanec wrote, Rethink your real design to see whether it's really needed to have so many generics.
I once went too far, and ended up with a interface hierarchy and two implementation hierarchies, based on interfaces like this:
interface Tree<N extends Node<N>,
T extends Tree<N, T>> { ... }
interface SearchableTree<N extends SearchableNode<N>,
S extends Searcher<N>,
T extends SearchableTree<N, S, T>>
extends Tree<N, T> { ... }
I do not recommend to follow that example. ;-)

I'd say: AA implements A, by defining List<AA> l = list() you expect it to extend B<X> which it does not. Anyway, you see how easly you get confused by writing such code. This is just TOO complex.

You have a slight misunderstanding of Java Generics. The thing to remember, and this is a subtle thing, a List<Y> is not about the contents of the list, but a modification of the list itself.
Let's extrapolate a little bit; say I have interface Animal and interface Dog extends Animal and interface Cat extends Animal. (I'll just invent more classes and interfaces as we go along.) Now if I declare a method that returns animals as List<Animal> createList(), there's nothing wrong with the following code:
List<Animal> litter = createList();
Cat tabby = new Tabby();
litter.add(tabby);
Dog poodle = new Poodle();
litter.add(poodle);
That's because a Dog is an Animal, and a Cat is an Animal; the method signature of add on type List<Animal> is add(Animal); we can call add with any valid instance of Animal, as expected. But the type parameter on List does not modify or restrict the contents of the list, it modifies the type of the list itself; and a "list of cats" is not a "list of animals", neither is a "list of dogs". Even if the createLitter() method actually returns a new ArrayList<Animal>() that contains only instances of Parrot, the above code is fine. What you cannot do however is 'narrow' the type of the list. For example, this is a compile error:
List<Bird> birds = createList(); // does not compile
Imagine if it were allowed, and createList returned a "list of animals" that contained our tabby; the following would result in a class cast exception:
Bird leaderOfTheFlock = birds.get(0);
You also cannot 'widen' the type of list. Imagine if it were possible:
List<Object> things = createList(); // does not compile
The reason this is not allowed either is that code could now add a new Integer(0) to things - because an Integer is an Object. Clearly that's not what we want either, and for the same reason - a "list of animals" is not a "list of objects". The type parameter "Animal" on List<Animal> modifies the type of the list itself, and we are talking about two distinct types of lists. This leads us to the first consequence of that point - generic types do not follow the inheritance (is-a) hierarchy.
Without knowing more of what you want to do it's hard to go from here and stay relevant. I don't mean to be harsh, but it looks like you started throwing generics at your code to see if something would work. I struggled for years with Generics. Even after running across a blog that explained this subtle point I had to recreate quite a few variations of the above to reinforce the lesson, looking for various ways I would end up with a class-cast-exception if I broke the rules. Likely the solution to your problem is that other parts of the code are not well defined with respect to the strict type system you are trying to introduce, and the generics problems you see are only a symptom of that. Try to reduce the generics and rely more on composition and inheritance. I still shoot myself in the foot occasionally by going off the generic deep end. It's also helpful to try and remember the point of generics is not to eliminate casts, but to make type information available to the compiler as an aid to verifying the correctness of how your code deals with the types; or in other words it turns runtime errors (class cast) into source / compile-time errors, so it is important to try to keep in mind the distinction between what type information you have at compile-time (which is limited, even with generics) and what type information you have at runtime (which is the full type information of the instances).

Related

Return ChildClass.class pointer in method which returns Class<T extends BaseClass>

I have a method that is supposed to analyze a String and determine the correct Class<T>, where T extends BaseClass.
Suppose that BaseClass is extended by Child1, Child2 and Child3.
In my method, I want to do something like this:
public <T extends BaseClass> Class<T> from(String number) {
if (number.contains("Child1")) {
return Child1.class;
} else if (number.contains("Child2")) {
return Child2.class;
} else if (number.contains("Child3")) {
return Child3.class;
}
throw new UnsupportedOperationException("Cannot recognize class from " + number);
}
The problem is that the above method doesn't compile on all return statements, because Required type is Class<T>, provided is Class<Child1> (same for Child2 and Child3 of course).
Hence, I am forced to (unchecked) cast:
return (Class<T>) Child1.class;
... which of course works fine, since Child1.class is compatible with Class<T>.
How can I do what I'm trying to do in a cleaner way (without having the warning)?
... which of course works fine, since Child1.class is compatible with Class<T>.
That's incorrect. Understandable, as you're making a common mistake.
The fix
The fix is to have the return type be Class<? extends T> instead. But, scratch that...
But this code is bad style
Generics serve to link things. Any type variable should therefore be declared once and used in at least 2 places, or it is one of:
useless.
actively misleading.
a type-safety breaking hack.
I assume you intended none of that. You have declared T once, and are using it once, which therefore means it's incorrect. The correct version is:
public Class<? extends BaseClass> from(String number) { ... }
This does everything you want. Specifically, something like this:
BaseClass bc = from("Child3").getConstructor().newInstance();
will just compile, no need for casts (you will need to festoon this up with rather a lot of try/catch, but no need for a cast, at least), and the compiler will not emit type safety warnings either. Which, presumably, is what you're trying to accomplish.
Explanation
In java, typing relationships are covariant. That means any type can stand in for any of its supertypes.
In other words:
Number n = Integer.valueOf(5);
is valid java.
But the thing that generics are for simply doesn't adhere to this rule. Here is a trivial example. Imagine generics was just as covariant as basic type usage in java would be. Then I could write this, it would compile, and that would be bad, because this code would then be breaking the typing system:
List<Integer> listOfInts = List.of(1, 2, 3);
List<Number> listOfNums = listOfInts;
listOfNums.add(Double.valueOf(5.5));
int value = listOfInts.get(3);
Go through the above code and you realize there's a fundamental issue here.
The fix is that generics are invariant - a type is a valid standin only for itself; not for anything else.
In other words, the one and only thing you can assign to a List<Number> is an expression of type List<Number> or perhaps ArrayList<Number> ( because the non-generics part is covariant, we're talking only about the stuff in the <>), not List<Integer>.
That's the fix - that's why the above code isn't actually a problem for the typing system in java - it simply won't compile.
Now, when there is no such thing as 'adding', this becomes dubious, and Class is just such a type: Yes it's got a type param but you can't 'break stuff' if generics was covariant. Unfortunately, the generics feature of java does not ship with a gigantic list of 'the generics on THIS type can be covariant, but here they cannot be'.
Instead, java lets you choose your variance, and the APIs change to reflect what that means:
List<? extends Number> list = someListOfIntegers; // co-variance
List<? super Number> list = someListOfObject; // contra-variance
List list = someListOfAnything; // legacy-variance a.k.a. raw
List<Number> list = someListOfNumber; // invariance
Of course, you don't get this stuff for free: That covariant list (List<? extends Number>), you cannot call add on this list, at all. Well, the literal .add(null), because null is a standin for all types, that works, but nothing else will, add is always a compile time error. That's the cost. If you opt out of all add methods on a list, then and only then can you write a method that accepts as parameter a list of numbers, or integers, or doubles, etc.
With Class it gets dubious (as there's no 'writing'), but the co/contra/invariant system is baked into generics and doesn't care about the fact that Class doesn't have any add-style methods in it.

Java: Generics on data structures and wildcards

I'm trying to learn how to use generics and for that, I'm creating my own data structure similar to a list with an Iterator and all.
The uppermost class is declared as:
public class BasicList<A> implements Iterable {
}
It's just a list with nodes and a single pointer to the next element.
There's another list, called DescendingList, that does pretty much the same, only this time around, you're getting another output since the Iterator is different. I'm giving a comparator to this List to get the Iterator to work. The comparator is just an interface:
public interface Bigger<A> {
boolean bigger(A x);
}
DescendingList looks like this:
public class DescendingList<A extends Bigger<A>> extends BasicList<A> implements Iterable {
}
The idea is that it could work with any kind of object that is comparable through the Bigger interface.
Now I have an abstract class:
public abstract class Rock implements Bigger<Rock> {
}
And finally, a normal class which extends the Rock class:
public class Mineral extends Rock {
}
So, the issue at hand is that, while I can easily create a new BasicList filled with Minerals like this:
BasicList<Mineral> min = new BasicList<Mineral>();
I can't do the same with the DescendingList. Whenever I try going with
DescendingList<Mineral> min = new DescendingList<Mineral>();
my IDE (IntelliJ) goes all
"Type parameter "Rock" is not within it's bound; should implement Bigger<Mineral>"
And I don't really get why that happens. I am pretty sure that I've messed up the type parameters somehow and I'm really not sure where. This should be solveable somehow (at least without removing any classes/interfaces - the class headers might be and probably are completely messed up). Thanks in advance for any help you might offer.
A Mineral isn't a Bigger<Mineral>, it's a Bigger<Rock>, and that is incompatible with Bigger<Mineral>, because even though a Mineral is a Rock, Java's generics are invariant. It needs to be a Bigger<Rock> because of how Rock is defined -- implementing Bigger<Rock> -- and that DescendingList declares type parameter A to be a Bigger<A>.
Because it's a consumer (type parameter as a method parameter), the type parameter A needs a lower-bound (super) on its declaration.
class DescendingList<A extends Bigger<? super A>> // ...
This way Mineral will be within its own bound.
As an aside, you are implementing the raw form of Iterable in BasicList; you should supply a type argument there.

Difference between List<T> and List<? extends T> [duplicate]

Given the following example (using JUnit with Hamcrest matchers):
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
This does not compile with the JUnit assertThat method signature of:
public static <T> void assertThat(T actual, Matcher<T> matcher)
The compiler error message is:
Error:Error:line (102)cannot find symbol method
assertThat(java.util.Map<java.lang.String,java.lang.Class<java.util.Date>>,
org.hamcrest.Matcher<java.util.Map<java.lang.String,java.lang.Class
<? extends java.io.Serializable>>>)
However, if I change the assertThat method signature to:
public static <T> void assertThat(T result, Matcher<? extends T> matcher)
Then the compilation works.
So three questions:
Why exactly doesn't the current version compile? Although I vaguely understand the covariance issues here, I certainly couldn't explain it if I had to.
Is there any downside in changing the assertThat method to Matcher<? extends T>? Are there other cases that would break if you did that?
Is there any point to the genericizing of the assertThat method in JUnit? The Matcher class doesn't seem to require it, since JUnit calls the matches method, which is not typed with any generic, and just looks like an attempt to force a type safety which doesn't do anything, as the Matcher will just not in fact match, and the test will fail regardless. No unsafe operations involved (or so it seems).
For reference, here is the JUnit implementation of assertThat:
public static <T> void assertThat(T actual, Matcher<T> matcher) {
assertThat("", actual, matcher);
}
public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
if (!matcher.matches(actual)) {
Description description = new StringDescription();
description.appendText(reason);
description.appendText("\nExpected: ");
matcher.describeTo(description);
description
.appendText("\n got: ")
.appendValue(actual)
.appendText("\n");
throw new java.lang.AssertionError(description.toString());
}
}
First - I have to direct you to http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html -- she does an amazing job.
The basic idea is that you use
<T extends SomeClass>
when the actual parameter can be SomeClass or any subtype of it.
In your example,
Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));
You're saying that expected can contain Class objects that represent any class that implements Serializable. Your result map says it can only hold Date class objects.
When you pass in result, you're setting T to exactly Map of String to Date class objects, which doesn't match Map of String to anything that's Serializable.
One thing to check -- are you sure you want Class<Date> and not Date? A map of String to Class<Date> doesn't sound terribly useful in general (all it can hold is Date.class as values rather than instances of Date)
As for genericizing assertThat, the idea is that the method can ensure that a Matcher that fits the result type is passed in.
Thanks to everyone who answered the question, it really helped clarify things for me. In the end Scott Stanchfield's answer got the closest to how I ended up understanding it, but since I didn't understand him when he first wrote it, I am trying to restate the problem so that hopefully someone else will benefit.
I'm going to restate the question in terms of List, since it has only one generic parameter and that will make it easier to understand.
The purpose of the parametrized class (such as List<Date> or Map<K, V> as in the example) is to force a downcast and to have the compiler guarantee that this is safe (no runtime exceptions).
Consider the case of List. The essence of my question is why a method that takes a type T and a List won't accept a List of something further down the chain of inheritance than T. Consider this contrived example:
List<java.util.Date> dateList = new ArrayList<java.util.Date>();
Serializable s = new String();
addGeneric(s, dateList);
....
private <T> void addGeneric(T element, List<T> list) {
list.add(element);
}
This will not compile, because the list parameter is a list of dates, not a list of strings. Generics would not be very useful if this did compile.
The same thing applies to a Map<String, Class<? extends Serializable>> It is not the same thing as a Map<String, Class<java.util.Date>>. They are not covariant, so if I wanted to take a value from the map containing date classes and put it into the map containing serializable elements, that is fine, but a method signature that says:
private <T> void genericAdd(T value, List<T> list)
Wants to be able to do both:
T x = list.get(0);
and
list.add(value);
In this case, even though the junit method doesn't actually care about these things, the method signature requires the covariance, which it is not getting, therefore it does not compile.
On the second question,
Matcher<? extends T>
Would have the downside of really accepting anything when T is an Object, which is not the APIs intent. The intent is to statically ensure that the matcher matches the actual object, and there is no way to exclude Object from that calculation.
The answer to the third question is that nothing would be lost, in terms of unchecked functionality (there would be no unsafe typecasting within the JUnit API if this method was not genericized), but they are trying to accomplish something else - statically ensure that the two parameters are likely to match.
EDIT (after further contemplation and experience):
One of the big issues with the assertThat method signature is attempts to equate a variable T with a generic parameter of T. That doesn't work, because they are not covariant. So for example you may have a T which is a List<String> but then pass a match that the compiler works out to Matcher<ArrayList<T>>. Now if it wasn't a type parameter, things would be fine, because List and ArrayList are covariant, but since Generics, as far as the compiler is concerned require ArrayList, it can't tolerate a List for reasons that I hope are clear from the above.
It boils down to:
Class<? extends Serializable> c1 = null;
Class<java.util.Date> d1 = null;
c1 = d1; // compiles
d1 = c1; // wont compile - would require cast to Date
You can see the Class reference c1 could contain a Long instance (since the underlying object at a given time could have been List<Long>), but obviously cannot be cast to a Date since there is no guarantee that the "unknown" class was Date. It is not typsesafe, so the compiler disallows it.
However, if we introduce some other object, say List (in your example this object is Matcher), then the following becomes true:
List<Class<? extends Serializable>> l1 = null;
List<Class<java.util.Date>> l2 = null;
l1 = l2; // wont compile
l2 = l1; // wont compile
...However, if the type of the List becomes ? extends T instead of T....
List<? extends Class<? extends Serializable>> l1 = null;
List<? extends Class<java.util.Date>> l2 = null;
l1 = l2; // compiles
l2 = l1; // won't compile
I think by changing Matcher<T> to Matcher<? extends T>, you are basically introducing the scenario similar to assigning l1 = l2;
It's still very confusing having nested wildcards, but hopefully that makes sense as to why it helps to understand generics by looking at how you can assign generic references to each other. It's also further confusing since the compiler is inferring the type of T when you make the function call (you are not explicitly telling it was T is).
The reason your original code doesn't compile is that <? extends Serializable> does not mean, "any class that extends Serializable," but "some unknown but specific class that extends Serializable."
For example, given the code as written, it is perfectly valid to assign new TreeMap<String, Long.class>() to expected. If the compiler allowed the code to compile, the assertThat() would presumably break because it would expect Date objects instead of the Long objects it finds in the map.
One way for me to understand wildcards is to think that the wildcard isn't specifying the type of the possible objects that given generic reference can "have", but the type of other generic references that it is is compatible with (this may sound confusing...) As such, the first answer is very misleading in it's wording.
In other words, List<? extends Serializable> means you can assign that reference to other Lists where the type is some unknown type which is or a subclass of Serializable. DO NOT think of it in terms of A SINGLE LIST being able to hold subclasses of Serializable (because that is incorrect semantics and leads to a misunderstanding of Generics).
I know this is an old question but I want to share an example that I think explains bounded wildcards pretty well. java.util.Collections offers this method:
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
If we have a List of T, the List can, of course, contain instances of types that extend T. If the List contains Animals, the List can contain both Dogs and Cats (both Animals). Dogs have a property "woofVolume" and Cats have a property "meowVolume." While we might like to sort based upon these properties particular to subclasses of T, how can we expect this method to do that? A limitation of Comparator is that it can compare only two things of only one type (T). So, requiring simply a Comparator<T> would make this method usable. But, the creator of this method recognized that if something is a T, then it is also an instance of the superclasses of T. Therefore, he allows us to use a Comparator of T or any superclass of T, i.e. ? super T.
what if you use
Map<String, ? extends Class<? extends Serializable>> expected = null;

Java Generics: Returning object of generic class with type parameter that is a super of argument T

I am trying to accomplish something with Java generics and am having a hell of a time since the approaches I would instinctively take do not work in this language, due to type erasure. I can cobble something reasonable together, though, if I get get the following to work. I have two classes:
class A {}
class B extends A {}
And a third class:
class C<T extends A> {}
I want a generic factory method that will return an instance of C, if I give it an instance of either A or B. A first attempt might look like this:
<T extends A> C<T> getObject(T t) { ... }
The issue I am having, which I suppose is not very unique, is most easily explained with the following line:
B b = new B();
C<A> = getObject(b);
The way I have defined getObject, the above call will return an object of type C<B>, which is not C<A> and does not inherit from C<A>, so this will not compile.
What I want to know is: is it possible to invoke some generics magic so that the compiler chooses the generic type T in getObject to be the superclass involved in the above function call, namely A?
Thanks so much!
One thing you can do is change the declaration to be like this:
// (I've deviated from Java generic naming convention for clarity)
<TRet extends A, TArg extends TRet> C<TRet> getObject(TArg arg) { ... }
So now the return type and argument type are inferred independently:
TRet is inferred based on the assignment type of the return value.
TArg is inferred based on the type of the argument.
But TArg still must be TRet or a subclass of TRet. (Or looking at it in the other direction, TRet must be TArg or a superclass of TArg.)
Though I think that is a bit of an ordeal. Too, it's already been mentioned in comments that the singular-typed version compiles on Java 8.
But this:
I can cobble something reasonable together, though, if I get get the following to work.
kind of makes me wonder. It seems like you've described an attempted solution but not the actual problem and it makes me wonder if our suggestions are actually helpful here. If they are, excellent, but if they aren't, don't hesitate to edit the OP or comment with clarification.
I am going ahead and "steal the answer" (see question comments :)).
There is nothing wrong with your class definition. Sometimes you just need to give a hint to the compiler to help it with type inference (guessing what it type should be substituted instead of the generic parameter) when calling a generic method:
public class Test {
static class A { }
static class B extends A { }
static class C<T extends A> { }
public static <T extends A> C<T> getObject(T obj) {
return null; // We don't need to construct anything here
}
public static void main(String[] args) {
// This compiles just fine
C<A> result1 = Test.<A>getObject(new B());
// Of course you can just type-cast the argument
C<A> result2 = Test.getObject((A) new B());
}
}
UPDATE (again, credits to Sotirios) Java 8 clearly has an improved generic type inference and your code would work without the explicit parameter specification as shown above (i.e. C<A> result = getObject(new B()); would simply work out of the box).

java generics - one impl class, multiple views

I have the interface defined as below and is implemented by a single class MatchedAddressImpl.
interface MatchedAddress extends HouseHelpData, StreetHelpData, TownHelpData
public class MatchedAddressDetails implements MatchedAddress
the client should be provided different views (HouseHelpData or StreetHelpData or TownHelpData or MatchedAddress) of the same MatchedAddressImpl. So I have provided the below API for the clients.
public List<MatchedAddress> matchedAddresses()
public List<? extends HouseHelpData> houseHelpData()
public List<? extends StreetHelpData> streetHelpData();
public List<TownHelpData> townHelpData();
the problem is that the client needs to do something like below and I read ineffective java that the return types should not contain wild cards as the client usage looks ugly...I appreciate it if someone can help me improve the API. what I want is to remove the wildcards from the above methods.
List<? extends StreetHelpData> streetHelpDataList = details.streetHelpData();
For most cases, the proper usage is simply List<StreetHelpData>. You would still be able to put objects of type StreetHelpDataImpl, for instance.
Wildcards are, in my opinion, misleading. Basically, for List<? extends StreetHelpData> it would mean: "This list contains elements all of a certain type, which is a sub-type of StreetHelpData."
Wildcard example:
Consider :
class Animal {}
class Lion extends Animal {}
class Tiger extends Animal {}
The list List<? extends Animal> contains either Lions only (List<Lion>), Tigers only (List<Tiger>), or both (List<Animal>). However, the list List<Animal> can contain all sorts of Animals - Lions and/or Tigers - at all times.
(Thanks to Tom Hawtin for his pointers)
Why do you need wildcards in your API to begin with? Get rid of them.
I'm guessing the reason you've done it that way is you've tried to do the following in your implementation:
public List<HouseHelpData> houseHelpData() {
List<MatchedAddressDetails> results = new ArrayList<MatchedAddressDetails>();
... // populate it
return results;
}
and you've got a compiler error. Java Generic Tutorial explains why the above is illegal - basically it's to prevent you from inadvertedly adding HouseHelpData implementation incompatible with MatchedAddressDetails to the list and then trying to access it (from the downcasted list) as MatchedAddressDetails instance. What you CAN do, however, is:
public List<HouseHelpData> houseHelpData() {
List<HouseHelpData> results = new ArrayList<HouseHelpData>();
...
results.add(new MatchedAddressDetails());
...
return results;
}
No wildcards necessary.
If that was not the reason for adding the wildcards to API, perhaps you can clarify your question and explain what was it.

Categories

Resources