Whats the Use of Saying <? Extends Someobject> Instead of <Someobject>

Whats the use of saying ? extends SomeObject instead of SomeObject

List<SomeObject> l;

In this you cannot say List<SomeObject> l = new ArrayList<SubClassOfSomeObjectClass>;(not allowed)
wheres for

List<? extends SomeObject> l;

you can say

List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>;(allowed)

But note that in List<? extends SomeObject> l = new ArrayList<SubClassOfSomeObject>; you cannot add anything to your list l because ? represents unknown class (Except null of-course).

Update: For your question in the comment What could I possibly do with a list if I cannot add anything to it?

Now consider a case in which you have to write a function to print your list but mind you it must only accept a List having objects which are subclasses of your SomeObject. In this case as I stated above you cannot use

public void printList(List<SubClassOfSomeObjectClass> someList)

So what would you do? You would do something like

    public void printList(List<? extends SomeObject> someList) {
for(SomeObject myObj : someList) {
//process read operations on myObj
}

Java - Using ? extends Interface vs Interface only

You can pass a List<Category> to public void persist(List<? extends IBean> beansList), but you cannot pass a List<Category> to public void persist(List<IBean> beansList).

On the other hand, you can pass a List<IBean> to both methods.

Java generics: why someObject.getClass() doesn't return Class? extends T?

As per the Javadoc of the getClass method:

The actual result type is Class<?
extends |X|>
where |X| is the erasure
of the static type of the expression
on which getClass is called. For
example, no cast is required in this
code fragment

Here, the value for |X| in your code snippet is MyClass, hence instance.getClass() is assignable to only Class<? extends MyClass> or Class<?>.

The reason for this specific wording is because when you say that for this variable having type T where <T extends MyClass>, there can be multiple classes which extend MyClass and hence capable of satisfying the T extends MyClass criteria. Without runtime information there is no way of knowing which concrete implementation subclass of MyClass was passed in the method. Hence to provide a generic solution, it returns <? extends MyClass> since that would hold true for any subclass of MyClass irrespective of what class instance is passed in.

Method in the type MapString,capture#1-of ? extends Object is not applicable

? extends Object

You are using generic wildcard. You cannot perform add operation as class type is not determinate. You cannot add/put anything(except null).

For more details on using wildcard you can refer oracle docs.

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error

Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.

Java API class having a method with a meaningless type wildcard

Not quite.

A Function<? super T, U> is not the same as a Function<? super T, ? extends U>.

For example, I could still get an Optional<CharSequence>, even if I passed a Function<Object, String> to the method. If the method was defined as <U> Optional<U> map(Function<? super T, U> mapper), then this would not be possible.

That is because generics are invariant: <T> is not the same as <? extends T>. That's a design decision implemented in the Java language.

Let's see how Jon Skeet explains what would happen if generics would not be invariant:

class Animal { }

class Dog extends Animal { }

class Cat extends Animal { }
public void ouch() {
List<Dog> dogs = Arrays.asList(new Dog(), new Dog());
List<Animal> animals;
// This would be legal, right? Because a list of dogs is a list of animals.
List<Animal> animals = dogs;
// This would be legal, right? Because a cat could be added to a
// list of animals, because a cat is an animal.
animals.add(new Cat());
// Unfortunately, we have a confused cat.
}

Although I'm not entirely sure what you mean in your comments, I'll try to elaborate.

If you have full control over the Function you provide, it doesn't matter whether the method's signature is Function<? super T, U> or Function<? super T, ? extends U>, you'll just adapt your Function accordingly. But the authors of the method probably wanted the method to be as flexible as possible, allowing one to provide a Function with its second parameter to be also a subclass of U, instead of only U itself. Actually you widen its lower bound from U to a certain subtype of U.

So the function should really read <U> Optional<? the-most-general-but-fixed-supertype-of U> map(Function<? super T, U> mapper) but expressing it that way would be awkward.

I would be indeed awkward. In addition, there is a difference between your proposed notation and the actual method signature of map(), which involve implications of lower bounds and upper bounds.

Read more:

  • A picture explaining the principle "Producer Extends Consumer Super"
  • What is the use of saying <? extends SomeObject> instead of <SomeObject>?
  • Upper and lower bounds

How do I parameterize an extended Collection

You need to specify a type for the ArrayList's type parameter. For generic type parameters, T is fairly common. Since the compiler doesn't know what a T is, you need to add a type parameter to MyList that can have the type passed in. Thus, you get:

public class MyList<T> extends ArrayList<T>

Additionally, you may want to consider implementing List and delegating to an ArrayList, rather than inheriting from ArrayList. "Favor object composition over class inheritance. [Design Patterns pg. 20]"

Difference between ? super T and ? extends T in Java

extends

The wildcard declaration of List<? extends Number> foo3 means that any of these are legal assignments:

List<? extends Number> foo3 = new ArrayList<Number>();  // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
  1. Reading - Given the above possible assignments, what type of object are you guaranteed to read from List foo3:

    • You can read a Number because any of the lists that could be assigned to foo3 contain a Number or a subclass of Number.
    • You can't read an Integer because foo3 could be pointing at a List<Double>.
    • You can't read a Double because foo3 could be pointing at a List<Integer>.
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can't add an Integer because foo3 could be pointing at a List<Double>.
    • You can't add a Double because foo3 could be pointing at a List<Integer>.
    • You can't add a Number because foo3 could be pointing at a List<Integer>.

You can't add any object to List<? extends T> because you can't guarantee what kind of List it is really pointing to, so you can't guarantee that the object is allowed in that List. The only "guarantee" is that you can only read from it and you'll get a T or subclass of T.

super

Now consider List <? super T>.

The wildcard declaration of List<? super Integer> foo3 means that any of these are legal assignments:

List<? super Integer> foo3 = new ArrayList<Integer>();  // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
  1. Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from List foo3:

    • You aren't guaranteed an Integer because foo3 could be pointing at a List<Number> or List<Object>.
    • You aren't guaranteed a Number because foo3 could be pointing at a List<Object>.
    • The only guarantee is that you will get an instance of an Object or subclass of Object (but you don't know what subclass).
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can add an Integer because an Integer is allowed in any of above lists.
    • You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.
    • You can't add a Double because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add a Number because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add an Object because foo3 could be pointing at an ArrayList<Integer>.

PECS

Remember PECS: "Producer Extends, Consumer Super".

  • "Producer Extends" - If you need a List to produce T values (you want to read Ts from the list), you need to declare it with ? extends T, e.g. List<? extends Integer>. But you cannot add to this list.

  • "Consumer Super" - If you need a List to consume T values (you want to write Ts into the list), you need to declare it with ? super T, e.g. List<? super Integer>. But there are no guarantees what type of object you may read from this list.

  • If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g. List<Integer>.

Example

Note this example from the Java Generics FAQ. Note how the source list src (the producing list) uses extends, and the destination list dest (the consuming list) uses super:

public class Collections { 
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}

Also see
How can I add to List<? extends Number> data structures?

java generics bounds

List<? extends SomeObject> l

What do you mean by that? Of course it will generate an error.

Take this example :SomeObject is Fruit, you have 2 derived classes Apple and Orange

Your list what will it contain? Apples or Oranges? The compiler cannot tell. So it generates error.

If you replace List<? extends SomeObject> l with List<SomeObject> l. Then this will work because Apple and Orange are both Fruit.

Java Generic with ArrayList ? extends A add element

ArrayList<? extends A> means an ArrayList of some unknown type that extends A.

That type might not be C, so you can't add a C to the ArrayList.

In fact, since you don't know what the ArrayList is supposed to contain, you can't add anything to the ArrayList.

If you want an ArrayList that can hold any class that inherits A, use a ArrayList<A>.

Method argument extends class implements interface

Your pattern class has to extend BasicObject and extend/implement CodeObject (which is actually an interface). You can do it with multiple classes declared in the wildcard definition of the method signature, like this:

public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz)

Note that it won't work if you do it any of these ways:

  • public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)

    This is technically valid syntax, but CodeObject is unused; the method will accept any classes that extends BasicObject, no matter whether they extend/implement CodeObject.

  • public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
    public void myMethod(Class<? extends BasicObject, CodeObject> clazz)

    These are just wrong syntax according to Java.



Related Topics



Leave a reply



Submit