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

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
stxrk___
Posts: 2
Joined: Thu May 14, 2020 2:02 pm
Contact:

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

Post by stxrk___ »

Working through the mock exams, which is really helpful.

I came acress this one:

"Given:

Code: Select all

class Base{
   public  <T extends Number, Z extends Number> Map<T, Z> getMap(T t, Z z)
   {
      return new HashMap<T, Z>();
   }
}

class Derived extends Base{
   //public  <T, Z> TreeMap<T, Z> getMap(T t, Z z) { return new TreeMap<T, Z>(); }; //1

   //public  Map<Number, Number> getMap(Number t, Number z) { return new TreeMap<Number, Number>(); }; //2

   //public  Map<Integer, Integer> getMap(Number t, Number z) { return new HashMap<Integer, Integer>(); };   //3
}
Identify correct statements about the methods defined in Derived assuming they are uncommented one at a time individually."

Correct answer is:
//1 correctly overloads while //2 and //3 correctly override the method in Base.
The rules for multiple type parameters are same as the rules for a single type parameter. You have to apply the same rules for both the type parameters separately. For example, we know that A<S> is a valid subtype of A<? extends T> (where S is a subtype of T). Therefore, Map<Integer, Integer> is a valid subtype of Map<T extends Number, Z extends Number>. The bounds defined by <T extends Number> and <T> are different. Therefore, the parameter list of //1 i.e. getMap(T t, Z z) is different from the parameter list of the Base class's method. Thus, it is a valid overload.

The way I see it. //1 and the baseClass have the same signature ( getMap(T t, Z z)), so one would be an override, no? Am I missing something? :)

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

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

Post by admin »

No, it is an overload because, as explained in the explanation, the bounds of T and Z are different in Base and Derived classes.

You can do a simple test to check this. Just call super.getMap(t, z); in the Derived class's getMap method. It will not compile. This means, the compiler doesn't consider the Derived class's method to be overiding the Base class's method.
If you like our products and services, please help us by posting your review here.

stxrk___
Posts: 2
Joined: Thu May 14, 2020 2:02 pm
Contact:

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

Post by stxrk___ »

hmm, thanks for clearing that up :)

dimitrilc
Posts: 35
Joined: Sat Jun 06, 2020 4:51 pm
Contact:

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

Post by dimitrilc »

So from this question, is the rule below correct?

1. When the parent method contains range-bounded generic type parameters,
2. If the child method modifies the range-bounded generic type parameters,
3. Then the child method is absolutely NOT Overriding the parent method.

For example, parent method:

Code: Select all

public  <T extends Number, Z extends Number> Map<T, Z> getMap(T t, Z z)
If the child method modifies the range-bounded type parameters, then there is no way that the child method can be an Override:

Code: Select all

public  <T super Number, Z super Number> Map<T, Z> getMap(T t, Z z)

Code: Select all

public  <T, Z> Map<T, Z> getMap(T t, Z z)

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

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

Post by admin »

That's correct. Please go through Section 8.4.8.3 "Requirements in Overriding and Hiding" of JLS 11 for details.
If you like our products and services, please help us by posting your review here.

philippe
Posts: 29
Joined: Sun Jul 16, 2017 4:24 pm
Contact:

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

Post by philippe »

Regarding this override:

Code: Select all

public Map<Integer, Integer> getMap(Number t, Number z) {
  return new HashMap<Integer, Integer>();
}
I don't understand why this compiles.

In the super class, geMap is defined as follows:

Code: Select all

public  <T extends Number, Z extends Number> Map<T, Z> getMap(T t, Z z) {
  return new HashMap<T, Z>();
}
In the sub type, the parameterized types are both Integer. How is it possible that the compiler doesn't complain about the method parameters, which are put as Number and not Integer?

