Why a simple package statement

L

lonelyplanet999

Hi,

I have below .java files:

c:\javapgm\Level1.java

File content:

package l1;

public class Level1 {
public static void main (String[] args) {
System.out.println("Level 1");
}
}

Compilation passed without error with above code. However, as I ran
the program, below run time error was output.

Exception in thread "main" java.lang.NoClassDefFoundError: Level1
(wrong name: l1/Level1)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.lang.security.SecureClassLoader.defineClass(SecureClassLoader.java:12)
..... skippped details.

After I commented out the statement package l1;, the program ran
without error.

Previously I have written a program Aclass3.java, the program also
passed compilation but failed in runtime with similar problem. The
problem got solved after I commented the package Aclass3.java;
statement at Aclass3.java.

I would like to ask why the simple package statement will cause the
program execution failed. :(

http://www.google.com.hk/groups?hl=...10200755.394c9fa8%40posting.google.com&rnum=1
 
J

John C. Bollinger

lonelyplanet999 said:
Hi,

I have below .java files:

c:\javapgm\Level1.java

File content:

package l1;

public class Level1 {
public static void main (String[] args) {
System.out.println("Level 1");
}
}

Compilation passed without error with above code. However, as I ran
the program, below run time error was output.

Exception in thread "main" java.lang.NoClassDefFoundError: Level1
(wrong name: l1/Level1)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.lang.security.SecureClassLoader.defineClass(SecureClassLoader.java:12)
..... skippped details.

After I commented out the statement package l1;, the program ran
without error.

That is because when you have the package statement in the source, the
fully-qualified name of your class is "l1.Level1", not just "Level1".
You must specify the fully-qualified name to the java executable. You
may then also find that java expects to find the class file in
l1/Level.class (substitute correct directory seperator for your OS) with
respect to one of the directories in your classpath (which apparently
includes the working directory). (I.e. class files arranged in a
directory tree mirroring the package hierarchy.) Best practice would be
to also arrange your source files in a similar (or the same) directory tree.
Previously I have written a program Aclass3.java, the program also
passed compilation but failed in runtime with similar problem. The
problem got solved after I commented the package Aclass3.java;
statement at Aclass3.java.

I would like to ask why the simple package statement will cause the
program execution failed. :(

It's not the package statement that's broken, it's the "java" command
line you use to try to load and run the class.


John Bollinger
(e-mail address removed)
 
L

lonelyplanet999

John C. Bollinger said:
That is because when you have the package statement in the source, the
fully-qualified name of your class is "l1.Level1", not just "Level1".
You must specify the fully-qualified name to the java executable. You
may then also find that java expects to find the class file in
l1/Level.class (substitute correct directory seperator for your OS) with
respect to one of the directories in your classpath (which apparently
includes the working directory). (I.e. class files arranged in a
directory tree mirroring the package hierarchy.) Best practice would be
to also arrange your source files in a similar (or the same) directory tree.


It's not the package statement that's broken, it's the "java" command
line you use to try to load and run the class.

That means, if I should give a .java file a package name such that
it's class can be referenced in other .java files. I must create
corresponding directory to accommodate it ?

e.g. Now I place all .java files under c:\javapgm. I call
c:\j2sdk1.4.1_01\bin\javac & c:\j2sdk1.4.1_01\bin\java under
c:\javapgm to compile & run java programs.

1. If I named File1.java as "package package1;", I need to place
File1.java under c:\javapgm\package1\

2. If another file under c:\javapgm named File2.java without package
statement needs to reference class inside package1.
3. File2.java needs the statement "import package1.*;" or
"package1.<specific class>;" to import specific class.

4. If another file named File3.java with "package package3;" statement
needs to reference class inside File1.java too.
5. File3.java needs to be stored under "c:\javapgm\package3\".
6. File3.java needs import "package1.*" or "package.<specific class>;"
inside it under "package package3;" statement.

Is that correct ?

:>
 
L

lonelyplanet999

John C. Bollinger said:
lonelyplanet999 said:
Hi,

I have below .java files:

c:\javapgm\Level1.java

File content:

package l1;

public class Level1 {
public static void main (String[] args) {
System.out.println("Level 1");
}
}

Compilation passed without error with above code. However, as I ran
the program, below run time error was output.

Exception in thread "main" java.lang.NoClassDefFoundError: Level1
(wrong name: l1/Level1)
at java.lang.ClassLoader.defineClass0(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:502)
at java.lang.security.SecureClassLoader.defineClass(SecureClassLoader.java:12)
..... skippped details.

1. Just moved Level1.java to c:\javapgm\l1 & called
c:\j2sdk1.4.1_01\bin\javac l1\Level1.java from c:\javapgm.
Compilation succeeded & Level1.class created in c:\javapgm\l1\.

2. Called c:\j2sdk1.4.1_01\bin\java l1\Level1 from c:\javapgm, same
runtime exception triggered.

3. Called c:\j2sdk1.4.1_01\bin\java Level1 from c:\javapgm\l1, same
runtime exception triggered.
 
J

John C. Bollinger

lonelyplanet999 said:
1. Just moved Level1.java to c:\javapgm\l1 & called
c:\j2sdk1.4.1_01\bin\javac l1\Level1.java from c:\javapgm.
Compilation succeeded & Level1.class created in c:\javapgm\l1\.

As it should be.
2. Called c:\j2sdk1.4.1_01\bin\java l1\Level1 from c:\javapgm, same
runtime exception triggered.
3. Called c:\j2sdk1.4.1_01\bin\java Level1 from c:\javapgm\l1, same
runtime exception triggered.

The name of the class is "l1.Level1". The command line
"c:\j2sdk1.4.1_01\bin\java l1.Level1" should be executed from directory
c:\javapgm.

The java class loader will find the correct directory on its own, based
on the class name and the applicable classpath.


John Bollinger
(e-mail address removed)
 
J

John C. Bollinger

lonelyplanet999 said:
That means, if I should give a .java file a package name such that
it's class can be referenced in other .java files. I must create
corresponding directory to accommodate it ?

That is not absolutely required, but it is very good practice. Among
other things, it allows the java compiler to find and compile
dependencies at need.
e.g. Now I place all .java files under c:\javapgm. I call
c:\j2sdk1.4.1_01\bin\javac & c:\j2sdk1.4.1_01\bin\java under
c:\javapgm to compile & run java programs.

1. If I named File1.java as "package package1;", I need to place
File1.java under c:\javapgm\package1\

That should work. There are alternatives, but I wouldn't worry about
them right now.
2. If another file under c:\javapgm named File2.java without package
statement needs to reference class inside package1.
3. File2.java needs the statement "import package1.*;" or
"package1.<specific class>;" to import specific class.

The location of the source file is not directly relevant to how the Java
class(es) it describes must refer to other classes. If classes in any
package other than package1 want to access members of package1, though,
then the alternatives you describe are indeed the available options.
4. If another file named File3.java with "package package3;" statement
needs to reference class inside File1.java too.
5. File3.java needs to be stored under "c:\javapgm\package3\".

This would be best.
6. File3.java needs import "package1.*" or "package.<specific class>;"
inside it under "package package3;" statement.

As described above, the relevant criterion is the package to which a
class is assigned, not the structure of the source tree, but yes, that's
correct.


John Bollinger
(e-mail address removed)
 
L

lonelyplanet999

John C. Bollinger said:
As it should be.



The name of the class is "l1.Level1". The command line
"c:\j2sdk1.4.1_01\bin\java l1.Level1" should be executed from directory
c:\javapgm.

Sorry, the compilation failed again after I renamed
c:\javapgm\l1\Level.java package name as "package l1.Level1;" and
compiled the file from c:\javapgm i.e. c:\j2sdk1.4.1_01\bin\javac
l1\Level1.java.

Compiler complained:
l1\Level1.java:3: package l1.Level1 clashes with class of same name
package l1.Level1;
^
1 error

Of course c:\j2sdk1.4.1_01\bin\javac Level1.java failed due to
Level1.java can't be read when javac called from c:\javapgm.

:(
 
C

Christophe Vanfleteren

lonelyplanet999 said:
Sorry, the compilation failed again after I renamed
c:\javapgm\l1\Level.java package name as "package l1.Level1;" and
compiled the file from c:\javapgm i.e. c:\j2sdk1.4.1_01\bin\javac
l1\Level1.java.

Compiler complained:
l1\Level1.java:3: package l1.Level1 clashes with class of same name
package l1.Level1;
^
1 error

Don't put capitals in packagenames (especially not the first letter), that
makes it confusing (by convention, only classes start with a capital
letter).
Of course c:\j2sdk1.4.1_01\bin\javac Level1.java failed due to
Level1.java can't be read when javac called from c:\javapgm.

:(

Of course that is not going to work.
Your compiler is expecting a directory called l1/Level1, but in your case,
that is allready a class file.

Take the following as a base rule when working with packages:
If you put a file in package aaaa.bbb, you'll need to put it in a directory
called aaa/bbb, and compile the class from the directory that contains the
aaa dir.

You cant just change a package statement and leave the file where it was
before.
 
S

Sudsy

lonelyplanet999 said:
Sorry, the compilation failed again after I renamed
c:\javapgm\l1\Level.java package name as "package l1.Level1;" and
compiled the file from c:\javapgm i.e. c:\j2sdk1.4.1_01\bin\javac
l1\Level1.java.

Compiler complained:
l1\Level1.java:3: package l1.Level1 clashes with class of same name
package l1.Level1;
^
1 error

Try reading this:
<http://www.sudsy.net/technology/java-classes.html>
 
L

lonelyplanet999

Christophe Vanfleteren said:
Don't put capitals in packagenames (especially not the first letter), that
makes it confusing (by convention, only classes start with a capital
letter).

It only confuses human reader, it shouldn't cause compilation error, right ?
Of course that is not going to work.
Your compiler is expecting a directory called l1/Level1, but in your case,
that is allready a class file.

Take the following as a base rule when working with packages:
If you put a file in package aaaa.bbb, you'll need to put it in a directory
called aaa/bbb, and compile the class from the directory that contains the
aaa dir.

Already put file Level1.java into c:\javapgm\l1 described above. Compilation failed.
 
C

Christophe Vanfleteren

lonelyplanet999 said:
It only confuses human reader, it shouldn't cause compilation error, right
? Yes

Already put file Level1.java into c:\javapgm\l1 described above.
Compilation failed.

Is the package statement in Level1.java "package l1;" ? That is the only
thing that will work of the Level1 file is in the c:\javapgm\l1 directory.

You said before that you changed it to "package l1.Level1;", so you'd also
have to move the file to the c:\javapgm\l1\Level1\Level1.java if you'd want
that to work.
 
J

John C. Bollinger

lonelyplanet999 said:
Sorry, the compilation failed again after I renamed
c:\javapgm\l1\Level.java package name as "package l1.Level1;" and
compiled the file from c:\javapgm i.e. c:\j2sdk1.4.1_01\bin\javac
l1\Level1.java.

If you had in fact tried the command line I gave you without modifying
your code or recompiling (where did I say to modify any code?) then it
would have worked.

A class' fully-qualified name is <package name>.<class name>, so for
example, as I wrote before, "l1.Level1" in your code as previously
written. The java program takes a fully-qualified class name as its
class argument. It finds that class based on the classpath with which
it is configured. The classpath is configured via a combination of the
default classpath, the CLASSPATH environment variable (if set), and the
classpath specified on the command line.

I am evidently having trouble explaining, so whether or not that does
it, I'm going to punt. Hopefully someone else around here can help
further on this matter if you continue to have problems.


John Bollinger
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top