google search

Custom Search

Friday, August 8, 2008

Servlet

Main article: Java Servlet

Java Servlet technology provides Web developers with a simple, consistent mechanism for extending the functionality of a Web server and for accessing existing business systems. Servlets are server-side Java EE components that generate responses (typically HTML pages) to requests (typically HTTP requests) from clients. A servlet can almost be thought of as an applet that runs on the server side—without a face.

// Hello.java
import java.io.*;
import javax.servlet.*;

public class Hello extends GenericServlet {
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
final PrintWriter pw = response.getWriter();
pw.println("Hello, world!");
pw.close();
}
}

The import statements direct the Java compiler to include all of the public classes and interfaces from the java.io and javax.servlet packages in the compilation.

The Hello class extends the GenericServlet class; the GenericServlet class provides the interface for the server to forward requests to the servlet and control the servlet's lifecycle.

The Hello class overrides the service(ServletRequest, ServletResponse) method defined by the Servlet interface to provide the code for the service request handler. The service() method is passed a ServletRequest object that contains the request from the client and a ServletResponse object used to create the response returned to the client. The service() method declares that it throws the exceptions ServletException and IOException if a problem prevents it from responding to the request.

The setContentType(String) method in the response object is called to set the MIME content type of the returned data to "text/html". The getWriter() method in the response returns a PrintWriter object that is used to write the data that is sent to the client. The println(String) method is called to write the "Hello, world!" string to the response and then the close() method is called to close the print writer, which causes the data that has been written to the stream to be returned to the client.

[edit] JavaServer Page

Main article: JavaServer Pages

JavaServer Pages (JSPs) are server-side Java EE components that generate responses, typically HTML pages, to HTTP requests from clients. JSPs embed Java code in an HTML page by using the special delimiters <% and %>. A JSP is compiled to a Java servlet, a Java application in its own right, the first time it is accessed. After that, the generated servlet creates the response.

[edit] Swing application

Main article: Swing (Java)

Swing is a graphical user interface library for the Java SE platform. This example Swing application creates a single window with "Hello, world!" inside:

// Hello.java (Java SE 5)
import java.awt.BorderLayout;
import javax.swing.*;

public class Hello extends JFrame {
public Hello() {
super("hello");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(new JLabel("Hello, world!"));
pack();
}

public static void main(String[] args) {
new Hello().setVisible(true);
}
}

The first import statement directs the Java compiler to include the BorderLayout class from the java.awt package in the compilation; the second import includes all of the public classes and interfaces from the javax.swing package.

The Hello class extends the JFrame class; the JFrame class implements a window with a title bar and a close control.

The Hello() constructor initializes the frame by first calling the superclass constructor, passing the parameter "hello", which is used as the window's title. It then calls the setDefaultCloseOperation(int) method inherited from JFrame to set the default operation when the close control on the title bar is selected to WindowConstants.EXIT_ON_CLOSE — this causes the JFrame to be disposed of when the frame is closed (as opposed to merely hidden), which allows the JVM to exit and the program to terminate. Next, the layout of the frame is set to a BorderLayout; this tells Swing how to arrange the components that will be added to the frame. A JLabel is created for the string "Hello, world!" and the add(Component) method inherited from the Container superclass is called to add the label to the frame. The pack() method inherited from the Window superclass is called to size the window and lay out its contents, in the manner indicated by the BorderLayout.

The main() method is called by the JVM when the program starts. It instantiates a new Hello frame and causes it to be displayed by calling the setVisible(boolean) method inherited from the Component superclass with the boolean parameter true. Note that once the frame is displayed, exiting the main method does not cause the program to terminate because the AWT event dispatching thread remains active until all of the Swing top-level windows have been disposed.

[edit] Generics

See also: Generics in Java

[edit] Criticism
It has been suggested that some of the information in this article's Criticism or Controversy section(s) be merged into other sections to achieve a more neutral presentation. (Discuss)

Main article: Criticism of Java

Java's performance has improved substantially since the early versions, and performance of JIT compilers relative to native compilers has in some tests been shown to be quite similar.[18][19][20] The performance of the compilers does not necessarily indicate the performance of the compiled code; only careful testing can reveal the true performance issues in any system.

The default look and feel of GUI applications written in Java using the Swing toolkit is very different from native applications. It is possible to specify a different look and feel through the pluggable look and feel system of Swing. Clones of Windows, GTK and Motif are supplied by Sun. Apple also provides an Aqua look and feel for Mac OS X. Though prior implementations of these looks and feels have been considered lacking,[citation needed] Swing in Java SE 6 addresses this problem by using more native widget drawing routines of the underlying platforms. Alternatively, third party toolkits such as wx4j, Qt Jambi or SWT may be used for increased integration with the native windowing system.

As in C++ and some other object-oriented languages, variables of Java's primitive types were not originally objects. Values of primitive types are either stored directly in fields (for objects) or on the stack (for methods) rather than on the heap, as is the common case for objects (but see Escape analysis). This was a conscious decision by Java's designers for performance reasons. Because of this, Java was not considered to be a pure object-oriented programming language. However, as of Java 5.0, autoboxing enables programmers to write as if primitive types are their wrapper classes, with their object-oriented counterparts representing classes of their own, and freely interchange between them for improved flexibility.

Java suppresses several features (such as operator overloading and multiple inheritance) for classes in order to simplify the language, to "save the programmers from themselves", and to prevent possible errors and anti-pattern design. This has been a source of criticism,[citation needed] relating to a lack of low-level features, but some of these limitations may be worked around. Java interfaces have always had multiple inheritance.

[edit] Target

Main article: Java Runtime Environment

The Java Runtime Environment, or JRE, is the software required to run any application deployed on the Java Platform. End-users commonly use a JRE in software packages and Web browser plugins. Sun also distributes a superset of the JRE called the Java 2 SDK (more commonly known as the JDK), which includes development tools such as the Java compiler, Javadoc, Jar and debugger.

One of the unique advantages of the concept of a runtime engine is that errors (exceptions) should not 'crash' the system. Moreover, in runtime engine environments such as Java there exist tools that attach to the runtime engine and every time that an exception of interest occurs they record debugging information that existed in memory at the time the exception was thrown (stack and heap values). These Automated Exception Handling tools provide 'root-cause' information for exceptions in Java programs that run in production, testing or development environments.

[edit] Class libraries

* Java libraries are the compiled byte codes of source code developed by the JRE implementor to support application development in Java. Examples of these libraries are:
o The core libraries, which include:
+ Collection libraries that implement data structures such as lists, dictionaries, trees and sets
+ XML Processing (Parsing, Transforming, Validating) libraries
+ Security
+ Internationalization and localization libraries
o The integration libraries, which allow the application writer to communicate with external systems. These libraries include:
+ The Java Database Connectivity (JDBC) API for database access
+ Java Naming and Directory Interface (JNDI) for lookup and discovery
+ RMI and CORBA for distributed application development
o User Interface libraries, which include:
+ The (lightweight, or native) Abstract Windowing Toolkit (AWT), which provides GUI components, the means for laying out those components and the means for handling events from those components
+ The (heavyweight) Swing libraries, which are built on AWT but provide (non-native) implementations of the AWT widgetry
+ APIs for audio capture, processing, and playback
* A platform dependent implementation of Java virtual machine (JVM) that is the means by which the byte codes of the Java libraries and third party applications are executed
* Plugins, which enable applets to be run in Web browsers
* Java Web Start, which allows Java applications to be efficiently distributed to end users across the Internet
* Licensing and documentation

