Page 1 of 1

About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Thu Jun 27, 2019 4:13 pm
by dongyingname
class Base{
public <T> Collection<T> transform(Collection<T> list) {
return new ArrayList<T>();
}
}

class Derived extends Base{
public <T> Collection<T> transform(Collection<T> list) {
return new HashSet<String>();
}; //1
}
This looks like a valid override to me.
Could someone explain?
And did anyone notice the extra semicolon at the end of each option? Doesn't it cause compile error?

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Thu Jun 27, 2019 9:45 pm
by admin
Did you try compiling it?

The return type of the method in Derived is Collection<T> but it returns HashSet<String>. HashSet is a Collection, so that part is ok, but the issue is with <T> vs String.

The extra semi-colon need not be there but it will not cause any error.

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Thu Jan 09, 2020 2:03 pm
by wdphipps
Could you explain the issue with <T> vs String? Will it not compile?

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Thu Jan 09, 2020 6:51 pm
by admin
Base class method returns Collection<T> but the overiding method is trying to return HashSet<String>.
What happened when you tried to compile?

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Sat Dec 12, 2020 6:48 pm
by 2014098616
Hello Admin, I don't understand why List<? super Number> is a subtype of List<? super Integer>, why can't it be List<? super Integer> is a subtype of List<? super Number> instead.

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Sat Dec 12, 2020 9:51 pm
by admin
It goes in the reverse direction with lower bounds. Think of it like this:
A subtype is always more precise (or specific or restrictive) than a supertype. For example, if something is-a Number, it can be an Integer or Short or Byte also but an Integer can only be an Integer. That means an Integer is more specific than a Number and is therefore a subtype.
Now, List<? super Number> means, it is a List of objects of a class that is a super type of Number. There are only two possibilities - Number and Object. But List<? super Integer> means, it is a List of objects of a class that is a super type of Integer, which means there are three possibilities - Integer, Number and Object.

That is why List<? super Number> is considered a subtype of List<? super Integer>.

You can also go through this tutorial for more details: https://docs.oracle.com/javase/tutorial ... yping.html

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Sun Dec 13, 2020 8:17 am
by 2014098616
Thank you very much admin. I perfectly understand now.

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Sat Feb 20, 2021 4:54 am
by mikolajczak4
Hi,

In explanation there is one sentence :

Second, if it is a potential override, check the generic type specification of the parameters. If the overriding method does not use a generic type specification for the parameter type, then it is valid. The reverse is not valid i.e. the overriding method is allowed to erase the generic type specification but is not allowed to add a generic type specification if the overridden method does not have it. If both the methods have a generic type specification, then the specification must match exactly. For example, if the overridden method has Set<Integer>, then the overriding method can use Set or Set<Integer>. But if overridden method has Set, then the overriding method must also have Set for a valid override.

The bold text says if overridden method has Set overriding method must also have Set but when I compile below example it seems jvm accepts that.

public class B {
public Set m() {
return null;
}
}

class C extends B {
@Override
public Set<Integer> m() {
return null;
}
}

Is there something I did not understand from that explanation ?
Thanks. :cheers:

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Sat Feb 20, 2021 7:35 am
by admin
The explanation is talking about parameters. Not return types.

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Wed Mar 03, 2021 5:45 am
by maria_maria
public <T> Collection<T> transform(Collection<T> list) { return new ArrayList<T>(); }

public <X> Collection<X> transform(Collection<X> list) { return new HashSet<X>();}; //4
public Collection<CharSequence> transform(Collection<CharSequence> list) { return new HashSet<CharSequence>();}; //5

Why is 4 a valid override? Isn't this similar to 5(which returns a compiler error) but instead of X you have a certain type?

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Wed Mar 03, 2021 7:17 am
by admin
4 and 5 are very different. X is not a type. It is just a placeholder for a type. So basically, 4 is exactly same as the overridden method (which uses T as the placeholder).
While CharSequence is not a placeholder. It is an actual type. Thus, 5 is more restrictive than the original method and is therefore, not a valid override.

Think about it this way, in the original method you are free to type the input parameter to any type. But in 5, you are restricting it to CharSequence.

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Mon Sep 27, 2021 4:30 am
by siletti.alberto
Hi,

In explanation there is one sentence :

Second, if it is a potential override, check the generic type specification of the parameters. If the overriding method does not use a generic type specification for the parameter type, then it is valid. The reverse is not valid i.e. the overriding method is allowed to erase the generic type specification but is not allowed to add a generic type specification if the overridden method does not have it. If both the methods have a generic type specification, then the specification must match exactly. For example, if the overridden method has Set<Integer>, then the overriding method can use Set or Set<Integer>...

But if I have:

Code: Select all

class BaseTest {
    public <T> void transform(Set<Integer> set) {    }
}

class DerivedTest extends BaseTest {
    public <T> void transform(Set set) {    }
}
The compiler give me:
'transform(Set)' in 'com.company.DerivedTest' clashes with 'transform(Set<Integer>)' in 'com.company.BaseTest'; both methods have same erasure, yet neither overrides the other
Please I dont understan: is it not in contradiction?

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Mon Sep 27, 2021 4:37 am
by siletti.alberto
Sorry please consider this more real example :

Code: Select all

class BaseTest {
    public <T> void transform(Set<Integer> set, T t) {  
// some code for example a  BiConsumer<Set<Integer> set, T )
  }
}

class DerivedTest extends BaseTest {
    public <T> void transform(Set set, T t) {   
// some other code
 }
}

Re: About Question enthuware.ocpjp.i.v11.2.3097 :

Posted: Mon Sep 27, 2021 4:54 am
by admin
Your example is not the right test case for the explanation because in your BaseTest's transform method , the parameter T t does not have the generic type specification. So, the case, "base uses generic type but sub doesn't" is not satisfied.

The following is the right example. It compiles fine:

Code: Select all

import java.util.*;
class BaseTest {
    public void transform(Set<Integer> set) {  
    }

    public <T> void transform2(Set<T> set) {  
    }

    public <T> void transform3(Set<Integer> set) {  
    }

}

class DerivedTest extends BaseTest {
    public void transform(Set set) {   
    }
    public void transform2(Set set) {   
    }

    public void transform3(Set set) {   
    }
}
In your previous example, you have <T> in base class as well as child class. If you remove <T> from child class, it will compile.