Monday, March 9, 2009

Managing Source and Class Files  

0 comments

            Many implementations of the Java platform rely on hierarchical file systems to manage source and class files, although The Java Language Specification does not require this. The strategy is as follows. 

Put the source code for a class, interface, enumeration, or annotation type in a text file whose name is the simple name of the type and whose extension is .java. For example: 
              // in the Rectangle.java file 
              package graphics;
              public class Rectangle() {
               . . . 
              }

Then, put the source file in a directory whose name reflects the name of the package to which the type belongs:               .....\graphics\Rectangle.java

The qualified name of the package member and the path name to the file are parallel, assuming the Microsoft Windows file name separator backslash (for Unix, use the forward slash). class name graphics.Rectangle
pathname to file              graphics\Rectangle.java


As you should recall, by convention a company uses its reversed Internet domain name for its package names. The Example company, whose Internet domain name is example.com, would precede all its package names with com.example. Each component of the package name corresponds to a subdirectory. So, if the Example company had a com.example.graphics package that contained a Rectangle.java source file, it would be contained in a series of subdirectories like this:       ....\com\example\graphics\Rectangle.java

When you compile a source file, the compiler creates a different output file for each type defined in it. The base name of the output file is the name of the type, and its extension is .class. For example, if the source file is like this 
                   // in the Rectangle.java file
                   package com.example.graphics;
                   public class Rectangle{
                    . . . 
                   }

                  class Helper{
                   . . . 
                  }

then the compiled files will be located at: 
\com\example\graphics\Rectangle.class
\com\example\graphics\Helper.class

Like the .java source files, the compiled .class files should be in a series of directories that reflect the package name. However, the path to the .class files does not have to be the same as the path to the .java source files. You can arrange your source and class directories separately, as: 
\sources\com\example\graphics\Rectangle.java

\classes\com\example\graphics\Rectangle.class
By doing this, you can give the classes directory to other programmers without revealing your sources. You also need to manage source and class files in this manner so that the compiler and the Java Virtual Machine (JVM) can find all the types your program uses. 

The full path to the classes directory, \classes, is called the class path, and is set with the CLASSPATH system variable. Both the compiler and the JVM construct the path to your .class files by adding the package name to the class path. For example, if 
\classes
is your class path, and the package name is 
com.example.graphics,

then the compiler and JVM look for .class files in 

\classes\com\example\graphics.

A class path may include several paths, separated by a semicolon (Windows) or colon (Unix). By default, the compiler and the JVM search the current directory and the JAR file containing the Java platform classes so that these directories are automatically in your class path.

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

Using Package Members  

0 comments

To use a public package member from outside its package, you must do one of the following: 

  • Refer to the member by its fully qualified name 
  • Import the package member 
  • Import the member's entire package 

Each is appropriate for different situations, as explained in the sections that follow.

So far, most of the examples in this tutorial have referred to types by their simple names, such as Rectangle and StackOfInts. You can use a package member's simple name if the code you are writing is in the same package as that member or if that member has been imported. 

However, if you are trying to use a member from a different package and that package has not been imported, you must use the member's fully qualified name, which includes the package name. Here is the fully qualified name for the Rectangle class declared in the graphics package in the previous example. 


                              graphics.Rectangle

Importing a Package Member

Here's how you would import the Rectangle class from the graphics package created in the previous section.

                 import graphics.Rectangle;

Importing an Entire Package

To import all the types contained in a particular package, use the import statement with the asterisk (*) wildcard character. 

                              import graphics.*;






Creating a Package  

0 comments

             To create a package, you choose a name for the package (naming conventions are discussed in the next section) and put a package statement with that name at the top of every source file that contains the types (classes, interfaces, enumerations, and annotation types) that you want to include in the package. 

The package statement (for example, package graphics;) must be the first line in the source file. There can be only one package statement in each source file, and it applies to all types in the file.

// only comment can be here
package world;  // package creation

public class HelloWorld {
  public static void main(String[] args) {
  System.out.println("Hello World");
  }
}

                   If you do not use a package statement, your type ends up in an unnamed package. Generally speaking, an unnamed package is only for small or temporary applications or when you are just beginning the development process. Otherwise, classes and interfaces belong in named packages.

Type Erasure  

0 comments

                     When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

public class MyClass {
  public static void myMethod(Object item) {
  if (item instanceof E) { //Compiler error
  ...
  }
  E item2 = new E(); //Compiler error
  E[] iArray = new E[10]; //Compiler error
  E obj = (E)new Object(); //Unchecked cast warning
  }
}
--------------------------------------------------

public class WarningDemo {
  public static void main(String[] args){
  Box bi;
  bi = createBox();
  }

  static Box createBox(){
  return new Box();
  }
}
Recompiling with -Xlint:unchecked reveals the following additional information: 
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box
  bi = createBox();
  ^
1 warning

Wildcards  

0 comments

               

               In generics, an unknown type is represented by the wildcard character "?".

                           Cage someCage = ...;
                       Read "? extends Animal" as "an unknown type that is a subtype of Animal, possibly Animal itself", which boils down to "some kind of animal". This is an example of a bounded wildcard, where Animal forms the upper bound of the expected type. If you're asked for a cage that simply holds some kind of animal, you're free to provide a lion cage or a butterfly cage.

                        It's also possible to specify a lower bound by using the super keyword instead of extends. The code , therefore, would be read as "an unknown type that is a supertype of Animal, possibly Animal itself". You can also specify an unknown type with an unbounded wilcard, which simply looks like . An unbounded wildcard is essentially the same as saying .

                        you could house your animals in their individual cages, as shown earlier, and invoke this method first for the lions and then for the butterflies: 
 feedAnimals(lionCage);
 feedAnimals(butterflyCage);