[edit] APIs

See also: Free Java implementations#Class library

Sun has defined three platforms targeting different application environments and segmented many of its APIs so that they belong to one of the platforms. The platforms are:

* Java Platform, Micro Edition (Java ME) — targeting environments with limited resources,
* Java Platform, Standard Edition (Java SE) — targeting workstation environments, and
* Java Platform, Enterprise Edition (Java EE) — targeting large distributed enterprise or Internet environments.

The classes in the Java APIs are organized into separate groups called packages. Each package contains a set of related interfaces, classes and exceptions. Refer to the separate platforms for a description of the packages available.

The set of APIs is controlled by Sun Microsystems in cooperation with others through the Java Community Process program. Companies or individuals participating in this process can influence the design and development of the APIs. This process has been a subject of controversy.

Applet

Main article: Java applet

Java applets are programs that are embedded in other applications, typically in a Web page displayed in a Web browser.

// Hello.java
import java.applet.Applet;
import java.awt.Graphics;

public class Hello extends Applet {
public void paint(Graphics gc) {
gc.drawString("Hello, world!", 65, 95);
}
}

The import statements direct the Java compiler to include the java.applet.Applet and java.awt.Graphics classes in the compilation. The import statement allows these classes to be referenced in the source code using the simple class name (i.e. Applet) instead of the fully qualified class name (i.e. java.applet.Applet).

The Hello class extends (subclasses) the Applet class; the Applet class provides the framework for the host application to display and control the lifecycle of the applet. The Applet class is an Abstract Windowing Toolkit (AWT) Component, which provides the applet with the capability to display a graphical user interface (GUI) and respond to user events.

The Hello class overrides the paint(Graphics) method inherited from the Container superclass to provide the code to display the applet. The paint() method is passed a Graphics object that contains the graphic context used to display the applet. The paint() method calls the graphic context drawString(String, int, int) method to display the "Hello, world!" string at a pixel offset of (65, 95) from the upper-left corner in the applet's display.




Hello World Applet







An applet is placed in an HTML document using the HTML element. The applet tag has three attributes set: code="Hello" specifies the name of the Applet class and width="200" height="200" sets the pixel width and height of the applet. Applets may also be embedded in HTML using either the object or embed element[16], although support for these elements by Web browsers is inconsistent.[17] However, the applet tag is deprecated, so the object tag is preferred where supported.

The host application, typically a Web browser, instantiates the Hello applet and creates an AppletContext for the applet. Once the applet has initialized itself, it is added to the AWT display hierarchy. The paint method is called by the AWT event dispatching thread whenever the display needs the applet to draw itself.

A more comprehensive example

// OddEven.java
import javax.swing.JOptionPane;

public class OddEven {
public static void main(String[] args) {
// This is the main method. It gets called when this class is run through a Java interpreter.
OddEven number = new OddEven();
/* This line of code creates a new instance of this class called "number" and
* initializes it, and the next line of code calls the "showDialog()" method,
* which brings up a prompt to ask you for a number
*/
number.showDialog();
}
private int input; // A whole number("int" means integer)
// "input" is the number that the user gives to the computer

public OddEven() {
/* This is the constructor method. It gets called when an object of the OddEven type
* is created.
*/
}

public void showDialog() {
try
/* This makes sure nothing goes wrong. If something does,
* the interpreter skips to "catch" to see what it should do.
*/
{
input = Integer.parseInt(JOptionPane.showInputDialog("Please Enter A Number"));
calculate();
/*
* The code above brings up a JOptionPane, which is a dialog box
* The String returned by the "showInputDialog()" method is converted into
* an integer, making the program treat it as a number instead of a word.
* After that, this method calls a second method, calculate() that will
* display either "Even" or "Odd."
*/
}
catch (NumberFormatException e)
/* This means that there was a problem with the format of the number
* (Like if someone were to type in 'Hello world' instead of a number).
*/
{
System.err.println("ERROR: Invalid input. Please type in a numerical value.");
}
}

private void calculate() {
if (input % 2 == 0)
System.out.println("Even");
/* When this gets called, it sends a message to the interpreter.
* The interpreter usually shows it on the command prompt (For Windows users)
* or the terminal (For Linux users).(Assuming it's open)
*/
else
System.out.println("Odd");
}
}

* The import statement imports the JOptionPane class from the javax.swing package.
* The OddEven class declares a single private field of type int named input. Every instance of the OddEven class has its own copy of the input field. The private declaration means that no other class can access (read or write) the input field.
* OddEven() is a public constructor. Constructors have the same name as the enclosing class they are declared in, and unlike a method, have no return type. A constructor is used to initialize an object that is a newly created instance of the class. The dialog returns a String that is converted to an int by the Integer.parseInt(String) method.
* The calculate() method is declared without the static keyword. This means that the method is invoked using a specific instance of the OddEven class. (The reference used to invoke the method is passed as an undeclared parameter of type OddEven named this.) The method tests the expression input % 2 == 0 using the if keyword to see if the remainder of dividing the input field belonging to the instance of the class by two is zero. If this expression is true, then it prints Even; if this expression is false it prints Odd. (The input field can be equivalently accessed as this.input, which explicitly uses the undeclared this parameter.)
* OddEven number = new OddEven(); declares a local object reference variable in the main method named number. This variable can hold a reference to an object of type OddEven. The declaration initializes number by first creating an instance of the OddEven class, using the new keyword and the OddEven() constructor, and then assigning this instance to the variable.
* The statement number.showDialog(); calls the calculate method. The instance of OddEven object referenced by the number local variable is used to invoke the method and passed as the undeclared this parameter to the calculate method.
* For simplicity, error handling has been ignored in this example. Entering a value that is not a number will cause the program to crash. This can be avoided by catching and handling the NumberFormatException thrown by Integer.parseInt(String).

Syntax: Hello world program

Main article: Java syntax

The syntax of Java is largely derived from C++. Unlike C++, which combines the syntax for structured, generic, and object-oriented programming, Java was built exclusively as an object oriented language. As a result, almost everything is an object and all code is written inside a class. The exceptions are the intrinsic data types (ordinal and real numbers, boolean values, and characters), which are not classes for performance reasons.

[edit] Hello world program

This is a minimal Hello world program in Java with syntax highlighting:

// HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}

To execute a Java program, the code is saved as a file named HelloWorld.java. It must first be compiled into bytecode using a Java compiler, which produces a file named HelloWorld.class. This class is then launched.

The above example merits a bit of explanation.

