My code compiles fine in Eclipse, but when I try to compile from the commandline (via our ruby-based buildr system), I get this error message:
static import only from classes and interfaces
Suggesting that static import of public static fields is not permitted. What should I look for to help diagnose this problem? How can I fix it?
Update:
per #Ted's request, the constant declaration in the referenced file:
public static final String NULL = "<NULL>";
and the (bowdlerized) reference in the referring file:
import static my.path.MyClass.NULL;
My guess is that Eclipse and buildr are using either different Java compiler versions or different compiler flags. There's a bug in the Java 7 compiler (bug ID: 715906) that generates this error when you statically import specific fields. The work-around is to use a wildcard static import. So instead of:
import static pkg.Class.staticField;
do this:
import static pkg.Class.*;
Late answer but I just got a similar issue and figured it out. I'll post in case it helps anyone else who finds this page...
I got a similar error when, after a big merge and refactor, I accidentally put a test class into src/main/java instead of src/test/java. Since the JUnit dependency was scope=tests, it didn't work in pure maven. Maybe you are having the same issue
I also had this error and my issue turned out to be a wayward static import of a junit 4 package in my test source file.
I had the following:
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTimeout;
I removed the import static org.junit.Assert.fail; (no idea how I managed to get that in there in the first place) and all is now working.
I accidentally set test directory as source. And Test sources were considered as source files.
sourceSets.main.java.srcDirs 'src'
| -- src
| -- main
| -- test
Fix:
sourceSets.main.java.srcDirs 'src/main'
Some how same solution mentioned by #m-watson
I have replaced
import static org.junit.Assert.assertThrows;
With
import static org.junit.jupiter.api.Assertions.assertThrows;
and it worked
Related
Here is my class:
package pepelu;
import pepelu.ImportTest.InnerClass.InnerEnum;
import javax.annotation.Resource;
public class ImportTest {
#Resource
public static class InnerClass {
public enum InnerEnum {
A
}
}
public static void main(String[] args) {
System.out.println(InnerEnum.A);
}
}
When I use maven to build, it will give a compilation error:
mvn clean compile
[ERROR] /Users/finup/Desktop/a/importtest/src/main/java/pepelu/ImportTest.java:[8,6] cannot find symbol
After changing the import order to:
import javax.annotation.Resource;
import pepelu.ImportTest.InnerClass.InnerEnum;
I got a successful maven build.
I searched for documents, but cannot find an explain for this.
Could anyone please explain how import works in this case?
I guess the reason is a "circular" dependency: you have some element X that you import within the same file/class where you are defining it.
Meaning:
import pepelu.ImportTest.InnerClass.InnerEnum;
actually refers to code following in the very same file:
public static class InnerClass {
public enum InnerEnum {
This means: for the compiler, in order to process that import, it has to look into the body of the class in the same file.
It seems that javac does that "immediately". Meaning: it starts reading import statements, and importing from the same class makes it "suspend" looking at imports, but checking out the following class definition.
And guess what: that class definition makes use of another import. In order to "process" the definition of that enum, the compiler needs to understand where/what that #Resource annotation is about. But it doesn't know the annotation yet (because the compiler didn't see the import, yet).
When you change the order, the compiler understands that #Resource usage in the class definition.
And of course: the real answer is not to reorder imports. The real answer is to not import something from the class that is following after the import statements. There is absolutely no point in doing so.
Edit, given the comment by the OP about how this can work in Redisson: honestly, I don't know. It might depend on how exactly that class is compiled. Maybe such code works with newer (or older) versions of javac, maybe this works with specific versions of the eclipse or intellij or xyz compiler.
Meaning: I gave you an explanation why you are running into this problem. That doesn't mean that any compiler must necessarily run into the same problem.
Trying to learn Java from Bruce Eckel's book, I don't understand why the compiler doesn't find the library I want to import. I have first done this on Windows/Cygwin and now on Centos 7, using OpenJDK 1.8.0. Same result on both platforms.
This line:
import static t.b.u.*;
causes compiler error
$ javac TestPrint.java
TestPrint.java:2: error: package t.b does not exist
import static t.b.u.*;
^
I agree that package t.b doesn't exist, but I actually wanted to import package t.b.u. Why does the compiler ignore the u?
CLASSPATH is set as follows:
$ export|grep CLASS
declare -x CLASSPATH="/home/bbausch/thinking-in-java"
The package is a single file:
$ cat /home/bbausch/thinking-in-java/t/b/u/Print.java
package t.b.u;
import java.io.*;
public class Print {
... etc ...
The error is probably so obvious that I don't see it. Can somebody help?
This is specifically related to the Java Language Specification: https://docs.oracle.com/javase/specs/jls/se7/html/jls-7.html#jls-7.5.3
These two lines inherently ask for different things:
import static t.b.u.*;
This statement asks to import all static methods from a class named u from a package t.b.
import t.b.u.*;
This statement asks to import all classes underneath t.b.u.
Static imports target a TypeName only. Normal imports target a package, or a specific class.
The roughly equivalent general import to the static import would be this:
import t.b.u;
This asks to import just the class u from a package t.b.
In your specific example, you'd probably want this statement to import all static methods of the Print class.
import static t.b.u.Print.*;
I've faced an issue with compilation, but cannot understand why it occurs.
Actually much time was spent to understand where the reason is (it was far from obvious in a "crap" project), but after reproducing that error I greatly simplifies all the code to show a little example especially for you:
Package structure:
com.company
|
----Main.class
|
----maker
|
----Maker.class
Maker.class
package com.company.maker;
public interface Maker {
}
Main.class
package com.company;
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
import com.company.maker.Maker;
public class Main {
public static void main(String[] args) {
System.out.println(STRATEGY1.name() + STRATEGY2.name());
}
static class MakerImpl implements Maker {
enum Strategy {
STRATEGY1, STRATEGY2
}
}
}
And I got compilation error in Main class:
Error:(15, 39) java: cannot find symbol
symbol: class Maker
location: class com.company.Main
And if I change the import sequence from
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
->import com.company.maker.Maker;
to
->import com.company.maker.Maker;
import static com.company.Main.MakerImpl.Strategy.STRATEGY1;
import static com.company.Main.MakerImpl.Strategy.STRATEGY2;
then it is compiled successfully.
Is it normal behaviour of Java Compiler? If so I want to clearly understand why it happens.
P.S. tested using java version 1.8.0_112 and 1.7.0_80 (MacOS)
check this :
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6391197
It seems that the compiler sees the first static import and then jumps to take care of your inner class, but fails because it did not read the last non static import.
So when you change the import order, this problem does not occur, since when the compiler reads the static import and jumps to take care of the inner class because those imports are used in the inner class, the compiler is happy since it already imported the non static Maker Interface.
Wich means that the imports are evaluated eagerly.
I hope this helps.
See also Java how import order matters when import class/enum inner an inner class to see that this problem also exists with non static imports.
I have a "Sprites" folder with some class files and a "Launcher" folder with some class files. I tried the following code for import:
package Sprites;
and it lead to the following
hw9\Launcher>javac *.java
TowerDefense.java:2: error: class, interface, or enum expected
package Sprites;
^
1 error
Am I doing this incorrectly? My Sprites and Launcher are in the hw9 directory, so I assumed it would work. A picture for clarification:
You can use a wildcard import to import all classes within the immediate directory:
import Sprites.*;
This opposed to something like:
import Sprites.Class1;
import Sprites.Class2;
import Sprites.Class3;
...
Generally, wildcard imports can produce conflicts and errors (for example java.awt.List and java.util.List), so usually better to avoid them.
Packages should also be lower-cased.
The error is due to syntax, usually when you see something like ...expected that is syntax error indicator.
In the class in your launcher package, include the import statements for the classes which are being referred to.
It should look something like the following:
package the.name.of.your.package;
import Spirites.NameOfclass; //quialify the import parth as is
class YourLauncherClass{
//class definition
}
Also make sure that semicolons aren't missing at the end of import and package.
Hope that helps.
Best practice is to import the specific class you require rather than importing the complete package.
import Spirites.NameOfclassRequired;
class YourClass{
//class definition
}
If you are using eclipse you can do that using CTRL+SHIFT+O When you do that eclipse imports the specific class you require. For an instance if you using an ArrayList rather than importing java.util.*; it will import java.util.ArrayList;
If you need multiple classes from a package then for sure you can import the entire package
in test classes I have the following import
import static org.junit.Assert.*;
when I do organize import via ctrl + shift + o then it automatically changes to following
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
How can I configure eclipse not to do it ?
PS: I only want junit imports not be handled in that way
=============
I added a save action to remove unused imports. [properties -> java editor -> save actions]
so everytime I save unused imports are removed (since I used ctrl + shift + o mainly to remove unused imports this looks like a way forward..)
Change the number of static imports to 1
Under Window, Preferences, Java, Code Style, Organize Imports there's an option called "Number of static imports needed for .*" - set that to 1. (Another way to find it quickly is just to type "static" into the search box in preferences.)
Note that this will mean that hitting Ctrl-Shift-O will always turn any static imports into an static import-on-demand form, which may not be what you want. If you have separate projects for test and non-test code, you could configure it on a per project basis.
Personally I'd just live with the explicit imports - I usually end up with static imports by starting off with the class-qualified call, and then hitting Ctrl-Shift-M on the method name to import it statically.