The use of ":" and "." in a call to java with classpath declaration - java

This is a scjp mock exam question.
Suppose I have the following two files:
package pkg;
public class Kit {
public String glueIt (String a, String b) {return a+b;}
}
import pkg.*;
class UseKit {
public static void main(String[]args) {
String s = new Kit().glueIt(args[1],args[2]);
System.out.println(s);
}
}
And the following directory structure:
test
|--UseKit.class
|
com
|--KitJar.jar
The current directory is test and the file pkg/Kit.class is in KitJar.jar
According to the answer, the java invocation that produces the output b c is
java -classpath com/KitJar.jar:. UseKit a b c
Please explain the use of the operators ":" and "."

: is the separator for entries in a Java classpath. . means "current directory". So the classpath com/KitJar.jar:. means to look for Java class files in two locations: com/KitJar.jar and the current directory.

The accepted answer is correct but it could have mentioned that the classpath separator is actually platform dependent as pointed out in comments.
For more information, including an explanation of class path wildcards, and a detailed description on how to clean up the CLASSPATH environment variable, see the Setting the Class Path technical note (and/or Setting the Class Path for the *nix version).

Related

Java program runs yet compilation fails

I wrote a Java program whose filename was (intentionally) different from the class I wrote inside the file. The javac command failed as expected on both CMD and WSL. The java command however worked and ran my print statement. I wrote the code intentionally this way so there is no way it was a previously compiled version of the code. The following code was written in a file called "explainJava.java" (notice the filename is different from the class name).
public class explain{
public static void main(String[] args) {
System.out.println("Java is weird");
}
}
I've had to google this myself, but I think I've found an explanation in this article.
According to that source as of Java 11 java is capable of compiling a single source file into memory.
What I conclude from that: When the file is compiled into memory and not written to disk it obviously cannot have a file name. If there is no filename there is no such thing as a wrong filename, therefore the code executes.
Please also note that the restriction of having to name a file like the public class within that file is more of a design decision to make work for the compiler easier/ faster. It is not a physical restriction so to speak. Have a look at the following thread for more details.
If you put this code:
public class explain {
public static void main(String[] args) {
System.out.println("Java is weird");
}
}
into a file named explainJava.java, and then compile it with this:
javac explainJava.java
you will get an error that correctly informs you that your filename ("explainJava") and the class defined inside that file ("explain") do not match:
explainJava.java:1: error: class explain is public, should be declared in a file named explain.java
public class explain{
^
1 error
If you run this command:
$ java explainJava.java
Java is weird
you see expected output, because you're skipping the explicit compilation step (that is, you aren't running javac first) and instead relying on behavior introduced in Java 11 that allows you to compile+run in a single step. Here's an explanation: Does the 'java' command compile Java programs?
So the answer is to either:
rename your file to match the class, so change the filename to "explain.java", or
rename the class to match the file, change public class explain to be public class explainJava

Execute java compiled class command line

