Import static does not work if the class has methods with the same name as the imported ones.

I have a Junit4 test case that statically imports the org.junit.Assert.assertEquals method.

 import static org.junit.Assert.assertEquals; 

In this class, I created a utility method for approving some complex inner classes that do not implement equals (and also have a hard time implementing it).

 private void assertEquals(MyObj o1, MyObj o2) { assertEquals(o1.getSomething(), o2.getSomething()); assertEquals(o1.getSomethingElse(), o2.getSomethingElse()); ... } 

I expected the code to behave as if I were "overloading" the assertEquals method that I import, but it looks like my private non-static method hides statically imported methods. I also tried to turn my method into public and static (all permutations), but without success - I had to rename it.

Any reason why she behaves like this? I could not find references to this behavior in the documentation.

+6
source share
4 answers

What you observe causes Shadowing . When two types in java have the same simple name, one of them will be shadow. the shadow type cannot be used by a simple name then.

The most common type of shading is the option to hide the field. usually cause the installer code to look like setMyInt(int myInt) {this.myInt = myInt; } setMyInt(int myInt) {this.myInt = myInt; }

Now read the relevant documentation :

A static-import-on-demand declaration never obscures any other declaration.

This indicates that on-demand static imports always come last, so any type with the same simple name as the on-demand import declaration will always hide (hide) static imports.

+3
source

Overloading and rewriting are performed in the inheritance tree. But static import does not create inheritance.

If you want to use assertEquals junit in your own assertEquals method, you must qualify it with a class name, for example. Assert.assertEquals.

Use non-static import org.junit.Assert.

+1
source

You stumbled upon the hiding method , where having a local method β€œhides” one from another class (often a superclass).

I always felt that statically importing methods are syntactically possible, somehow "wrong."

As a style, I prefer to import the class and use TheirClass.method() in my code. This makes it clear that the method is not a local method, and one of the hallmarks of good code is clarity.

I recommend you import org.junit.Assert and use Assert.assertEquals(...) .

0
source

It makes sense. Suppose javac does what you want, it selects your assertEquals(MyObj, MyObj) today. What if tomorrow org.junit.Assert adds its own assertEquals(MyObj, MyObj) method assertEquals(MyObj, MyObj) ? The call value of assertEquals(mo1,mo2) has changed dramatically if you don't know it.

The question makes sense of the name assertEquals . Javac should decide that this is the name of the method (s) in org.junit.Assert . Only after that it can overload the method permission: consider all the methods in org.junit.Assert with the name assertEquals , select the most suitable one.

It can be assumed that java can handle overloading methods from several classes, however, as the first paragraph shows, this causes great uncertainty for the developer of the class that he calls. Since these classes are not related to each other, the semantics of the method can vary greatly.

If, during compilation, without a doubt, you develop a class to which this method belongs, it is still possible that the class will overload the method tomorrow and then change the called method. However, since this is done by the same class, we can assign responsibility to it. For example, if org.junit.Assert decides to add a new assertEquals(MyObj, MyObj) method assertEquals(MyObj, MyObj) , he should know that some previous calls to assertEquals(Object,Object) now redirected to the new method, and he must make sure that there are no semantics changes that Call sites will be broken.

0
source

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


All Articles