Exception thrown when using static import?

I experience strange behavior when using static import of inherited static methods:

com / example / Util / BaseUtil.java:

package com.example.util; /*default*/ class BaseUtil { public static final void foo(){ System.out.println("foo"); } } 

com / example / Util / Util.java:

 package com.example.util; public final class Util extends BaseUtil{ public static void bar(){ System.out.println("bar"); } //foo() will be inherited } 

com / example / UtilTest.java

 package com.example; import static com.example.util.Util.bar; import static com.example.util.Util.foo; public class UtilTest { public static void main(String[] args) { bar(); foo(); } } 

Running UtilTest will result in an unchecked exception!

Exception in thread "main" java.lang.IllegalAccessError: tried to access the class com.example.util.BaseUtil from class com.example.UtilTest

  at com.example.UtilTest.main(UtilTest.java:15) 

However, if I had to invoke methods using Util (without static import), everything works as expected:

com / example / UtilTest.java

 package com.example; import com.example.util.Util; public class UtilTest { public static void main(String[] args) { Util.bar(); Util.foo(); } } 

So what gives?

+4
source share
3 answers
 /*default*/ class BaseUtil { //only visible within the package com/example/util 

This class has a defualt access specifier, which makes it invisible from outside this package.

You need to make this publicly available.

Update

Below is what decompilation looks like:

 public class com.example.UtilTest extends java.lang.Object{ public com.example.UtilTest(); Code: 0: aload_0 1: invokespecial #8; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: invokestatic #16; //Method com/example/util/Util.bar:()V 3: invokestatic #21; //Method com/example/util/BaseUtil.foo:()V 6: return } 

And this is what I get with the JD GUI

 package com.example; import com.example.util.BaseUtil; import com.example.util.Util; public class UtilTest { public static void main(String[] args) { Util.bar(); BaseUtil.foo(); } } 

which, of course, is not going to compile.

Here it looks like a hole in the compiler (possibly due to static import).

+5
source

Not quite the answer, but something else needs to be considered when importing static functions.

When you work with static functions / constants, they can sometimes be compiled in a string. It depends on which compiler you are using. I can’t remember from my head which ones.

This is a problem when you import a static variable / function from an external library and then update this library at runtime, your code will still have the old OLD function.

My suggestion is to generally avoid static functions and use a singleton object instead. Use a framework such as spring to inject singleton into your class at runtime.

It is good practice to make this object final and use the constructor to set it.

It also makes testing easier because you can make fun of a singleton.

+1
source

The first version of your code compiles efficiently

 package com.example; public class UtilTest { public static void main(String[] args) { com.example.util.Util.bar(); com.example.util.BaseUtil.foo(); } } 

and since BaseUtil has a package scope, you cannot call it from another package, and you get an exception.

The second version of your code compiles efficiently

 package com.example; public class UtilTest { public static void main(String[] args) { com.example.util.Util.bar(); com.example.util.Util.foo(); } } 

Since Util is a public class, you get access to all methods, including foo , since foo displayed in Util.

What makes me wonder why any of the versions compiles correctly?

0
source

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


All Articles