Note: this is an editable page. You can either add comments using the box below or just edit them in. If someone puts up comment spam, please feel free to remove it.
2004/12/28 17:20 EST (via web):
Urgh, I can think of an immediate bugette as such.
Let's say, for example, that I have an interface to mess with CORBA objects
import org.omg.CORBA.Object;
public interface CORBABroker? {
public Object broker(String name);
}
or something akin when you choose to instead reference an item that would not be directly imported.
This will not actually fail, but could stop the entire project building....
Possibly missing something..
admin, 2004/12/28 20:32 EST (via web):
I don't understand. An import is either necessary for compilation or it isn't. --Bruce
2004/12/29 04:19 EST (via web):
In case Eclipse is your Java IDE of choice and it's Java code formatter is sufficient for your custom settings you might want to check Eclipse 3.1M4. Now it allows you to specify custom formatter settings per project. This way you could have the book source code in a separate project with a separate formatter settings to keep things neat and at the same time get the import redundancy checks as you develop the code. BTW Apart from messy source I can think of at least two practical reasons to hate redundant imports:
- Some exotic JVM's (usually ones on resource limited devices) do ahead of time classloading - this means that all redundantly imported classes will be loaded and eat up the scarce device memory for no good reason.
- On some dynamic pluggable Java platforms such as OSGi? (the new Eclipse core) it is imperative for each plugin to declare very throughly the pieces of Java code it depends on so that the platform may resolve them. When you have redundant imports you either forget to declare them in the plugins metadata which causes your plugin to break or in case you're a real slacker you do declare them and make the platform work for their resolving in vain.
-- Todor Boev
2004/12/29 07:30 EST (via web):
The JTools? plugin for jEdit is capable of removing unused imports from multiple jEdit buffers at the same time (without messing with formatting). Performance is quite good with around a dozen files, I don't known how it scales, though. I'm quite sure you could hack a Beanshell/Jython script for doing it in batch mode, without opening the editor. -- Carlos Santos
One thing I had noticed while using Java decompilers is that they only include the correct import statements. So what about this idea? Run the decompiler on the Java class files, extract the import statements from the .java files and replace the import statements of the original cod with the decompiler's version.
(Ravi Venkataraman)
This occurred to me as well, since Jeremy and I had written the class file tool. I wondered if the compiled java code only included the actual necessary imports or all the imports you specified. If the former then I can imagine a much faster tool.
Just tried it on this:
import java.io.*;
public class Test {}
Note the redundant import of java.io.*
$ javap -verbose Test Compiled from "Test.java" public class Test extends java.lang.Object SourceFile: "Test.java" minor version: 0 major version: 49 Constant pool: const #1 = Method #3.#10; // java/lang/Object."":()V const #2 = class #11; // Test const #3 = class #12; // java/lang/Object const #4 = Asciz ; const #5 = Asciz ()V; const #6 = Asciz Code; const #7 = Asciz LineNumberTable; const #8 = Asciz SourceFile; const #9 = Asciz Test.java; const #10 = NameAndType #4:#5;// " ":()V const #11 = Asciz Test; const #12 = Asciz java/lang/Object; { public Test(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."
":()V 4: return LineNumberTable: line 3: 0 }
It would seem from this simple experiment that only the necessary imports survive into the .class file. So a bit more bytecode engineering could produce a fast redundancy checker (perhaps with Javassist).
-- Bruce
------------------------------------
Here's what I did. Using a JavaDecompiler? (http://www.kpdus.com/jad.html) on the class generated from the Test.java file as given above, I got the following file (Test.jad)
public class Test
{
public Test() {}
}
There are no import statements in the new file.
I ran another test using this class:
import java.util.*;
public class TestA
{
private Map map = new HashMap();
public TestA() {map.put("X", "Y");}
}
which, on decompiling, gave me this result:
import java.util.HashMap;
import java.util.Map;
public class TestA
{
public TestA()
{ map = new HashMap();
map.put("X", "Y");
}
private Map map;
}
The single import line java.util.* has been replaced by the two specific lines for Map and HashMap?. It is relatively fast to do this. And this process can be run as a batch process. The task now reduces to replacing the original import statements with the import statements from the decompiled file. Even a Java program for that will not be significantly longer than a Python program, if you have wrapper classes for handling files.
--Ravi
I use WSAD 5.1.2, and it is not built on Eclipse 3.0. The formatting and Organize import options are truly pathetic in WSAD. Formatting is horrible with hardly any scope to tweak and "Organize imports" requires me to go one file at a time. I use JBuilder? just for these two and it is a wonder :-) Well, it is certainly a pain to switch between 2 IDEs? just to perform a single task, but im still waiting for one of these batch import + formatters to be available as an eclipse (not 3.0) plugin :-)
Above comment posted by : Dushyanth Inguva who forgot to include his name :-)
2004/12/29 13:31 EST (via web):
It depends what you are compiling. If you compile the entire project while removing imports, then yes, you will be safe. But if you solely compile the class in question, then it can go wrong. An interface might return a specific class, and simply recompiling that interface doesn't guarantee (to my knowledge) that all classes implementing it will be recompiled (thus revealing the usefullness of the import).
Definitely worth checking.
(The particular case when an import can "appear" to be unnecessary in an interface is when an import hides a package level class, or an automatically imported class (ie, anything in java.lang)
2004/12/30 10:52 EST (via web):
Can you show a code example? -- Bruce
2004/12/31 4:24 EST (via web):
I'm not using J2SE5 yet, so I cannot guarantee satisfaction; however, Intellij IDEA 4.x will "optimize imports" in a single file, a package/subdir, or across an entire project. It will let you specify various prefs (ex. how many imports before using a star/asteriks, or which packages to never/always use star/asteriks).
And for about the third year in a row, they are offering a "holiday" personal license for special pricing of $249... almost worth it just for the formatting/optimization features, let alone the great refactoring and IDE in the bargain.
- Please note
- I don't work for JetBrains? Inc. -- I'm just a happy user. :-) Cheers, Tim Colson
2005/01/04 12:35 EST (via web):
Okay, here's a code example of something that would break with partial compilation.
I can email you a zip if you wish.
import org.omg.CORBA.Object;
public interface Dispatcher {
public Object getCharacterForPerson(String name);
}
Slap that in Dispatcher.java
import org.omg.CORBA.Object;
public class SampleDispatcher? implements Dispatcher {
public Object getCharacterForPerson(String name) { return null; }
}
Slap that in SampleDispatcher?.java
Now. Those two should compile fine. $ javac SampleDispatcher?.java $ javac Dispatcher.java
Now let's remove the CORBA import from SampleDispatcher? $ javac SampleDispatcher?.java SampleDispatcher?.java:4: getCharacterForPerson(java.lang.String) in SampleDispatcher? cannot implement getCharacterForPerson(java.lang.String) in Dispatcher; attempting to use incompatible return type found : java.lang.Object required: org.omg.CORBA.Object public Object getCharacterForPerson(String name) { ^ 1 error
Marvellous, so we wouldn't remove that import.
Now let's try and remove it from Dispatcher.java
$ javac Dispatcher.java
$
So, marvellous. Unnecessary right?
$ javac SampleDispatcher?.java SampleDispatcher?.java:4: getCharacterForPerson(java.lang.String) in SampleDispatcher? cannot implement getCharacterForPerson(java.lang.String) in Dispatcher; attempting to use incompatible return type found : org.omg.CORBA.Object required: java.lang.Object public Object getCharacterForPerson(String name) { ^ 1 error
This is why it can fail. Might be an edge case, but it can happen.
2005/01/17 17:10 EST (via web):
"I don't understand. An import is either necessary for compilation or it isn't. --Bruce" That's an odd comment. Of course, in some cases, the project may compile even if a necessary import is missing because the imported class has the same name as a standard class, or the same name as another class in an imported package (think of java.util.* and java.sql.Date). This isn't very good style but it happens and if you automatically remove java.sql.Date, the program will have changed its meaning but will still compile. I prefer the way Eclipse handles the problem. -- piglet