Difference between revisions of "Compiling and Launching"

From Suhrid.net Wiki
Jump to navigationJump to search
 
(5 intermediate revisions by the same user not shown)
Line 70: Line 70:
 
* Exactly 1 class must be specified which has the main() method.
 
* Exactly 1 class must be specified which has the main() method.
 
* This class name has to be the fully qualified class name.
 
* This class name has to be the fully qualified class name.
 +
* If the directory containing top level package is present from where java is being executed, then cp is not mandatory.
 +
* However if cp is specified, the current directory is NOT included by default, it has to be made explicit.
 
* java [options] class-name [cmd-line arguments to the class]
 
* java [options] class-name [cmd-line arguments to the class]
  
Line 76: Line 78:
 
* If no args are passed, String[] args will be a zero-length array - it won't be null.
 
* If no args are passed, String[] args will be a zero-length array - it won't be null.
 
* The first-argument is args[0] and the fourth will be args[3]
 
* The first-argument is args[0] and the fourth will be args[3]
 +
* Anything in the command-line after the class-name is treated as an argument, space separated string should be double quoted
 +
** java net.suhrid.ClassA -ea -cp (-ea,-cp are treated as arguments and not as switches)
 +
** java net.suhrid.ClassA "Hello World" (Hello World is a single argument string)
 +
 +
* IMPORTANT : If a class does not have a main() method and is launched from the command-line, a NoSuchMethodError will be thrown!
 +
* However, since the class is loaded, all the static init blocks will be executed !
 +
* For the below class, with the invocation: java init.Init3, the following is the output:
 +
 +
<syntaxhighlight lang="java5">
 +
java init.Init3
 +
[1, 2, 3]
 +
Exception in thread "main" java.lang.NoSuchMethodError: main
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="java5">
 +
 +
package init;
 +
 +
import java.util.Arrays;
 +
 +
public class Init3 {
 +
 +
static int[] ia = {1,2,3};
 +
 +
static {
 +
System.out.println(Arrays.toString(ia));
 +
}
 +
 +
{
 +
int x  = 10;
 +
System.out.println("Inited x to 10");
 +
}
 +
}
 +
 +
</syntaxhighlight>
  
 
options
 
options
Line 106: Line 143:
 
* This does not extend to subpackages! for e.g it won't apply to java.util.regex. Import only applies to a single package.
 
* This does not extend to subpackages! for e.g it won't apply to java.util.regex. Import only applies to a single package.
 
* ambiguous imports and static imports (like using the same classname twice from different packages) will cause compiler errors.
 
* ambiguous imports and static imports (like using the same classname twice from different packages) will cause compiler errors.
* For some reason this works: import java.util.Collections.*; (Behaves the same as import java.util.Collections)
+
* To import inner classes, we can specify the name or a wildcard after the outer class name e.g. import java.util.Map.*;  
  
Static imports
+
=== Static imports ===
 
* Used to alias a class's static members (field's and methods)
 
* Used to alias a class's static members (field's and methods)
 
* Has to be "import static" only
 
* Has to be "import static" only
 +
* Can only be used to import a classes fields. '''Static import of only a CLASS IS ILLEGAL.'''
 +
* Enum constants can be static imported so that they can be used without type name.
 
* wildcards can be used
 
* wildcards can be used
 
* e.g.  
 
* e.g.  
Line 119: Line 158:
 
import static java.lang.Thread.MAX_PRIORITY;
 
import static java.lang.Thread.MAX_PRIORITY;
 
import static java.util.Collections.*;
 
import static java.util.Collections.*;
 +
//import static java.lang.System; //ILLEGAL
  
 
public class SITest {
 
public class SITest {

Latest revision as of 10:03, 13 September 2011

javac

  • javac by default places the generated class files in the same directory as the source files.
  • use the javac -d option to place the class files in some other directory.
  • if the directory does not exist, there will be an error.
  • the directories for the package structure will however be automatically created by javac.
  • javac does not need to be invoked in a package-aware manner for compiling classes (unlike java)
  • So a source file need not reside in a package specific location, unlike a .class file.
  • For e.g. if there is a net.suhrid.SomeClass - SomeClass.java can be located in any directory not mandatory to have a net/suhrid directory hierarhcy.
  • javac can also be invoked from any directory to compile a file. Of course it will generate the appropriate directories as per the package name for the .class file - because it matters.

There are four things to keep in mind while compiling:

  • Which are the files that need to be compiled ?
  • The directory where javac looks for other .java source files that are used by the file to be compiled.
  • The directory where javac looks for class files that are used by the file to be compiled.
  • The directory to place the generated class files in.

Options:

  • the -sourcepath is the directory where the compiler looks for other java files.
  • It has to be the directory that contains the hierarchy of the package structure of the source files.

for e.g. if we are compiling ClassB.java in directory src/net/suhrid/pkgB/ClassB.java which uses ClassA located in net/suhrid/pkgA/pkgA/ClassA.java then argument to sourcepath must be the "src" directory: javac -sourcepath src net/suhrid/pkgB/ClassB.java


