Why is type compatibility not applicable to primitives, and also when overriding methods?

When we say that the base class Base and its derived class Derived are type compatible , we refer to the fact that the Base reference can refer to an instance of Derived .
That is, Base b = new Derived();
Casting will be required for the oposite because types are not compatible with the type. Now this concept is not applicable to primitive types?
I mean it

 short shortNumber = 10; int intNumber = shortNumber; 

it seems to me the same thing (since no casting is required, and both short and int are integer types).
Therefore, overriding the method in the base class, why is it acceptable that the return type is either the same, or at least compatible with the return type of the base class, but it also does not apply to integral types?

For example. why is this unacceptable?

 public class Person { public int getId(){ return 1; } } public class Employee extends Person { public short getId(){ return 0; } } 
+7
source share
4 answers

The direct answer why your sample code is unacceptable is simple: the Java language function obviously does not use covariance return types for primitives . See JLS 8.4.5 and JLS 8.4.8.3 .

Autoboxing is not applicable here. If you changed the return types to Integer and Short , they would still not be replaceable return-types, because none of them are a subclass of the other.

I can not answer the question "why JLS does not allow covariant return types for primitives", that is why the language developers decided that this should not be allowed.

+7
source

Since Java 1.5, your shorts and ints are all automatically loaded into Short and Integer , and Short does not extend Integer (for example, it has a different MAX_VALUE).

This is one of the reasons why this would be problematic, but I think the true reasons are one of the Java design development decisions: if you are going to change the type, we want you to know about it.

+3
source

you cannot override a method based on return types, it is not allowed, and the compiler will complain that it will not be considered as an overridden method.

Also, function calls are not deterministic based on return types. For example, if you call

someObj.getId ();

How does the compiler determine which method should be called? it does not matter from the point of view of the compiler that you are not processing the return value.

+2
source
  • JLS # 8.4.8.3 : Override and Hide Requirements

    If the declaration of method d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be replaced with the return type (ยง8.4.5) for d2 or a compile-time error occurs.
    This rule allows covariant return data types - refining the return type of a method when overriding it.

  • JLS # 8.4.5 : Method return type: objects and primitives are not processed the same way (main focus):

    Declaration of method d1 with return type R1 is a return type-replaceable for another method d2 with return type R2, if and only if the following conditions are true:

    • If R1 is invalid, then R2 is invalid.
    • If R1 is a primitive type, then R2 is identical to R1.
    • If R1 is a reference type, then:
      • R1 is either a subtype of R2, or R1 can be converted to a subtype of R2 by an unchecked conversion (ยง5.1.9) or
      • R1 = | R2 |

As for your initial example, it is called an expanding transform (short โ†’ int) and is not used in the context of method overrides.

+2
source

All Articles