When I put it in my IDE, the following warning is given (I don't understand why):

Code: Select all

Type safety: The return type Map<Integer,Integer> for getMap(Number, Number) from the type Derived needs unchecked conversion to conform to Map<Number,Number> from the type Base

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

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

Post by admin »

The following code explains the issue:

Code: Select all

class A {
   public <T extends Number, Z extends Number> Map<T, Z> getMap(T t, Z z) {
      return new HashMap<T, Z>();
   }
}

public class TestClass extends A {
   public Map<Integer, Integer> getMap(Number t, Number z) {
      return new HashMap<Integer, Integer>();
   }

   public static void main(String[] args) {
      Double d = 1.0;
      A a = new TestClass(); //1
      Map<Double, Double> m = a.getMap(d, d);
   }
}
In the main method at //1, the reference a is of type A. Therefore, anyone calling a.getMap(d, d), will expect a Map of Doubles to be returned. However, the object to which a points is of type TestClass, which overrides the getMap method to return a Map of Integers. The compiler cannot prevent this from happening because Integer satisfies the requirement "T extends Number" imposed by the method in the superclass. Therefore, it generates the warning saying:

Code: Select all

warning: [unchecked] getMap(Number,Number) in TestClass overrides <T,Z>getMap(T,Z) in A
public Map<Integer, Integer> getMap(Number t, Number z) {
                             ^
  return type requires unchecked conversion from Map<Integer,Integer> to Map<T,Z>
  where T,Z are type-variables:
    T extends Number declared in method <T,Z>getMap(T,Z)
    Z extends Number declared in method <T,Z>getMap(T,Z)
The JLS makes a special provision to allow this type of overriding. As per section 8.4.5:
An unchecked conversion is allowed in the definition, despite being unsound, as a special allowance to allow smooth migration from non-generic to generic code. If an unchecked conversion is used to determine that R1 is return-type-substitutable for R2, then R1 is necessarily not a subtype of R2 and the rules for overriding (§8.4.8.3, §9.4.1) will require a compile-time unchecked warning.
Please go through the sections quoted above from the JLS.
If you like our products and services, please help us by posting your review here.

philippe
Posts: 29
Joined: Sun Jul 16, 2017 4:24 pm
Contact:

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

Post by philippe »

Thanks for the clear explanation!

enthunoob
Posts: 60
Joined: Thu Apr 15, 2021 12:21 pm
Contact:

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

Post by enthunoob »

Hello, in the explanation of this question I think a word 'overriding' should be replaced with 'overridden'.

Third, if it is a potential override, check the return type. Java allows "covariant" returns, which means, the return type of the overriding method must be the same or be a subtype of the return type mentioned in the overridden method. Check the two return types without the generic type specification. If return type of the overriding method is covariant with respect to the return type of the >>>>>overriding<<<<<< method (for example, ArrayList is covariant with List), then perform the same check including the generic type specification (for example, ArrayList<CharSequence> is covariant with List<? extends CharSequence>).

Is my assumption correct?

enthunoob
Posts: 60
Joined: Thu Apr 15, 2021 12:21 pm
Contact:

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

Post by enthunoob »

And a point of feedback. Please add a step by step analysis per answer/line of code, instead of a half one for only the correct answer. I've come across this (very general) explanation before and find it very hard to get through.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

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

Post by admin »

You are right, it is a typo and should be fixed.

Regarding explanations to each option, we do try to provide explanations to the wrong options as well whereever the author feels it is warranted. But you are right, the author may sometimes feel that an option is obviously wrong and deserves no further explanation but it may not be so obvious to the reader. We will improve. Did you feel any particular option of this question requires more explanation? Please do tell.


Regarding generic explanations at the end of a question, such explanations may contain a larger theoretical discussion/points on a concept or topic and in that case, it may be repeated in multiple questions. Their purpose is to cover all important aspects of that concept
(even if that question does not test on all aspects) so that the reader can answer other questions on that concept later.
If you like our products and services, please help us by posting your review here.

steinov
Posts: 19
Joined: Wed Feb 08, 2023 3:11 am
Contact:

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

Post by steinov »

I was trying some code to understand the answers better. I tried this override:

Code: Select all

public Map<Integer, Integer> getMap(Integer t, Number z) {
    return new HashMap<Integer, Integer>();
}
If I annotate it with @Override I get a compiler error: `method does not override or implement a method from a supertype`. I don't understand why, my logic would be that T is of type Integer and therefore it should be allowed as parameter type in an override. Can you explain why this is not the case?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

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

Post by admin »

T and Z are defined in the base class as something that "extends Number". You are trying to override the method with Integer but that make the overriding method more specific than the one which it is overriding. The reason is that "? extends Number" includes many classes such as Integer, Long, Double etc. But Integer is just one specific class. Hence, this method cannot be considered an override.

Think of it this way:

Let us say you got a reference to a Base class object from some method like this:
Base b = getBaseObject(); //you don't know how getBaseObject is implemented. It is implemented by someone else.

You should be able to invoke b.getMap() by passing a Double, Double also because Double extends Number. This is promised by the method definition of Base.getMap.

Now, getBaseObject() method is free to return any subclass of Base also. It is ok because a Derived IS-A Base. But you are overriding getMap(T Z) in Derived with getMap(Integer, Integer). What will happen when you call getMap(Double, Double) on this Derived object? It will fail because Derived's getMap expects Integer.

This shows that getMap(Integer, Number) is not really a valid override for getMap(T, Z). It is a different method altogether.
If you like our products and services, please help us by posting your review here.

steinov
Posts: 19
Joined: Wed Feb 08, 2023 3:11 am
Contact:

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

Post by steinov »

Thanks! I get it now!

Post Reply

Who is online

Users browsing this forum: No registered users and 23 guests