Você está na página 1de 51

Introduction to Java

Java is a programming language originally developed by James Gosling at Sun


Microsystems (which is now a subsidiary of Oracle Corporation) 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
(class file) that can run on any Java Virtual Machine (JVM) regardless of
computer architecture. Java is a general-purpose, concurrent, class-based, object-
oriented language that is specifically designed to have as few implementation
dependencies as possible. It is intended to let application developers "write once,
run anywhere". Java is currently one of the most popular programming languages
in use, and is widely used from application software to web applications.

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 relicensed most of its
Java technologies under the GNU General Public License. Others have also
developed alternative implementations of these Sun technologies, such as the
GNU Compiler for Java, GNU Classpath, and Dalvik.

History
James Gosling, Mike Sheridan, and Patrick Naughton initiated the Java language
project in June 1991. Java was originally designed for interactive television, but it
was too advanced for the digital cable television industry at the time. The language
was initially called Oak after an oak tree that stood outside Gosling's office; it
went by the name Green later, and was later renamed Java, from a list of random
words. Gosling aimed to implement a virtual machine and a language that had a
familiar C/C++ style of notation. Sun Microsystems released the first public
implementation as Java 1.0 in 1995. It promised "Write Once, Run Anywhere"
(WORA), providing no-cost run-times on popular platforms. Fairly secure and
featuring configurable security, it allowed network- and file-access restrictions.
Major web browsers soon incorporated the ability to run Java applets within web
pages, and Java quickly became popular. With the advent of Java 2 (released
initially as J2SE 1.2 in December 1998–1999), new versions had multiple
configurations built for different types of platforms. For example, J2EE targeted
enterprise applications and the greatly stripped-down version J2ME for mobile
applications (Mobile Java). J2SE designated the Standard Edition. In 2006, for
marketing purposes, Sun renamed new J2 versions as 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.[15] Java remains a de facto standard, controlled through the Java
Community Process.[16] At one time, Sun made most of its Java implementations
available without charge, despite their proprietary software status. Sun generated
revenue from Java through 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) (a subset of the SDK); the primary
distinction involves the JRE's lack of the compiler, utility programs, and header
files.

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

Sun's vice-president Rich Green has said that Sun's ideal role with regards to Java
is as an "evangelist”

Following Oracle Corporation's acquisition of Sun Microsystems in 2009–2010,


Oracle has described itself as the "steward of Java technology with a relentless
commitment to fostering a community of participation and transparency".

Principles
There were five primary goals in the creation of the Java language:

1. It should be "simple, object oriented and familiar".


2. It should be "robust and secure".
3. It should have "an architecture-neutral and portable environment".
4. It should execute with "high performance".
5. It should be "interpreted, threaded, and dynamic".

Java Platform
Standardized libraries provide a generic way to access host-specific features such
as graphics, threading, and networking.

A major benefit of using bytecode is porting. However, the overhead of


interpretation means that interpreted programs almost always run more slowly
than programs compiled to native executables would. Just-in-Time compilers were
introduced from an early stage that compile bytecodes One characteristic of Java is
portability, which means that computer programs written in the Java language
must run similarly on any supported hardware/operating-system platform. This is
achieved by compiling the Java language code to an intermediate representation
called Java bytecode, instead of directly to platform-specific machine code. Java
bytecode instructions are analogous to machine code, but are intended to be
interpreted by a virtual machine (VM) written specifically for the host hardware.
End-users commonly use a Java Runtime Environment (JRE) installed on their
own machine for standalone Java applications, or in a Web browser for Java
applets.

to machine code during runtime.

Implementations
officially licenses the Java Standard Edition platform for Linux, Mac OS Xhas
expired and has not been renewed Through a network of third-party vendors and
licensees, alternative Java environments are available for these and other
platforms.

, and Solaris. Although in the past Sun has licensed Java to Microsoft, the license
Sun MicrosystemsSun'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
RMI or JNI and had added platform-specific features of their own. Sun sued in
1997, and in 2001 won a settlement of US$20 million, as well as a court order
enforcing the terms of the license from Sun. 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. Sun, and others, have made
available free Java run-time systems for those and other versions of Windows.

Platform-independent Java is essential to the Java EE strategy, and an even more


rigorous validation is required to certify an implementation. This environment
enables portable server-side applications, such as Web services, Java 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.

Sun also distributes a superset of the JRE called the Java Development Kit
(commonly known as the JDK), which includes development tools such as the
Java compiler, Javadoc, Jar, and debugger.

Performance
Programs written in Java have a reputation for being slower and requiring more
memory than those written in C. However, Java programs' execution speed
improved significantly with the introduction of Just-in-time compilation in
1997/1998 for Java 1.1 the addition of language features supporting better code
analysis (such as inner classes, StringBuffer class, optional assertions, etc.), and
optimizations in the Java Virtual Machine itself, such as HotSpot becoming the
default for Sun's JVM in 2000. Currently, Java code has approximately half the
performance of C code. Some platforms offer direct hardware support for Java;
there are microcontrollers that can run java in hardware instead of a software
JVM, and ARM based processors can have hardware support for executing Java
bytecode through its Jazelle option.

Automatic memory management


Java uses an automatic garbage collector to manage memory in the object
lifecycle. The programmer determines when objects are created, and the Java
runtime is responsible for recovering the memory once objects are no longer in
use. Once no references to an object remain, the unreachable memory becomes
eligible to be freed automatically by the garbage collector. Something similar to a
memory leak may still occur if a programmer's code holds a reference to an object
that is no longer needed, typically when objects that are no longer needed are
stored in containers that are still in use. If methods for a nonexistent object are
called, a "null pointer exception" is thrown.One of the ideas behind Java's
automatic memory management model is that programmers can be spared the
burden of having to perform manual memory management. In some languages,
memory for the creation of objects is implicitly allocated on the stack, or explicitly
allocated and deallocated from the heap. In the latter case the responsibility of
managing memory resides with the programmer. If the program does not
deallocate an object, a memory leak occurs. If the program attempts to access or
deallocate memory that has already been deallocated, the result is undefined and
difficult to predict, and the program is likely to become unstable and/or crash. This
can be partially remedied by the use of smart pointers, but these add overhead and
complexity. Note that garbage collection does not prevent "logical" memory leaks,
i.e. those where the memory is still referenced but never used.

Garbage collection may happen at any time. Ideally, it will occur when a program
is idle. It is guaranteed to be triggered if there is insufficient free memory on the
heap to allocate a new object; this can cause a program to stall momentarily.
Explicit memory management is not possible in Java.

Java does not support C/C++ style pointer arithmetic, where object addresses and
unsigned integers (usually long integers) can be used interchangeably. This allows
the garbage collector to relocate referenced objects and ensures type safety and
security.

As in C++ and some other object-oriented languages, variables of Java's primitive


data types are not 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
commonly true 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 proceed as if primitive types were
instances of their wrapper class.

