I. Java Overview A. Goals ------------------------------------------ GOALS OF JAVA "... a Java program should compute the same result on all machines and in all implementations" ("The Java Language Specification") - simplicity - avoid new, untested features - few implementation dependencies so very portable - avoid safety problems garbage collection checked array access - programmer productivity safety features exception handling multithreading ------------------------------------------ Why does that quote seem important? What's not here vs. C++? B. Basics ------------------------------------------ PARTS OF THE LANGUAGE primitive expressions: data: values: boolean, int, short, long, char (unicode characters), float, double (IEEE 754 standard), references, null objects: arrays, class instances, variables assignments method calls means of combination: statements (if, while, ...), methods, arrays, classes, inheritance (extends) means of abstraction: classes, packages, interfaces, nested and anonymous classes, monitors (synchronzied methods and stmts) ------------------------------------------ ------------------------------------------ MISSING VS. C++ primitive expressions: data: values: pointers, pointer arithmetic, references to stack locations objects: unions, structs means of combination: goto (use labeled break and continue), data layout control, multiple inheritance (both kinds), private and protected inheritance means of abstraction: macros, templates, namespaces (but has packages), friends ------------------------------------------ C. semantics of objects ------------------------------------------ REFERENCES vs. POINTERS A *pointer* is A *reference* in Java is C++ code: int i = 3; int * ip = &i; int * p2 = new int; ip = ip + 1; p2 = p2 + 1; int & ir = i; int & r2 = *(new int); Java code: int i = 3; Integer j = new Integer(7); j = new Integer(8); j = null; ------------------------------------------ ------------------------------------------ DOMAINS (KINDS OF VALUES) ExpressibleValue = PureValue + Reference PureValue = boolean + int + short + long + char + float + double Reference = Object + null DenotableValue = ExpressibleValue ------------------------------------------ What's a denotable value in C++ that isn't expressible? What benefit from not having references to variables? What benefit from not having pointer arithmetic? ------------------------------------------ PARAMETER PASSING AND ASSIGNMENT Java is a language with: direct model of arrays (Pascal, Ada): indirect model of arrays (C, C++, Scheme): ------------------------------------------ ------------------------------------------ EXAMPLE import java.util.*; class Demo { public static void main(String[] args){ Vector x, y; x = new Vector(); y = new Vector(); x.addElement(new Integer(3)); x.addElement(new Integer(4)); y = x; y.setElementAt(new Integer(7), 0); System.out.println(x.elementAt(0)); } } ------------------------------------------ II. Execptions, esp. in Java A. the problem ------------------------------------------ EXCEPTION HANDLING: THE PROBLEM What to do when a procedures is called: - outside its intended domain e.g., Math.sqrt(-7.4) - when a resourse isn't available e.g., new long[999999999999999] - when the result isn't "normal" or when an expected failure occurs e.g., file.read() robot.moveForward(3) table.search(foo) def: an *exception* is ------------------------------------------ other circumstances? Is it worth writing code to handle stack overflow, running out of memory or other "unexpected" problems? B. potential solutions What's usually done in C (e.g., the standard libraries or the Unix system calls)? 1. status codes ------------------------------------------ STATUS CODES: A SOLUTION? - status codes /* in C */ #include ... fp = fopen(argv[1]); if (fp == NULL) { perror("can't open file!\n"); exit(1); } ------------------------------------------ What's the problem with that? ------------------------------------------ SOME PARANOID C CODE #include int main(int argc, char * argv[]) { FILE * fp; int i,j; if (argc < 1) { if (fprintf(stderr, "no file name!\n") < 0) { exit(3); } exit(2); } fp = fopen(argv[1], "r"); if (fp == NULL) { perror("can't read file!\n"); exit(4); } if (fscanf(fp, "%d %d", &i, &j) != 2) { perror("bad format file!\n"); exit(5); } if (printf("%d\n", i+j) < 0) { perror("can't do output!\n"); exit(6); } if (fclose(fp) == EOF) { perror("can't close file!\n"); exit(7); } return(0); } ------------------------------------------ ------------------------------------------ CAREFUL_x FUNCTIONS: A SOLUTION? int do_x(/* ... */) { /* ... */ } void careful_do_x(/* ... */) { int status; status = do_x(/* ... */); if (status != GOOD) { perror("do_x failed!\n") exit(status); } } ------------------------------------------ What's are the advantages and disadvantages of that? 2. stronger preconditions ------------------------------------------ A SOLUTION? - require the callers to check conditions (use stronger preconditions) void pop(); //@ REQUIRES: self is not empty //@ ... ------------------------------------------ What are the advantages and disadvantages of this? 3. handlers as parameters ------------------------------------------ A SOLUTION? - pass procedures (Smalltalk block) to handle the exceptions that may occur Example in Smalltalk: class: Array ... "instance methods" at: i ifAbsent: aBlock (0 <= i and: [i < size]) ifFalse: [^aBlock value] ifTrue: [^self basicAt: i] "client code" ... myArray at: k ifAbsent: [^self error: 'oops'] ... ------------------------------------------ What are the advantages and disadvantages of these? C. exception mechanisms 1. terms ------------------------------------------ EXCEPTION HANDLING MECHANISMS A convenient form of passing blocks Terms: An exception may be The text that is executed in response ------------------------------------------ 2. single vs. multi-level mechanisms ------------------------------------------ SINGLE vs. MULTI-LEVEL MECHANISMS Single-level (CLU): all exceptions that can be thrown by or propogated from a method are Multi-level (Mesa, Ada, C++): exceptions are not ------------------------------------------ 3. termination vs. resumption model ------------------------------------------ TERMINATION vs. RESUMPTION MODEL Termination (CLU, Ada, Java): Resumption (Mesa): ------------------------------------------ 4. exceptions as objects ------------------------------------------ EXCEPTIONS AS OBJECTS IN A HIERARCHY Throwable Error AWTError LinkageError ThreadDepthError VirtualMachineError OutOfMemoryError ... Exception AWT Exception ClassNotFoundException CloneNotSupportedException IOException EOFException FileNotFoundException ... RuntimeException ArithmeticException ArrayStoreException ClassCastException SecurityException IndexOutOfBoundsException ... ------------------------------------------ Advantages? D. in Java 1. declarations in Java of what exceptions a method can throw ------------------------------------------ DECLARING EXCEPTIONS THROWN BY METHODS IN JAVA Java uses a model that is: single-level for checked exceptions and multi-level for unchecked exceptions Syntax for declaring exceptions that may be thrown by a method: throws [, ] ... Example: char readChar() throws IOException; ------------------------------------------ Why? In C readChar returns an int not a char; Why? 2. throwing and catching exceptions ------------------------------------------ JAVA EXCEPTIONS Java uses a termination model; Syntax: throw(new FooException); try [catch ( ) ] ... [finally ] ------------------------------------------ What else needs to be said? III. Types and Classes in OOP and Java A. Basic concepts 1. type and type error ------------------------------------------ BASIC CONCEPTS OF TYPE AND CLASS Recall that: A *type* is a set of objects that obey a protocol. Some questions: - Who decides what set of objects that obeys a protocol is a type? - What is a type error? ------------------------------------------ 2. behavioral reasoning aided by type checker can we make even stronger behavioral guarantees? ------------------------------------------ REASONING ABOUT ADTs Data type induction argument example: Sets represented by lists To prove: every Set's list has no duplicates How to prove this? ------------------------------------------ What part of the program has to be examined for this to work? 3. Seals (Morris 1973) ------------------------------------------ SEAL GOALS Only by using the ADTs ops can a client: alter = discover = Clients cannot: impersonate = SEALS MECHANISM createSeal -> (seal_t, unseal_t) gives unique seal and unseal functions Properties: unseal_t(seal_t(x)) = x unseal_t(anything else) is an error ------------------------------------------ How could these cause problems for a program that kept a table in sorted order? Does Smalltalk prevent impersonation? How does this allow for data type induction? How could we use seals to define what a "type error" means? How does this relate to security in Java? 4. static and conservative nature of type systems ------------------------------------------ TYPE SYSTEMS AS STATIC APPROXIMATIONS Does this code have a type error? int i; Foo f; bool test = myReader.read_bool(); if (test) { i = i + 1; } else { f = i; } ------------------------------------------ Why are all elements of an array assumed to have the same type? ------------------------------------------ BASIC STRATEGY OF STATIC TYPE SYSTEMS Variables have a statically declared type Expresssions are assigned a type based on Examples: In an OO language with subtyping ------------------------------------------ 5. soundness and completeness ------------------------------------------ SOUNDNESS AND COMPLETENESS A type system is *sound* iff A type system is *complete* iff ------------------------------------------ How to prove this? How is this affected by subtyping? B. types in Java 1. security and types in the JVM ------------------------------------------ WHY TYPE SOUNDNESS MATTERS IN JAVA OR HOW THEORETICIAL WORK CAN MAKE YOU FAMOUS class T { SecurityManager x; ... } class U { MyObject x; ... } T t; U u; // ...somehow make u and t aliases... t.x = System.getSecurity(); MyObject m = u.x; ------------------------------------------ 2. overview ------------------------------------------ TYPES IN JAVA Types: primitive types: byte, short, int, long float, double char boolean reference types: classes, interfaces, T[] ------------------------------------------ a. primitives b. references 3. interfaces, classes and types ------------------------------------------ CLASSES AND TYPES Every class name Object is the superclass of all classes and of all array classes SUBCLASS ==> SUBTYPE class T {...} class S extends T {...} T x = new S(); CHECKED CASTING casting to a reference type generates ------------------------------------------ ------------------------------------------ INTERFACES // example public interface Colorable { byte CLEAR = 0; void setColor(byte r, byte b, byte g); } Contains declarations of: constants, and abstract methods ------------------------------------------ ------------------------------------------ INTERFACE EXTENSION public interface PointType { int x(); int y(); } public interface ColorPointType extends Colorable, PointType { byte redness(); byte greenness(); byte blueness(); } ------------------------------------------ ------------------------------------------ INTERFACE IMPLEMENTATION class ColorPoint extends Point implements ColorPointType { byte r, g, v; public ColorPoint(int xv, int yv, byte rv, byte gv, byte bv) { super(xv, yv); r = rv; g = gv; b = bv; } public byte redness() {...} public byte greenness() {...} public byte blueness() {...} ... } class PolarColorPoint implements ColorPointType { ... } ------------------------------------------ Why doesn't Java infer when a class implements a type? ------------------------------------------ EXTENSION AND IMPLEMENTATION SUMMARY Point PointType Colorable | \ / | \ / | \ / ColorPoint -------- ColorPointType / / PolarColorPoint ------------------------------------------ ------------------------------------------ USE OF INTERFACE TYPES class Demo { public static void main(String[] args){ ColorPointType myCP; if (args.length > 1) { myCP = new ColorPoint(3,4,8,9,2); } else { myCP = new PolarColorPoint(...); } ... myCP.redness() ... } } ------------------------------------------ Can Java still do type checking when interface types are used? C. inheritance and requirements on types of methods ------------------------------------------ INHERITANCE AND METHOD TYPES class Object {...} class Number extends Object {...} class Integer extends Number {...} class Point { Number x() {...} void set_x(Number xv) {...} ... } class ColorPoint extends Point { x() { ... } void set_x( xv) ... } Point myP = new ...; myP.x() myP.set_x( ------------------------------------------ What can the return type of the ColorPoint's x method be? What can the argument typ of ColorPoint's set_x method be? Why? What about exceptions? Can you allow more or less in the subclass? ------------------------------------------ STATIC OVERLOADING vs. DYNAMIC OVERRIDES (MESSAGE PASSING) class Foo { public int f (Float f) { return 1; } } class Bar extends Foo { public int f (String s) { return 2; } } // client code Foo x = new ...; x.f (new Float(3.14)); x.f ("a string"); // static type error ------------------------------------------ D. arrays and templates ------------------------------------------ ARRAYS IN JAVA Suppose ColorPoint is a subtype of Point. Is ColorPoint[] a subtype of Point[]? ------------------------------------------ ------------------------------------------ TEMPLATES What would the subtyping rule be for templates (if Java had them)? Example: Is X a subtype of X if S is a subtype of T? ------------------------------------------ How would you declare the relationships that might exist? IV. Other features of Java A. portability ------------------------------------------ PORTABILITY What helps Java code be more easily portable? ------------------------------------------ And how does that compare to C or C++? B. initialization ------------------------------------------ INITIALIZATION All variables void foo(Float f) { Double d; if (...) { d = new Double(7.3 + f); } else { ... } Double d2 = d; } ------------------------------------------ C. final ------------------------------------------ FINAL final double pi = 3.14159; class Foo { public final void int f() { ... } } final class Bar extends Foo { } ------------------------------------------ Why would one want to prevent overriding a method? Why would one want to prevent a class from being subclassed? D. control flow ------------------------------------------ CONTROL FLOW Like C/C++ but: search: { if (k == i) { loop: for (z = 0; z < size; z++) { if (a[z] == j) { break search; } for (y = 0; y < lb; y++) { ... if (a[z] < m && b[y] > q) { continue loop; } ... } ... } } } ------------------------------------------ In what way is this more "structured" than a goto? E. threads ------------------------------------------ THREAD-SAFE CODE (MONITORS) synchronized void doWhenCondition() { while (!condition) { wait(); } ... processing for when condition holds } synchronized void changeCondition() { ... change some value used in condition notify(); // or notifyAll(); } ------------------------------------------ ------------------------------------------ class Stack { // STACK AS A MONITOR int maxSize, siz; Object[] elems; public synchronized void push(Object o) throws InterruptedException { while (full()) { wait(); } elems[siz - 1] = o; notifyAll(); } public synchronized void pop() { if (!empty()) { siz -= 1; } notifyAll(); } public synchronized Object top() throws InterruptedException { while (empty()) { wait(); } return elems[siz - 1]; } public synchronized boolean full() { return siz == maxSize; } public synchronized boolean empty() { return siz == 0; } Stack(int msiz) { maxSize = msiz; siz = 0; elems = new Object[msiz]; } } ------------------------------------------ Should the notify() call be implicit when a synchronized method returns? F. packages and privacy 1. packages ------------------------------------------ PACKAGES Goals: Packages contain: classes, interfaces, packages Example: java .lang Object Integer ... .util BitSet ... edu .iastate BitSet .cs Dequeue ------------------------------------------ ------------------------------------------ SYNTAX EXAMPLES Compilation Units (types and interfaces): package edu.iastate.cs; import java.util.Vector; import java.lang.*; public abstract class ADequeue { private Vector rep; public void addToEnd(Object o); public void add(java.lang.Object o); void packageOnlyOp(); } ------------------------------------------ What prevents a client from accessing packageOnlyOp by writing new code in the package edu.iastate.cs? 2. protection levels ------------------------------------------ PROTECTION IN A CLASS public class Point { protected int x, y; private int init_x, init_y; public Point(int a, int b) { x = a; init_x = a; y = b; init_y = b; } public int get_x() { return x; } public int get_y() { return y; } public void move_x(int dist) { x += dist; } public void move_y(int dist) { y += dist; } public void reset() { x = init_x; y = init_y; } ------------------------------------------ G. reflection ------------------------------------------ REFLECTION API Goals: Running code can: - discover information about: - fields, - methods, and - constructors of loaded classes - operate on the objects - create new objects Used by: ------------------------------------------ ------------------------------------------ MECHANISM In java.lang: Class methods: getField getMethod getConstructor In java.lang.reflect: Method Field Constructor Member (interface) Modifier ------------------------------------------ What does reflection have to do to preserve type safety? To preserve privacy?