* All executable statements in Java are written inside a class, including stand-alone programs.
* Source files are by convention named the same as the class they contain, appending the mandatory suffix .java. A class that is declared public is required to follow this convention. (In this case, the class HelloWorld is public, therefore the source must be stored in a file called HelloWorld.java).
* The compiler will generate a class file for each class defined in the source file. The name of the class file is the name of the class, with .class appended. For class file generation, anonymous classes are treated as if their name was the concatenation of the name of their enclosing class, a $, and an integer.
* The keyword public denotes that a method can be called from code in other classes, or that a class may be used by classes outside the class hierarchy.
* The keyword static indicates that the method is a static method, associated with the class rather than object instances.
* The keyword void indicates that the main method does not return any value to the caller.
* The method name "main" is not a keyword in the Java language. It is simply the name of the method the Java launcher calls to pass control to the program. Java classes that run in managed environments such as applets and Enterprise Java Beans do not use or need a main() method.
* The main method must accept an array of String objects. By convention, it is referenced as args although any other legal identifier name can be used. Since Java 5, the main method can also use variable arguments, in the form of public static void main(String... args), allowing the main method to be invoked with an arbitrary number of String arguments. The effect of this alternate declaration is semantically identical (the args parameter is still an array of String objects), but allows an alternate syntax for creating and passing the array.
* The Java launcher launches Java by loading a given class (specified on the command line) and starting its public static void main(String[]) method. Stand-alone programs must declare this method explicitly. The String[] args parameter is an array of String objects containing any arguments passed to the class. The parameters to main are often passed by means of a command line.
* The printing facility is part of the Java standard library: The System class defines a public static field called out. The out object is an instance of the PrintStream class and provides the method println(String) for displaying data to the screen while creating a new line (standard out).

Java (programming language)

Java is a programming language originally developed by Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities. Java applications are typically compiled to bytecode that can run on any Java virtual machine (JVM) regardless of computer architecture.

The original and reference implementation Java compilers, virtual machines, and class libraries were developed by Sun from 1995. As of May 2007, in compliance with the specifications of the Java Community Process, Sun made available most of their Java technologies as free software under the GNU General Public License. Others have also developed alternative implementations of these Sun technologies, such as the GNU Compiler for Java and GNU Classpath.
History
Duke, the Java mascot
Duke, the Java mascot

Main articles: Java (Sun)#History and Java version history

The Java language was created by James Gosling in June 1991 for use in one of his many set-top box projects.[4] The language was initially called Oak, after an oak tree that stood outside Gosling's office—and also went by the name Green—and ended up later being renamed to Java, from a list of random words.[5] Gosling's goals were to implement a virtual machine and a language that had a familiar C/C++ style of notation.[6] The first public implementation was Java 1.0 in 1995. It promised "Write Once, Run Anywhere" (WORA), providing no-cost runtimes on popular platforms. It was fairly secure and its security was configurable, allowing network and file access to be restricted. Major web browsers soon incorporated the ability to run secure Java applets within web pages. Java quickly became popular. With the advent of Java 2, new versions had multiple configurations built for different types of platforms. For example, J2EE was for enterprise applications and the greatly stripped down version J2ME was for mobile applications. J2SE was the designation for the Standard Edition. In 2006, for marketing purposes, new J2 versions were renamed Java EE, Java ME, and Java SE, respectively.

In 1997, Sun Microsystems approached the ISO/IEC JTC1 standards body and later the Ecma International to formalize Java, but it soon withdrew from the process.[7][8][9] Java remains a de facto standard that is controlled through the Java Community Process.[10] At one time, Sun made most of its Java implementations available without charge although they were proprietary software. Sun's revenue from Java was generated by the selling of licenses for specialized products such as the Java Enterprise System. Sun distinguishes between its Software Development Kit (SDK) and Runtime Environment (JRE) that is a subset of the SDK, the primary distinction being that in the JRE, the compiler, utility programs, and many necessary header files are not present.

On 13 November 2006, Sun released much of Java as free and open source software under the terms of the GNU General Public License (GPL). On 8 May 2007 Sun finished the process, making all of Java's core code free and open-source, aside from a small portion of code to which Sun did not hold the copyright.[11]

[edit] Philosophy

[edit] Primary goals

There were five primary goals in the creation of the Java language:[12]

1. It should use the object-oriented programming methodology.
2. It should allow the same program to be executed on multiple operating systems.
3. It should contain built-in support for using computer networks.
4. It should be designed to execute code from remote sources securely.
5. It should be easy to use by selecting what were considered the good parts of other object-oriented languages.

[edit] Platform independence

Main article: Java Platform

One characteristic, platform independence, means that programs written in the Java language must run similarly on any supported hardware/operating-system platform. One should be able to write a program once, compile it once, and run it anywhere.

This is achieved by most Java compilers by compiling the Java language code halfway (to Java bytecode) – simplified machine instructions specific to the Java platform. The code is then run on a virtual machine (VM), a program written in native code on the host hardware that interprets and executes generic Java bytecode. (In some JVM versions, bytecode can also be compiled to native code, either before or during program execution, resulting in faster execution.) Further, standardized libraries are provided to allow access to features of the host machines (such as graphics, threading and networking) in unified ways. Note that, although there is an explicit compiling stage, at some point, the Java bytecode is interpreted or converted to native machine code by the JIT compiler.

The first implementations of the language used an interpreted virtual machine to achieve portability. These implementations produced programs that ran slower than programs compiled to native executables, for instance written in C or C++, so the language suffered a reputation for poor performance. More recent JVM implementations produce programs that run significantly faster than before, using multiple techniques.

One technique, known as just-in-time compilation (JIT), translates the Java bytecode into native code at the time that the program is run, which results in a program that executes faster than interpreted code but also incurs compilation overhead during execution. More sophisticated VMs use dynamic recompilation, in which the VM can analyze the behavior of the running program and selectively recompile and optimize critical parts of the program. Dynamic recompilation can achieve optimizations superior to static compilation because the dynamic compiler can base optimizations on knowledge about the runtime environment and the set of loaded classes, and can identify the hot spots (parts of the program, often inner loops, that take up the most execution time). JIT compilation and dynamic recompilation allow Java programs to take advantage of the speed of native code without losing portability.

Another technique, commonly known as static compilation, is to compile directly into native code like a more traditional compiler. Static Java compilers, such as GCJ, translate the Java language code to native object code, removing the intermediate bytecode stage. This achieves good performance compared to interpretation, but at the expense of portability; the output of these compilers can only be run on a single architecture. Some see avoiding the VM in this manner as defeating the point of developing in Java; however it can be useful to provide both a generic bytecode version, as well as an optimized native code version of an application.

[edit] Implementations

Sun Microsystems officially licenses the Java Standard Edition platform for Microsoft Windows, Linux, and Solaris. Through a network of third-party vendors and licensees[13], alternative Java environments are available for these and other platforms. To qualify as a certified Java licensee, an implementation on any particular platform must pass a rigorous suite of validation and compatibility tests. This method enables a guaranteed level of compliance and platform through a trusted set of commercial and non-commercial partners.