  • this option will also compile the files which are referenced by the file being compiled.
  • -classpath and -cp can be either of the arguments to instruct the compiler to look for classes used by the compiled file.
  • Typically used for pre-compiled third party classes/libraries.
  • In case of directories, the directory which contains the hierarchy of the package structure of the class files. (similar to sourcepath). This is quirky and very important:

Assume this directory structure:

somedir
  |
  foo
   |
   bar
    | -- A.class
    | -- B.java

and the declarations:

package bar;
public class A;

package bar;
public class B;
  • When in bar directory, javac B.java will not work ! even with the classpath pointing to the current directory.
  • Why ? the classpath has to be the location containing the hierarchy of the package structure starting from bar (i.e. foo).

To compile B we can:

  1. change to foo directory and then use: javac bar/B.java (since default classpath points to . no need to use -classpath)
  2. from testdir : javac -classpath foo foo/bar/B.java
  • In case of jar files, the argument is the location of the jar file - including the jar file name. Here the jar file acts as the directory which contains the hierarchy of the package structure of the third party class files.
  • Note multiple directories can be specified in the -sourcepath and the -classpath options (separated by ":" in unix and ";" in Windows). Typically the sourcepath will be a single directory whereas the classpath will have multiples directories or jar files for various third party libraries.

java

  • Launches the JVM.
  • Exactly 1 class must be specified which has the main() method.
  • This class name has to be the fully qualified class name.
  • If the directory containing top level package is present from where java is being executed, then cp is not mandatory.
  • However if cp is specified, the current directory is NOT included by default, it has to be made explicit.
  • java [options] class-name [cmd-line arguments to the class]

cmd-line arguments

  • args are space separated.
  • If no args are passed, String[] args will be a zero-length array - it won't be null.
  • The first-argument is args[0] and the fourth will be args[3]
  • Anything in the command-line after the class-name is treated as an argument, space separated string should be double quoted
    • java net.suhrid.ClassA -ea -cp (-ea,-cp are treated as arguments and not as switches)
    • java net.suhrid.ClassA "Hello World" (Hello World is a single argument string)
  • IMPORTANT : If a class does not have a main() method and is launched from the command-line, a NoSuchMethodError will be thrown!
  • However, since the class is loaded, all the static init blocks will be executed !
  • For the below class, with the invocation: java init.Init3, the following is the output:
java init.Init3
[1, 2, 3]
Exception in thread "main" java.lang.NoSuchMethodError: main
package init;

import java.util.Arrays;

public class Init3 {
	
	static int[] ia = {1,2,3};
	
	static {
		System.out.println(Arrays.toString(ia));
	}
	
	{
		int x  = 10;
		System.out.println("Inited x to 10");
	}
}

options

  • -D is used to pass properties to the JVM which can be retrieved using System.getProperties().
  • e.g. java -Dname=suhrid someclass
  • There is no space between -D and the name=value pair!
  • -cp / -classpath : same as in javac.
  • Order of loading classes
  1. Bootstrap classes : Core classes
  2. Extensions in jre/lib/ext
  3. Defined classpath either through OS env variable or command line. Cmdline ovverrides OS classpath.
  • If no classpath is specified, the current directory (from which java is executed) is searched. If a classpath is specified, the current directory (if required) needs to be added explicitly to the classpath.
  • As soon as a class is found, jvm will stop searching for that class. So order of specifying is important.


  • Note: javac will compile a file even it is not located in the directory structure corresponding to its package.
  • java however expects the file to be located in the directory appropriate package.

jar

  • jar -cf <jartobecreated.jar> <dirname1-withclasses> <dirname2-withclasses>
  • jar is recursive when adding directories

imports

  • import is only an alias for a qualified class name. It's only purpose is to save typing and make code more readable.
  • import java.util.* will allow us to use HashMap without saying java.util.HashMap everytime
  • import java.util.* says use short name for all classes in java.util package ONLY.
  • This does not extend to subpackages! for e.g it won't apply to java.util.regex. Import only applies to a single package.
  • ambiguous imports and static imports (like using the same classname twice from different packages) will cause compiler errors.
  • To import inner classes, we can specify the name or a wildcard after the outer class name e.g. import java.util.Map.*;

Static imports

  • Used to alias a class's static members (field's and methods)
  • Has to be "import static" only
  • Can only be used to import a classes fields. Static import of only a CLASS IS ILLEGAL.
  • Enum constants can be static imported so that they can be used without type name.
  • wildcards can be used
  • e.g.
import java.util.*;

import static java.lang.System.out;
import static java.lang.Thread.MAX_PRIORITY;
import static java.util.Collections.*;
//import static java.lang.System; //ILLEGAL

public class SITest {
	
	public static void main(String[] args) {
		out.println("A thread's max priority is " + MAX_PRIORITY); //instead of System.out.println(Thread.MAX_PRIORITY);
		List<String> aList = new ArrayList<String>(); 
		sort(aList); //Instead of Collections.sort
		binarySearch(aList,"key"); //Instead of Collections.binarySearch
	}
	
}