I have the following question. Given a correctly compiled class whose source code is:
1. package com.sun.sjcp;
2.
3. public class Commander {
4. public static void main(String[] args) {
5. // more code here
6. }
7. }
Assume that the class file is located in /foo/com/sun/sjcp/, 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.sjcp.Commander
C. java com/sun/sjcp/Commander
D. java -cp com.sun.sjcp Commander
E. java -cp com/sun/sjcp Commander
Answer: B
A. We are in the root dir, so we can't see the file from
/foo/com/sun/sjcp/ directly
B. is correct
C. I think is correct too ???
D. We are in /foo/com/sun/sjcp/ and there is only class file with
package package com.sun.sjcp; so the compiler can't find it.
If the file was without package declaration and was build in this dir
then it will work if we try to run it in this way.
E. The same as D - does not work
The only answer given is B. Where am I making a mistake?
C is incorrect because "com/sun/sjcp/Commander" isn't a valid class name. Path to a file and class name are not the same things.
(edited): It's appeared "that the jvm allows you to use a forward slash in place of a dot in the fully qualified name of the class to run" (but you must use only forward slashes). So it seems that C is also correct
A class name can never have forward slashes on it (it's not the same concept as a filesystem path), that's why B is the only right answer.

Java : compile error

I have created a package:
path : /home/myid/py_ejb
File : XmppMnager.java
package xmpp;
import org.jivesoftware.smack.Chat;
public class XmppManager {
}
Compiled with
javac -d . -classpath .:smack.jar XmppManager.java
File: XmppTest.java
import xmpp.*;
public class XmppTest {
public static void main(String[] args) throws Exception {
String username = "testuser1";
String password = "testuser1pass";
XmppManager xmppManager = new XmppManager("myserver", 5222);
..}
Compiled with
$ javac -classpath .:smack.jar:./xmpp XmppTest.java
XmppTest.java:10: cannot access XmppManager
bad class file: RegularFileObject[./xmpp/XmppManager.class]
class file contains wrong class: xmpp.XmppManager
Please remove or make sure it appears in the correct subdirectory of the classpath.
XmppManager xmppManager = new XmppManager("myserver", 5222);
^
1 error
I tried a lot of way to fix this compilation issue but it just does not go away
Move the source files into a folder named xmpp so that the package names match that of the folder
Package names are directly related to the classpath directory structure. All the classes in the xmpp package need to be in a folder named xmpp, and this folder must be on the classpath. Similarly, if you had a package called xmpp.util.io you would have to put the files in xmpp/util/io/.
The usual convention is to make a src directory to hold all your source files, and then that can be filled with a directory structure that exactly matches your package structure. A pretty decent tutorial on packages can be found here.
Also, it looks like this is probably just a typo in the question, but if your file is actually named XmppMnager.java rather than XmppManager.java, that won't compile either.

Java package - class not found, same directory

I have two Java classes "giveMyOb" and "dataConn" declared in the same directory. Both are public classes. "giveMyOb" has a static method "getMine()". Inside dataConn, I called the static method as
giveMyOb.getMine();
When I try to compile dataConn.java, the following error is returned.
"Cannot find symbol
symbol: variable giveMyOb
location : class dataConn
giveMyOb.getMine(); "
It used to work earlier. But is not working now. Why is that?
Additional Information: JDK 1.6. Windows 7. 64 bit.
Update(30 days after the question): When compiled from Eclipse, the classes are referenced and it works. But the same won't work when compiling from command line. I was unable to figure out the reason and nothing logical comes to my mind!
javac -classpath . *.java
ought to create both .class files at the same time. It's more complicated by packages. I'm assuming you have none.
Learn the Sun Java coding conventions. You aren't following them with those class names. They should start with a capital letter.
Try this:
giveMyOb.java
public class giveMyOb {
public static String getMine() {
return "Yay, it works!";
}
}
dataConn.java
public class dataConn {
public static void main(String[] args) {
System.out.println(giveMyOb.getMine());
}
}
Then compile it all:
javac *.java
and run the main class:
java -cp . dataConn
// output: Yay, it works!
Note that Java's coding conventions recommend class names start with a capital.
If "it" still doesn't work, try removing the .class files manually then recompile again.

Why can't I compile my java file on cygwin, when it needs classes from a jar?

I'm trying to compile my class along with a provided .jar file which contains classes that my class will use.
This is what I've been trying:
javac -classpath .:WordSearch.jar WordSearchSolver.java
And this is the response:
WordSearchSolver.java:16: cannot find symbol
symbol : class PuzzleWord
location: class WordSearchSolver
public ArrayList<PuzzleWord> findwords()
^
WordSearchSolver.java:18: cannot find symbol
symbol : class PuzzleWord
location: class WordSearchSolver
return new ArrayList<PuzzleWord>();
^
2 errors
This is my class:
import java.util.ArrayList;
public class WordSearchSolver
{
public WordSearchSolver(int size, char[][] puzzleboard, ArrayList<String> words)
{
}
public ArrayList<PuzzleWord> findwords()
{
return new ArrayList<PuzzleWord>();
}
}
WordSearch.jar contains:
PuzzleUI.class
PuzzleWord$Directions.class
PuzzleWord.class
Natural.class
(WordSearchSolver.java and Wordsearch.jar are in the same directory)
Am I missing something?
Although you're on Cygwin, I'm guessing that your path separator should be a semicolon, since the Java compiler/JVM will be running in a Windows environment.
javac -cp .\;WordSearch.jar ...
Note that the semicolon must be escaped to prevent interpretation by the Cygwin shell (thanks to bkail below)
You aren't importing any of the classes from your WordSearch.jar in your WordSearchSolver class. You need import statements at the top of this class including their package.
It ended up being a combination of semicolons and quotation marks.
javac -classpath ".;WordSearch.jar" WordSearchSolver.java
Thanks everyone for pointing me in the right direction!

Categories