Java's designers state that it is a simple, robust, object-oriented, architecture-neutral, portable, secure, multithreaded, distributed, interpreted, dynamic, and high-performance language.
A Java program is nothing more than a collection of classes, optionally grouped into packages. Here is a simple program made up of one class that is not part of a package
/**
* An application class that writes a little greeting.
*/
public class Greeter {
/**
* Writes a greeting followed by the first command line argument
* if one is present.
*/
public static void main(String[] args) {
System.out.print("Hello there");
if (args.length > 0) {
System.out.print(", " + args[0]);
}
System.out.println(".");
}
}
If you are using Sun's JDK 6 compiler, you would put the above code into the file Greeter.java and compile it like this
This would produce the file Greeter.class, which is only 674 bytes in size (only 580 if you compile with javac -g:none Greeter.java).
Class files are interpreted (run) by a Java interpreter. A Java interpreter can be
(Class files can also be turned into native code before/during interpretation.)
Using Sun's JDK 6, the invocation
interprets (executes) Greeter.class. That's just another way to say "runs the application". Java is said to be "portable" because these class files contain byte codes for an abstract machine which are interpreted, and you can write interpreters for many platforms. There are interpreters running on Solaris, Linux, Windows and many other operating systems as well as consumer electronic devices.
(Note, however, that the "portability of Java" is due only to this Java Virtual Machine, on which class files are interpreted, rather than to the Java language. Hundreds of other languages can be compiled into class files too!)
Generally you make classes so that you can make objects of that class.
/**
* A simple cylinder.
*/
public class Cylinder {
private double radius;
private double height;
public Cylinder(double r, double h) {radius = r; height = h;}
public double getRadius() {return radius;}
public double getHeight() {return height;}
public double getVolume() {return capArea() * height;}
public double getSurfaceArea() {return 2 * capArea() + sideArea();}
private double capArea() {return Math.PI * radius * radius;}
private double sideArea() {return 2.0 * Math.PI * radius * height;}
public void widen(double factor) {radius *= factor;}
public void lengthen(double factor) {height *= factor;}
}
The class in this file contains two fields (radius and height), one constructor, and eight methods (getRadius, getHeight, getVolume, getSurfaceArea, capArea, sideArea, lengthen and widen). Compiling this file with Sun's JDK 6 compiler makes the file Cylinder.class. You can give this small class file to a friend who doesn't believe that a glass which is twice as wide as another glass holds four times as much water. Then your friend could write the following:
/**
* An application that creates some cylinders and calls a couple
* methods, just for fun.
*/
public class VolumeChecker {
public static void main(String[] args) {
Cylinder c1 = new Cylinder(1, 4);
Cylinder c2 = new Cylinder(1, 4);
Cylinder c3 = c2;
c2.widen(2);
System.out.println("Volume of first glass is " + c1.getVolume());
System.out.println("Volume of second glass is " + c2.getVolume());
System.out.println("Volume of third glass is " + c3.getVolume());
}
}
Here we made two objects of the class Cylinder. Objects are created with the "new" operator. The first object is referenced by the variable c1 while the second is referenced by the variables c2 and c3. Never confuse the term 'variable' with the term 'object'. They are completely different things! See how we have three variables but two objects:

The "new" operator in Java allocates memory for the cylinder objects, but the programmer never explicitly deallocates memory for objects. The Java runtime automatically does garbage collection of objects that are no longer referenced.
Logically, Java programs are made up of classes that are grouped into packages. Physically, your program is written in a collection of source code files. Almost every Java compiler in the world forces this organization:

Each class definition is compiled into a .class file. Packages can be split over several source code files, but each class has to be wholly contained in a file.

