When preparing for the SCJP exam, we were going through the following code:
package certificaton;
public class OtherClass
{
public void testIt()
{
System.out.println("otherclass");
}
}
And this:
package somethingElse;
import certification.OtherClass;
public class AccessClass
{
public static void main( String args[])
{
OtherClass o= new OtherClass();
o.testIt();
}
}
I placed both the above files in the following directory: C:\scjp\temp8 ; and the strange thing is that, the .java files are compiling and results in two .class files being created in the same directory. The thing I want to ask, is that, the difference between packages and directory. Isn't it true that the class files could be created in a directory other than the one stated in the package declaration? And the package declaration is something 'virtual', and disregards the windows directory structure. In addition, isn't it also true that, by executing the following command:
javac -d . OtherClass.java
The directories are created conforming to the package declaration, which isn't always mandatory?
The directories are created conforming
to the package declaration, which
isn't always mandatory?
No, the package and directory structures must match. It's mandatory, not optional.
Related
Here My first file code
package com.shubham.packages.a;
import static com.shubham.packages.b.Message.Hello;
public class Greeting {
public static void main(String[] args) {
System.out.println("Hello World");
Hello();
}
}
Here my second file code
package com.shubham.packages.b;
public class Message {
public static void main(String[] args) {
}
public static void Hello() {
System.out.println("This is Awesome.");
}
}
Here the error I got when I run the program.
When you compile your code javac needs to know where to look for all of your source/class files. You could go to "java_tutorial" folder and run.
javac com/shubham/packages/a/Greeting.java com/shubham/packages/b/Message.java
That should compile both of your java files into class files at the same location. Then you should be able to run.
java com.shubham.packages.a.Greeting
I might be using the wrong slashes for windows
You can explicitly name all of the necessary java files, so this should cause both Greeting.java and Message.java to be compiled in place.
When you run java, the CWD is on the classpath by default so that means the package com.shubham.packages.a and ...b should be on the classpath in their correct location.
A slightly better way to do this is to create a folder called "build" or whatever you like.
javac -d build com/shubham/packages/a/Greeting.java com/shubham/packages/b/Message.java
That will output the class files to the build folder. Then when you run it.
java -cp build com.shubham.packages.a.Greeting
I've the following two source files
File World.java
package planets;
public class World {
public static void main(String[] args) {
Mars.land();
}
}
File Moon.java
package planets;
public class Moon {
public static void land() {
System.out.println("Hello Moon");
}
}
class Mars {
public static void land() {
System.out.println("Hello Mars");
}
}
As we can see, the Moon.java contains two classes: the public Moon class and the nonpublic Mars class.
The files are located inside planets directory, below is showed the directory tree
+current-dir:
+----+planets:
+----+World.java
+----+Moon.java
Now, if I try to compile from Windows command prompt (I'm inside current-dir folder) typing
javac planets\World.java
I receive this error message:
planets\World.java:5: error: cannot find symbol
Mars.land();
^
symbol: variable Mars
location: class World
1 error
It's very strange, because I know that the compiler searches for nonpublic classes inside all the source files of the current package.
Also Cay Horstmann's Core Java Vol 1, 10th ed. at pp. 192-193 says that:
[...]you can import nonpublic classes from the current package. These
classes may be defined in source files with different names. If you
import a class from the current package, the compiler searches all
source files of the current package to see which one defines the
class.
In addition I tried to write these files using Eclipse Oxygen and it compile without problems. But I know that Eclipse use a different compiler.
Why does javac compiler fail?
EDIT: I have not set CLASSPATH variable. So by default compiler looks inside current directory.
you need to type the following commands in order (inside your 'current-dir')
javac planets\Moon.java
javac -cp . planets\World.java
java -cp . planets.World
I am writing some Java code without IDE, I got a little problem when I try run the code after compiling it. (I am using Ubuntu 64)
$ javac ClassName.java
$ java ClassName
Could not find or load main class ClassName
My directory structure is the following:
Projectname
----- PackageName
---------- className.java
---------- className.class
My code start by writing down the packageNmae. When I remove the package statement, it works. While error occur when that statement is included.
package PackageName;
public class myClass {
// .... to be used in the main class
}
public class ClassName {
public static void main(String args[]) {
// ....
}
}
Could anyone tell me what is the problem.
The main issue is where are you trying to run the command from. You do not run it from inside the package directory, but from the root of your package tree (in your example, the Projectname directory).
From there, you should be doing:
javac PackageName.className
which tells it to compile "className"[sic] inside package "PackageName"[sic]. The way you are doing it, you are telling it to compile a class that is not part of a package (which is strongly discouraged).
Notes:
Each file can only have a "general" class, with the name of that file.
You may define inner classes inside a class, but that would be inside the code block of the class.
package packageName;
public class ClassName {
public class InnerClass {
...
}
public static void main(String args[]) {
...
}
}
File name and class name must be the same. That includes case (lowercase or uppercase) of the name.
Class names always begin in uppercase.
Package names should be in camelCase.
Usually you do not want to leave your compiled (.class) files with the source (.java) files. The usual structure is, at the minimum:
--> Project --> src --> myPackage --> MyClass.java
--> bin --> myPackage --> MyClass.class
so you only need to copy your .class files to distribute the executable.
I am trying to understand how javac deals with cyclic imports. After few attempts, I got the below code to be compiled:
package com.test.p1;
import com.test.p2.ClassP2;
public class ClassP1 {
public static void main(String[] args) {
System.out.println("ClassP1 loaded");
ClassP2.testP2();
}
}
And
package com.test.p2;
import com.test.p1.ClassP1;
public class ClassP2 {
public static void testP2() {
System.out.println("ClassP2 loaded");
}
}
When I compiled ClassP2.java first, I was expecting it to fail as ClassP1.java was not yet compiled and no class file was generated. Yet, it compiled ok, and generated ClassP2.class and ClassP1.class. Running ClassP1 worked fine as well.
Now my question is how did javac generate class file for ClassP1 when I only compiled ClassP2. And why does this not happen when cyclic reference is not there - i.e. when ClassP2 imports ClassP1, but ClassP1 does not import ClassP2 ?
I am still new to Java and trying to understand how compilation works.
There's nothing cyclic going on here. It sounds like you, along with a lot of other people, confuse import with class loading.
All the import statement does is allow you to use the short name to refer to a Java class in your code:
import java.sql.ResultSet;
public V find() {
ResultSet rs = null; // You can type ResultSet instead of java.sql.ResultSet
}
The import statement won't help you if the short name is ambiguous (e.g. java.util.Date and java.sql.Date in the same class).
The byte code for java.sql.ResultSet is not loaded into the JVM until your code needs it at runtime.
It is not a result of cyclic imports, it is a result of importing ClassP1 in ClassP2.java and javac being able to find the source for ClassP1 based on the arguments you passed to javac and the location from which you executed the command.
See the -sourcepath option in the docs for javac:
-sourcepath sourcepath
Specify the source code path to search for class or interface definitions. As with the user class path, source path entries are separated by semicolons (;) and can be directories, JAR archives, or ZIP archives. If packages are used, the local path name within the directory or archive must reflect the package name.
Note: Classes found through the class path may be subject to automatic recompilation if their sources are also found. See Searching For Types.
I'm getting Java code generated for me from an application.
I took the JRE and extracted all the files into a new directory.
There is a META-INF folder that has a MANIFEST.MF without any main method.
Witin this JRE is the class of the code I'm interested in however when I CMD the following...
java Steve.class
I get this error...
Could not load for find Main Class Steve.class.
I'm assuming that somewhere in all these class files there is a Main class but how do I search all these documents to find it? Is there an application?
Thanks!
You don't need the .class suffix when invoking a Java program. Do it like this:
java Steve
To work out which class has a main method, you can use javap (Java Class File Disassembler) on each class file. For example:
$ javap Foo
Compiled from "Foo.java"
public class Foo extends java.lang.Object{
public Foo();
public static void main(java.lang.String[]);
}
First: every class that exposes this method signature:
public static void main(String[] args) { }
could be a main class launchable from the JVM and eligible to be put in the manifest to enable shell execution.
Second: when you launch a class in a JRE you must specify the fully qualified name of the class; for example if Steve.class file is in a tree structure such as com/mycompany/app, starting from the root of your application where the MANIFEST directory is, you should launch it, from the root directory, typing:
java com.mycompany.app.Steve
So if Steve exposes a main method and if you can correctly point to it from the root, you can launch it.