public class a {
public static void main(String[] args) {
System.out.println("Hello, World");
}
}
For the above code, I can run it by javac a.java, and then java a.
But if I add a package for it:
package hello;
public class a {
public static void main(String[] args) {
System.out.println("Hello, World");
}
}
I need add the classpath -cp in order to run it: java -cp ../ hello.a
Why I do not need to set the classpath in the first situation? When do I need to add -cp?
To answer your question
When should I set my classpath
Always, as you work on more complex projects you will find that your classpath will almost always need to be set. This will either be done manually like you have done with -cp command or by your IDE.
To answer your second question
Why I do not need to set the classpath in the first situation
I first need to explain a little bit about classpaths. In short classpath exist to tell the VM where to look for your files. In the first situation since you didnt have a package the default location was used to find your class so no classpath was needed. However when you complicated things and added a package at this point a classpath is needed
The classpath is where java (the program) looks for classes. The default contains a bunch of system-wide things (for the JDK), and then also the current directory: ..
Without the package line, your class was in the "default package," which is basically no package. This means its full name is a (more or less), and java will look for it in a file called $CP_ELEM/a.class for each element CP_ELEM in the classpath. In the default case, that amounts to ./a.class, which is fine because that file exists.
With the package line, your class is in the hello package, and its full name is hello.a. That means that java will look for it in $CP_ELEM/hello/a.class, which amounts to ./hello/a.class -- which doesn't exist. But if the directory you're in happens to be called "hello", then java -cp .. hello.a, which amounts to looking in ../hello/a.class, will work.
Classpath is like telling the system where to find my classes:
If you don't have a classpath the java will try to load the class
from the default directory (Probably where you're running the command at).
Now let's say you put your compiled classes in folder "bin" and sources in "src" folder
To tell the system to load the classes from "bin" folder you have to give him the following parameter:
-cp bin;
Also i see you don't understand the packaging system in java so here's fast explain:
Packaging is like you the directory of your class for example:
If you set the class's package to package a; and your classpath directory is set to "bin"
You have to create folder called "a" in "bin" folder, and then move the compiled class there, do the same for the source file, but in "src" folder
Just saying you could use eclipse which is located at : http://www.eclipse.org
If this didn't help you, Then take a look at this: https://www3.ntu.edu.sg/home/ehchua/programming/java/J9c_PackageClasspath.html
Related
I installed JDK7 in my computer. I just specified the path like that:
I didn't set CLASSPATH.
I writed a test program , the program like that:
import java.io.File;
public class Hello_1 {
public static void main(String[] args) {
System.out.println(File.separator);
}
}
I complied it and runned it like that:
According the result, we could see that it didn't have any error.I was confused. I didn't set CLASSPATH, according the ORACLE DOC, it said:
The default value of the class path is ".", meaning that only the
current directory is searched. Specifying either the CLASSPATH
variable or the -cp command line switch overrides this value.
if i didn't set CLASSPATH variable, the default class path is ".", so when I compiled Hello_1.java it would only search java.io.File in current directory, there nothing about the java.io.File, so it would thrown exception. But why it worked well?
The classpath is used to search for your own classes, but the built-in class library is available automatically without needing to be added to the classpath. So Hello_1 is found on the default classpath (the current directory) and java.io.File is found in the built-in class library.
You have put the path to JDK bin in the PATH variable. So now your OS know java/javac as the commands and hence you can run your code. Classpath comes into picture if your source code or libraries are in some other directory than your current directory.
This sounds embarrassing. My purpose is to understand how Scala treats package statements, written in the Java style. To this end, I wrote up a little example class (that I named DinnerTimeP.scala as below:
package dinnertime
class Dinner {
val veggie = "broccoli"
def announceDinner(veggie: String) {
println("Dinner happens to be tasteless " + veggie + " soup")
}
}
I have a folder called scaladev, under which I have created the package folder, dinnertime. Under this package lives DinnerTimeP.scala. On the DOS command I then navigate to dinnertime and compile the file DinnerTimeP (the name sounds silly) with scalac as below.
C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>set CLASSPATH=.;C:\scala- 2.9.1.final\scala-2.9.1.final\scaladev
C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>scalac DinnerTimeP.scala
I was hoping to find Dinner.class generated right under the dinnertime folder and sitting next to the source file DinnerTimeP.scala.
To confirm my understanding, I created a HelloWorld.java program under the same folder:
package dinnertime;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
I compiled HelloWorld.java on the command line as follows:
C:\scala-2.9.1.final\scala-2.9.1.final\scaladev\dinnertime>javac HelloWorld.java
The HelloWorld.class file was generated right next to its source file.
This was the exact situation I wanted to see with the Scala source file and its compiled file.
Instead I see a new package folder generated by Scala inside the package folder dinnertime.
This might be naive. I am probably betraying a fundamental understanding of Scala and packages, but I was perplexed by this behaviour.
This is the problem I can't explain to myself: Why is the nested package created for the newly generated class file. This is the problem to which I which I had hoped to solve, based on my own sincere efforts
Because my experience with Scala at the present time is limited, I have resorted to asking the Scala gurus on stackoverflow to help me understand what is going on and why?
Is there a reason for this nested package to be created by Scala and not by Java?
Tomasz explained everything you need to get it working, so let me explain the why.
Scala does not mandate that source files be in a directory hierarchy that reflects the packages. That is, Dinner.scala could be anywhere: it simply doesn't matter.
And, to be really clear, even if you have a complex package hierarchy, deep and with multiple subpackages at each level, you can put all source files in a single directory. The directory where Scala files are put in is not relevant.
Sorry for giving it so much emphasis, but coming from Java it might be difficult to grasp this.
Ok, now, how to explain dinnertime/Dinner.class? Well, JVM demands that class file be put in a directory hierarchy that corresponds to the package names, so even if Scala source files can be put in arbitrary directories, scalac must produce an output whose directory structure reflects the package names.
So, to review everything, Scala doesn't care what directory you were in, so it ignored the fact that you were in a directory called dinnertime. However, since the source code indicated that the class was in a package named dinnertime, it created such directory and put the class file in it. It assumed the base for that was the current directory, which can be changed with the -d parameter, as per Tomasz answer.
First of all try compiling from the root directory, so that dinnertime is a subdirectory:
$ javac dinnertime/HelloWorld.java
and:
$ scalac dinnertime/Dinner.scala
They both produce the same output, i.e. in both cases .class file is placed under dinnertime subdirectory.
The difference arises when you run a compiler inside a package. Turns out javac is clever enough to put target binary files relative to root directory, not current direcotyr. This is not the case with scalac which always uses current directory as base. You can easily fix this by using -d parameter:
$ cd dinnertime
$ scalac -d .. Dinner.scala
I am using Notepad++ to write my Java code and Command Prompt to compile and run it.
Following is my sample Java code,
package abraKadabra;
public class SuperClass{
protected int anInstance;
public static void main(String [] abc){
System.out.println("Hello");
}
}
However, this file is in the following folder structure :
"usingprotected\superPkg" (usingProtected is a folder somewhere in the hierarchy in C:)
So, my package name here should be something like usingProtected.superPkg instead of abraKadabra as I wrote it.
But, when I compile this Java code from command prompt, it compiles fine with no error or warnings. Why is it so? Shouldn't the package name adhere to the folder structure?
And if it should, how would it adhere?
For e.g. if my package name is usingProtected.superPkg, will the compiler check in the reverse order. The present working directory should be superPkg, then the parent directory should be usingProtected and its done. Is it how it checks the folder structure with package name?
The Java language specification doesn't force files to be in a certain directory. It optionally allows the compiler to require that public classes are in files with the same name of the class, but I don't think there's anything similar for packages. Section 7.2.1 talks about possible storage options in a file system, but it doesn't say anything about enforcing source code structure, as far as I can see.
However, it's best practice - and a pretty much universally accepted convention - to reflect the package structure in the source directory structure... and javac will use this to try to find source files which aren't explicitly specified to be compiled.
Note that if you're compiling from the command line, by default each class will appear in the same location as the corresponding source file, but if you use the "-d" option (e.g. "-d bin") the compiler will build an appropriate output directory structure for you, rooted in the specified directory.
After experimenting a bit, I got the way how to use package name and run Java class files from command prompt.
Suppose following is my Java source file:-
package mySample;
public abstract class Sample{
public static void main(String... a){
System.out.println("Hello ambiguity");
}
}
This file is in directory "D:\Code N Code\CommandLine".
Now, when compile the source code (by going to the above directory from cmd) using following command:-
javac -d . Sample.java
This automatically creates "mySample" folder in my current directory. So, my class file Sample.class is present in directory "D:\Code N Code\CommandLine\mySample". Compiler created this new folder "mySample" from the package name that I gave in my source code.
So if I had given my package name to be "package com.mySample", compiler would create two directories and place my class file in "D:\Code N Code\CommandLine\com\mySample".
Now, I am still in the present working directory i.e. in "D:\Code N Code\CommandLine". And to run my class file, I give the following command:
java mySample.Sample
So, I give the complete hierarchy of package and then the class name. The Java Interpreter will search the current directory for "mySample" directory and in that for "Sample.class". It gets it right and runs it successfully. :)
Now, when I asked that why it compiles my wrong package source code, it would compile the code successfully though, but it gives NoClassDefFoundError when I run my class file. So above method can be used to use package names from command line.
If you're compiling a single class, javac doesn't need to look elsewhere for it. It'll just compile the file as is and put the resulting .class into the same folder. However, you generally won't be able to use the class til you put it into an "abraKadabra" directory in one of the directories in the class path.
If your class uses another class in the package, though, you might have problems compiling it where it is, for the same reason (javac wants to find the class and make sure it has the methods and such that your class uses).
Java compiler does not check the directory structure when it compiles source files. As you mentioned, suppose you have a source file that starts with the directive
package abraKadabra;
You can compile the file even if it is not contained in a subdirectory .../abraKadabra . The source file will compile without errors if it doesn’t depend on other packages. However, the resulting program will not run (unless also including package name in execution). The virtual machine won’t find the resulting classes when you try to run the program.
I am new to java. I write a simple code like this:
import java.io.*;
public class a
{
public static void main(String []argc)
{
System.out.println("S");
}
}
I compile it with below bash command:
javac a.java
then this:
java a
But it said:
Could not find or load main class a
My java version is 1.6.0.
What should I do?
A common reason for this is that you've set the environment variable CLASSPATH.
This is usually not a good idea, because that setting always influences your whole system.
You can easily define a per-instance classpath, by specifying the -cp parameter.
In your case you can do
java -cp . a
This tells Java to look for classes in the current directory (.).
Use this to run :
java -cp . a
Basically, you need to add the directory where your compiled .class file is to your classpath (which is the current directory, ., in your case).
Also, your code at this time uses no other APIs from external libraries, but most likely you would going forward. In that case, ensure that you add those JARs to you classpath (using java -cp .;<jar1 path>;<jar2 path> a) when running your code.
You need to specify classpath containing current directory:
java -cp ./ a
I was just reading this line:
The first thing the format() method does is load a Velocity template from the classpath named output.vm
Please explain what was meant by classpath in this context, and how I should set the classpath.
When programming in Java, you make other classes available to the class you are writing by putting something like this at the top of your source file:
import org.javaguy.coolframework.MyClass;
Or sometimes you 'bulk import' stuff by saying:
import org.javaguy.coolframework.*;
So later in your program when you say:
MyClass mine = new MyClass();
The Java Virtual Machine will know where to find your compiled class.
It would be impractical to have the VM look through every folder on your machine, so you have to provide the VM a list of places to look. This is done by putting folder and jar files on your classpath.
Before we talk about how the classpath is set, let's talk about .class files, packages, and .jar files.
First, let's suppose that MyClass is something you built as part of your project, and it is in a directory in your project called output. The .class file would be at output/org/javaguy/coolframework/MyClass.class (along with every other file in that package). In order to get to that file, your path would simply need to contain the folder 'output', not the whole package structure, since your import statement provides all that information to the VM.
Now let's suppose that you bundle CoolFramework up into a .jar file, and put that CoolFramework.jar into a lib directory in your project. You would now need to put lib/CoolFramework.jar into your classpath. The VM will look inside the jar file for the org/javaguy/coolframework part, and find your class.
So, classpaths contain:
JAR files, and
Paths to the top of package hierarchies.
How do you set your classpath?
The first way everyone seems to learn is with environment variables. On a unix machine, you can say something like:
export CLASSPATH=/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/
On a Windows machine you have to go to your environment settings and either add or modify the value that is already there.
The second way is to use the -cp parameter when starting Java, like this:
java -cp "/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/" MyMainClass
A variant of this is the third way which is often done with a .sh or .bat file that calculates the classpath and passes it to Java via the -cp parameter.
There is a "gotcha" with all of the above. On most systems (Linux, Mac OS, UNIX, etc) the colon character (':') is the classpath separator. In windowsm the separator is the semicolon (';')
So what's the best way to do it?
Setting stuff globally via environment variables is bad, generally for the same kinds of reasons that global variables are bad. You change the CLASSPATH environment variable so one program works, and you end up breaking another program.
The -cp is the way to go. I generally make sure my CLASSPATH environment variable is an empty string where I develop, whenever possible, so that I avoid global classpath issues (some tools aren't happy when the global classpath is empty though - I know of two common, mega-thousand dollar licensed J2EE and Java servers that have this kind of issue with their command-line tools).
Think of it as Java's answer to the PATH environment variable - OSes search for EXEs on the PATH, Java searches for classes and packages on the classpath.
The classpath is one of the fundamental concepts in the Java world and it's often misunderstood or not understood at all by java programmes, especially beginners.
Simply put, the classpath is just a set of paths where the java compiler and the JVM must find needed classes to compile or execute other classes.
Let's start with an example, suppose we have a Main.java file thats under C:\Users\HP\Desktop\org\example,
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
And Now, suppose we are under C:\ directory and we want to compile our class, Its easy right, just run:
javac .\Users\HP\Desktop\org\example\Main.java
Now for the hard question, we are in the same folder C:\ and we want to run the compiled class.
Despite of what you might think of to be the answer, the right one is:
java -cp .\Users\HP\Desktop org.example.Main
I'll explain why, first of all, the name of the class that we want ro tun is org.exmaple.Main not Main, or Main.class or .\users\hp\desktop\org\example\Main.class ! This is how things works with classes declared under packages.
Now, we provided the name of the class to the JVM (java command in this case), But how it (JVM) will know where to find the .class file for the Main class? Thats where the classpath comes into picture. Using -cp flag (shortcut for -classpath), we tell the JVM that our Main.class file will be located at C:\users\hp\Desktop.. In fact, not really, we tell it to just go to the Desktop directory, and, because of the name of the class org.example.Main, the JVM is smart and it will go from Desktop to org directory, and from org to example directory, searching for Main.class file, and it will find it and it will kill it, I mean, it will run it :D .
Now lets suppose that inside the Main class we want to work with another class named org.apache.commons.lang3.StringUtils and the latter is located in a jar file named commons-lang3-3.10.jar thats inside C:\Users\HP\Downloads. So Main.java will look like this now:
package org.example;
import org.apache.commons.lang3.StringUtils;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world");
System.out.println(StringUtils.equals("java", "java")); //true
}
}
How to compile the Main.java if we are always inside C:\ ? The answer is:
javac -cp .\Users\HP\Downloads\commons-lang3-3.10.jar .\Users\HP\Desktop\org\example\Main.java
.\Users\HP\Desktop\org\example\Main.java is because our .java file is there in the filesystem.
-cp .\Users\HP\Downloads\commons-lang3-3.10.jar is because the java compiler (javac in this case) need to know the location of the class org.apache.commons.lang3.StringUtils, so we provided the path of the jar file, and the compiler will then go inside the jar file and try to find a file StringUtils.class inside a directory org\apache\commons\lang3.
And if we want to run the Main.class file, we will execute:
java -cp ".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" org.example.Main
org.example.Main is the name of the class.
".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" are the paths (separated by ; in Windows) to the Main and StringUtils classes.
The classpath is the path where the Java Virtual Machine look for user-defined classes, packages and resources in Java programs.
In this context, the format() method load a template file from this path.
The classpath in this context is exactly what it is in the general context: anywhere the VM knows it can find classes to be loaded, and resources as well (such as output.vm in your case).
I'd understand Velocity expects to find a file named output.vm anywhere in "no package". This can be a JAR, regular folder, ... The root of any of the locations in the application's classpath.
Setting the CLASSPATH System Variable
To display the current CLASSPATH variable, use these commands in Windows and UNIX (Bourne shell):
In Windows: C:\> set CLASSPATH
In UNIX: % echo $CLASSPATH
To delete the current contents of the CLASSPATH variable, use these commands:
In Windows: C:\> set CLASSPATH=
In UNIX: % unset CLASSPATH; export CLASSPATH
To set the CLASSPATH variable, use these commands (for example):
In Windows: C:\> set CLASSPATH=C:\users\george\java\classes
In UNIX: % CLASSPATH=/home/george/java/classes; export CLASSPATH
Classpath is an environment variable of system. The setting of this variable is used to provide the root of any package hierarchy to java compiler.
CLASSPATH is an environment variable (i.e., global variables of the operating system available to all the processes) needed for the Java compiler and runtime to locate the Java packages used in a Java program. (Why not call PACKAGEPATH?) This is similar to another environment variable PATH, which is used by the CMD shell to find the executable programs.
CLASSPATH can be set in one of the following ways:
CLASSPATH can be set permanently in the environment: In Windows, choose control panel ⇒ System ⇒ Advanced ⇒ Environment Variables ⇒ choose "System Variables" (for all the users) or "User Variables" (only the currently login user) ⇒ choose "Edit" (if CLASSPATH already exists) or "New" ⇒ Enter "CLASSPATH" as the variable name ⇒ Enter the required directories and JAR files (separated by semicolons) as the value (e.g., ".;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar"). Take note that you need to include the current working directory (denoted by '.') in the CLASSPATH.
To check the current setting of the CLASSPATH, issue the following command:
> SET CLASSPATH
CLASSPATH can be set temporarily for that particular CMD shell session by issuing the following command:
> SET CLASSPATH=.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar
Instead of using the CLASSPATH environment variable, you can also use the command-line option -classpath or -cp of the javac and java commands, for example,
> java –classpath c:\javaproject\classes com.abc.project1.subproject2.MyClass3
For linux users, and to sum up and add to what others have said here, you should know the following:
$CLASSPATH is what Java uses to look through multiple directories to find all the different classes it needs for your script (unless you explicitly tell it otherwise with the -cp override). Using -cp requires that you keep track of all the directories manually and copy-paste that line every time you run the program (not preferable IMO).
The colon (":") character separates the different directories. There is only one $CLASSPATH and it has all the directories in it. So, when you run "export CLASSPATH=...." you want to include the current value "$CLASSPATH" in order to append to it. For example:
export CLASSPATH=.
export CLASSPATH=$CLASSPATH:/usr/share/java/mysql-connector-java-5.1.12.jar
In the first line above, you start CLASSPATH out with just a simple 'dot' which is the path to your current working directory. With that, whenever you run java it will look in the current working directory (the one you're in) for classes. In the second line above, $CLASSPATH grabs the value that you previously entered (.) and appends the path to a mysql dirver. Now, java will look for the driver AND for your classes.
echo $CLASSPATH
is super handy, and what it returns should read like a colon-separated list of all the directories, and .jar files, you want java looking in for the classes it needs.
Tomcat does not use CLASSPATH. Read what to do about that here: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
Static member of a class can be called directly without creating object instance.
Since the main method is static Java virtual Machine can call it without creating any instance of a class which contains the main method, which is start point of program.