Sun's trademark license for usage of the Java brand insists that all implementations be "compatible". This resulted in a legal dispute with Microsoft after Sun claimed that the Microsoft implementation did not support the RMI and JNI interfaces and had added platform-specific features of their own. Sun sued in 1997, and in 2001 won a settlement of $20 million as well as a court order enforcing the terms of the license from Sun.[14] As a result, Microsoft no longer ships Java with Windows, and in recent versions of Windows, Internet Explorer cannot support Java applets without a third-party plugin. However, Sun and others have made available Java run-time systems at no cost for those and other versions of Windows.

Platform-independent Java is essential to the Java Enterprise Edition strategy, and an even more rigorous validation is required to certify an implementation. This environment enables portable server-side applications, such as Web services, servlets, and Enterprise JavaBeans, as well as with Embedded systems based on OSGi, using Embedded Java environments. Through the new GlassFish project, Sun is working to create a fully functional, unified open-source implementation of the Java EE technologies.

[edit] Automatic memory management

See also: Garbage collection (computer science)

One of the ideas behind Java's automatic memory management model is that programmers be spared the burden of having to perform manual memory management. In some languages the programmer allocates memory for the creation of objects stored on the heap and the responsibility of later deallocating that memory also resides with the programmer. If the programmer forgets to deallocate memory or writes code that fails to do so, a memory leak occurs and the program can consume an arbitrarily large amount of memory. Additionally, if the program attempts to deallocate the region of memory more than once, the result is undefined and the program may become unstable and may crash. Finally, in non garbage collected environments, there is a certain degree of overhead and complexity of user-code to track and finalize allocations. Often developers may box themselves into certain designs to provide reasonable assurances that memory leaks will not occur.[15]

In Java, this potential problem is avoided by automatic garbage collection. The programmer determines when objects are created, and the Java runtime is responsible for managing the object's lifecycle. The program or other objects can reference an object by holding a reference to it (which, from a low-level point of view, is its address on the heap). When no references to an object remain, the unreachable object is eligible for release by the Java garbage collector - it may be freed automatically by the garbage collector at any time. Memory leaks may still occur if a programmer's code holds a reference to an object that is no longer needed—in other words, they can still occur but at higher conceptual levels.

The use of garbage collection in a language can also affect programming paradigms. If, for example, the developer assumes that the cost of memory allocation/recollection is low, they may choose to more freely construct objects instead of pre-initializing, holding and reusing them. With the small cost of potential performance penalties (inner-loop construction of large/complex objects), this facilitates thread-isolation (no need to synchronize as different threads work on different object instances) and data-hiding. The use of transient immutable value-objects minimizes side-effect programming.

Comparing Java and C++, it is possible in C++ to implement similar functionality (for example, a memory management model for specific classes can be designed in C++ to improve speed and lower memory fragmentation considerably), with the possible cost of adding comparable runtime overhead to that of Java's garbage collector, and of added development time and application complexity if one favors manual implementation over using an existing third-party library. In Java, garbage collection is built-in and virtually invisible to the developer. That is, developers may have no notion of when garbage collection will take place as it may not necessarily correlate with any actions being explicitly performed by the code they write. Depending on intended application, this can be beneficial or disadvantageous: the programmer is freed from performing low-level tasks, but at the same time loses the option of writing lower level code. Additionally, the garbage collection capability demands some attention to tuning the JVM, as large heaps will cause apparently random stalls in performance.

Java does not support pointer arithmetic as is supported in, for example, C++. This is because the garbage collector may relocate referenced objects, invalidating such pointers. Another reason that Java forbids this is that type safety and security can no longer be guaranteed if arbitrary manipulation of pointers is allowed.

Summary of Creating and Using Packages and Questions and Exercises: Creating and Using Packages

To create a package for a type, put a package statement as the first statement in the source file that contains the type (class, interface, enumeration, or annotation type).

To use a public type that's in a different package, you have three choices: (1) use the fully qualified name of the type, (2) import the type, or (3) import the entire package of which the type is a member.

The path names for a package's source and class files mirror the name of the package.

You might have to set your CLASSPATH so that the compiler and the JVM can find the .class files for your types.
Questions

Assume you have written some classes. Belatedly, you decide they should be split into three packages, as listed in the following table. Furthermore, assume the classes are currently in the default package (they have no package statements).

Destination Packages

Package Name


Class Name

mygame.server


Server

mygame.shared


Utilities

mygame.client


Client

1. Which line of code will you need to add to each source file to put each class in the right package?

2. To adhere to the directory structure, you will need to create some subdirectories in the development directory and put source files in the correct subdirectories. What subdirectories must you create? Which subdirectory does each source file go in?

3. Do you think you'll need to make any other changes to the source files to make them compile correctly? If so, what?

Exercises

Download the source files as listed here.

* Client
* Server
* Utilities

1. Implement the changes you proposed in questions 1 through 3 using the source files you just downloaded.

