Why is the difference in argument types in an overridden method (one primitive and the other a shell) unacceptable?

I started with JAVA programming recently and asked one question. Let's say I have one SuperClass and one SubClass that extends SuperClass and tries to override the method defined in SuperClass as follows:

public class SuperClass{ public void method1(int val){ System.out.println("This is method in SuperClass.Val is:" + val); } } 

I am trying to extend SuperClass in my SubClass and override the method with only one exception, instead of the int type declared in method 1, I use the type for the argument as Integer as follows:

  public class SubClass extends SuperClass{ @Override public void method1(Integer val){ ///compiler gives an error } } 

This declaration of the SubClass method is not permitted by the compiler (I use the eclipse IDE). Why is this so? An integer is essentially an int wrapper then why is such a declaration forbidden?

thanks

+5
source share
4 answers

The formal explanation , as you probably already understand, is that the two functions have different signatures (as Andrew Tobikko already pointed out), so you cannot override the other.

So, I suppose that by asking this question, you really want to ask, โ€œwhy is this so,โ€ or โ€œwhy the compiler cannot figure out what to do to let me do this.โ€

So, the practical explanation is as follows:

This is because you might have some method somewhere (some class not related to the class) that takes SuperClass as a parameter and tries to call its method1() as follows:

 public void someMethod( SuperClass s ) { s.method1( 7 ); } 

When the compiler finds this, it will pass 7 as a parameter to method1() , it will not go through wrapped 7 . However, s cannot be an instance of SuperClass , it can be an instance of SubClass , for example:

 /* some code somewhere */ someMethod( new SubClass() ); 

This is true because the PLO has a principle known as the Liskov Substitution Principle , which states that

if S is a subtype of T, then objects of type T can be replaced with objects of type S (i.e. objects of type S can replace objects of type T) without changing any desired properties of this program (correctness, task performed, etc.) .

This is the same principle that allows you to assign new ArrayList<String>() variable of type List<String> , and without it, nothing will work in OOP.

So, the compiler would have to pass a simple primitive 7 , but the SubClass receiver method SubClass expect a wrapped 7 , and that didn't work. Thus, the language indicates that an implicit conversion of this kind is not valid to ensure that such meaningless situations may not occur.

Amendment

You may ask, "Why doesnโ€™t this work?" The answer is that primitives in java correspond to machine data types of the main equipment, and wrapped primitives are objects. So, on the machine stack, a 7 will be represented by a machine word with the value 7 , while wrapped 7 will be a pointer to an object that contains wrapped 7 , so it will be represented by a machine word containing the address of this object, and it will be something like 0x46d7c8fe .

+2
source

This is simply because you added the @Override syntax above the public void method1(Integer val) method, which asks the compiler to look for a method with the same signature in the base class that it cannot find, so it gives a compile-time error indicating The method method1(Integer) of type SubClass must override a superclass method .

To understand the problem you asked

The whole is essentially an int shell, then why is such an announcement forbidden?

Just because in any class you can declare a method with these signatures

 class SuperClass { public void method1(int val){ System.out.println("This is method in SuperClass.Val is:" + val); } public void method1(Integer val){ System.out.println("This is method in SuperClass.Val is:" + val); } } 

The above declaration is valid and therefore @Override will try to match the method with the exact signature in the base class.

+1
source

Why is it important that Integer be a wrapper for int? They are still different. You can use methods with the same name that just differ for those who have a primitive type and the other is the corresponding type.

The only relationship between int and Integer: the compiler inserts a conversion from one to another when one is specified in any situation and the other is required.

Therefore, when you have a reference to the super-type and call method1, the compiler generates bytecode, which essentially conveys the primitive. If at run time you use the actual SubClass, an overridden method will not match this call.

Of course, the compiler can be written in a style that allows for such overrides, but this will cause other problems:

If the decision was made at runtime, calling overriden methods would become expensive for boxing / unpacking and checking, they could even call NullPointerExceptions

If this is done by converting all the code in the box at compile time, such calls will cause the box to constantly disassemble.

It would also prohibit constructs in which you have a method that is overloaded to either take a type parameter or a primitive, because the type parameter can be a nested type for this primitive, as a result both methods are the same.

+1
source

The integer and int are different. You can change Integer to int or remove "@Override"

-1
source

Source: https://habr.com/ru/post/1237251/


All Articles