A Quick Intro to Java for C and C++ Programmers
(Thanks to Scott Hudson for providing this)
Will be assuming you are a fluent C or C++ programmer.
This is going to be a quick introduction to the language.
I'm not going to teach anything much about object oriented programming.
nxt
What is Java
-
Java is a programming language designed by James Gosling at Sun
-
Designed to be "squirted" across a network into a device, the primary device
right now being a web browser
-
Interpreted from byte codes (virtual machine approach)
-
Dynamically loaded
-
=> very portable (except...)
-
"A pretty good object oriented language with C++ camouflage on"
-
"The latest thing" and massively hyped
nxt
Why the hype?
-
Was at the right place at the right time (fills an important need on the
web)
-
Highly portable
-
Seen by lots of companies as a way to break the Microsoft monopoly
-
=> huge amounts of money involved
-
=> major corporate politics/warfare (Sun & Netscape vs. Microsoft)
-
Hype builds on itself (bandwagon effect)
nxt
Beyond the Hype
-
Not much fundamentally new here (we have seen almost all the concepts in
other languages before)
-
But, its fairly well designed (which is more than can be said for a lot
of things)
-
Its better than C++ for many uses
-
It was built by someone who knew the "landscape" of programming languages
and has some taste
-
In my opinion its the best current language with wide platform support
(backing of many solid implementations)
nxt
Goals
-
Downloadable into a wide range of devices/platforms
-
Good OO language to replace C++
-
Relatively small/simple/clean language
-
Camouflaged as C++ for sneak attack when C++ was the dominant language
(if you are C++ programmer you will feel mostly at home -- and much happier
in the end)
-
Lots of checking and safety
nxt
Major differences from C++
-
Generally simplified
-
No pointers
-
Actually everything is a pointer (reference), but their are no dangling
pointers!
-
No pointer dereferencing (where you used to say "->" you now always
use ".")
-
Garbage collection added (big big win)
nxt
What's been added from C (all found in C++)
-
Object-oriented concepts & information hiding
-
Stronger typing
-
Constants in the language (not just a macro)
-
Overloading (two functions with the same name, but different parameter
types)
-
New comment style ("//" to end of line)
nxt
What's been added beyond C++
-
More checking
-
Exceptions (yes they were in C++, but...)
-
(Limited) signature based typing ("interfaces" -- a big win)
-
Runtime type identification (plus other reflection capabilities)
-
Built in thread and synchronization support
-
Packages (collections of classes in a namespace)
-
Dynamic runtime loading
-
Strings (as objects)
-
A root class (Object)
-
Unicode character set (16 bit characters)
-
64 bit longs, bytes, booleans (literals true
and false)
-
A (small) container library (hashtables, etc.)
-
Special "doc" comments /** ... */ + post-processing to produce
hyperlinked API documentation (html + special @ directives in
the comments)
nxt
Things that are missing (but we probably won't miss):
-
Virtual functions (everything is virtual!)
-
Virtual base classes
-
Virtual destructors
-
Implicit constructor invocation (and other constructor/destructor weirdness)
-
Arcane type conversion rules (and generally loose typing)
-
16 different meanings for const
-
extern (now have strong load-time checking)
-
->* operator (member pointers)
-
:: (scope operator)
-
void *
-
Null terminated strings
-
Declaration vs. definition (always done together, need not declare before
use)
-
(Brain dead) multiple inheritance
-
Templates
-
Macros, include files, and conditional compilation (the preprocessor)
nxt
Other things that are missing (that we might
miss):
-
Independent functions
-
Pointers to functions
-
Operator functions
-
Default parameters
-
Unsigned types
-
Bare metal performance(?)
nxt
So is it too slow?
-
See item on "huge amounts of money involved" :-)
-
Full story is not in yet, but I estimate with new JIT compiler technology
we will land at about 2-4x C code.(a year or two from now, right now can
be more like 5-10x)
-
Think of this as our machines being 2-3 years older
-
Plenty fast for most interactive applications
nxt
More details on differences with C++...
Lexical level
-
Designed to look almost exactly like C++ (which is almost identical to
C)
-
Minor differences, but not worth mentioning
Syntactic level
-
Designed to look a lot like C++ (which was designed as a superset of C)
...but cleaned up some of the egregious parts
-
Changes:
-
inheritance syntax,
-
initialization in constructors,
-
split definition vs. declaration (and scope operator)
-
protection declaration
Flow control
-
All C/C++ flow control constructs except goto (added labeled break
and continue to handle the few remaining legit uses)
-
if/else for while do/while switch/case/break
-
return break continue
-
throw try/catch/finally
-
Now have booleans and you can't test integers and pointers directly
-
"if (ptr)" must be "if (ptr != null)"
Classes
-
The major construct in Java (like most object oriented languages) is the
class.
-
Classes are a type definition: They define the data and operations of an
object.
-
You can create several instances of objects; several things with
that data and those operations
-
For C programmers you can think of this for now as a struct with the functions
operating on the struct "inside" the struct.
-
For C++ programmers you can think of this as a class.
class point_list {
int x;
int y;
point_list next;
double distance_to(point_list other)
{
double dx, dy;
dx = (double)(x - other.x);
dy = (double)(y - other.y);
return Math.sqrt(dx*dx + dy*dy);
}
double distance_to_next()
{
if (next == null)
return 0;
else
return distance_to(next);
}
}
What have we got here.
-
Three members: 3 instance variables (C++ == fields)
-
two method s(C++ == member functions).
-
Note: There are no functions in Java, just methods (notice that
we had to say Math.sqrt() to get a square root).
-
If we had two points: pt1 and pt2, then we could compute
the distance between them as pt1.distance_to(pt2)
Except... we have some problems here what are they?
1p 2v 3c
nxt
Problem #1
It looks like we just declared a point_list to be part of a point_list...
-
Like C++ there are two distinct forms of data in Java, primitive types
and Objects.
| Primitive types are: |
| byte |
8 bit signed integer |
| short |
16 bit signed integer |
| int |
32 bit signed integer |
| long |
64 bit signed integer |
| boolean |
true or false |
| char |
16 bit character (Unicode) |
| float |
single precision floating point |
| double |
double precision floating point |
| note: exact definition of these is not left up to
the implementation! |
-
Everything else is an object (including arrays and strings!).
-
All variables declared using an object type are actually a reference to
(pointer to) an object of that type.
-
Can have two values: reference to some object, or null.
-
So our next field is a reference to a point list (and we have a classic
singly linked list) and this isn't a problem
back
Problem #2 Visibility
Classes also provide information hiding and the default is to not allow
full access to instance variables or methods. So a better version would
be:
public class point_list {
protected int x;
protected int y;
protected point_list next;
public double distance_to(point other)
{
double dx, dy;
dx = (double)(x - other.x);
dy = (double)(y - other.y);
return Math.sqrt(dx*dx + dy*dy);
}
public double distance_to_next()
{
if (next == null)
return 0;
else
return distance_to(next);
}
}
nxt
Specifying protection
Members can be:
| public |
Accessible to all |
| protected |
Accessible to classes within the same package and subclasses. |
| private |
Accessible only within the class itself |
| <unlabeled> |
Inside package: protected.
Outside package: private (no subclass access outside package). |
Almost all classes are public, but can also be left unlabeled to create
a "local" or "private" class (typically you do not want to do this).
nxt
Point of style
-
Its a good idea for all but the simplest classes to not have any public
instance variables. (This has saved my sorry butt many times!)
-
Instead have a protected variable with read and write access methods.
-
This lets you change your mind later without breaking all the code that
uses yours.
protected int _x;
protected int _y;
public int x() {return _x;}
public void set_x(int val) {_x = val;}
back
Problem #3: No constructor
-
We haven't provided a way to create any useful objects of this type.
-
Java initializes instance variables:
| int, et. al |
0 |
| boolean |
false |
| float, double |
0.0 |
| char |
'\0' |
| Object reference |
null |
-
You can also explicitly initialize variables:
protected int x = 0;
protected int y = 0;
protected point_list next = null;
nxt
Declaring constructors
-
Typically, you want provide a constructor.
-
If you don't provide a constructor, one (that does nothing and takes no
parameters) will be provided for you.
-
Constructor looks like a method with the same name as the class but no
return type:
public point_list(int xv, int yv, point_list nxt)
{
x = xv; y = yv; next = nxt;
}
-
Often want to provide several constructors (Java does not do default parameters):
public point_list(int xv, int yv)
{
this(xv,yv, null);
}
public point_list()
{
this(0,0);
}
-
Notice that we can "chain" constructors together using "this()".
(We can also invoke the super class constructor using "super()").
-
This must be the first thing in the constructor.
back
Some misc basics
-
All parameters are pass-by-value.
-
However, for all object types we are passing references by values, so...
-
Can return at most one value.
-
Arithmetic, etc. operations (precedence, etc.) are the same as C/C++.
-
Except use of comma operator is limited to for statements.
-
Can apply bitwise operations to booleans (but not mixed int/boolean) to
get non-shortcutting operations.
-
== and != mean "refer to the same object".
-
Like C++ can declare variables anywhere a statement is legal (including
inside parens of for statements).
-
Same scoping rules (scope limited to enclosing block: {... } ).
-
Don't have to declare before use.
nxt
Hierarchical Types and Inheritance
-
The big win in object-oriented programming is hierarchical typing and inheritance.
-
Two things of importance:
-
Inheritance: the ability to derive the implementation of something from
some existing code (AKA getting someone else to do the work for you).
-
Substitutability: the ability to write code that doesn't care about exactly
what type it operates over (so you can substitute related but different
types).
nxt
Inheritance
-
In Java (like most OO languages) you can base the implementation of a class
on another class.
-
Basically, you take what is in the other class (the base or superclass)
and then extend it to do new and/or different things.
-
The new class (the derived class or subclass) preserves the
API of the superclass (so it does everything the superclass did)
-
Consequently, an instance of a subclass can be substituted for an instance
of a superclass (a variable that references a the superclass can safely
be used to reference the subclass).
nxt
Declaring inheritance in class declarations
-
Suppose we wanted to create a colored_point_list which keeps a color value
with each point:
public class colored_point_list extends point_list {
protected Color _pt_color;
public Color pt_color() {return _pt_color;}
public void set_pt_color(Color val) {_pt_color = val;}
public colored_point_list(
int xv, int yv, point_list nxt, Color clr)
{
super(xv,yv,nxt);
set_color(clr);
}
}
-
Note the extends clause -- gives the base class we are derived
from.
-
If there is no extends clause we automatically inherit from Object
(the Java root class).
-
Java only supports single inheritance, so you only get to list one thing.
-
Now if we have a piece of code which declares a variable of type point_list,
we can safely let it operate on an object of type colored_point_list.
-
Note also that we call the superclass constructor (might as well let them
do the work here) using the special form: "super(...)".
-
Like "this()" this must be the first thing in the constructor.
nxt
Super
-
Another (completely different) use of super: super can
be used to invoke a method out of the superclass that has be overridden
(replaced) in the subclass.
public class grid8_point_list extends point_list {
public void set_x(int val)
{
int rounded = (val / 8)*8 + ((val%8 >= 4)?1:0);
super.set_x(rounded);
}
...
}
-
Boy its a good thing we put that set_x() in there!
-
Note we call the super class set_x() here and not just directly
set the variable (what's good for the goose...).
nxt
This
-
Sometimes you need to refer to the object itself in one of its methods
(pass it somewhere).
-
Reserved word this is used for this purpose. As in:
manager.put_in_table(this);
-
Note that instance variable references such as "_x" above are
really shorthand for "this._x".
nxt
Abstract classes
-
Its not necessary to completely define a class
-
This is useful to define the API to something without requiring a particular
implementation (see also interfaces, below which are even better for this).
-
This is useful also if you have a lot of common functionality to put in
a base class but details (i.e., implementation of particular methods) have
to be provided by various subclasses.
-
(Must) declare the class "abstract"
-
Declare each missing method abstract and put a semicolon where the body
would be.
abstract public class stack {
abstract public void push(Object obj);
abstract public Object pop();
abstract public boolean empty();
}
-
Can't instantiate an abstract class (but can declare variables).
nxt
Interfaces
-
Signature based typing (a good thing not in C++).
-
Syntactically an interface declaration looks a lot like a class declaration
(replace "class" with "interface").
-
But, no variables and methods don't have bodies.
-
Basically interfaces define an API, but no implementation
-
Interfaces are used as a "promise".
-
Class can say: "implements interface_name" after extends
clause
-
This means that the class promises to implement the API of the interface.
-
It doesn't say anything about how its going to do it, just that it will
-
The compiler checks that it does.
-
Can inherit from multiple interfaces.
nxt
Substitutability for interfaces
-
Can declare variables and parameters with interface types
-
Variable can then refer to object of any type that implements the
interface
-
Has promised to implement the API (& compiler has checked), so this
is completely typesafe!
-
Gives you a lot of flexibility to reimplement, etc.
-
Advice: use this whenever you can (it will save you even more than the
protected variables and access methods).
nxt
Packages
-
Classes are organized into collections of related things (what constitutes
one package is entirely up to you).
-
Each source file belongs to a particular package and that package is listed
at the top with the package declaration:
package sub_arctic.lib;
-
Note: its possible to leave the package declaration out which indicates
the special "unnamed package" -- don't do this! it just gets confusing
to everyone concerned (see finding things below).
-
Package names have multiple parts separated by "."
-
Can have "subpackages":
java.awt and java.awt.image
-
However these don't have a special relationship between them (except in
how you store them see below)
-
Packages are primarily to segregate the name space (class names must be
unique within the package, but not across all packages)
-
Also have an effect on protection rules (see above)
nxt
Imports
-
You can use package names to disambiguate types.
-
Recall we had an example that used the class Color.
-
This comes from the library package java.awt and its full name
is java.awt.Color.
-
If you get tired of writing out the full name, you can "import" the class:
import java.awt.Color;
-
(placed after the package declaration at the start of the file). This basically
brings the name Color into the local namespace
-
You can also import all the classes in a package:
import java.awt.*;
-
If you get two classes with the same name from different packages you use
full names to disambiguate.
-
Since compiler knows how to find packages (as we will see below),
this eliminates the need for #includes (you can also import from compiled
code without the source!)
-
java.lang.* is imported automatically.
nxt
Exceptions: (skip
ahead)
-
If an error or other exceptional condition occurs, you can throw an exception:
throw <exception-expr>;
-
where <exception-expr> is an expression that results in something
of type Throwable (usually a subclass of Exception).
Typically we allocate a new object and throw that:
throw new exception("error message");
-
This causes execution to end at the point of the throw and resume in special
exception handling code (handing off the object).
-
You provided this code using the try/catch construct:
try {
...main code...
} catch (Exception ex) {
...recovery body ...
}
nxt
Exceptions Cont.
-
You can catch more than one kind of exception (based on type) using:
try {
...main code...
} catch (ex_type ex) {
...recovery body ...
} catch (ex_type2 ex2) {
...recovery body 2 ...
} finally {
... always executed ...
}
-
If main code throws an exception of one of the types listed, that body
is executed. Catch clauses are tried in order, so you should put more specific
things (subclasses) first, and less specific things (like the base class
exception as a catch-all) last
-
The (optional) finally clause is always executed
-
If there is no enclosing try with a matching exception to the
one thrown, the method being executed returns, and the exception is thrown
in the caller. (Can have zero catch clauses on a try,
in which case finally clause is executed "as the exception passes
through").
-
This basically walks back the dynamic call stack to find the closest exception
handler.
nxt
Declaring Exceptions
-
The class hierarchy under throwable looks like:
java.lang.Throwable
java.lang.Error
java.lang.Exception
java.lang.RuntimeError
-
If object thrown is not an Error or a RuntimeError, then methods which
throw it (or pass it on from one of their callees) must declare that they
throw that type:
pubic void adjust() throws monkey_wrench { ... }
-
This means you can look at a method declaration and know what exceptions
you might need to handle if you call it.
nxt
Static members (skip
ahead)
-
Instance variables belong to (have a copy in) each instance.
-
Can also declare variables that belong to the whole class.
-
Do this with static:
class a_class {
protected static int count = 0;
public a_class() {count++;}
}
-
There is only one copy of the static variable -- belongs to the class (shared
by all instances).
-
You can also have static methods.
-
These can be invoked without an instance (using the class name):
Math.sqrt(3.1415d)
nxt
Initialization of statics
-
You can use conventional initializers (after =)
-
These are executed when the class is loaded
-
Can also have special static initialization blocks (outside of methods):
static {
... some code ...
}
-
Also executed when class is loaded (Java loader takes care of loading classes
you depend on first).
nxt
Final members
-
You can declare classes, methods, and variables final.
-
For variables this means they can't be assigned to after initialization
(AKA constants):
public static final double PI2 = Math.PI*Math.PI;
-
For methods, this means you cannot override the method in subclasses.
-
For classes this means all the methods are final.
-
You can declare final variables in interfaces
-
Java idiom: to collect a bunch of reusable constants together put them
in an interface and "implement" them in the classes where they
are used.
nxt
Strings
-
In Java, strings are objects of class String (not array's of char, although
there are operations to get back and forth)
-
Special literal e.g: "abc" represents a String object.
-
Character escapes such as \n similar to C.
-
Strings are immutable -- operations create new strings, don't modify existing
ones.
-
"+" is used for string concatenation, and is treated specially
-
Any + with at least one String operand is treated as string concatenation
-
The other operand is converted to a string (this actually works in general,
not just for +)
-
For primitive types there is a standard (and obvious) conversion
-
For Objects, the toString() method is called
-
Object provides one (prints class name and unique id)
-
Or you can override
nxt
Arrays
-
Arrays are also objects in Java
-
Can declare as "int foo[]" or "int[] foo" both declare
a variable which refers to an array of ints
-
Important note: array size is not part of the type (that gets established
by the instance):
int[] foo = new int[52];
...
foo = new int[42]
-
each array object has a read-only field: length
foo.length == 42
-
Note that arrays are collections of Object references.
-
All set to null by default.
-
Can initialize arrays to refer to particular object with special form similar
to C/C++
init[] foo = {3, 5, 9};
Object[] bar = {"one", new Stack(), new Integer()};
nxt
Array types
Arrays are hierarchically typed
If sub is a subclass of base then sub[] is
a subclass of base[]
So you could have:
base[] base_var = new sub[42];
nxt
Checking and converting types at runtime
-
Can determine if an object qualifies as a particular type at runtime using
expression: "obj instanceof aclass"
-
"null instanceof aclass" is always false.
-
Can convert to a sub- or super-class with a C style cast expression: "(aclass)expr"
Does runtime type check and throws an exception if this is not a legal
conversion (i.e., object being cast is not of that type or a subclass thereof).
nxt
Output to stdout
-
java.lang.System has lots of useful stuff for accessing the local
environment including: System.out, System.err, and System.in
(for stdout, stderr, and stdin).
-
Two operations of particular interest: System.out.print() and
System.out.println() print anything convertible to a string (overloaded
versions for all the primitives) with or without a newline.
-
Where this shows up, for example, in a browser is another question.
-
Since we are dynamically linked and compilation is fast (~10-20 sec for
a small class) this is actually not bad debugging if your tool doesn't
provide a debugger.
nxt
Threads
-
Threads are built into the language
-
Concurrent threads can greatly simplify program structure and design for
a number of things
-
They also make testing and debugging nearly impossible
-
So unless your programs all work without testing (and/or there is no reasonable
way around it), I advise: Just say no!
nxt
Using a Java System, some non-obvious things...
Organizing Java source code so it can be found by the tools
-
Java source files are organized around classes
-
One public class per source file (but you can put "unlabeled"classes in
the same file if they are only used by the main "public" class in the file
-- you are better off if you just ignore this and just put one class in
each file).
-
Unlike other languages, you can't name your source files anything you want!
-
The source file for a (public) class my_class must be in
a file named my_class.java. The corresponding loadable class files
(i.e., byte code) will be placed in my_class.class.
-
Why? This provides a very simple lookup mechanism for finding things (when
fetching classes from remote sites and compiling).
nxt
Packages
-
To make finding things easier you have to organize your files in a particular
way.
-
Files in the package sub_arctic.lib must be placed in a directory
called sub_arctic/lib/. Again this makes it easy to find things.
nxt
CLASSPATH
-
The last part of finding things has to do with telling the system where
to find packages
-
Your CLASSPATH environment variable should contain the names of each directory
where packages are found (separated by colons in UNIX and semicolons in
Windows)
-
Easiest if you just set up one directory:
~hudson/java_src
java_cup
...
sub_arctic
lib
interactor.class
interactor.java
...
input
...
output
...
-
and set your CLASSPATH to point at that directory:
setenv CLASSPATH ~hudson/java_src
-or-
export CLASSPATH=~hudson/java_src
-
Best not to put "." in your CLASSPATH (at least initially).
nxt
Running Java programs
-
Since Java is intended to come over a wire, what does it mean to have a
Java "program"?
-
Piece of Java code can get invoked in a number of different ways:
-
Stand alone program:
public static void main(String[] args)
-
can be invoked as a stand-alone program (via the Unix command "Java")
nxt
Applets
-
Java code is more typically invoked as an "applet" (small interactive application
embedded in a web page).
-
Any subclass of Java.applet.Applet can be used
-
Class in named in a special HTML tag:
<APPLET CODE="sub_arctic.test.my_test.class"
WIDTH=400 HEIGHT=200 CODEBASE="../..">
<PARAM NAME="option1" VALUE=5>
<PARAM NAME="option1" VALUE=5>
Alternate HTML for non-Java browsers
</APPLET>
-
Other html for new Java plugins
-
Java code can also be invoked via other conventions -- example "servelets"
nxt
Invoking the compiler (assuming JDK)
In the directory with the source do:
javac my_source.java
Compiler basically does a "make" -- it will compile anything which is needed
and out of date.
nxt
To run a standalone program
(in class in a package in your CLASSPATH) do:
java my_package.myclass
Nifty feature:
java -cs my_package.myclass
will compile everything it needs first.
nxt
To run an applet
-
Put an <APPLET> tag in an HTML document. Run your favorite Java enabled
browser on that document.
-
Or if you don't like core dumps (Java in browsers tend to be in variousl
"states of being"), use the appletviewer program:
appletviewer my_page.html
nxt
Good luck...
... and, to quote from Scott: "as always, if you or any of your programming team are caught or killed, I will disavow that I ever taught you anything about Java."