Java - Subtyping: inheritance and interfaces - Liskov substitution principle. How does this relate to the simple syntactic definition of subtyping? - If A is a subtype of B, then when an A is used as a B, it should act like one. - Polymorphism - Subtyping vs. parametric vs. ad hoc - In what ways are these all "polymorphic" (what's the def)? How do they differ? Why does this matter? - Generics - Class-level generics (e.g., class Stack { ... }) - Compare subtype polymorphism version of container (Java 1.4) with the generic version (1.5). How different? - Method-level generics - the identity function examples - Subtyping and generics - Stack <= Stack ? NO! - analogy with arrays - Solution I: some methods can be made polymorphic - Solution II: more generally, use wildcards - This works because there is no way to cast from type Foo to type ?. So we have "readers" and not "writers." - Moreover, prevents swapping. - Bounding (in declarations for classes and methods) - Wildcards - Normal type variables - Translation via erasure - Types are not first-class - new T() no good - new T[n] == new Object[n] (OK, but warning) - some casts instanceof will fail - LinkedList.class == LinkedList.class - Raw types - just skip the instantiation; warns about possible type violation at run time. Testing - Black box vs. white box testing - scalability, code coverage are issues - Generating tests - via "paths" in the spec - by guessing problem spots in a typical implementation - boundary conditions - common mistakes (e.g., memcpy over the same buffer, adding a list to itself, etc.) - White box testing coverage - Statement - Branch - Condition - JUnit Specifications - Definition of correctness! - Needed for black box testing - How do these relate to subtyping? - I.e., if we override a method, how to the specs of the original and new methods relate? (p. 7 or on-line slides) Design Patterns - Example patterns - Strategy - How does this differ from Command? - Observer - Java Observable, and our genericized version of it - Decorator - How does this differ from Proxy? - Factory Method and Abstract Factory - How do these differ from one another? - Singleton - Concurrency issues? - Command - Composite - Why is an AST like a composite? - How was the Menu system in the book like a composite? - tradeoff: transparency vs. safety - Visitor - Motivation - Why the need for double dispatch? - How does this impact OO principles? - Variations - Traversal visitor + payload visitor - Iterator - How different from visitor? - Adapter - How does this differ from Proxy and Decorator? - Principles of OO - encapsulate what varies - favor composition over inheritance - program to interfaces, not to implementations - strive for loosely coupled designs between objects that interact - what does "loosely coupled" mean? - cf. Observer, Command - classes should be open for extension but closed for modification - cf. Decorator - depend on abstractions. Do not depend on concrete classes. - high-level components should not depend on low-level components. Rather, they should both depend on abstractions (i.e., interfaces). - no variable should hold a reference to a concrete class - no class should derive from a concrete class - no method should override an implemented method of any of its base classes. - cf. FactoryMethod, Abstract Factory - a class should have only one reason to change - cf. Iterator Concurrency - Threads overview - MP vs. non-MP threads - Benefits of threads - Performance - Easy to express certain paradigms - Separate computations (vs. event-based) - Drawbacks - Many hazards: safety and liveness - overhead - Thread creation: subclass vs. runnable - runnable is the command pattern - Thread scheduling - which of the RUNNABLE threads should be scheduled? - preemptive vs. non-preemptive schedulers - causes for blocking, waiting - thread priority - Thread routines - join(), sleep(), currentThread(), setDaemon() - Producer/Consumer - using Java 1.5 Condition variables - using Java 1.4 wait/notify - broken: lock but no wait - broken: no lock and busywaiting: race! - broken: if rather than while() - bad idea: using busywaiting with volatile - Java 1.5 implementation: Queue offer and remove methods - Thread cancellation - .stop() or .kill() vs. .interrupt() - InterruptedException vs. isInterrupted() Threading Design Patterns - Object safety - Isolation (i.e., thread locality) - Immutability (e.g., Strings) - Locking - Containment - thread-unsafe objects encapsulated within thread-safe ones (e.g., by using locking for the outer calls) - must prevent outside calls into the unprotected objects - hierarchical: gives some outside access - internal locking - internal objects protect themselves with their owners' locks - easy to do with inner classes - external locking - clients do this; acquire owner's lock, then access inner data - more dangerous, but can reduce locking - can implement via subclassing (adding sync) - Volatile - handles visibility, but not ordering - State Dependent actions - What are these? - when the operation depends on the object's state for success - removing/adding an element to a collection - maintaing a counter >= 0 - printing a file (resource may be busy) - reading a file after opening it, etc. - Balking - pushes failure to the client - Guarding - handles possible failure by waiting in the host - busywaiting useful for latches, but not generally so - notify vs. notifyAll - with and without timeouts - timeouts give you a space between balking and guarding