Or, you could choose to combine your animals in the all-animal cage instead: 
 feedAnimals(animalCage);

Subtyping  

0 comments

you can assign an Integer to an Object, since Object is one of Integer's supertypes: 
  Object someObject = new Object();
  Integer someInteger = new Integer(10);
  someObject = someInteger; // OK
In object-oriented terminology, this is called an "is a" relationship. Since an Integer is a kind of Object, the assignment is allowed. But Integer is also a kind of Number, so the following code is valid as well: 
  public void someMethod(Number n){
  // method body omitted 
  }

  someMethod(new Integer(10)); // OK
  someMethod(new Double(10.1)); // OK

Bounded Type Parameters  

0 comments

There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for. 

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number. Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces). 

/**
 * This version introduces a bounded type parameter.
 */
public class Box {

  private T t;  

  public void add(T t) {
  this.t = t;
  }

  public T get() {
  return t;
  }

  public void inspect(U u){
  System.out.println("T: " + t.getClass().getName());
  System.out.println("U: " + u.getClass().getName());
  }

  public static void main(String[] args) {
  Box integerBox = new Box();
  integerBox.add(new Integer(10));
  integerBox.inspect("some text"); // error: this is still String! 
  }
}
By modifying our generic method to include this bounded type parameter, compilation will now fail, since our invocation of inspect still includes a String: 
Box.java:21: inspect(U) in Box cannot
  be applied to (java.lang.String)
  integerBox.inspect("10");
  ^
1 error

To specify additional interfaces that must be implemented, use the & character, as in: 

Generic Methods and Constructors  

0 comments

                

Type parameters can also be declared within method and constructor signatures to create generic methods and generic constructors. This is similar to declaring a generic type, but the type parameter's scope is limited to the method or constructor in which it's declared. 

/**
 * This version introduces a generic method.
 */
public class Box {

  private T t;  

  public void add(T t) {
  this.t = t;
  }

  public T get() {
  return t;
  }

  public void inspect(U u){
  System.out.println("T: " + t.getClass().getName());
  System.out.println("U: " + u.getClass().getName());
  }

  public static void main(String[] args) {
  Box integerBox = new Box();
  integerBox.add(new Integer(10));
  integerBox.inspect("some text");
  }
}
Here we've added one generic method, named inspect, that defines one type parameter, named U. This method accepts an object and prints its type to standard output. For comparison, it also prints out the type of T. For convenience, this class now also has a main method so that it can be run as an application. 

The output from this program is: 
T: java.lang.Integer
U: java.lang.String
         

Type Parameter Naming Conventions  

0 comments

By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name. 

The most commonly used type parameter names are: 
E - Element (used extensively by the Java Collections Framework) 
K - Key 
N - Number 
T - Type 
V - Value 
S,U,V etc. - 2nd, 3rd, 4th types 
You'll see these names used throughout the Java SE API and the rest of this tutorial.

Generic Types  

0 comments

Generic Types:                 

    Just we update our Box class to use generics. We'll first create a generic type declaration by changing the code "public class Box" to "public class Box"; this introduces one type variable, named T, that can be used anywhere inside the class. This same technique can be applied to interfaces as well. There's nothing particularly complex about this concept. In fact, it's quite similar to what you already know about variables in general. Just think of T as a special kind of variable, whose "value" will be whatever type you pass in; this can be any class type, any interface type, or even another type variable. It just can't be any of the primitive data types. In this context, we also say that T is a formal type parameter of the Box class. 

/**
 * Generic version of the Box class. 
 */
public class Box {

  private T t; // T stands for "Type"  

  public void add(T t) {
  this.t = t;
  }

  public T get() {
  return t;
  }
}

As you can see, we've replaced all occurrences of Object with T. To reference this generic class from within your own code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:

generics introduction  

0 comments

Generics:                   

   Generics add stability to your code by making more of your bugs detectable at compile time. Some programmers choose to learn generics by studying the Java Collections Framework; after all, generics are heavily used by those classes. However, since we haven't yet covered collections, this chapter will focus primarily on simple "collections-like" examples that we'll design from scratch. This hands-on approach will teach you the necessary syntax and terminology while demonstrating the various kinds of problems that generics were designed to solve. 

A Simple Class

                       Box class need only provide two methods: add, which adds an object to the box, and get, which retrieves it:

 public class Box {

  private Object object;

  public void add(Object object) {
  this.object = object;
  }

  public Object get() {
  return object;
  }
  }

 

public class BoxDemo1 {

  public static void main(String[] args) {

  // ONLY place Integer objects into this box!
  Box integerBox = new Box();

  integerBox.add(new Integer(10));
  Integer someInteger = (Integer)integerBox.get();
  System.out.println(someInteger);
  }
}
The BoxDemo1 program creates an Integer object, passes it to add, then assigns that same object to someInteger by the return value of get. It then prints the object's value (10) to standard output. We know that the cast from Object to Integer is correct because we've honored the "contract" specified in the comment. But remember, the compiler knows nothing about this — it just trusts that our cast is correct. Furthermore, it will do nothing to prevent a careless programmer from passing in an object of the wrong type, such as String: 

public class BoxDemo2 {

  public static void main(String[] args) {

  // ONLY place Integer objects into this box!
  Box integerBox = new Box();

  // Imagine this is one part of a large application
  // modified by one programmer. 
  integerBox.add("10"); // note how the type is now String

  // ... and this is another, perhaps written
  // by a different programmer
  Integer someInteger = (Integer)integerBox.get();
  System.out.println(someInteger);
  }
}

Extension Factory Builder