2. Compile the revised source files. (Hint: If you're invoking the compiler from the command line (as opposed to using a builder), invoke the compiler from the directory that contains the mygame directory you just created.)


Questions

Assume you have written some classes. Belatedly, you decide they should be split into three packages, as listed in the following table. Furthermore, assume the classes are currently in the default package (they have no package statements).

Destination Packages

Package Name


Class Name

mygame.server


Server

mygame.shared


Utilities

mygame.client


Client

1. Which line of code will you need to add to each source file to put each class in the right package?

2. To adhere to the directory structure, you will need to create some subdirectories in the development directory and put source files in the correct subdirectories. What subdirectories must you create? Which subdirectory does each source file go in?

3. Do you think you'll need to make any other changes to the source files to make them compile correctly? If so, what?

Exercises

Download the source files as listed here.

* Client
* Server
* Utilities

1. Implement the changes you proposed in questions 1 through 3 using the source files you just downloaded.

2. Compile the revised source files. (Hint: If you're invoking the compiler from the command line (as opposed to using a builder), invoke the compiler from the directory that contains the mygame directory you just created.)

Managing Source and Class Files

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

The types that comprise a package are known as the package members.

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.
Referring to a Package Member by Its Qualified Name
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

You could use this qualified name to create an instance of graphics.Rectangle:

graphics.Rectangle myRect = new graphics.Rectangle();

Qualified names are all right for infrequent use. When a name is used repetitively, however, typing the name repeatedly becomes tedious and the code becomes difficult to read. As an alternative, you can import the member or its package and then use its simple name.
Importing a Package Member
To import a specific member into the current file, put an import statement at the beginning of the file before any type definitions but after the package statement, if there is one. Here's how you would import the Rectangle class from the graphics package created in the previous section.

import graphics.Rectangle;

Now you can refer to the Rectangle class by its simple name.

Rectangle myRectangle = new Rectangle();

This approach works well if you use just a few members from the graphics package. But if you use many types from a package, you should import the entire package.
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.*;

Now you can refer to any class or interface in the graphics package by its simple name.

Circle myCircle = new Circle();
Rectangle myRectangle = new Rectangle();

The asterisk in the import statement can be used only to specify all the classes within a package, as shown here. It cannot be used to match a subset of the classes in a package. For example, the following does not match all the classes in the graphics package that begin with A.

import graphics.A*; //does not work

Instead, it generates a compiler error. With the import statement, you generally import only a single package member or an entire package.

Note: Another, less common form of import allows you to import the public nested classes of an enclosing class. For example, if the graphics.Rectangle class contained useful nested classes, such as Rectangle.DoubleWide and Rectangle.Square, you could import Rectangle and its nested classes by using the following two statements.

import graphics.Rectangle;
import graphics.Rectangle.*;

Be aware that the second import statement will not import Rectangle.

Another less common form of import, the static import statement, will be discussed at the end of this section.

For convenience, the Java compiler automatically imports three entire packages for each source file: (1) the package with no name, (2) the java.lang package, and (3) the current package (the package for the current file).
Apparent Hierarchies of Packages
At first, packages appear to be hierarchical, but they are not. For example, the Java API includes a java.awt package, a java.awt.color package, a java.awt.font package, and many others that begin with java.awt. However, the java.awt.color package, the java.awt.font package, and other java.awt.xxxx packages are not included in the java.awt package. The prefix java.awt (the Java Abstract Window Toolkit) is used for a number of related packages to make the relationship evident, but not to show inclusion.

Importing java.awt.* imports all of the types in the java.awt package, but it does not import java.awt.color, java.awt.font, or any other java.awt.xxxx packages. If you plan to use the classes and other types in java.awt.color as well as those in java.awt, you must import both packages with all their files:

import java.awt.*;
import java.awt.color.*;

Name Ambiguities
If a member in one package shares its name with a member in another package and both packages are imported, you must refer to each member by its qualified name. For example, the graphics package defined a class named Rectangle. The java.awt package also contains a Rectangle class. If both graphics and java.awt have been imported, the following is ambiguous.

Rectangle rect;

In such a situation, you have to use the member's fully qualified name to indicate exactly which Rectangle class you want. For example,

graphics.Rectangle rect;

The Static Import Statement
There are situations where you need frequent access to static final fields (constants) and static methods from one or two classes. Prefixing the name of these classes over and over can result in cluttered code. The static import statement gives you a way to import the constants and static methods that you want to use so that you do not need to prefix the name of their class.

The java.lang.Math class defines the PI constant and many static methods, including methods for calculating sines, cosines, tangents, square roots, maxima, minima, exponents, and many more. For example,

public static final double PI 3.141592653589793
public static double cos(double a)

Ordinarily, to use these objects from another class, you prefix the class name, as follows.

double r = Math.cos(Math.PI * theta);

You can use the static import statement to import the static members of java.lang.Math so that you don't need to prefix the class name, Math. The static members of Math can be imported either individually:

import static java.lang.Math.PI;

or as a group:

import static java.lang.Math.*;

Once they have been imported, the static members can be used without qualification. For example, the previous code snippet would become:

double r = cos(PI * theta);

Obviously, you can write your own classes that contain constants and static methods that you use frequently, and then use the static import statement. For example,

import static mypackage.MyConstants.*;

Note: Use static import very sparingly. Overusing static import can result in code that is difficult to read and maintain, because readers of the code won't know which class defines a particular static object. Used properly, static import makes code more readable by removing class name repetition.

Naming a Package

With programmers worldwide writing classes and interfaces using the Java programming language, it is likely that many programmers will use the same name for different types. In fact, the previous example does just that: It defines a Rectangle class when there is already a Rectangle class in the java.awt package. Still, the compiler allows both classes to have the same name if they are in different packages. The fully qualified name of each Rectangle class includes the package name. That is, the fully qualified name of the Rectangle class in the graphics package is graphics.Rectangle, and the fully qualified name of the Rectangle class in the java.awt package is java.awt.Rectangle.

This works well unless two independent programmers use the same name for their packages. What prevents this problem? Convention.

Naming Conventions
Package names are written in all lowercase to avoid conflict with the names of classes or interfaces.

Companies use their reversed Internet domain name to begin their package names—for example, com.example.orion for a package named orion created by a programmer at example.com.

Name collisions that occur within a single company need to be handled by convention within that company, perhaps by including the region or the project name after the company name (for example, com.company.region.package).

Packages in the Java language itself begin with java. or javax.

In some cases, the internet domain name may not be a valid package name. This can occur if the domain name contains a hyphen or other special character, if the package name begins with a digit or other character that is illegal to use as the beginning of a Java name, or if the package name contains a reserved Java keyword, such as "int". In this event, the suggested convention is to add an underscore. For example:

Legalizing Package Names Domain Name Package Name Prefix
clipart-open.org org.clipart_open
free.fonts.int int_.fonts.free
poetry.7days.com com._7days.poetry

Creating a Package

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.

Note: If you put multiple types in a single source file, only one can be public, and it must have the same name as the source file. For example, you can define public class Circle in the file Circle.java, define public interface Draggable in the file Draggable.java, define public enum Day in the file Day.java, and so forth.

You can include non-public types in the same file as a public type (this is strongly discouraged, unless the non-public types are small and closely related to the public type), but only the public type will be accessible from outside of the package. All the top-level, non-public types will be package private.

If you put the graphics interface and classes listed in the preceding section in a package called graphics, you would need six source files, like this:

//in the Draggable.java file
package graphics;
public interface Draggable {
. . .
}

//in the Graphic.java file
package graphics;
public abstract class Graphic {
. . .
}

//in the Circle.java file
package graphics;
public class Circle extends Graphic implements Draggable {
. . .
}

//in the Rectangle.java file
package graphics;
public class Rectangle extends Graphic implements Draggable {
. . .
}

//in the Point.java file
package graphics;
public class Point extends Graphic implements Draggable {
. . .
}

//in the Line.java file
package graphics;
public class Line extends Graphic implements Draggable {
. . .
}

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.

Packages: Creating and Using Packages

To make types easier to find and use, to avoid naming conflicts, and to control access, programmers bundle groups of related types into packages.

Definition: A package is a grouping of related types providing access protection and name space management. Note that types refers to classes, interfaces, enumerations, and annotation types. Enumerations and annotation types are special kinds of classes and interfaces, respectively, so types are often referred to in this lesson simply as classes and interfaces.

The types that are part of the Java platform are members of various packages that bundle classes by function: fundamental classes are in java.lang, classes for reading and writing (input and output) are in java.io, and so on. You can put your types in packages too.

Suppose you write a group of classes that represent graphic objects, such as circles, rectangles, lines, and points. You also write an interface, Draggable, that classes implement if they can be dragged with the mouse.

//in the Draggable.java file
public interface Draggable {
. . .
}

//in the Graphic.java file
public abstract class Graphic {
. . .
}

//in the Circle.java file
public class Circle extends Graphic implements Draggable {
. . .
}

//in the Rectangle.java file
public class Rectangle extends Graphic implements Draggable {
. . .
}

//in the Point.java file
public class Point extends Graphic implements Draggable {
. . .
}

//in the Line.java file
public class Line extends Graphic implements Draggable {
. . .
}

You should bundle these classes and the interface in a package for several reasons, including the following:

* You and other programmers can easily determine that these types are related.
* You and other programmers know where to find types that can provide graphics-related functions.
* The names of your types won't conflict with the type names in other packages because the package creates a new namespace.
* You can allow types within the package to have unrestricted access to one another yet still restrict access for types outside the package.

Summary of Generics and Questions and Exercises: Generics

This chapter described the following problem: We have a Box class, written to be generally useful so it deals with Objects. We need an instance that takes only Integers. The comments say that only Integers go in, so the programmer knows this (or should know it), but the compiler doesn't know it. This means that the compiler can't catch someone erroneously adding a String. When we read the value and cast it to an Integer we'll get an exception, but that's not ideal since the exception may be far removed from the bug in both space and time:

1. Debugging may be difficult, as the point in the code where the exception is thrown may be far removed from the point in the code where the error is located.

2. It's always better to catch bugs when compiling than when running.

Specifically, you learned that generic type declarations can include one or more type parameters; you supply one type argument for each type parameter when you use the generic type. You also learned that type parameters can be used to define generic methods and constructors. Bounded type parameters limit the kinds of types that can be passed into a type parameter; they can specify an upper bound only. Wildcards represent unknown types, and they can specify an upper or lower bound. During compilation, type erasure removes all generic information from a generic class or interface, leaving behind only its raw type. It is possible for generic code and legacy code to interact, but in many cases the compiler will emit a warning telling you to recompile with special flags for more details.

For additional information on this topic, see Generics by Gilad Bracha.

Questions

1. Consider the following classes:

public class AnimalHouse {
private E animal;
public void setAnimal(E x) {
animal = x;
}
public E getAnimal() {
return animal;
}
}

public class Animal{
}

public class Cat extends Animal {
}

public class Dog extends Animal {
}

For the following code snippets, identify whether the code:

* fails to compile,
* compiles with a warning,
* generates an error at runtime, or
* none of the above (compiles and runs without problem.)

a. AnimalHouse house = new AnimalHouse();

b. AnimalHouse house = new AnimalHouse();

c. AnimalHouse house = new AnimalHouse();
house.setAnimal(new Cat());

d. AnimalHouse house = new AnimalHouse();
house.setAnimal(new Dog());

Exercises

1. Design a class that acts as a library for the following kinds of media: book, video, and newspaper. Provide one version of the class that uses generics and one that does not. Feel free to use any additional APIs for storing and retrieving the media.

Type Erasure

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.

For instance, Box is translated to type Box, which is called the raw type — a raw type is a generic class or interface name without any type arguments. This means that you can't find out what type of Object a generic class is using at runtime. The following operations are not possible:

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
}
}