If you don't give a package declaration your class(es) will go in the "default package". This is considered unprofessional and stupid, but it's fine when you are learning or experimenting.
People have written millions of classes since Java was created, but a few thousand of them have been collected into one of Java's standard, or core, APIs. The APIs vary by platform, of which there are three:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* An application which displays each of the times on a twelve-hour
* clock that the hour and second hands make an angle of 180 degrees.
*/
public class AntiparallelClockHandsComputer {
public static void main(String[] args) {
long midnight = new GregorianCalendar(0, 0, 0).getTimeInMillis();
for (int i = 0; i < 12; i++) {
Date d = new Date(midnight + Math.round((0.5+i) * 43200000/11.0));
System.out.println(new SimpleDateFormat("hh:mm:ss").format(d));
}
}
}
Our AntiparallelClockHandsComputer class uses the classes
java.lang.String
java.lang.System
java.lang.Math
java.text.SimpleDateFormat;
java.util.Date;
java.util.GregorianCalendar;
The import statements at the top of the source file allow us to avoid specifying the full name of these classes throughout our code. Note that import statements are never necessary, they are simply a convenience. (Also note that classes from java.lang don't have to be mentioned in import statements.)
Besides the 202 "core" packages, there are many hundreds of additional packages that you can buy or download for free.
The core classes are, as a rule, bundled into the file rt.jar which your compiler always knows how to find.
Java has evolved over time. Java SE has evolved like this:
| Version | Released | Packages in Core API |
Classes in Core API |
What's New |
|---|---|---|---|---|
| 1.0 | 1995 | 8 | 210 | |
| 1.1 | 1997 | 22 | 477 | I/O design flaws fixed; inner classes; internationalization; AWT enhancements; JavaBeans API; JARs; RMI; reflection; JDBC; JNI; ... |
| 1.2 | 1999 | 59 | 1524 | Swing; collections; Permissions, policies, certificates, signers; Java2D; accessibility API; extensions framework; RMI enhancements; reference objects; sound; ... |
| 1.3 | 2000 | 76 | 1840 | JNDI; Java Sound; Swing and Java2D enhancements; Security enhancements; Networking enhancements; Improved serialization support; Input method framework; timers; ... (Sun released the HotSpot VM during this time.) |
| 1.4 | 2002 | 135 | 2723 | New IO library (NIO); assertions; XML, crypto, SSE, authentication added to core API; Image IO; Java Print Service; many Swing enhancements; Logging API; WebStart; JDBC 3.0; Chained Exceptions; IPv6; Unicode 3.0; Regexes; ... |
| 5.0 | 2004 | 166 | 3279 | Generics; better for statement; annotations; enumerations; sophisticated concurrency packages; autoboxing; varargs; static import; Unicode 4.0 (uh-oh); tons of library enhancements; ... |
| 6.0 | 2006 | 202 | 3777 | Scripting languages can be embedded; XML and web services; JDBC 4; Many GUI enhancements (e.g. for tables and trees); monitoring and management, programmatic access to compiler; pluggable annotations; improved desktop deployments; a few more security apis; ... |
The official reference for the language is The Java Language Specification. It contains a nice one-page syntax of the language.
Some useful items follow here anyway:
Reserved words are words that cannot be used as identifiers.
abstract continue for new switch
assert default if package synchronized
boolean do goto private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while
Note that false, true, and null are not reserved words, but they are literals of built-in types, so you can't use them as identifiers even if you tried.
The statements are
Here are the Java operators, presented from highest to lowest precedence.
| Operators | Operand Types | Associativity | Arity | Description |
|---|---|---|---|---|
| ++, -- +, - ~ ! (typename) | arithmetic arithmetic integral boolean any | R | 1 | increment and decrement unary plus and minus bitwise complement logical not cast |
| *, /, % | arithmetic | L | 2 | multiplication, division, remainder |
| +, - + | arithmetic string | L | 2 | addition, subtraction concatenation |
| << >> >>> | integral | L | 2 | left shift right shift with sign extension right shift with zero extension |
| <, <=, >, >= instanceof | arithmetic object/type | L | 2 | arithmetic comparison has type |
| == != == != | primitive primitive object object | L | 2 | equal values different values refer to same object refer to different objects |
| & | integral boolean | L | 2 | bitwise AND boolean AND |
| ^ | integral boolean | L | 2 | bitwise XOR boolean XOR |
| | | integral boolean | L | 2 | bitwise OR boolean OR |
| && | boolean | L | 2 | short-circuit boolean AND |
| || | boolean | L | 2 | short-circuit boolean OR |
| ?: | boolean/any/any | R | 3 | if-then-else |
| = *=, /=, %=, +=, –= <<=, >>=, >>>= &=, ^=, |= | variable/any variable/arithmetic variable/integral variable/integral | R | 2 | assignment |
Every expression in Java has a value and a type. There are two kinds of types.
The value of an expression of a primitive type is the primitive entity (like true or 759 or 4322.95 or '@'), but the value of a variable of a reference type (object or array) is either null or a reference to the object or array, NOT the object itself.

Primitive entities can just be written down; objects (and arrays) are only created using "new."
Important: Remember that variables of non-primitive types contain references; therefore, the "=" and "==" operators DO NOT copy and test the equality of object values. (There may be clone() and equals() methods available, or you can define these if needed.)
This example shows how variables of primitive types differ from variables of reference types:
float x;
x = 3; // value 3 stored in x
float y = x; // value 3 stored in y
y = 4; // after this x is still 3
Cylinder c1; // just declares a variable
c1 = new Cylinder(1, 1); // now we have a cylinder created
Cylinder c2 = c1; // does NOT create a new cylinder
c2.widen(2); // exactly the same effect as c1.widen()
c1 = null; // the cylinder still exists
double d = c1.getRadius(); // OOPS!! Throws a NullPointerException
double r = c2.getRadius(); // This is perfectly fine: c2 isn't null
c2 = null; // Now the object is unhooked. It is
// "garbage" and the runtime system
// will eventually reclaim the storage.
An interesting note: variables which are fields of a class are automatically initialized in Java: for primitive types they are automatically initialized to 0 for numbers and false for booleans; for objects they are initialized to null.
There are dozens of "throwable" classes in the Java Core API. Throwables are either errors or exceptions. Exceptions are either runtime exceptions (a.k.a unchecked exceptions) or checked exceptions.
In many cases you will define your own exceptions, but if your situation can use a pre-existing one, please do so. The most common pre-defined exceptions that you will have occasion to throw are:
| Class | Used when |
|---|---|
| IllegalArgumentException | Arguments passed to a method don't make sense. |
| IllegalStateException | An object isn't in the right state to execute this method. |
| NoSuchElementException | You're trying to remove an element from an empty collection, or looking for a specific item that isn't there. |
| UnsupportedOperationException | The requested operation isn't implemented |
Programmers have a couple responsibilites when it comes to using memory and other resources efficiently: