Compiling a .java file with incorrect package name - java

In the book "OCA Oracle Certified Associate Java SE 8 Programmer I Study Guide Exam 1Z0-808" by Boyarsky and Selikoff I encountered a confusing question in the review exam for Chapter I:
14. Given the following class in the file /my/directory/named/A/Bird.java:
INSERT CODE HERE
public class Bird { }
Which of the following replaces INSERT CODE HERE if we compile from /my/directory? (Choose all that apply)
A. package my.directory.named.a;
B. package my.directory.named.A;
C. package named.a;
D. package named.A;
E. package a;
F. package A;
G. Does not compile
The book states that the correct answer is just D. (we'll ignore the fact that they wrote "Choose all that apply" despite stating that they would only do so if there were more than 1 answer, earlier in the book), with the explanation:
D. The package name represents any folders underneath the current path, which is
named.A in this case. Option B is incorrect because package names are case sensitive,
just like variable names and other identifiers.
I'm totally confused with this on various levels:
I tried to compile the file from /my/directory using javac /named/A/Bird.java and the code compiles successfully with any of the answers above. Furthermore, the code compiles no matter what I write after package in the first line of the class.
Let's assume I completely missed the point in (no pun intended) point 1 and that's not how we compile from /my/directory, then I've got these questions:
How do we compile from /my/directory?
Why is the option B. incorrect? The explanation they provided for B. makes no sense, obviously.
Can someone shed some light on this matter?

The short answer is the question is wrong.
A single class can be compiled from anywhere, without considering the package hierarchy if it has no references to other custom classes (so you can use String etc.). This is because it doesn't need to do any lookups for other classes, so there's no need for anything special in the compile-time classpath. As soon as you add a reference to let's say class named.A.Rock the compilation will no longer work, because the directory hierarchy doesn't match the package hierarchy (unless you put Bird in named.A package as well).
So the example in the question is just bad. As soon as you add a reference to another class and the package hierarchy starts to matter, D is the correct answer. The question is a bit poor since you can set the compile time classpath explicitly, at which point the concept of "current directory" doesn't matter one bit and all of the answers would be valid.

Related

Unwanted import added by compiler [duplicate]

This question already has an answer here:
When is a Java Class loaded?
(1 answer)
Closed 1 year ago.
I need the same code to work on different servers with different libraries.
So for example serverB contains libraryB. ClassB while serverA doesn't.
To make the code work on both servers I do not import the class explicitly but I declare it only when needed. For example:
If(serverB) {
libraryB.ClassB foo = new libraryB. ClassB();
foo.doSomething();
}else{
whatever();
}
This usually works for me but now I installed my code on new servers and I get a NoClassFoundException. I decompile my class and the library is imported. Why? Can I avoid it?
Thanks
Importing some class from a package has nothing to do with trying to locate that class at runtime. Whenever the JVM detects that a class like ClassB is needed, it will try to locate and load that class.
The exact specification when this will happen has some complexities, but it makes no difference whether you wrote the fully qualified libraryB.ClassB or the abbreviated ClassB and an import statement. And locating that class will surely happen before the JVM even tries to execute code that contains a reference to the class (like the code snippet you showed us).
Don't be mislead by the decompilation containing an import statement. You can try for yourself and compare two versions of your code, one written with import, and the other with fully qualified classname. The results will be the same. It's just a convenience of the decompiler preferring short classnames, so it always adds the relevant import statements (as long as that doesn't cause name collisions).
It's hard to understand why code like yours ever ran without throwing that error.

Copy class but overwrite the existing class imports

I have a class with an existing import:
import org.packageA.Peeler
public class Potato {
Peeler peeler = new Peeler();
}
I'd like to be able to copy this class or create an object with it but change "import org.packageA.Peeler" to "import org.packZ.Peeler".
Is this possible to do dynamically?
No.
import statements are a bit of a misnomer. import com.foo.A; means: Anytime I write just A in this source file, imagine I wrote com.foo.A and that is all it means. It does not mean: Initialize this class or parse this source file or any other such thing (which is usually what import means in other environments).
Thus, what you're asking is: Can I take class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } and somehow dynamically create a different Potato class that is as if I wrote class Potato { org.packA.Peeler peeler = new org.packA.Peeler(); } - to which the answer is no; org.packA.Peeler is as related to org.packZ.Peeler as guns and grandmas (i.e.: That they have the same name is immaterial).
Even if you could, what would that mean? Java is statically and nominally typed, it wouldn't be possible to write code that refers to this rewritten potato class without using reflection or dynamic code generation which, in java at any rate, are almost always the wrong answer.
Some exotic options you do have:
Use a regexp or build script plugin to make a source file with some renames applied and include it in the build and compilation process (bad idea, but I guess you can do that)
Use ASM, BCEL or some other classfile tool to create a new class file in byte array form with renames applied, have a custom classloader that dynamically loads this, and then generate bytecode that uses this, or use reflective access. This is extremely convoluted, requires a ton of code, and is almost useless.
Perhaps take a step back and explain the problem you have that made you think: I know! I'll dynamically rewrite this class to use a different package! But I don't know how so I'll ask SO - except you're asking the wrong question, ask about your original problem.

Why only one public class per Java file? [duplicate]

In any Java file, why can we have only one public class whose name is same as the Java file name?
It forces all Java code to be organized in a certain way, which in the long run helps improve code readability.
The Java designers chose a strict approach that enforces their idea of good design practices, and this is part of that theme. Contrast that with the anything-goes attitude in Perl.
According to this source, it is for efficient compilation :
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
The same applies also for imports of source files in IDEs. Another reason would be reasonable source sizes.
These are the rules. Although it is not quite true. You can define internal classes inside you "main" class like this:
public class A {
public class B {
...
}
}
Courtesy of Dr Heinz Kabutz and his excellent newsletter....
Why is each public class in a separate
file?
This is a question that I have
frequently been asked during my
courses. Up to now I have not had a
good answer to this question. In
section 1, we read: "Although each Oak
compilation unit can contain multiple
classes or interfaces, at most one
class or interface per compilation
unit can be public".
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
We can have only one top level public either class or interface in any java compilation unit ( .java source file ).
But there can be any number of default classes/interfaces per src file.
why:
JLS leaves the option to the java compiler. And most of the compiler implementations force to have file name same as :
(1) the public class/interface name
(2) if there is a main method and no public class then any name
(3) If there is main method and public class then main method should be in that public class
(4) if there is no public class and no main method then any valid name which may or may not be matching with the class/interface names in the file.
From (2): If two public classes allowed, we should give the file two names which is terribly meaningless to file system.
From (3): If two public classes allowed, we should have two main methods which is terribly meaningless to java
Hence a Java source file can have one only public class.
I think the above 4 points are forced by compiler to make the job of both compiler and jvm to find particular java source file or class file easy-so-quick for the compilation/loading/linking. Java has such built in restrictions which developers should follow to have better programming.
Source: My readings and understanding.
To understand the basic reason behind these restrictions, let's suppose compiler doesn't give compile error for not naming file name same as public class name.
Suppose there is a package A
A
/ \
file1.java file2.java
file1.java
package A;
class file1
{
public static void main(String args[])
{
}
}
public class file3
{
public static void main(String args[])
{
}
}
Now as we know that a public class can also be accessed outside the package, now it will become the responsibility of a developer to make it accessible to the outside world. Let's see how:
Suppose package A is containing only Java files(no class files) and some class outside the package A tries to access public class file3, compiler will first try to find file3.class ( not available ), then it will try to find file3.java ( not available ). So even though file3 class is public in nature, it is not visible to the outside world. So if a compiler puts the restriction that if a file is containing public class, it should be named same as the public class name, then above issue can be resolved and the developer won't have to think of exposing public class to the outside world.
Compiler also puts the restriction that there should be atmost one public class per Java file, so that every public class can be accessed by the outside world.
Java utilizes this convention to find class/interface bytecode by starting at the classpath and scanning for the package hierarchy in subdirectories. Filesystem representation of this hierarchy also enforces some basic rules.
Any two Java classes or interfaces
in the same package cannot have the
same name. File names would
conflict.
Any two Java packages in
the same parent package could not
have the same name. Folder paths
would conflict.
A class has visibility to all classes in the same package without modification
to the classpath.
To have an understanding between the compiler and the programmer.It is a rule that the source code must have atmost one public class and that class must contain the main function.So without any confusion/restriction the compiler can access(public) the class and name the class name to the class file.Also since this class contains the main(), executing the class file will give correct flow
Public modifier with a class is exposed to the world that means any other class which is outside of the package can also access it to resolve dependency.
Now this dependency chain containing multiple classes are verified two times - one is while compilation ( one level of dependency is verified) & other one is while execution ( whole dependency chain is verified ).
Now suppose there is public class (class A) whose source file name is something different from class name. Now if some other class (say class B) depends on it , then while compilation of class B , java compiler will surely check where that class A is located & for that compiler has to go thru all the packages in search of class A ,which is time consuming.
Now suppose in the same scenario we give source file name of class A as A.java , then while compiling class B , compiler will search for class A & for that it only need to find source file whose name is A.java , so it doesn't need to go thru all packages ( which may contain multiple classes) it will now only search that package in which a source file A.java is present.
So from compilation time , performance point if view one source file should have one public class.
It enables a more efficient lookup of source (.java) and compiled (.class) files during compilation (import directive) and a more efficient classloading during execution. The idea being: if you know the name of a class, you know where it should be found for each classpath entry. No indexing required.
I think that this may be a possible reason.
There can be only one public class in a java file because the name of java file is same as the name of public class.And obviously we can't have a file with two different names.
It is how it has been designed and I am not sure if the reason is documented. But here is a good reason on why it is done that way. Let's assume we have two public classes Y & Z in a file named Y.java. Now, let's assume a different class X is using Z. Now, when we compile X, the compiler first tries to locate Z.class and if it cannot find it, then it tries to locate Z.java so that it can compile it automatically. But, since we only have Y.java, the class Z cannot be located and hence we get a compilation error. So, we do need to place them in separate files.
Class A{
}
public Class B{
}
So this is correct becoz A is not public and compiler will not confuse that which class compiler should execute.
public Class A{
}
public Class B{
}
So this is incorrect becoz here compiler get confused which class should execute becoz both are public.

Why only 1 public class in Java file

In any Java file, why can we have only one public class whose name is same as the Java file name?
It forces all Java code to be organized in a certain way, which in the long run helps improve code readability.
The Java designers chose a strict approach that enforces their idea of good design practices, and this is part of that theme. Contrast that with the anything-goes attitude in Perl.
According to this source, it is for efficient compilation :
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
The same applies also for imports of source files in IDEs. Another reason would be reasonable source sizes.
These are the rules. Although it is not quite true. You can define internal classes inside you "main" class like this:
public class A {
public class B {
...
}
}
Courtesy of Dr Heinz Kabutz and his excellent newsletter....
Why is each public class in a separate
file?
This is a question that I have
frequently been asked during my
courses. Up to now I have not had a
good answer to this question. In
section 1, we read: "Although each Oak
compilation unit can contain multiple
classes or interfaces, at most one
class or interface per compilation
unit can be public".
In the sidebar it explains why: "This
restriction is not yet enforced by the
compiler, although it's necessary for
efficient package importation"
It's pretty obvious - like most things
are once you know the design reasons -
the compiler would have to make an
additional pass through all the
compilation units (.java files) to
figure out what classes were where,
and that would make the compilation
even slower.
We can have only one top level public either class or interface in any java compilation unit ( .java source file ).
But there can be any number of default classes/interfaces per src file.
why:
JLS leaves the option to the java compiler. And most of the compiler implementations force to have file name same as :
(1) the public class/interface name
(2) if there is a main method and no public class then any name
(3) If there is main method and public class then main method should be in that public class
(4) if there is no public class and no main method then any valid name which may or may not be matching with the class/interface names in the file.
From (2): If two public classes allowed, we should give the file two names which is terribly meaningless to file system.
From (3): If two public classes allowed, we should have two main methods which is terribly meaningless to java
Hence a Java source file can have one only public class.
I think the above 4 points are forced by compiler to make the job of both compiler and jvm to find particular java source file or class file easy-so-quick for the compilation/loading/linking. Java has such built in restrictions which developers should follow to have better programming.
Source: My readings and understanding.
To understand the basic reason behind these restrictions, let's suppose compiler doesn't give compile error for not naming file name same as public class name.
Suppose there is a package A
A
/ \
file1.java file2.java
file1.java
package A;
class file1
{
public static void main(String args[])
{
}
}
public class file3
{
public static void main(String args[])
{
}
}
Now as we know that a public class can also be accessed outside the package, now it will become the responsibility of a developer to make it accessible to the outside world. Let's see how:
Suppose package A is containing only Java files(no class files) and some class outside the package A tries to access public class file3, compiler will first try to find file3.class ( not available ), then it will try to find file3.java ( not available ). So even though file3 class is public in nature, it is not visible to the outside world. So if a compiler puts the restriction that if a file is containing public class, it should be named same as the public class name, then above issue can be resolved and the developer won't have to think of exposing public class to the outside world.
Compiler also puts the restriction that there should be atmost one public class per Java file, so that every public class can be accessed by the outside world.
Java utilizes this convention to find class/interface bytecode by starting at the classpath and scanning for the package hierarchy in subdirectories. Filesystem representation of this hierarchy also enforces some basic rules.
Any two Java classes or interfaces
in the same package cannot have the
same name. File names would
conflict.
Any two Java packages in
the same parent package could not
have the same name. Folder paths
would conflict.
A class has visibility to all classes in the same package without modification
to the classpath.
To have an understanding between the compiler and the programmer.It is a rule that the source code must have atmost one public class and that class must contain the main function.So without any confusion/restriction the compiler can access(public) the class and name the class name to the class file.Also since this class contains the main(), executing the class file will give correct flow
Public modifier with a class is exposed to the world that means any other class which is outside of the package can also access it to resolve dependency.
Now this dependency chain containing multiple classes are verified two times - one is while compilation ( one level of dependency is verified) & other one is while execution ( whole dependency chain is verified ).
Now suppose there is public class (class A) whose source file name is something different from class name. Now if some other class (say class B) depends on it , then while compilation of class B , java compiler will surely check where that class A is located & for that compiler has to go thru all the packages in search of class A ,which is time consuming.
Now suppose in the same scenario we give source file name of class A as A.java , then while compiling class B , compiler will search for class A & for that it only need to find source file whose name is A.java , so it doesn't need to go thru all packages ( which may contain multiple classes) it will now only search that package in which a source file A.java is present.
So from compilation time , performance point if view one source file should have one public class.
It enables a more efficient lookup of source (.java) and compiled (.class) files during compilation (import directive) and a more efficient classloading during execution. The idea being: if you know the name of a class, you know where it should be found for each classpath entry. No indexing required.
I think that this may be a possible reason.
There can be only one public class in a java file because the name of java file is same as the name of public class.And obviously we can't have a file with two different names.
It is how it has been designed and I am not sure if the reason is documented. But here is a good reason on why it is done that way. Let's assume we have two public classes Y & Z in a file named Y.java. Now, let's assume a different class X is using Z. Now, when we compile X, the compiler first tries to locate Z.class and if it cannot find it, then it tries to locate Z.java so that it can compile it automatically. But, since we only have Y.java, the class Z cannot be located and hence we get a compilation error. So, we do need to place them in separate files.
Class A{
}
public Class B{
}
So this is correct becoz A is not public and compiler will not confuse that which class compiler should execute.
public Class A{
}
public Class B{
}
So this is incorrect becoz here compiler get confused which class should execute becoz both are public.

Java package and classpath question

Can anyone please explain the answer to the following question:
Given a correctly compiled class whose source code is:
package com.sun.test;
public class Commander {
public static void main(String[] args) {
}
}
Assume that the class file is located in /foo/com/sun/test/, the current directory is /foo/, and that the classpath contains "." (current directory). Which command line correctly runs Commander?
A. java Commander
B. java com.sun.test.Commander
C. java com/sun/test/Commander
D. java -cp com.sun.test Commander
E. java -cp com/sun/test Commander
And the best answer would be B. C also works on some platforms but is not recommended and is very uncommon (at least, I've not seen it in over 10 years programming Java).
EDIT
A common misconception with beginners in Java is that a class name is something like "MyClass". But that is not accurate; the nomenclature "MyClass" as seen in the declaration class MyClass is really a convenience for the programmer which the compiler combines with the package declaration to create what Java refers to as a qualified class name, which all class names really are to the runtime. (In C#, they use namespaces for this).
This becomes quite evident in many cases such as stack traces and method signatures which always contain, for example, java.lang.String. Because "String" is just a short form that is resolved to java.lang.String. You can prove this by making your own String in your own package... but beware doing so will require that you explicitly use java.lang.String or my.package.String everywhere that both packages or classes are imported.
Once you assimilate the fact that all class names are fully qualified, and that the compiler helps you avoid tedious work by using imports to resolve short forms to fully qualified forms, things become clearer.
It should then be evident why:
java -cp com/sun/test Commander
doesn't work. The cp option puts the directory ./com/sun/test (relative to the current directory) on the class path, but there is no class named Commander... it's com.sun.test.Commander. This implies two things: (a) the command line requires com.sun.test.Commander and (b) the classpath must contain an entry for the directory which contains "com" in order to resolve this class since a class named x.y.MyClass must be in x/y relative to some classpath element.
PS: You should not be using com.sun as a package name unless you are employed by Sun, since the domain name sun.com belongs to Sun. This convention exists to avoid class packaging and naming collisions.
PPS: There is such a thing as the default package, which is "specified" by omitting the package declaration -- but it should almost never be used. The one legitimate place I have found is with a self-contained "Launcher/Classloader" where it is desired to be able to do:
java -cp . Launcher com.xxx.yyy.TargetApp
with Launcher.class in the current directory... and that is only because JAR files are held locked while the app is running while class files are not, which means that Launcher.class can self-update, while Launcher.jar cannot.
Assuming CLASSPATH environment variable is not set (and thus current working directory is in the classpath by default), the answers are the following:
A. Does not work, there is no Commander class in the default package
B. This one works
C. This one works also, but B is preferred
D. Class path is foo/com.sun.test where there is no Commander class in the default package
E. Class path is foo/com/sun/test where there is no Commander class in the default package
A. Not working, as Java will not found the Commander class
B. Will work, as Java will not found the com.sun.test.Commander class
C. Will work, at least on a Windows plateform. That's why you must use . instead of /.
D and E. They will not work because we still ask Java to search for the class Commander and not com.sun.test.Commander

Categories

Resources