The operations shown in bold are meaningless at runtime because the compiler removes all information about the actual type argument (represented by the type parameter E) at compile time.

Type erasure exists so that new code may continue to interface with legacy code. Using a raw type for any other reason is considered bad programming practice and should be avoided whenever possible.

When mixing legacy code with generic code, you may encounter warning messages similar to the following:

Note: WarningDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

This can happen when using an older API that operates on raw types, as shown in the following WarningDemo program:

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

Earlier we mentioned that English is ambiguous. The phrase "animal cage" can reasonably mean "all-animal cage", but it also suggests an entirely different concept: a cage designed not for any kind of animal, but rather for some kind of animal whose type is unknown. In generics, an unknown type is represented by the wildcard character "?".

To specify a cage capable of holding some kind of animal:

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.

Note: 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 .

While Cage and Cage are not subtypes of Cage, they are in fact subtypes of Cage:

someCage = lionCage; // OK
someCage = butterflyCage; // OK

So now the question becomes, "Can you add butterflies and lions directly to someCage?". As you can probably guess, the answer to this question is "no".

someCage.add(king); // compiler-time error
someCage.add(monarch); // compiler-time error

If someCage is a butterfly cage, it would hold butterflies just fine, but the lions would be able to break free. If it's a lion cage, then all would be well with the lions, but the butterflies would fly away. So if you can't put anything at all into someCage, is it useless? No, because you can still read its contents:

void feedAnimals(Cage someCage) {
for (Animal a : someCage)
a.feedMe();
}

Therefore, 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

As you already know, it's possible to assign an object of one type to an object of another type provided that the types are compatible. For example, 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

The same is also true with generics. You can perform a generic type invocation, passing Number as its type argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number:

Box box = new Box();
box.add(new Integer(10)); // OK
box.add(new Double(10.1)); // OK

Now consider the following method:

public void boxTest(Box n){
// method body omitted
}

What type of argument does it accept? By looking at its signature, we can see that it accepts a single argument whose type is Box. But what exactly does that mean? Are you allowed to pass in Box or Box, as you might expect? Surprisingly, the answer is "no", because Box and Box are not subtypes of Box.

Understanding why becomes much easier if you think of tangible objects — things you can actually picture — such as a cage:

// A cage is a collection of things, with bars to keep them in.
interface Cage extends Collection;

Note: The Collection interface is the root interface of the collection hierarchy; it represents a group of objects. Since a cage would be used for holding a collection of objects (the animals), it makes sense to include it in this example.

A lion is a kind of animal, so Lion would be a subtype of Animal:

interface Lion extends Animal {}
Lion king = ...;

Where we need some animal, we're free to provide a lion:

Animal a = king;

A lion can of course be put into a lion cage:

Cage lionCage = ...;
lionCage.add(king);

and a butterfly into a butterfly cage:

interface Butterfly extends Animal {}
Butterfly monarch = ...;
Cage butterflyCage = ...;
butterflyCage.add(monarch);

But what about an "animal cage"? English is ambiguous, so to be precise let's assume we're talking about an "all-animal cage":

Cage animalCage = ...;

This is a cage designed to hold all kinds of animals, mixed together. It must have bars strong enough to hold in the lions, and spaced closely enough to hold in the butterflies. Such a cage might not even be feasible to build, but if it is, then:

animalCage.add(king);
animalCage.add(monarch);

Since a lion is a kind of animal (Lion is a subtype of Animal), the question then becomes, "Is a lion cage a kind of animal cage? Is Cage a subtype of Cage?". By the above definition of animal cage, the answer must be "no". This is surprising! But it makes perfect sense when you think about it: A lion cage cannot be assumed to keep in butterflies, and a butterfly cage cannot be assumed to hold in lions. Therefore, neither cage can be considered an "all-animal" cage:

animalCage = lionCage; // compile-time error
animalCage = butterflyCage; // compile-time error


Without generics, the animals could be placed into the wrong kinds of cages, where it would be possible for them to escape.

Bounded Type Parameters

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

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

By passing in different types, the output will change accordingly.

A more realistic use of generic methods might be something like the following, which defines a static method that stuffs references to a single item into multiple boxes:

public static void fillBoxes(U u, List> boxes) {
for (Box box : boxes) {
box.add(u);
}
}


To use this method, your code would look something like the following:

Crayon red = ...;
List> crayonBoxes = ...;

The complete syntax for invoking this method is:

Box.fillBoxes(red, crayonBoxes);

Here we've explicitly provided the type to be used as U, but more often than not, this can be left out and the compiler will infer the type that's needed:

Box.fillBoxes(red, crayonBoxes); // compiler infers that U is Crayon

This feature, known as type inference, allows you to invoke a generic method as you would an ordinary method, without specifying a type between angle brackets.

Generic Types

Let's 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:

Box integerBox;

