Java's Origins
Java was created in 1991 by Patrick Naughton and James Gosling.
They wanted a language that was small, to be used for consumer devices
and which supported tight, portable code. Moreover they hoped for a
language that could be used for distributed applications which would
have open standards, as would the language itself.
They resurrected Nicklaus Wirth's design for UCSD Pascal, using
a virtual machine.
file.java --> Java Compiler --> bytecodes | 4 | 2 | 17 | ... -->
virtual machine (executes bytecodes) --> specific architecture
At that time there was no market for their product.
Then browsers for the WWW were becoming hot, and they brought up issues not
encountered in the workstation world, such as
- The need for architecture neutrality
- The need for real-time capability
- An increased need for reliability
- An increased need for security
So they built a browser that intrepreted bytecodes, as with the
language they had designed after UCSD virtual-machine based Pascal.
In 1995 Netscape released a Java-enabled browser, and the explosion
of use currently underway with Java began.
Java's Philosophy
Look carefully at sources of bad coding and bugs from C++ and other languages.
Then add features (or delete them) to deal with these. They did a large number
of studies and determined the following important sources of problems (among others):
- manual memory allocation and deallocation
- the use of pointer arithmetic in array addressing
- the use of pointers in general
- subtle syntactic differences with large semantic consequence (e.g. = vs ==)
- the inappropriate use of multiple inheritance to support other needs
- the use of closed language standards
The importance of using studies of language use in practice cannot be stressed
too much. Java was the first language to rely so heavily on this kind of
empirical evidence for guiding the language design choices.
Java's White Paper Buzzwords
A white paper was published describing the qualities that this new language was
to have. Each one is discussed in turn in what follows.
SIMPLE
- minimal learning curve (make it similar to C/C++)
- omit rare & confusing features
- small (full environment is only 40K, w/microkernel it is bigger)
It is generally agreed that simplicity is achieved in Java, with a few exceptions
such as the switch statement which retains the same form as in C/C++. It is not
likely that a full-power general-purpose high-level language can be without any
sublety.
OBJECT-ORIENTED
- focus on the design of data (objects)
- and on their interfaces (behavioral contracts to other objects)
- NO MULTIPLE INHERITANCE
Java is a good object-oriented language. The elimination of multiple inheritance is
a controversial one. It is based on the results of the aforementioned studies, which
indicated that over 90% of the time multiple inheritance was used in the service of
code organization not related to actual inherited attributes or behavior. Moreover it
is usually used incorrectly.
For example, you may have objects that have their own behavior (interaction in a simulation
let's say) but which you also want to have graphical (visual/windowing) behavior. Typically
the objects are made to inherit from both. A new mechanism called INTERFACES can provide
this functionality and organization without the complexity of inheritance.
DISTRIBUTED
- networking capability strong and easy
- same ease of coding whether accessing locally or remotely
- e.g. opening a socket is remarkably easy in Java compared to C/C++
- language that is thread-aware (easily works in threaded environment)
- language that is distribution-aware (ease of programming distributed application)
ROBUST AND RELIABLE
- early problem detection
- dynamic (run-time) type checking
- removal of error-prone situations
- e.g. new pointer model prevents manual memory access, overwrites, data corruption
SECURE
- motivated by intended use for distributed and networked environments
- open standard helps to ensure (many people can dig in and work on problems in sped)
- provide quick response on trouble areas
- disallowed overrunning the run-time stack (source of Internet worm disaster)
- corruption of memory outside processes own space disallowed
- can write to local files ONLY through a browser, not remote
- introduction of digitally signed classes for valid source confirmation
ARCHITECTURE NEUTRAL
- achieved using virtual machine design based on UCSD Pascal
- this is very well-executed
- and well-mapped to *most* of today's architectures (continues to improve)
PORTABLE
- not just hardware but software independent also
- this means writing one program, even GUI components, that work in "all" windowing environments
- sizes of primitive data types clearly indicated in spec., not up to compiler vendor
- libraries and their interfaces are specified, not up to compiler vendor
INTERPRETED
- Java's virtual machine can interpret (execute) bytecodes on any machine to which the virtual
machine itself has been ported
- linking is more incremental, development is more rapid and exploratory
- this last item is true but currently somewhat overstated
HIGH-PERFORMANCE
- generally good enough, but on-the-fly bytecode translation (at run-time) can be used for better
- eventually can use native compilers, some (Borland...) are available
- JIT (just-in-time) comipling: virtual machine caches native code for frequent bytecodes
- get 10-20X speedup (Symantec, Borland, Microsoft)
- remember, most code is data-rate bound, code can usually keep up except for special
applications where you wouldn't use Java anyway
MULTITHREADED
- better interactive responsiveness and real-time behavior
- VERY GOOD and easy to use!!
- unfortunately still offloaded to OS and not always platform independent
DYNAMIC
- adding new methods and instance variables to existing libraries easily without effect
on clients
- getting run-time type information is pretty easy (getting better all the time)
- supports code downloading, eventually mobile code
Possible Misconceptions
- Easy to learn? -- like any other general purpose language
- Easy to use? -- nothing yet like Visual Basic...
- Universal Programming Language for all Platforms? -- of course not. Indeed it is a
point of this course that no such thing could ever exist. They are all equivalent in
power and choices are made based on appropriateness of provided computational models.
- Too slow for real applications? -- most applications are data-rate bound and Java keeps
up just fine. JITs are available to increase. Bottom-line: if Java is fast enough for the
problem who cares if another language is faster, if Java offers what you need, you can use it.
- It is only for web programming? -- Definitely not. It is a general-purpose language. You'll
see for yourself after your assignment that the web is not a big part of it!
Details of Using Java
Applets are used with browsers. The details of their creation differs just somewhat
from regular applications. Often used to download code, to offload computation to other
machines, or for "content handlers".
Applications are standalone.
To compile a .java file that contains at least one Java class, use the
Java compiler (javac). This will create a file of the same name with the final
extension changed from .java to .class. This file contains the bytecodes
for the virtual machine. To run a java program simply execute the virtual
machine (java) on the file that contains the function "main". Do not include
an extension on that file when you give it as the argument to the virtual
machine. For example,
22% javac Item.java Queue.java Test.java
23% ls
Item.java Item.class Queue.java Queue.class Test.java Test.class
24% java Test
... execution commences ...
To use a java program in a browser, create an applet. You then create an
HTML file that contains links to the applet code. Finally you can link that
HTML file into any other HTML file. See the text for more details on this
procedure.
If you wish to view an applet without using a browser, again create the HTML
file that contains links to the applet code and execute the following:
appletviewer <your HTML file>.html
Details of Java Design
- All "functions" are methods; defined in a class
- One class per file
- One class has a "main" method
- // is used for comments "to-end-of-line"
- It is case-sensitive
- It is strongly typed (not so much as ML)
- The only built-in types are: int, short, long, byte, float, double, char, boolean
- Everything else is an object
- boolean values are false and true
- Variables begin with [a-z]|[A-Z]|[_][$] continue with same, including [0-9], UNICODE can be used
- declarations, assignments, and initializations are like C++
- No casts on boolean
- Casts up allowed: byte->short->int->long->float->double
- Assignments allowed in same direction
- Constants are: public static final m = 5;
- Operators are usual; exponentiation and other functions are in Math package
- ++, -- post- and pre- increment and decrement available with usual meanings
- Relational operators as usual: ==, !=, <=, >=, &&, ||, !
- The single = cannot be used in a boolean expression: if (k=0) .. is a compile-time error
- Usual bitwise operators
- Precedence is as usual in C++
- Conditionals are: if () {}, and if () {} else {}, and cascaded
- Loops are: while () {}, and for( , ; ; , ) {}
- Switch is identical to C++
- There is a labelled break: { read_data; while (..) { ....; break read_data; }
- Methods and data are either public or private
- Recursion is of course supported
- Arrays are first-class objects, cannot change size (use vectors for that)
- Arrays index at 0. Declaration syntax a bit different
- Valid array declaraion: int[] arrayOfInt = new int[100];
- Valid array declaraion: int[] smallPrimes = {2 ,3 ,5 ,7, 11, 13 }
- Returning array function declaration: public int[] createIntegerArray()...
- Methods access private members of all like-class objects (a built-in "friend"ly behavior)
- Private methods used as utilities to other methods in class
- Static methods do not operate on any particular instance and can be called without creating one
- Overloading of methods, including constructors, is possible. Argument # and types distinguish
- Every object has a this pointer, which points to itself
- Finalize is a method you can provide that will be called just before relinquising memory for object
- The keyword final is used to prevent subclassing or overriding
- Strings are classes not arrays of char or pointers to char
- Examples: String e = " "; String greeting = "Hello";
- Examples: String test = greeting + e + greeting;
- Examples: System.out.println(test); ==> Hello Hello
- Examples: String s = test.substring(0,3); //indexed starting at 0
Summary of Major Differences from C++
- Interfaces instead of multiple inheritance
- Automatic memory management (creation, deletion, garbage collection)
- No explicit pointers
- Thread/Net/Distributed aware
- Interpreted virtual machine environment