Java contains multiple types of garbage collectors. By default, HotSpot uses the
Concurrent Mark Sweep collector, also known as the CMS Garbage Collector.
However, there are also several other garbage collectors that can be used to
manage the Heap. For 90% of applications in Java, the CMS Garbage Collector is
good enough.

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
almost exclusively as an object-oriented language. All code is written inside a
class, and everything is an object, with the exception of the primitive data types
(integers, floating-point numbers, boolean values, and characters), which are not
classes for performance reasons.

Unlike C++, Java does not support operator overloading and multiple inheritance
for classes in order to simplify the language and to prevent possible errors and
anti-pattern design.

Java uses similar commenting methods to C++. There are three different styles of
comment: a single line style marked with two slashes (//), a multiple line style
opened with a slash asterisk (/*) and closed with an asterisk slash (*/), and the
Javadoc commenting style opened with a slash and two asterisks (/**) and closed
with an asterisk slash (*/). The Javadoc style of commenting allows the user to run
the Javadoc executable to compile documentation for the program.

Example:

// This is an example of a single line comment using two slashes

/* This is an example of a multiple line comment using the slash and asterisk.
This type of comment can be used to hold a lot of information or deactivate
code but it is very important to remember to close the comment. */

/**
* This is an example of a Javadoc comment; Javadoc can compile documentation
* from this text.
*/

Examples

Hello world
The traditional Hello world program can be written in Java as;

class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the
string.
}
}

To compare this to other programming languages see the list of hello world
program examples.

Source files must be named after the public class they contain, appending the
suffix .java, for example, HelloWorld.java. It must first be compiled into
bytecode, using a Java compiler, producing a file named HelloWorld.class. Only
then can it be executed, or 'launched'. The java source file may only contain one
public class but can contain multiple classes with less than public access and any
number of public inner classes.

A class that is not declared public may be stored in any .java file. 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 were 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
class hierarchy is related to the name of the directory in which the .java file is
located.

The keyword static in front of a method indicates a static method, which is


associated only with the class and not with any specific instance of that class. Only
static methods can be invoked without a reference to an object. Static methods
cannot access any method variables that are not static.

The keyword void indicates that the main method does not return any value to the
caller. If a Java program is to exit with an error code, it must call System.exit()
explicitly.

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 JavaBean
do not use or need a main() method. A java program may contain multiple classes
that have main methods, which means that the VM needs to be explicitly told
which class to launch from.

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 alternative syntax for creating and passing the array.

The Java launcher launches Java by loading a given class (specified on the
command line or as an attribute in a JAR) 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.

Printing is part of a 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
many methods for printing data to standard out, including println(String) which
also appends a new line to the passed string.

The string "Hello, world!" is automatically converted to a String object by the


compiler.

A more comprehensive example


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