You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you're passing a type argument — Integer in this case — to the Box class itself. Like any other variable declaration, this code does not actually create a new Box object. It simply declares that integerBox will hold a reference to a "Box of Integer", which is how Box is read.

An invocation of a generic type is generally known as a parameterized type.

To instantiate this class, use the new keyword, as usual, but place between the class name and the parenthesis:

integerBox = new Box();

Or, you can put the entire statement on one line, such as:

Box integerBox = new Box();

Once integerBox is initialized, you're free to invoke its get method without providing a cast, as in BoxDemo3:

public class BoxDemo3 {

public static void main(String[] args) {
Box integerBox = new Box();
integerBox.add(new Integer(10));
Integer someInteger = integerBox.get(); // no cast!
System.out.println(someInteger);
}
}

Furthermore, if you try adding an incompatible type to the box, such as String, compilation will fail, alerting you to what previously would have been a runtime bug:

BoxDemo3.java:5: add(java.lang.Integer) in Box
cannot be applied to (java.lang.String)
integerBox.add("10");
^
1 error

It's important to understand that type variables are not actually types themselves. In the above examples, you won't find T.java or T.class anywhere on the filesystem. Furthermore, T is not a part of the Box class name. In fact during compilation, all generic information will be removed entirely, leaving only Box.class on the filesystem. We'll discuss this later in the section on Type Erasure

Also note that a generic type may have multiple type parameters, but each parameter must be unique within its declaring class or interface. A declaration of Box, for example, would generate an error on the second occurrence of T, but Box, however, would be allowed.

Type Parameter Naming Conventions
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.

generics-Introduction

In any nontrivial software project, bugs are simply a fact of life. Careful planning, programming, and testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. This becomes especially apparent as new features are introduced and your code base grows in size and complexity.

Fortunately, some bugs are easier to detect than others. Compile-time bugs, for example, tell you immediately that something is wrong; you can use the compiler's error messages to figure out what the problem is and fix it, right then and there. Runtime bugs, however, can be much more problematic; they don't always surface immediately, and when they do, it may be at a point in time that's far removed from the actual cause of the problem.

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 Box Class
Let's begin by designing a nongeneric Box class that operates on objects of any type. It 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;
}
}

Since its methods accept or return Object, you're free to pass in whatever you want, provided that it's not one of the primitive types. However, should you need to restrict the contained type to something specific (like Integer), your only option would be to specify the requirement in documentation (or in this case, a comment), which of course the compiler knows nothing about:

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);
}
}

In BoxDemo2 we've stored the number 10 as a String, which could be the case when, say, a GUI collects input from the user. However, the existing cast from Object to Integer has mistakenly been overlooked. This is clearly a bug, but because the code still compiles, you wouldn't know anything is wrong until runtime, when the application crashes with a ClassCastException:

Exception in thread "main"
java.lang.ClassCastException:
java.lang.String cannot be cast to java.lang.Integer
at BoxDemo2.main(BoxDemo2.java:6)

If the Box class had been designed with generics in mind, this mistake would have been caught by the compiler, instead of crashing the application at runtime.

Summary of Characters and Strings

Most of the time, if you are using a single character value, you will use the primitive char type. There are times, however, when you need to use a char as an object—for example, as a method argument where an object is expected. The Java programming language provides a wrapper class that "wraps" the char in a Character object for this purpose. An object of type Character contains a single field whose type is char. This Character class also offers a number of useful class (i.e., static) methods for manipulating characters.

Strings are a sequence of characters and are widely used in Java programming. In the Java programming language, strings are objects. The String class has over 60 methods and 13 constructors.

Most commonly, you create a string with a statement like

String s = "Hello world!";

rather than using one of the String constructors.

The String class has many methods to find and retrieve substrings; these can then be easily reassembled into new strings using the + concatenation operator.

The String class also includes a number of utility methods, among them split(), toLowerCase(), toUpperCase(), and valueOf(). The latter method is indispensable in converting user input strings to numbers. The Number subclasses also have methods for converting strings to numbers and vice versa.

In addition to the String class, there is also a StringBuilder class. Working with StringBuilder objects can sometimes be more efficient than working with strings. The StringBuilder class offers a few methods that can be useful for strings, among them reverse(). In general, however, the String class has a wider variety of methods.

A string can be converted to a string builder using a StringBuilder constructor. A string builder can be converted to a string with the toString() method.

The StringBuilder Class

StringBuilder objects are like String objects, except that they can be modified. Internally, these objects are treated like variable-length arrays that contain a sequence of characters. At any point, the length and content of the sequence can be changed through method invocations.

Strings should always be used unless string builders offer an advantage in terms of simpler code (see the sample program at the end of this section) or better performance. For example, if you need to concatenate a large number of strings, appending to a StringBuilder object is more efficient.
Length and Capacity
The StringBuilder class, like the String class, has a length() method that returns the length of the character sequence in the builder.

Unlike strings, every string builder also has a capacity, the number of character spaces that have been allocated. The capacity, which is returned by the capacity() method, is always greater than or equal to the length (usually greater than) and will automatically expand as necessary to accommodate additions to the string builder.

StringBuilder Constructors Constructor Description
StringBuilder() Creates an empty string builder with a capacity of 16 (16 empty elements).
StringBuilder(CharSequence cs) Constructs a string builder containing the same characters as the specified CharSequence, plus an extra 16 empty elements trailing the CharSequence.
StringBuilder(int initCapacity) Creates an empty string builder with the specified initial capacity.
StringBuilder(String s) Creates a string builder whose value is initialized by the specified string, plus an extra 16 empty elements trailing the string.

For example, the following code

StringBuilder sb = new StringBuilder(); // creates empty builder, capacity 16
sb.append("Greetings"); // adds 9 character string at beginning

will produce a string builder with a length of 9 and a capacity of 16:

A string builder's length is the number of characters it contains; a string builder's

The StringBuild

Comparing Strings and Portions of Strings

The String class has a number of methods for comparing strings and portions of strings. The following table lists these methods.

Methods for Comparing Strings Method Description
boolean endsWith(String suffix)

boolean startsWith(String prefix) Returns true if this string ends with or begins with the substring specified as an argument to the method.
boolean startsWith(String prefix, int offset) Considers the string beginning at the index offset, and returns true if it begins with the substring specified as an argument.
int compareTo(String anotherString) Compares two strings lexicographically. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument.
int compareToIgnoreCase(String str) Compares two strings lexicographically, ignoring differences in case. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument.
boolean equals(Object anObject) Returns true if and only if the argument is a String object that represents the same sequence of characters as this object.
boolean equalsIgnoreCase(String anotherString) Returns true if and only if the argument is a String object that represents the same sequence of characters as this object, ignoring differences in case.
boolean regionMatches(int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument.

Region is of length len and begins at the index toffset for this string and ooffset for the other string.
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument.

Region is of length len and begins at the index toffset for this string and ooffset for the other string.

The boolean argument indicates whether case should be ignored; if true, case is ignored when comparing characters.
boolean matches(String regex) Tests whether this string matches the specified regular expression. Regular expressions are discussed in the lesson titled "Regular Expressions."

The following program, RegionMatchesDemo, uses the regionMatches method to search for a string within another string:

public class RegionMatchesDemo {
public static void main(String[] args) {
String searchMe = "Green Eggs and Ham";
String findMe = "Eggs";
int searchMeLength = searchMe.length();
int findMeLength = findMe.length();
boolean foundIt = false;
for (int i = 0; i <= (searchMeLength - findMeLength); i++) {
if (searchMe.regionMatches(i, findMe, 0, findMeLength)) {
foundIt = true;
System.out.println(searchMe.substring(i, i + findMeLength));
break;
}
}
if (!foundIt) System.out.println("No match found.");
}
}

The output from this program is Eggs.

The program steps through the string referred to by searchMe one character at a time. For each character, the program calls the regionMatches method to determine whether the substring beginning with the current character matches the string the program is looking for.

Manipulating Characters in a String

The String class has a number of methods for examining the contents of strings, finding characters or substrings within a string, changing case, and other tasks.
Getting Characters and Substrings by Index
You can get the character at a particular index within a string by invoking the charAt() accessor method. The index of the first character is 0, while the index of the last character is length()-1. For example, the following code gets the character at index 9 in a string:

String anotherPalindrome = "Niagara. O roar again!";
char aChar = anotherPalindrome.charAt(9);

Indices begin at 0, so the character at index 9 is 'O', as illustrated in the following figure:

Use the charAt method to get a character at a particular index.

If you want to get more than one consecutive character from a string, you can use the substring method. The substring method has two versions, as shown in the following table:

The substring Methods in the String Class Method Description
String substring(int beginIndex, int endIndex) Returns a new string that is a substring of this string. The first integer argument specifies the index of the first character. The second integer argument is the index of the last character + 1.
String substring(int beginIndex) Returns a new string that is a substring of this string. The integer argument specifies the index of the first character. Here, the returned substring extends to the end of the original string.

The following code gets from the Niagara palindrome the substring that extends from index 11 up to, but not including, index 15, which is the word "roar":

String anotherPalindrome = "Niagara. O roar again!";
String roar = anotherPalindrome.substring(11, 15);

Use the substring method to get part of a string.

Other Methods for Manipulating Strings
Here are several other String methods for manipulating strings:

Other Methods in the String Class for Manipulating Strings Method Description
String[] split(String regex)
String[] split(String regex, int limit) Searches for a match as specified by the string argument (which contains a regular expression) and splits this string into an array of strings accordingly. The optional integer argument specifies the maximum size of the returned array. Regular expressions are covered in the lesson titled "Regular Expressions."
CharSequence subSequence(int beginIndex, int endIndex) Returns a new character sequence constructed from beginIndex index up until endIndex - 1.
String trim() Returns a copy of this string with leading and trailing white space removed.
String toLowerCase()
String toUpperCase() Returns a copy of this string converted to lowercase or uppercase. If no conversions are necessary, these methods return the original string.
Searching for Characters and Substrings in a String
Here are some other String methods for finding characters or substrings within a string. The String class provides accessor methods that return the position within the string of a specific character or substring: indexOf() and lastIndexOf(). The indexOf() methods search forward from the beginning of the string, and the lastIndexOf() methods search backward from the end of the string. If a character or substring is not found, indexOf() and lastIndexOf() return -1.

The String class also provides a search method, contains, that returns true if the string contains a particular character sequence. Use this method when you only need to know that the string contains a character sequence, but the precise location isn't important.

The following table describes the various string search methods.

The Search Methods in the String Class Method Description
int indexOf(int ch)
int lastIndexOf(int ch) Returns the index of the first (last) occurrence of the specified character.
int indexOf(int ch, int fromIndex)
int lastIndexOf(int ch, int fromIndex) Returns the index of the first (last) occurrence of the specified character, searching forward (backward) from the specified index.
int indexOf(String str)
int lastIndexOf(String str) Returns the index of the first (last) occurrence of the specified substring.
int indexOf(String str, int fromIndex)
int lastIndexOf(String str, int fromIndex) Returns the index of the first (last) occurrence of the specified substring, searching forward (backward) from the specified index.
boolean contains(CharSequence s) Returns true if the string contains the specified character sequence.

Note: CharSequence is an interface that is implemented by the String class. Therefore, you can use a string as an argument for the contains() method.

Replacing Characters and Substrings into a String
The String class has very few methods for inserting characters or substrings into a string. In general, they are not needed: You can create a new string by concatenation of substrings you have removed from a string with the substring that you want to insert.

The String class does have four methods for replacing found characters or substrings, however. They are:

Methods in the String Class for Manipulating Strings Method Description
String replace(char oldChar, char newChar) Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
String replace(CharSequence target, CharSequence replacement) Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
String replaceAll(String regex, String replacement) Replaces each substring of this string that matches the given regular expression with the given replacement.
String replaceFirst(String regex, String replacement) Replaces the first substring of this string that matches the given regular expression with the given replacement.
An Example
The following class, Filename, illustrates the use of lastIndexOf() and substring() to isolate different parts of a file name.

Note: The methods in the following Filename class don't do any error checking and assume that their argument contains a full directory path and a filename with an extension. If these methods were production code, they would verify that their arguments were properly constructed.

public class Filename {
private String fullPath;
private char pathSeparator, extensionSeparator;

public Filename(String str, char sep, char ext) {
fullPath = str;
pathSeparator = sep;
extensionSeparator = ext;
}

public String extension() {
int dot = fullPath.lastIndexOf(extensionSeparator);
return fullPath.substring(dot + 1);
}

public String filename() { // gets filename without extension
int dot = fullPath.lastIndexOf(extensionSeparator);
int sep = fullPath.lastIndexOf(pathSeparator);
return fullPath.substring(sep + 1, dot);
}

public String path() {
int sep = fullPath.lastIndexOf(pathSeparator);
return fullPath.substring(0, sep);
}
}

Here is a program, FilenameDemo, that constructs a Filename object and calls all of its methods:

public class FilenameDemo {
public static void main(String[] args) {
final String FPATH = "/home/mem/index.html";
Filename myHomePage = new Filename(FPATH,
'/', '.');
System.out.println("Extension = " +
myHomePage.extension());
System.out.println("Filename = " +
myHomePage.filename());
System.out.println("Path = " +
myHomePage.path());
}
}

And here's the output from the program:

Extension = html
Filename = index
Path = /home/mem

As shown in the following figure, our extension method uses lastIndexOf to locate the last occurrence of the period (.) in the file name. Then substring uses the return value of lastIndexOf to extract the file name extension — that is, the substring from the period to the end of the string. This code assumes that the file name has a period in it; if the file name does not have a period, lastIndexOf returns -1, and the substring method throws a StringIndexOutOfBoundsException.

The use of lastIndexOf and substring in the extension method in the Filename class.

Also, notice that the extension method uses dot + 1 as the argument to substring. If the period character (.) is the last character of the string, dot + 1 is equal to the length of the string, which is one larger than the largest index into the string (because indices start at 0). This is a legal argument to substring because that method accepts an index equal to, but not greater than, the length of the string and interprets it to mean "the end of the string."

 

blogger templates | Make Money Online