This question already has answers here:
Is the use of Java's default package a bad practice?
(3 answers)
Closed 6 years ago.
I'm pretty new to Java, and I know what packages do. You use them to sort multiple files of a Java application together. However, is it standard to put it in a package if your application only has a single class? What are the pros and cons of doing this?
EDIT: I'm packaging this single class into a .jar file after.
From oracle documentation, it is clear that
The primary motivation for jar development was so that Java applets
and their requisite components (.class files, images and sounds) can
be downloaded to a browser in a single HTTP transaction, rather than
opening a new connection for each piece. This greatly improves the
speed with which an applet can be loaded onto a web page and begin
functioning. The JAR format also supports compression, which reduces
the size of the file and improves download time still further.
Additionally, individual entries in a JAR file may be digitally signed
by the applet author to authenticate their origin.
From Package Documentation of Oracle,
For small programs and casual development, a package can be unnamed
(ยง7.4.2) or have a simple name, but if code is to be widely
distributed, unique package names should be chosen using qualified
names. This can prevent the conflicts that would otherwise occur if
two development groups happened to pick the same package name and
these packages were later to be used in a single program.
It really depends on how you're compiling and running the program, but ultimately it's your choice.
Let's have a look at some of the different ways you might build your program.
1. Compiling the file with javac
If you're compiling the file using javac then the package will not matter. It will generate the .class file the same directory as the source file.
2. Compiling to a JAR File
If you're compiling to a JAR File, then the .class file will be inside the directories specified in your package name. Although this would not affect how the program is ran.
In both of these cases, I'd say that the package identifier is unnecessary for a single-file program. However, there is an exception.
The exception...
If ever you plan to use the class in a larger program, then adding a relevant package name would be essential.
This is because it would...
Prevent name collisions when other classes in the default packages have the same name.
Help people know whether or not your class is the one they want.
Can you imagine if 20 different developers made a List class in the default package, and somehow they all ended up in a project? It would be chaos! How would I choose the right List?
So in the case of writing a class that others will use in their own projects, you should definitely use package names.
It is probably non-production application if it has a single class and doesn't have any dependencies or resource files. So it is completely up to you how you will start your app.
If you want to distribute your app - make it in compliance with the standards, put it in a jar, publish to maven...
Java classloaders identify your classes by concatenating the package and the class name. So, if you don't use packages, the probabilities of name collisions are higher. Even though your app consists of only one class, you're going to reference many others, explicitly or not.
Also consider that you'll only be able to build very trivial applications with only one class, so probably that condition won't last forever.
Besides that, a class without package is a border case, so you'll probably find many tools that don't work with it.(I had this problem with the Web Service builder tool for Eclipse).
In short, use a package. It won't cause you any trouble, and (at least potentially) will save you many.
Related
I am currently working on a program which compares two control - flow graphs with each other(the graphs are generated with Soot). These graphs belong to two different classes; so one cfg for each.
Currently I am using the following to load classes:
SootClass sClassNew = Scene.v().loadClassAndSupport("Calc");
sClassNew.setApplicationClass();
SootClass sClassOld = Scene.v().loadClassAndSupport("Calc2");
sClassOld.setApplicationClass()
This works if I add a folder with classes Calc.java and Calc2.java by right-clicking on the project | Java Build Path | Add External Class folder| choose the folder.
Unfortunately this is not exactly what I want since:
The two classes will have the same name since they are different versions of each other. In other words, one class is an updated version of the other.
When the program is executed, I want to make the user capable of choosing the files so that a cfg is built. Therefore, I must eliminate the above steps so as to add the classes and need a way to add them at run-time.
An important note is that Soot will only load files from JAR files and directories found on Soot's classpath.
Does anyone have an idea how I can solve problems these two problems please?
Soot is not really set up to deal with this. It's main data structure is the Scene, in which it holds all classes it reasons about and the scene can only hold exactly one class instance per class name - there can be no two different versions.
Having said that, we have recently built an extension to Soot called Reviser (currently under submission): https://github.com/StevenArzt/reviser
Reviser incrementally updates a program's inter-procedural control flow graph and the induced IFDS/IDE analysis information. To make this work, we had to poke around with Soot's class-loading mechanism quite a bit, though; this is far from trivial. If you are interested in the details please send a personal mail to Steven Arzt and myself.
I'm aware that it isn't easily feasible to get all of the classes in a package using reflection, but I'm wondering if someone knows of a good solution/workaround, specifically for an Android project?
Given a package, I need to be able to retrieve all of the classes from it and process annotations from them using reflection.
Does anyone know of a way to do this? Are there any libraries available?
Scanning the filesystem as most solutions for non-Android Java do won't help on Android. Here's a (theoretical) solution that is android-specific: http://mindtherobot.com/blog/737/android-hacks-scan-android-classpath/
However, it remains a hack, since Java unfortunately does not directly support this.
Existing dependency injection solutions use reflection for processing the annotations, but still need the resources to be declared. See this example of DI using reflection.
If you are using Ant to build your artifacts, you could read the contents of your source directory using Bash or Java, and use this to regenerate the full hierarchy of classes automatically during each build. This might make things tricky if you rely on heavily on the Eclipse IDE though, since the list might be out of date until you run another Ant build. (Note: according to Pyscho you can make Eclipse use Ant by altering the project configuration, see comments)
Another option might be to process the AndroidManifest file using the AssetManager, but you would be limited to the resources declared in that file. The compiled classes themselves are in-lined and optimised in the classes.dex file, and as such you're unlikely to get much useful information from it.
I think you might find the answer here https://stackoverflow.com/a/1457971/1199538
there is a java file attached so you can download it and try it
short snippet from the answer following:
This method can only be used when:
You have a class that is in the same package you want to discover, This class is called a
SeedClass. For example, if you want to list all classes in 'java.io', the seed class may be java.io.File.
Your classes are in a directory or in a JAR file it has source file information (not source code file, but just source file). As far as I've tried, it work almost 100% except the JVM class (those classes come with the JVM).
Your program must have permission to access ProtectionDomain of those classes. If your program is loaded locally, there should be no problem.
You can do classpath scanning for Android at compiletime, before the JVM bytecodes have been converted to Dalvik bytecodes, e.g. using the ClassGraph library (I am the author):
https://github.com/classgraph/classgraph/wiki/Build-Time-Scanning
I recently started using Eclipse IDE and have read at a number of places that one shouldn't use the default(src) package and create new packages.
I just wanted to know the reason behind this.
Using the default package may create namespace collisions. Imagine you're creating a library which contains a MyClass class. Someone uses your library in his project and also has a MyClass class in his default package. What should the compiler do? Package in Java is actually a namespace which fully identifies your project. So it's important to not use the default package in the real world projects.
Originally, it was intended as a means to ensure there were no clashes between different pieces of Java code.
Because Java was meant to be run anywhere, and over the net (meaning it might pick up bits from Sun, IBM or even Joe Bloggs and the Dodgy Software Company Pty Ltd), the fact that I owned paxdiablo.com (I don't actually but let's pretend I do for the sake of this answer) meant that it would be safe to call all my code com.paxdiablo.blah.blah.blah and that wouldn't interfere with anyone else, unless they were mentally deficient in some way and used my namespace :-)
From chapter 7, "Packages", of the Java Language Spec:
Programs are organized as sets of packages. Each package has its own set of names for types, which helps to prevent name conflicts.
I actually usually start by using the default package and only move it into a real package (something fairly easy to do with the Eclipse IDE) if it survives long enough to be released to the wild.
Java uses the package as a way to differentiate between classes. By using packages, you can have an org.example.Something class and an org.example.extended.Something class and be able to differentiate between them even though they are both named Something. Since their packages are different, you can use them both in the same project.
By declaring a package you define your own namespace (for classes). This way if you have two identical classes using a different package name (namespace) will differentiate between which one you want to use.
The main reasons I can think of are:
It keeps things organised, which will help you (and others!) know where to look for classes/functionality.
You can define classes with the same name if they are in different packages.
Classes/etc in the default package cannot be imported into named packages. This means that in order to use your classes, other people will have to put all their classes in the default package too. This exacerbates the problems which reasons 1 & 2 solve.
From a java point of view, there are two general dev/deploy lifecycles you can folllow, either using ant to build and deploy, or the maven lifecycle. Both of these lifecycles look for source code and resources in local directories, and in the case of maven, in defined repositories, either locally or on the net.
The point is, when you set up a project, for development and eventually deployment, you want to build a project structure that is portable, and not dependent on the IDE, ie. your project can be built and deployed using either of your build environments. If you use a heavy dependence on the Eclipse framework for providing class variables, compile paths, etc.. you may run into the problem that your project will only build and deploy using that configurationj, and it may not be portable to another developers environment, so to speak.
Separate Jars
When creating JAR files, I've always kept the source separate and offered it as an optional extra.
eg:
Foo.jar
Foo-source.jar
It seems to be the obvious way to do things and is very common. Advantages being:
Keeps binary jar small
Source may not be open / public
Faster for classloader? (I've no idea, just guessing)
Single Jar
I've started to doubt whether these advantages are always worth it. I'm working on a tiny component that is open-source. None of the advantages I've listed above were problems in this project anyway:
Classes + source still trivially small (and will remain that way)
Source is open
Class loading speed of this jar is irrelevant
Keeping the source with the classes does however bring new advantages:
Single dependency
No issues of version mismatch between source and classes
Developers using this jar will always have the source to hand (to debug or inspect)
Those new advantages are really attractive to me. Yes, I could just zip source, classes and even javadoc into a zip file and let clients of my component decide which they want to use (like Google do with the guava libraries) but is it really worth it?
I know it goes against conventional software engineering logic a little, but I think the advantages of a single jar file out-weigh the alternatives.
Am I wrong? Is there a better way?
Yes, I could just zip source, classes and even javadoc into a zip file and let clients of my component decide which they want to use (like Google do with the guava libraries) but is it really worth it?
Of course it is worth it! It takes about 2 seconds to do it, or just a few minutes to change your build scripts.
This is the way that most people who distribute sources and binaries handle this problem.
EDIT
It is not your perspective you need to consider. You have to think of this from the perspective of the people deploying / using your software.
They aren't going to use the source code on the deployment platform.
Therefore putting the source code in the binary JAR is a waste of disc space, slows down deployment and slows down application startup.
If they want to do something about it, they've got a problem. How do they rebuild the JAR file to get rid of the source code? How do they know what is safe to leave out?
From the deployer / user's perspectives, there are no positives, only negatives.
Finally, your point about people not being able to track source versus binary versions doesn't really hold water. Most people who would be interested in the source code are perfectly capable of doing this. Besides, there some simple things you can do to address the issue, like using JAR filenames that include your software's version number, or putting the version number into the manifest.
I have just come across a potential pitfall for the java+classes in a single jar.
If you have java files in a jar and that jar is included in the classpath of a subsequent javac execution, you MUST make sure that the timestamps of the java file is less than the timestamp of the class file.
This scenario can happen when you copy/move the java or class files prior to packaging as a jar.
If the java file is newer than the class, then even though the java file is found on the classpath (rather than an argument to javac), javac will attempt to compile that java file and then potentially end up with duplicate class errors during the compilation stage.
For this reason I would recommend keeping the source in a separate jar to the class files.
Note that relevant flags in javac will not allow you to prefer class over source: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#searching
I prefer 'Separate Jars'.
Because binary class jar is for running on JVM, but source not. Source should be carefully maintained by your source control system(SVN). If source needs to release, zip it in separate jar. Many open source separates class jar and source one.
If you want others to test and inspect/improve your code then you can have your source with the binaries. If not, keep the source away from the jar.
How small is small and why should your jar act differently from others?
Unless you have a very good reason why your jar should have the sources, not simply debugging but something specific to this one jar then I'd say no, choice is best.
I say this because if your jar should not be different from other, then you have to work on the assumption that others should do the same as you. If so, the size of the jar is not important, because its duplicated over all "small" jars. Then my WAR is much bigger than needed which, admittedly is not a massive issue, but is not something I would chose for production when I can download sources in DEV so easily.
When writing code in an Eclipse project, I'm usually quite messy and undisciplined in how I create and organize my classes, at least in the early hacky and experimental stages. In particular, I create more than one class with a main method for testing different ideas that share most of the same classes.
If I come up with something like a useful app, I can export it to a runnable jar so I can share it with friends. But this simply packs up the whole project, which can become several megabytes big if I'm relying on large library such as httpclient.
Also, if I decide to refactor my lump of code into several projects once I work out what works, and I can't remember which source files are used in a particular run configuration, all I can do it copy the main class to a new project and then keep copying missing types till the new project compiles.
Is there a way in Eclipse to determine which classes are actually used in a particular run configuration?
EDIT: Here's an example. Say I'm experimenting with web scraping, and so far I've tried to scrape the search-result pages of both youtube.com and wrzuta.pl. I have a bunch of classes that implement scraping in general, a few that are specific to each of youtube and wrzuta. On top of this I have a basic gui common to both scrapers, but a few wrzuta- and youtube-specific buttons and options.
The WrzutaGuiMain and YoutubeGuiMain classes each contain a main method to configure and show the gui for each respective website. Can Eclipse look at each of these to determine which types are referenced?
Take a look at ProGuard, it is a "java shrinker, optimizer, obfuscator, and preverifier". I think you'll mainly be interested in the first capability for this problem.
Yes it's not technically part of Eclipse, as you requested, but it can be run from an Ant script, which can be pretty easily run in Eclipse.
I create more than one class with a main method for testing different ideas that share most of the same classes.
It's better to be pedantic than lazy, it saves you time when coding :-)
You can have one class with a main method that accepts a command-line argument and calls a certain branch of functionality based on its value.