public class OddEven {


// "input" is the number that the user gives to the computer
private int input; // a whole number("int" means integer)

/*
* This is the constructor method. It gets called when an object of the OddEven
type
* is being created.
*/
public OddEven() {
/*
* In most Java programs constructors can initialize objects with default values,
or create
* other objects that this object might use to perform its functions. In some Java
programs, the
* constructor may simply be an empty function if nothing needs to be
initialized prior to the
* functioning of the object. In this program's case, an empty constructor would
suffice, even if
* it is empty. A constructor must exist, however if the user doesn't put one in
then the compiler
* will create an empty one.
*/
}

// This is the main method. It gets called when this class is run through a Java
interpreter.
public static void main(String[] args) {
/*
* This line of code creates a new instance of this class called "number" (also
known as an
* Object) and initializes it by calling the constructor. The next line of code
calls
* the "showDialog()" method, which brings up a prompt to ask you for a
number
*/
OddEven number = new OddEven();
number.showDialog();
}

public void showDialog() {


/*
* "try" makes sure nothing goes wrong. If something does,
* the interpreter skips to "catch" to see what it should do.
*/
try {
/*
* The code below 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."
*/
input = Integer.parseInt(JOptionPane.showInputDialog("Please Enter A
Number"));
calculate();
} catch (NumberFormatException e) {
/*
* Getting in the catch block means that there was a problem with the
format of
* the number. Probably some letters were typed in instead of a number.
*/
System.err.println("ERROR: Invalid input. Please type in a numerical
value.");
}
}

/*
* 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)
*/
private void calculate() {
if (input % 2 == 0) {
System.out.println("Even");
} 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 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.
• input = Integer.parseInt(JOptionPane.showInputDialog("Please Enter
A Number")); is a statement that converts the type of String to the
primitive data type int by using a utility function in the primitive wrapper
class Integer.

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

// Hello.java
import javax.swing.JApplet;
import java.awt.Graphics;

public class Hello extends JApplet {


@Override
public void paintComponent(Graphics g) {
g.drawString("Hello, world!", 65, 95);
}

The import statements direct the Java compiler to include the


javax.swing.JApplet 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. JApplet) instead of the fully qualified class name (i.e.
javax.swing.JApplet).

The Hello class extends (subclasses) the JApplet (Java Applet) class; the JApplet
class provides the framework for the host application to display and control the
lifecycle of the applet. The JApplet class is a JComponent (Java Graphical
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 paintComponent(Graphics) method inherited from


the Container superclass to provide the code to display the applet. The
paintComponent() method is passed a Graphics object that contains the graphic
context used to display the applet. The paintComponent() 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.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"


"http://www.w3.org/TR/html4/strict.dtd">
<!-- Hello.html -->
<html>
<head>
<title>Hello World Applet</title>
</head>
<body>
<applet code="Hello" width="200" height="200">
</applet>
</body>
</html>

An applet is placed in an HTML document using the <applet> HTML element.


The applet tag has three attributes set: code="Hello" specifies the name of the
JApplet 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,[33] although support for these elements by Web browsers is
inconsistent.[34] 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 paintComponent() method is called by
the AWT event dispatching thread whenever the display needs the applet to draw
itself.

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.

JavaServer Pages
JavaServer Pages (JSP) 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.

Swing application

Swing is a graphical user interface library for the Java SE platform. 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. Where prior implementations of
these looks and feels may have been considered lacking, Swing in Java SE 6
addresses this problem by using more native GUI widget drawing routines of the
underlying platforms.

This example Swing application creates a single window with "Hello, world!"
inside:

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

public class Hello extends JFrame {


public Hello() {
super("hello");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
add(new JLabel("Hello, world!"));
setVisible(true);
pack();
}

public static void main(String[] args) {


new Hello();
}
}

The first 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, 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.

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

Generics
In 2004, generics were added to the Java language, as part of J2SE 5.0. Prior to the
introduction of generics, each variable declaration had to be of a specific type. For
container classes, for example, this is a problem because there is no easy way to
create a container that accepts only specific types of objects. Either the container
operates on all subtypes of a class or interface, usually Object, or a different
container class has to be created for each contained class. Generics allow compile-
time type checking without having to create a large number of container classes,
each containing almost identical code.

Criticism
A number of criticisms have been leveled at Java programming language for
various design choices in the language and platform. Such criticisms include the
implementation of generics[who?], the handling of unsigned numbers[citation needed], the
implementation of floating-point arithmetic[citation needed], and security
vulnerabilities[clarification needed].

Class libraries

Java Platform and Class libraries diagram

• Java libraries are the compiled bytecodes 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, sets, queues and double-ended queue,
or stacks
 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
 JMX for managing and monitoring applications
o User interface libraries, which include:
 The (heavyweight, or native) Abstract Window Toolkit
(AWT), which provides GUI components, the means for
laying out those components and the means for handling
events from those components
 The (lightweight) 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.

Documentation
Javadoc is a comprehensive documentation system, created by Sun Microsystems,
used by many Java developers. It provides developers with an organized system
for documenting their code. Javadoc comments have an extra asterisk at the
beginning, i.e. the tags are /** and */, whereas the normal multi-line comment tags
comments in Java and C are set off with /* and */.

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

• Java Card for smartcards.


• Java Platform, Micro Edition (Java ME) — targeting environments with
limited resources.
• Java Platform, Standard Edition (Java SE) — targeting workstation
environments.
• 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.
Sun also provided an edition called PersonalJava that has been superseded by
later, standards-based Java ME configuration-profile pairings.

Java is an object-oriented programming language with a built-in application


programming interface (API) that can handle graphics and user interfaces and that
can be used to create applications or applets. Because of its rich set of API's,
similar to Macintosh and Windows, and its platform independence, Java can also
be thought of as a platform in itself. Java also has standard libraries for doing
mathematics.

Much of the syntax of Java is the same as C and C++. One major difference is that
Java does not have pointers. However, the biggest difference is that you must
write object oriented code in Java. Procedural pieces of code can only be
embedded in objects. In the following we assume that the reader has some
familiarity with a programming language. In particular, some familiarity with the
syntax of C/C++ is useful.

In Java we distinguish between applications, which are programs that perform the
same functions as those written in other programming languages, and applets,
which are programs that can be embedded in a Web page and accessed over the
Internet. Our initial focus will be on writing applications. When a program is
compiled, a byte code is produced that can be read and executed by any platform
that can run Java.

To use this tutorial you should run and study each program as you read along, so
that you can see how added features affect the programs.

Objects
Object-oriented programming focuses on constructs called “objects.” An object
consists of data and functions known as methods which use or change the data.
(Methods are similar to procedures or functions in other languages.) Objects of the
same kind are said to have the same type or be in the same class. A class defines
what data can be in an object, and what operations are performed by the methods.
One or more objects can be created or “instantiated” from a class. The structure of
a Java program consists of various objects exchanging messages. The keyword
class defines a blueprint for objects with similar properties. In our first example
we define the class Particle.

public class Particle


{
double x, y, vx, vy, mass;
}
This class does not do anything (because it has no methods), but it can be used to
describe a particle by its position, velocity, and mass. For simplicity, we will
consider only two dimensions.

Constructors
Every class has at least one constructor, a method which has the same name as the
class. A constructor initializes a new object belonging to the class.

public class Particle


{
double x, y, vx, vy, mass; // these variables can be used by any method in the
class

// example of constructor method


public Particle(double x, double y, double vx, double vy, double mass)
{

/* Use this keyword to make explicit that a method


is accessing its own variables. */
this.x = x; // set instance variable x equal to value of x in parameter list
this.y = y;
this.vx = vx;
this.vy = vy;
this.mass = mass;
}
}

The constructor Particle creates an object of the Particle class by specifying five
parameters: the initial position and velocity of a particle and the value of its mass.
We say that Particle is the constructor for the Particle class.

We have used the following properties of Java:

• Variable Declaration: The types of all variables must be declared. The


primitive types are byte, short, int, long (8, 16, 32, and 64 bit integer
variables, respectively), float and double (32 and 64-bit floating point
variables), boolean (true or false), and char. Boolean is a distinct type
rather than just another way of using integers. Strings are not a primitive
type, but are instances of the String class. Because they are so common,
string literals may appear in quotes just as in other languages. Summary of
primitive data types.
• Naming Conventions: Java distinguishes between upper and lower case
variables. The convention is to capitalize the first letter of a class name. If
the class name consists of several words, they are run together with
successive words capitalized within the name (instead of using underscores
to separate the names). The name of the constructor is the same as the name
of the class. All keywords (words that are part of the language and cannot
be redefined) are written in lower case.
• Instance variables and methods can be accessed from any method within
the class. The x in the argument list of the above constructor refers to the
local value of the parameter which is set when Particle is called. We use the
this keyword to refer to those variables defined for the entire class in
contrast to those defined locally within a method and those that are
arguments to a method. In the above example, this.x refers to the variable x
which is defined just after the first line of the class definition. After we
have introduced multiple constructors, we show a more iillustrative
example of the this keyword.
• Classes are effectively new programmer-defined types; each class defines
data (fields) and methods to manipulate the data. Fields in the class are
template for the instance variables that are created when objects are
instantiated (created) from that class. A new set of instance variables is
created each time that an object is instantiated from the class.
• The members of a class (variables and methods) are accessed by referrring
to an object created from thr clas using the dot operator. For example,
suppose that a class Particle contains and instance variable x amd a method
step. If an object of this class is named p, then the instance variable in p
would be accessed as p.x and the method accessed as p.step.
• A semicolon is used to terminate individual statements.
• Comments. There are three comment styles in Java. A single line comment
starts with // and can be included anywhere in the program. Multiple line
comments begin with /* and end with */; these are also useful for
commenting out a portion of the text on a line. Finally, text enclosed within
/** ... */ serves to generate documentation using the javadoc command.
• Assignments. Java uses the C/C++ shortcuts summarized in Table 2.

Table 2. Assignment shortcuts.

operator example meaning


+= x += y x=x+y
-= x -= y x=x–y
*= x *= y x = x*y
/= x /= y x = x/y
%= x %= y x=x%y

The modulus operator % returns the remainder of a division. For example, 5


%3 returns 2. The increment operator ++ works as
follows:

i++;

is equivalent to

i = i + 1;

Similarly, the decrement operator -- works as follows:

i--;

is equivalent to

i = i - 1;

• Type casting changes the type of a value from its normal type to some other
type. For example:
• double distance;
• distance = 10.0;
• int x;
• x = (int)distance; // example of a type cast

What would be the value of x in the above example if distance = 9.9?

Multiple Constructors
The arguments of a constructor specify the parameters for the initialization of an
object. Multiple constructors provide the flexibility of initializing objects in the
same class with different sets of arguments, as in the following example.

public class Particle


{
double x, y, vx, vy, mass;

// examples of multiple constructors

public Particle()
{
this(0.0,0.0);
}

public Particle(double x, double y)


{
this(x,y,1.0);
}

public Particle(double x, double y, double m)


{
this(x,y,0.0,0.0,m);
}

public Particle(double x, double y, double vx, double vy)


{
this(x,y,vx,vy,1.0);
}

public Particle(double x, double y, double vx, double vy, double mass)


{
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.mass = mass;
}
}

• The multiple constructors (all named Particle) are distinguished only by the
number of arguments. The constructors can be defined in any order. Hence,
the keyword this in the first constructor refers to the next in the sequence
because the latter has two arguments. The first constructor has no
arguments and creates a particle of unit mass at the origin; the next is
defined with two arguments: the spatial coordinates of the particle. The
second constructor in turn references the third constructor which uses the
spatial coordinates and the mass. The third and fourth constructors each
refer to the final constructors which uses all five arguments. (The order of
the constructors is unimportant.) Once the Particle class with its multiple
constructors is defined, any class can call the constructor Particle using the
number of arguments appropriate to that application. The advantage of
having multiple constructors is that applications that use a particular
constructor are unaffected by later additions made to the class Particle,
whether variables or methods. For example, adding acceleration as an
argument does not affect applications that rely only on the definitions given
above.
• Using multiple constructors is called method overloading -- the method
name is used to specify more than one method. The rule for overloading is
that the argument lists for all of the different methods must be unique,
including the number of arguments and/or the types of the arguments.

All classes have at least one implicit constructor method. If no constructor is


defined explicitly, the compiler creates one with no arguments.

We next give an example of a Particle class with methods for computing the
weight of a particle and its distance from the origin. We will omit the velocity
components for now.

public class Particle


{
double x, y, mass;

public Particle()
{
}

public Particle(double x, double y)


{
this(x,y,1);
}

public Particle(double x, double y, double mass)


{
this.x = x; this.y = y; this.mass = mass;
}

public double getWeight()


{
return 9.8*mass;
}

public double distanceFromOrigin()


{
return Math.sqrt(x*x + y*y);
}
}
1. The fundamental parts of a method are its name, arguments, return type,
and the body. Methods can be created only as part of a class. By
convention, variable and method names begin with a lower case letter.
2. The keyword return followed by an expression returns the value of the
expression to the caller of the method. The type of the expression must be
the same as specified by the method. (Note that a constructor does not
return a value and hence no type is specified.) A method can return only the
value of a single expression.
3. The method distanceFromOrigin in the class Particle computes the distance
of a particle from the origin using the particle coordinates x and y. The
square root function Math.sqrt in this calculation is part of the Math class, a
library of mathematical functions which consists of a collection of static
methods. We will postpone a discussion of such classes, but their use is
clear from the context.

A program consists of one or more class definitions, each of which should be in


separate files. The name of the file should be the same as the name of the class, for
example, MyApplication.java. One of these classes must define a method main.

The following program creates two objects of type Particle.

public class MyApplication


{
public static void main(String[] args)
{

/* Need an instance of class Particle - a particle object;


assign it to the variable a which is of type Particle. */

Particle a = new Particle(1.0,1.0);


System.out.println("Distance of particle a from origin = " +
a.distanceFromOrigin());
System.out.println("Mass of particle a = " + a.mass);
Particle b = new Particle();
b.x = 2.0;
b.y = 3.0;
b.mass = 3;
System.out.println("Distance of particle b from origin = " +
b.distanceFromOrigin());
System.out.println("Mass of particle b = " + b.mass);
System.out.println("Weight of particle b = " + b.getWeight());
}
}
• The first statement in main declares a to be a Particle and uses the new
keyword to instantiate an object. These two operations could have been
done separately in two lines as illustrated for Particle b. Note that Java
already defines primitive data types such as int and double.
• If a program has more than one class, one and only one of the classes must
define main().
• The statement System.out.println() allows us to print the argument to the
standard output with a call to the System class. System.out is an object used
for sending output to the screen and println is a method that this object
invokes.

Public and Private Variables


Java uses three explicit keywords and one implied keyword to set the boundaries
in a class: public, private, and protected. The default access specifier for the names
of variables and methods is “package visibility” or “friendly,” which means that
all the other classes in the current package have access to them. (Packages are
Java's way of grouping classes to make libraries and will be discussed later.) The
access specifier public means that the variables and methods are available from
any package; private implies that the variables and methods can only be accessed
inside methods of the same class. The keyword protected indicates additional
access to variables and methods that are available to subclasses. We will clarify its
meaning when we discuss inheritance.

One reason to make a variable private is to restrict access to it. Access becomes an
issue for threading which refers to the sequence of execution of program code. For
example, we would want to avoid changing the value of a variable while another
portion of the code is trying to read it. Make x private and see what happens when
you run MyApplication.

If we declare x, y, and mass as private variables, we have to include explicit


methods in Particle to allow another class to access the variable information in
Particle. For simplicity, we will consider only the variables x and mass. Our
Particle class becomes:

public class Particle


{
private double x;
private double mass;

public Particle(double x)
{
this(x, 1.0);
}

public Particle(double x, double mass)


{
this.x = x;
this.mass = mass;
}

public double getX()


{
return x;
}

public void setX(double newX)


{
x = newX;
}

public double getWeight()


{
return 9.8*mass;
}

public double distanceFromOrigin()


{
return Math.abs(x);
}
}

Note the new methods getX and setX. They are used in the following.

public class MyApplication


{
public static void main(String[] args)
{
Particle p = new Particle(10.0, 2.0);
System.out.println("Distance of particle from origin = " +
p.distanceFromOrigin());
System.out.println("x-coordinate = " + p.getX()); // would have written p.x if x
were public
System.out.println(weight = " + p.getWeight());
p.setX(3.0); // change value of x
System.out.println("new x-coordinate = " + p.getX());
System.out.println("new distance from origin = " + p.distanceFromOrigin());
}
}

In the following, we will not make variables such as x and y private, because they
will be used in so many classes.

Using the Particle class


We now redefine the class Particle to include a method to compute the distance
between two particles. The application that follows creates two particles and gives
their mutual separation.

public class Particle


{
double x, y, mass;

public Particle(double x, double y)


{
this(x, y, 1.0);
}

public Particle(double x, double y, double mass)


{
this.x = x;
this.y = y;
this.mass = mass;
}

public double distanceFrom(Particle a)


{
double r2 = Math.pow(this.x - a.x, 2) + Math.pow(this.y - a.y,2);
return Math.sqrt(r2);
}

public double distanceFromOrigin()


{
return Math.sqrt(x*x + y*y);
}
}
public class MyApplication
{
public static void main(String[] args)
{

Particle a = new Particle(5.0, 7.0);


Particle b = new Particle(1.0, 2.0);
System.out.println("Distance of a from b = " + a.distanceFrom(b));
System.out.println("Distance of b from a = " + b.distanceFrom(a));
}
}

Extending a class
Object oriented programming allows the user to reuse existing code rather than
rewrite it. Classes have a hierarchical relationship, allowing the user to extend or
modify the behavior of classes derived from base classes using inheritance. For
example, we can expand the Particle class to include charged particles. The new
class ChargedParticle will combine all the behavior and functionality of Particle
with the ability to have a charge. We can implement ChargedParticle as an
extension of Particle as shown below.

public class ChargedParticle extends Particle


{
// magnitude of electron charge in Coulombs
public static final double ELQ = 1.602e-19;
private int charge;

public ChargedParticle(double x,double y, double mass, int charge)


{
super(x, y, mass); // constructor for Particle
this.charge = charge;
}

public int getCharge()


{
return charge*ELQ;
}

public void setCharge(int newCharge)


{
charge = newCharge;
}

public static int netCharge(ChargedParticle a, ChargedParticle b)


{
return a.charge + b.charge;
}
}

An example of the use of this new class is given below.

public class MyApplication


{
public static void main(String[] args)
{

// particle charge is expressed in units of electron charge


ChargedParticle a = new ChargedParticle(10.0,0,0,1);
System.out.println("distance of a from origin = " + a.distanceFromOrigin());
System.out.println("charge of a = " + a.getCharge());
System.out.println("charge of a in coulombs = " +
ChargedParticle.ELQ*a.getCharge());
ChargedParticle b = new ChargedParticle(-5.0,0,0,-1);
System.out.println("distance of b from origin: " + b.distanceFromOrigin());
System.out.println("charge of b = " + b.getCharge());
System.out.println("net charge of a and b = " + ChargedParticle.netCharge(a,b));
b.setCharge(3);
System.out.println("new charge of b = " + b.getCharge());
System.out.println("net charge of a and b = " + ChargedParticle.netCharge(a,b));
}
}

Note how the (named) constant ELQ, the charge of an electron, has been
introduced.

• The keyword super refers to the constructor of the base class, in this case
Particle. An inherited subclass contains all the members of the superclass
except the private ones. Thus a derived class can receive the same messages
as a base class.
• A variable declared final is a constant. Its value must be specified when it is
declared and this value cannot be changed. The static keyword means that
there is only one copy of this variable, regardless of the number of
instances of the class that are created. (A better name is class variable.) The
C convention of using CAPITAL letters for constants will be used
whenever it will not cause confusion.

The method setCharge defines the behavior of a particular object. In contrast, the
static method netCharge belongs to the class and not to a particular instantiation of
the class. To call a static method we use the class name rather than an instance
name. Thus, to call the method netCharge we use ChargedParticle.netCharge(a,b)
not a.netCharge(a,b). A static method is equivalent to a global function in C.

Static methods (class methods) and static variables, belong to a class and not a
given instance of the class. The following example illustrates the nature of static
variables:

public class StaticTest


{
public static int x = 0;
public int y = 0;

public String getCoordinates()


{
return "x = " + x + ", y = " + y;
}

public static void main(String[] args)


{
StaticTest a = new StaticTest();
StaticTest b = new StaticTest();
a.x = 5; // static variable
a.y = 12; // instance variable
System.out.println(a.getCoordinates()); // outputs 5, 12
b.x = 7;
b.y = 13;
System.out.println(a.getCoordinates()); // outputs 7, 12
System.out.println(b.getCoordinates()); // outputs 7, 13
StaticTest.x = 2;
System.out.println(a.getCoordinates()); // outputs 2, 12
System.out.println(b.getCoordinates()); // outputs 2, 13
}
}

The (static) x member belongs to class Test and hence belongs to a and b. There is
only one variable x and thus the value of x is always the one most recently
specified. In contrast, y belongs to the instances a and b of the class Test and
hence a.y and b.y are distinct variables.

The String type is unique among all classes because it is the only class to support
an operator: the + operator can be used to concatenate strings. When a number is
concatenated with a string, the number is converted to a string. Because a String
variable is an object, it has methods. (The class String is different than other
classes.) Some of its associated methods are summarized in Table 4.

Arrays
An array is a special object containing a group of contigious memory locations
that have the same name and the same type and a separate variable containing an
integer constant equal to the number of array elements. The elements of Java
arrays are numbered starting from 0.

An array must be created before it can be used. We first declare a reference or


"handle" to an array that permits Java to locate the object in memory when it is
needed. Then we create an array object to assign to the reference using the new
operator. For example, we can write

double x[]; // create an array reference


x = new double[5]; // create array object

Or we can create an array reference and an array object on a single line:

double x[] = new double[5];

The number of elements in the array x is x.length. The elements of the array are
written as x[0], x[1], x[2], x[3], x[4].

An array object may be created and initialized when its reference is declared. For
example,

double x[] = {1.0, 1.4, 1.6, 1.8, 3.0};

It is a good idea to declare array sizes using named constants (final variables) so
that the length of the arrays can be easily changed.

final int ARRAY_SIZE = 1000;


double x[] = new double[ARRAY_SIZE];
Two-dimensional arrays
A two-dimensional array is implemented by creating a one-dimensional array each
of whose elements is also an array. We first declare a reference to an array of
arrays and then create the individual arrays associated with each element. For
example
double x[][]; / create reference to an array of arrays
Then we can write for example,
x = new double[3][5]; create array objects
Methods and Scope

The general form of a method definition is


return-value-type method-name(parameter list)
{
declarations and statements
(return statement)
}

• The return-value-type is the data type of the result returned by the method
to the caller. If no value is returned, the return-value-type is void. If the
return-value-type is not void, then there must be a return statement.
• The parameter-list is a comma-separated list containing the parameters
received by the method whenever it is called. A type must be declared for
every parameter in the list. If the parameter-list is empty, the parentheses is
still required.
• Variables that are used within a method and that are not accessible by
calling methods are local variables.
• Java programs communicate with their methods using pass-by-value. The
method works with a copy of the original argument, not the argument itself
which means that the method cannot modify the original argument even if it
modifies the parameter. A program that illustrates pass-by-value os shown
below.

public class TestPassByValue


{
public static void main(String[] args)
{
// instantiate a TestPassByValue object
TestPassByValue t = new TestPassByValue();
int i = 1; // local variable
System.out.println("value of i before test = " + i);
// pass value of local variable
int j = t.test(i);
System.out.println("value of i after test = " + i);
System.out.println("value of j = " + j);
j = t.test2(j);
System.out.println("value of i after test2 = " + i);
System.out.println("value of j after test2 = " + j);
}

public int test (int i)


{
i = ++i; // same as i = i + 1;
System.out.println("value of i in test = " + i);
return i;
}

public int test2 (int k)


{
int i = k; // i refers to instance variable
System.out.println("value of k = " + k);
i = ++i;
System.out.println("value of i in test2 = " + i);
return i;
}
}

Variables have either class scope or block scope. Methods and the instance
variables of a class have class scope. Class scope begins at the opening left brace
and ends at the closing right brace of the class definition. Class scope allows any
method in the class to directly invoke any other method in the class and to directly
access any instance variable of the class. In effect, instance variables are global
variables within a class. Instance variables can be used to communicate between
methods in a class or to retain information between calls of a given method in the
class.

A block is a compound statement and consists of all the statements between an


opening and closing brace. Variables defined inside a block have block scope.
Variables defined within a block have block scope and are visible within the
block; they are not visible outside the block.

A variable can have the same name as an instance variable as an instance variable
or method in the class in which the method is defined. In this case the instance
variable is hidden from the method by the local variable. Example:

public class Point


{
// define instance data
public double x,y; // instance variables

// define constructors

public Point()
{
x = 1; // same variables as instance variables
y = 1;
}

public Point (double x, double y)


{
this.x = x; // this.x refers to instance variable
this.y = y;
this.x++;
System.out.println("this.x = " + this.x);
System.out.println("x = " + x); // parameter variable
}

public Point (double x, double y, boolean dummy)


{
x++;
System.out.println("x = " + x);
}
}

public class TestPoint


{
public static void main(String[] args)
{

/* Need an instance of class Particle - a particle object;


assign it to the variable a which is of type Particle. */

Point a = new Point(2.0,1.0);


System.out.println("x = " + a.x);
Point b = new Point();
b.x = 3.0;
System.out.println("xb = " + b.x);
}
}

Simple Graphics
A powerful feature of Java is its ability to do graphics relatively simply. We next
introduce several methods in the Particle class to draw a representation of the
particle.
import java.awt.*;
public class Particle
{
double x,y;
Color color; // part of AWT package

public Particle(double x, double y)


{
// constructor with color variable
this.x = x;
this.y = y;
color = Color.blue; // define default color
}

// Draw representation of particle in given graphics context


public void draw(Graphics g)
{
Color oldColor = g.getColor();
g.setColor(color);
g.fillOval((int)x, (int)y, 12, 12);
g.setColor(oldColor);
}

public Color getColor()


{
return color;
}

public void setColor(Color newColor)


{
color = newColor;
}

public void move(double dx, double dy)


{
x += dx; // same as x = x + dx;
y += dy;
}
}

• The import statement allows us to use the Java libraries. The notation
java.awt.* means that all the classes in the java.awt package can be used.
This package implements the Java Abstract Window Toolkit (AWT) and
contains all the classes and interfaces necessary for creating a user
interface. Packages are a way of grouping a collection of related classes. A
description of all the packages is given at the Sun Web site.
• We have used the java.awt.Graphics class which provides drawing and
painting methods. The method draw has an argument g of type Graphics.
Think of g as a part of the screen (a bit map) where painting will take place
and the methods that are associated with it.
• The four principal elements need to create a GUI include:
1. Components. A component is a visual object containing text or
graphics that can respond to keyboard or mouse inputs. Examples of
components include buttons, labels, text boxes, check boxes, and
lists. A blank component is known as a canvas, which can be used
as a drawing area for text or graphics. All components inherit a
common set of methods, the most common of which is paint.
2. A container is a graphical object that can hold components or other
containers. The most important type of container is a Frame.
3. Layout Manager. A layout manager is automatically associated
with each container when it is created, but the layout manager can be
changed. Examples include BorderLayout, BoxLayout, GridLayout.
4. Event Handlers. Events, such as the click of a mouse, are handled
by creating listener classes which implement listener interfaces.
The standard listener interfaces are in java.awt.event.

The following simple class draws the particle:


import java.awt.*;
public class ParticleDrawer extends Frame
{
public static void main(String[] args)
{
// Create new frame
ParticleDrawer frame = new ParticleDrawer();
}

// Construct ParticleDrawer frame


public ParticleDrawer()
{
// predefined methods
setSize(512, 342); // units of coordinate system in pixels
setVisible(true);
}

// Paint particles
public void paint(Graphics g)
{
Particle p = new Particle(3.1, 4.1);
p.draw(g);
p.move(26.5, 35.8);
p.setColor(Color.red);
p.draw(g);
}
}

• A frame is a very simple window, with a border, a place for a title, and a
close window button.
• Note how the {paint method is used. It is not called directly. Instead,
whenever the frame is shown, the paint method is called. In addition, if one
covers the frame with another window, the paint method will be called
again when the frame is uncovered. To directly call the paint method, use
the repaint() method.

As an example we draw the trajectory of a projectile. To do so we add to Particle


the method step to integrate the equations of motion for one time step. The
arguments of step are the time step and the Force on the particle, which is defined
in another class. We also add other useful methods.
public class Particle
{
private double x,y,vx,vy,ax,ay;
private double mass = 1.0;
private boolean firststep = true;

public Particle(double x, double y, double vx, double vy)


{
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
}

public double getMass()


{
return mass;
}

public void setMass(double mass)


{
this.mass = mass;
}
public double getX()
{
return x;
}

public double getY()


{
return y;
}

public double getVx()


{
return vx;
}

public double getVy()


{
return vy;
}

public double getAx()


{
return ax;
}

public double getAy()


{
return ay;
}

public void setX(double x)


{
this.x = x;
}

public void setY(double y)


{
this.y = y;
}

public void setVx(double vx)


{
this.vx = vx;
}

public void setVy(double vy)


{
this.vy = vy;
}

public void step(double dt, Force f)


{
if (firststep)
{
ax = f.getfx(x,y,vx,vy,this)/mass; // acceleration at beginning of interval
ay = f.getfy(x,y,vx,vy,this)/mass;
firststep = false;
}
// Euler-Richardson algorithm
double vxm = vx + 0.5*ax*dt; // velocity at middle of interval
double vym = vy + 0.5*ay*dt;
double xm = x + 0.5*vx*dt; // position at middle of interval
double ym = y + 0.5*vy*dt;
double axm = f.getfx(xm,ym,vxm,vym,this)/mass;
double aym = f.getfy(xm,ym,vxm,vym,this)/mass;
vx += axm*dt; // velocity at end of interval
vy += aym*dt;
x += vxm*dt; // position at end of interval
y += vym*dt;
ax = f.getfx(x,y,vx,vy,this)/mass; // acceleration at end of interval
ay = f.getfy(x,y,vx,vy,this)/mass;
}
}

public class Force


{
private final static double g = 9.8; // not convention
double b = 0; // used in drag force

public void setb(double b)


{
this.b = b;
}

public double getfx(double x, double y, double vx, double vy, Particle p)


{
return -b*vx;
}

public double getfy(double x, double y, double vx, double vy, Particle p)


{
return -b*vy - g*p.getMass();
}
}

Note that {\tt If} statements are the same as in C/C++ except that Java uses a
boolean value to condition the execution. Summary of relational operators.

The step method implements the Euler-Richardson integration algorithm. We need


to compute the acceleration at the beginning of the interval the first time the
algorithm is used. Then we can use the acceleration computed at the end of the
previous interval. Note how this is used in the step method to refer to the Particle
itself; in Force we use the argument Particle to get the particle's mass.

The class that draws the trajectory is given below.

import java.awt.*;
public class Simulation extends Frame
{
public static void main(String[] args)
{
Simulation sim = new Simulation(); // set up window for application
}

public Simulation()
{
setSize(512,342);
setVisible(true);
}

public void paint(Graphics g)


{
setBackground(Color.white);
calculateTrajectory(g);
}
private void calculateTrajectory(Graphics g)
{
final double tmax = 10.0;
final double dt = 0.5;
Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
Force f = new Force();
g.setColor(Color.blue);
double time = 0.0;
while (time < tmax)
{
// draw circle of diameter 10 pixels. note use of casting
g.drawOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
p.step(dt,f);
time += dt;
}
}
}

• The Simulation class extends the Frame class. The paint method is called
when the Frame is first shown and anytime Frame is brought to the front.
• Java uses a coordinate system whose origin is at the upper left-hand corner
with positive x values to the right and positive y values down. Because of
this choice of screen coordinate system, we need to convert world
coordinates to screen coordinates when drawing an oval to represent the
particle. Because the last two arguments of drawOval are the same, the oval
is a circle. (Note that drawOval requires integers.)
• Note the use of the while statement which allows all the statements within
the braces of the while statement to be executed again and again as long as
the argument of the while statement (time < tmax) is true.
• An alternative to the while loop is the for loop which looks like
• for (int i = 0; i < 10; i++)
• statement;

or

for (int i = 0; i < 10; i++)


{
statement 1;
...
statement n;
}
Semicolons are used to separate the fields inside the parenthesis. The first
field initializes a variable. Usually, the variable is also declared here. The
second field determines under what condition the loop will continue. The
third field lists how the variable in the first field changes at the end of each
pass through the loop. More information about loops.

Offscreen buffers
When the window of another application covers the frame, Java automatically
calls paint when the user returns to our original program. This action allows us to
see the contents of the original window. However, in the above program it means
that the trajectory must be recomputed. A better approach is to first draw the
trajectory to an offscreen image buffer and then blast the latter to the screen. As
long as the buffer is saved, no new calculations need to be done.

First we will show how this is done for the Simulation class and then we will show
an example where it is more useful. // Image and Graphics do not use constructors.

import java.awt.*;
public class Simulation extends Frame
{
Image offscreen; // make image class variable so available to all methods

public static void main(String[] args)


{
Simulation sim = new Simulation(); // set up window for application
}

public Simulation()
{
setSize(512, 342);
setVisible(true);
offscreen = createImage(getSize().width, getSize().height);
calculateTrajectory();
}

public void paint(Graphics g)


{
setBackground(Color.white);
g.drawImage(offscreen, 0, 0, this); // draw image onto screen
}

public void calculateTrajectory()


{
final double tmax = 10.0;
final double dt = 0.5;
Graphics g = offscreen.getGraphics();
g.setColor(Color.blue);
Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
Force f = new Force();
double time = 0.0;
while (time < tmax)
{
g.drawOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
p.step(dt,f);
time += dt;
}
}
}

• The Graphics class is used here to provide drawing methods for offscreen,
which is an instantiation of the Image class. Both Graphics and Image
cannot be instantiated directly with a constructor, instead we can use the
getGraphics and createImage methods, respectively. The Image class
represents a displayable image.
• Note how we declare offscreen outside of any method, and instantiate it
with the createImage method in the constructor. This is a common
technique for making objects accessible to all the methods of a class, and to
insure that they continue to exist after a method returns.

User Interaction
Offscreen buffers are useful when we want to draw more than one trajectory
without running the program over again. To do so we want the user to interact
with the program. This feature is very easy to accomplish using components such
as Buttons, TextFields, and Menus. Below we show how to use a TextField to
receive a number from the user. We put the TextField on a separate frame and use
an actionListener to detect whether the user has entered a number in the
TextField. The number entered will be the friction coefficient, b, used in a drag
force of the form -bv.
import java.awt.*;
import java.awt.event.*; // needed for actionListener

class ParameterInput extends Frame


{
TextField tf;
Label lb;
Simulation sim;

public FrictionInput (Simulation sim) // pass address of object


{
this.sim = sim;
setUpFrame();
}

public void setUpFrame()


{
setTitle("Friction Input");
setSize(200,100);
setLocation(400,50); // location for frame
setLayout(null); // not using any layout manager
lb = new Label("Friction Coefficient"); // new label for textfield
lb.setSize(150,20);
lb.setLocation(30,70);
add(lb); // add label
tf = new TextField(); // new textfield
tf.addActionListener(new actionTF()); // add listener
tf.setSize(50,20);
tf.setLocation(30,40);
add(tf); // add textfield
setVisible(true);
}

class actionTF implements ActionListener // example of Internal class


// user has to tell ActionLister what to do so have to implement it.
{

public void actionPerformed(ActionEvent e)


{
Double R = new Double(tf.getText().trim()); // convert text to number
// trim gets rid of extra zeros
sim.calculateTrajectory(R.doubleValue());
}
}
}

• There are two objects attached to the Frame. Label lb represents some text
that will be placed under the TextField tf. The size and location of each of
these components is specified. There are layout managers that
automatically decide these specifications for you, but they frequently do not
look good.
• One of the features of Java is the use of the actionListener which is
implemented by using the addActionListener method and an internal class
which implements the ActionListener interface. An interface is like a class
except none of the methods have implementations. Instead the user must
supply these as we have done above for the method
actionPerformed(ActionEvent e). The beauty of the above event model is
that the user does not have to write code to check for an occurence of an
event in other parts of the program. Whenever, a number is entered into the
TextField, the actionPerformed method will be executed. Here we extract
the number by converting the string in the TextField to a number using the
Double class, and then call the calculateTrajectory method of the object
sim.

The following modification of Simulation uses FrictionInput.

import java.awt.*;

public class Simulation extends Frame


{
private Image offscreen;
private int counter = 0; // used to change color for each trajecto
public static void main(String[] args)
{
Simulation sim = new Simulation(); // set up window for application
FrictionInput fi = new FrictionInput(sim); // set up second window
}

public Simulation() // constructor


{
setSize(512, 342);
setVisible(true);
offscreen = createImage(getSize().width, getSize().height);
}

public void paint(Graphics g)


{
setBackground(Color.white);
g.drawImage(offscreen, 0, 0, this); // draw image on screen
}

public void calculateTrajectory(double b)


{
final double tmax = 10.0;
final double dt = 0.5;
Graphics g = offscreen.getGraphics(); // create buffer
changeColor(g);
Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
Force f = new Force();
f.setb(b);
double time = 0.0;
while (time < tmax)
{
g.drawOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
p.step(dt,f);
time += dt;
}
repaint();
}

public void changeColor(Graphics g)


{
switch(counter++)
{
case 0:
g.setColor(Color.red);
break;
case 1:
g.setColor(Color.blue);
break;
case 2:
g.setColor(Color.green);
break;
case 3:
g.setColor(Color.yellow);
break;
case 4:
g.setColor(Color.magenta);
break;
case 5:
g.setColor(Color.orange);
break;
case 6:
g.setColor(Color.cyan);
break;
case 7:
g.setColor(Color.pink);
break;
default:
g.setColor(Color.black);
}
}
}

• Note the use of the method repaint which clears the Frame and calls paint.
However, all the trajectories are still on on the offscreen buffer so that they
will all appear on the screen.
• We have added a method, changeColor, which uses a different color each
time a new trajectory is drawn, up to 8 trajectories. Any more trajectories
are colored black. Note the use of the switch statement. Each time a
trajectory is drawn, the value of counter is checked and then incremented
(using counter++. (Note that counter++; means that the current value of
counter is used in the switch statement before it is incremented by 1. If we
used ++counter; instead, counter would be incremented by 1 first.) The
value checked then determines which statement to execute. Also note the
use of the break statement. Without it every case would be executed.
• The switch statement is useful if there are many possible choices. If there
are only a few choices or if the choices cannot be encoded as an integer,
then the if statement can be used. Examples of the latter are as follows:
• if (x < 0)
• {
• y = 20;
• x = 10;
• }

• if (x < 0)
• y = 10; // braces not needed for single statement
• else
• y = 20;

• if (x < 0)
• y = 10;
• else if (x > 0)
• y = 20;
• else
• y = 30;

Animation
We now return to a single trajectory and discuss animation. Instead of showing the
trajectory we will simply show a ball as it moves. The following code does this so
that there is very little flicker. We have reduced the time step so that the motion of
the ball will be slowed down.

import java.awt.*;

public class Simulation extends Frame


{
Image offscreen;

public static void main(String[] args)


{
Simulation sim = new Simulation(); // set up window for application
sim.calculateTrajectory();
}

public Simulation()
{ // constructor
setSize(512, 342);
setVisible(true);
offscreen = createImage(getSize().width, getSize().height);
}

public void paint(Graphics g)


{
setBackground(Color.white);
g.drawImage(offscreen,0,0,this);
}

public void calculateTrajectory()


{
final double tmax = 10.0;
final double dt = 0.005;
Graphics b = offscreen.getGraphics();
Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
Force f = new Force();
double time = 0.0;
while (time < tmax)
{
Rectangle oldRect = new Rectangle((int)p.getX(),getSize().height -
(int)p.getY(),11,11);
p.step(dt,f);
time += dt;
Rectangle newRect = new Rectangle((int)p.getX(),getSize().height -
(int)p.getY(),11,11);
// new region of ball
Rectangle r = newRect.union(oldRect); // new plus old region
// b is buffer. key to avoid flicker is not to call repaint
b.clearRect(r.x,r.y,r.width,r.height); // clear new plus old region on buffer
b.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
Graphics g = getGraphics();
g.drawImage(offscreen,0,0,this);
}
}
}

The basic strategy used above is to define three rectangles. One containing the old
position of the ball, one containing the new position, and one which is the union of
the two. Then we clear the buffer of this latter rectangle, and draw our new ball.
We then draw our image to the screen. Note how we grab the Graphics object for
the screen within calculateTrajectory instead of using repaint. This avoids some of
the flickering that would occur from clearing the Frame.

Threads
Often we want the user to be able to interrupt a simulation while it is running, and
then start it going again. For example, we might want to know the coordinates of
our ball at some instant while we are watching it. One can use Threads to
accomplish this. Basically, a Thread is a process which is running parallel to
another process. Below we set up a Thread and use a MouseListener to interrupt
the program. The interface Runnable contains the methods we need to start, stop,
and run the Thread.
import java.awt.*;
import java.awt.event.*;

public class Simulation extends Frame implements MouseListener, Runnable


{
Image offscreen;
Graphics gb; // graphics buffer
Particle p;
Force f;
boolean running = false;
Thread runner;

public static void main(String[] args)


{
Simulation sim = new Simulation(); // set up window for application
}

public Simulation()
{ // constructor
setSize(512, 342);
setVisible(true);
offscreen = createImage(getSize().width, getSize().height);
p = new Particle(0.0, 200.0, 40.0, 25.0);
f = new Force();
gb = offscreen.getGraphics();
start(); // method associated with thread
addMouseListener(this); // this refer to frame class
}

public void paint(Graphics g)


{
setBackground(Color.white);
g.drawImage(offscreen,0,0,this);
}

public void start()


{
runner = new Thread(this); // this refers to frame
runner.start();
}

public void stop()


{
runner.stop();
}

public void run()


{
while(true)
{
try {Thread.sleep(5);} // delay 5 msec between updates
catch (InterruptedException e){}; // would catch the moue click
if(running) calculateTrajectory();
}
}
public void mouseClicked(MouseEvent e)
{
// see coordinates
Graphics g = getGraphics();
g.clearRect(0,0,getSize().width, getSize().height);
g.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
g.drawString("x = " + String.valueOf(p.getX()),e.getX(),e.getY());
g.drawString("y = " + String.valueOf(p.getY()),e.getX(),e.getY() + 30);
running = false;
}

public void mouseEntered(MouseEvent e) {running = true;}


// move inside frame, runs; otherwise stops
public void mouseExited(MouseEvent e) {running = false;}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}

public void calculateTrajectory()


{
// should be draw trajectory
private final double dt = 0.005;
Rectangle oldRect = new Rectangle((int)p.getX(),getSize().height -
(int)p.getY(),11,11);
p.step(dt, f);
time += dt;
Rectangle newRect = new Rectangle((int)p.getX(),getSize().height -
(int)p.getY(),11,11);
Rectangle r = newRect.union(oldRect);
gb.clearRect(r.x,r.y,r.width,r.height);
gb.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
Graphics g = getGraphics();
g.drawImage(offscreen,0,0,this);
}
}

We have modified calculateTrajectory so that it only computes and draws one


step. We have eliminated the while statement. Instead control of the trajectory is
given to the run method of the Thread runner. The try catch statement is used to
interrupt the Thread for 5 milliseconds to check to see if any event occurred. The
MouseListener checks for events. In this case we can stop the motion by moving
the mouse outside the Frame, and start it again by moving it into the Frame and
start it again by moving it into the Frame. If the mouse is clicked, we write the x
and y coordinates of the ball at the locatiuon of the mouse click, redraw the ball,
and stop the motion. Note that the interface methods mousePressed and
mouseReleased must be defined even though they do not do anything in this
example.

Você também pode gostar