There is a class a.b.c.Hello of which I would just get the Hello.class file delivered. I would like to run using something like:
java Hello
//or
java a.b.c.Hello
This leads me to a NoClassDefFoundError. Normally I'd have the a/b/c dirs with the class insdie and I'd add them to the -classpath option, but:
Is there a way of running a class in a package like this without having to put it inside a/b/c to match the package name?
All solutions I've found state the directory structure has to match the package naming, but I'd like to run the .class file directly from the folder where it is without recreating the folder structure
Is there a way of running a class in a package like this without having to put it inside a/b/c to match the package name?
Yes: By using a jar. Put the .class file in the jar (with the correct path), and then:
java -cp TheJarFile.jar a.b.c.Hello
This is, of course, very much like putting it in an a/b/c directory; it's just that the directory is in the jar, not the file system.
The packages do not just structure your classes (in folders), they also create a namespace. While the simple class name is Hello, the real class name is a.b.c.Hello.
That's because class names might repeat frequently (in different libs, f.e), but must be addressable on the other hand. For example: 'User', 'Logger', 'List', 'Date'.
Its not recommended, but you can put your class in the default package, too. Just remove the 'package ...' line.
Related
I'm a C++ developer - not a java developer, but have to get this code working...
I have 2 public classes that will be used by another product. I used the package directive in each of the java files.
package com.company.thing;
class MyClass ...
When I try to compile a test app that uses that I add
import com.company.thing.*;
The javac compiler fails with errors about com.company does not exist. (even if I compile it in the same directory as the class files I just made a package of)
I am sure I am doing something bone-headed and silly.
I've read the http://java.sun.com/docs/books/tutorial/java/package/usepkgs.html pages and tried to set up a directory structure like /com/company/thing etc, but either I have totally screwed it all up or am missing something else.
EDIT
thanks for the suggestions - I had tried the classpath previously. It does not help.
I tried compiling
javac -classpath <parent> client.java
and the result is:
package com.company does not exist
I have the code I want to import (the two java files) in \com\company\product. I compile those fine. (they contain MyClass) I even made a jar file for them. I copied the jar file up to the parent directory.
I then did (in the parent directory with the client java file)
javac -cp <jarfile> *.java
the result is:
cannot access MyClass
bad class file: MyClass.class(:MyClass.class)
class file contains wrong class: com.company.product.MyClass
Please remove or make sure it appears in the correct subdirectory of the classpath.
EDIT
I got the client code to compile and run if I used the fully qualified name for MyClass and compiled it in the parent directory. I am totally confused now.
compiled with no classpath set - just
javac *.java
in the parent directory - and it worked fine.
I can get a test app to compile, but that is not going to cut it when i have to integrate it into the production code. Still looking for help.
EDIT:
Finally - not sure why it didn't work before - but I cleaned up all the files all over the directory structure and now it works.
Thanks
Okay, just to clarify things that have already been posted.
You should have the directory com, containing the directory company, containing the directory example, containing the file MyClass.java.
From the folder containing com, run:
$ javac com\company\example\MyClass.java
Then:
$ java com.company.example.MyClass
Hello from MyClass!
These must both be done from the root of the source tree. Otherwise, javac and java won't be able to find any other packages (in fact, java wouldn't even be able to run MyClass).
A short example
I created the folders "testpackage" and "testpackage2". Inside testpackage, I created TestPackageClass.java containing the following code:
package testpackage;
import testpackage2.MyClass;
public class TestPackageClass {
public static void main(String[] args) {
System.out.println("Hello from testpackage.TestPackageClass!");
System.out.println("Now accessing " + MyClass.NAME);
}
}
Inside testpackage2, I created MyClass.java containing the following code:
package testpackage2;
public class MyClass {
public static String NAME = "testpackage2.MyClass";
}
From the directory containing the two new folders, I ran:
C:\examples>javac testpackage\*.java
C:\examples>javac testpackage2\*.java
Then:
C:\examples>java testpackage.TestPackageClass
Hello from testpackage.TestPackageClass!
Now accessing testpackage2.MyClass
Does that make things any clearer?
Yes, this is a classpath issue. You need to tell the compiler and runtime that the directory where your .class files live is part of the CLASSPATH. The directory that you need to add is the parent of the "com" directory at the start of your package structure.
You do this using the -classpath argument for both javac.exe and java.exe.
Should also ask how the 3rd party classes you're using are packaged. If they're in a JAR, and I'd recommend that you have them in one, you add the .jar file to the classpath:
java -classpath .;company.jar foo.bar.baz.YourClass
Google for "Java classpath". It'll find links like this.
One more thing: "import" isn't loading classes. All it does it save you typing. When you include an import statement, you don't have to use the fully-resolved class name in your code - you can type "Foo" instead of "com.company.thing.Foo". That's all it's doing.
It sounds like you are on the right track with your directory structure. When you compile the dependent code, specify the -classpath argument of javac. Use the parent directory of the com directory, where com, in turn, contains company/thing/YourClass.class
So, when you do this:
javac -classpath <parent> client.java
The <parent> should be referring to the parent of com. If you are in com, it would be ../.
You got a bunch of good answers, so I'll just throw out a suggestion. If you are going to be working on this project for more than 2 days, download eclipse or netbeans and build your project in there.
If you are not normally a java programmer, then the help it will give you will be invaluable.
It's not worth the 1/2 hour download/install if you are only spending 2 hours on it.
Both have hotkeys/menu items to "Fix imports", with this you should never have to worry about imports again.
The standard Java classloader is a stickler for directory structure. Each entry in the classpath is a directory or jar file (or zip file, really), which it then searches for the given class file. For example, if your classpath is ".;my.jar", it will search for com.example.Foo in the following locations:
./com/example/
my.jar:/com/example/
That is, it will look in the subdirectory that has the 'modified name' of the package, where '.' is replaced with the file separator.
Also, it is noteworthy that you cannot nest .jar files.
Just add classpath entry ( I mean your parent directory location) under System Variables and User Variables menu ...
Follow : Right Click My Computer>Properties>Advanced>Environment Variables
I am a complete beginner when it comes to Java. I recently picked up Head First Java and it says: "Put a class in a source file. Put methods in a class. Put statements in a method." When I open eclipse i started a new project called helloWorld, this created a project with a src folder(guessing this is the source file?), i then followed an eclipse tutorial from their website and it stated that i needed to first create a project, then a package, then a class in that package. What is the difference between a source file and a package?
A package more-or-less equates to a directory under your "src" folder in this case. Examples might include "com.project.ui" or "com.project.models" (and so there would be a "com" directory inside "src" and inside "com" you would have "project" and so on).
A source file is just that--it's an individual file that will live in one of those packages, probably named as "MyClass.java" where "MyClass" corresponds exactly to the name you give the one public class that the source file should contain.
BTW, if you will build your code with Maven, you should follow the suggested Maven directory structure--see this. In the case of Maven then, your java packages would start under "src/main/java" rather than under just "src" which is maybe what Eclipse will assume you want by default.
EDIT: Also take care to align the package you declare at the top of your Java source file with the package that it actually "lives in" on your filesystem--it's essential that these be in agreement. So, if your "MyClass.java" lives on the filesystem in com/projects/models, your package statement at the top of "MyClass.java" must be "package com.projects.models;" By convention package names will be all lowercase, class names will be upper and lower ("camel case") starting with a capital letter and method names start with a lowercase letter, but then are also camel case.
The following is a java source text:
package org.apache.twinkle;
public class Elfie {
...
}
It resides under a sources directory (generally src), and has a file path:
org/apache/twinkle/Elfie.java
(Directories org, apache, twinkle and file Elfie.java.)
So a package indicates some hierarchy and corresponds 1:1 with a directory.
The source file has a .java extension.
Paths should be case-sensitive. Package paths are hierarchical and generally follow the convention of starting with a reversed URL.
http://mit.com
package com.mit.mathlib.graphs;
http://univ-abu-dabi2.net
package net.univAbuDabi2.linguistics;
import com.mit.mathlib.graphs.GraphUtils;
Source file is complete Java code.
Package gather a several Java file under some issue like: GUI, server, login and etc.
Try to create several package and then go to the workspace to see what you got.
Also, when it comes to package issues, you also have the 'package' definition for class variables, which means that you are able to use this variable from other classes in the same package.
So I made a folder called util and placed four classes along with program named unit10Assignment in it. I created a package util and typed " package util; " at the top of each one of the classes code like this:
package util;
public class Employee
Then i wrote:
import util.*;
import javax.swing.JOptionPane;
public class unit10Assignment
On top of the program. However when I compile it, it tells me. Anyone know why? I tried playing around with it and it disappeared when I typed in import java.util*; instead but I'm not sure that what my teacher wanted as her example did not have the java in front.
It also says " bad source file" "package does not contain class Employee " However, everything compiled and ran perfectly before I typed in the package statement and I have not made any change to the code since then. If I removed the package statement from the employee class tho, the same message would appear but it would say another class does not exist.
Thanks for any help
Note: whether or not i put java.util or just util, this problem with the bad source still appears.
thanks for any help
I'm going to make the assumption that you have your project set up like this:
util/
Employee.java
unit10Assignment.java
bin/
(If it isn't, that's fine - so long as they're in some folder. bin/ should exist, though.)
The way that packages work is that they're folders on the hard drive - the package you want to import requires that the folder and class you wish to import both exist in that specific folder. This is why packages are handy - you can have two classes named Employee and have them live in completely different locations.*
Here's how you compile these into a package-like structure without the use of an IDE. Substitute $HOME for the full path of your Java class folder.
javac -sourcepath $HOME/util -d $HOME/bin *.java
And here's how you run your main class:
java -cp $HOME/bin util.$MAIN_CLASS
A breakdown of what these flags mean:
-sourcepath instructs javac to look in this specific directory for your source files.
-d specifies an output directory for your .class files.
-cp instructs java to add this folder to its classpath.
*: Really, really large projects can often use the same name as other classes; if you wanted to use a specific one, you'd have to use the fully-qualified class name for it.
Make sure that:
the filename matches the class name (e.g. Employee.java for class Employee)
the files are inside the corresponding folder according to their package (i.e. util)
Are you using any IDE? If not, using one realy helps a lot with this kind of things.
I am trying to run the java prog I've built, but I want to run it from a specific directory. When specifying the relative path to the class file I want to run, that path contains a directory with a period in it, and it seems to be tripping java up; So for example I try to run:
java -classpath myPath/myPath-1.2.3/myLongPath myPath/myPath-1.2.3/myLongPath/myProg
Java errors out saying that it cannot find the class (NoClassDefFoundError); This makes sense because I see that java is looking in different directory than the one I specified; It is looking in:
myPath/myPath-1/2/3/myLongPath
instead of:
myPath/myPath-1.2.3/myLongPath
Try as I might, I cannot figure out how to specify to java.exe that the directory I want it to look in contains periods. I tried \ escaping the periods, but that doesn't help. Anyone run into this problem before? btw, I am running on linux within gnome terminal. Thanks for any help.
The final parameter in the call to java is the name of the class to run. This is not a file name, but a class name. It includes the full package name (unless the class is in the default package), separated by dots (not slashes). Neither the classname nor any package name can include dots. The folder that represent the path to the package must not be included in the directories included in the classpath (only the top directory for the class folder should be there).
In your case, that seems to be just myProg, but to make sure, what is the class name (including package name) of the class with the main method?
Example:
If I have a class mypackage.mysubpackage.MainClass, and the class file is in /home/me/project/1.3/build/mypackage/mysubpackage/MainClass.class, then the command to run the class would be java -cp /home/me/project/1.3/build mypackage.mysubpackage.MainClass.
Java uses the period as the package component separator, so it simply cannot appear in class names. Since class names are tied to directory structures, it cannot appear in directory names used in class paths either, and no amount of escaping will help you there. (It would have been better to use the directory separator itself as the package component separator, but they differ between operating systems, and Java wanted to be OS independent. This is one of the prices to be paid for that.)
I'm trying to figure out how organize source and class files working with packages. I found a very useful tutorial. But I still have some questions.
As far as I understood it is a good practice to have an isomorphism between name of packages and name of the directories where elements of a package are stored. For example if I have a package named aaa.bbb.ccc which contains class ddd it is a good practice to have a class file called "ddd.class" and located in "$CLASSPATH/aaa/bbb/ccc/". Did I get it right?
If it is the case, will Java compiler put *.class files into the correct directory automatically?
I was not able to get this behavior. I set the $CLASSPATH variable to "/home/myname/java/classes". I executed javac KeyEventDemo.java which contains package events;. I expected that javac will create a subdirectory events under /home/myname/java/classes and put the KeyEventDemo.class in this subdirectory.
It did not happen. I tried to help to javac and created "events" subdirectory by myself. I used javac again but it does not want to put class files under "/home/myname/java/classes/events". What am I doing wrong?
You need to use the -d option to specify where you want the .class files to end up. Just specify the base directory; javac will create any directories necessary to correspond to the right package.
Example (based on your question):
javac -d ~/java/classes KeyEventDemo.java
For example if I have a package named
"aaa.bbb.ccc" which contains class
"ddd" it is a good practice to have a
class file called "ddd.class" and
located in "$CLASSPATH/aaa/bbb/ccc/".
Did I get it right?
That's not "good practice" - this is how the Sun JDK expects things to be. Otherwise, it will not work. Theoretically, other Java implementations could work differently, but I don't know any that do.
If it is the case, will Java compiler
put *.class file into a correct
directory automatically?
Yes
What am I doing wrong?
The source code must also already follow this structure, i.e. KeyEventDemo.java must reside in a subdirectory named "events". Then you do "javac events/KeyEventDemo.java", and it should work.
It is not only good practice but a must in most cases.
consider a Java class named:
com.example.Hello
If you store it on the filesystem, it has to got to
/path/to/my/classes/com/example/Hello.java
The compiler (or at least the vast majority) will create the class file at
/path/to/my/classes/com/example/Hello.class
Personally I would not use the CLASSPATH variable to set the path but the -cp option on java. A call to the above "application" could be done with:
java -cp /path/to/my/classes com.example.Hello