====== Java == ===== Related Pages == * [[java plumbing]] * [[java web programming]] * [[apache click]] * [[apache tomcat]] * [[jrunscript]] ===== Java Versions and Compatibility == Tested all on Slack 10.0 2005-09 ==== Bytecode Generation with javac 1.5 == | Source 1.4 | Source 1.5 | | | IYES | INO | -> Bytecode 1.4 | | IYES | IYES | -> Bytecode 1.5 | ==== Bytecode Execution with different VM's == | Bytecode 1.4 | Bytecode 1.5 | Bytecode 1.6 | | | IYES | INO | INO | -> VM 1.4 | | IYES | IYES | INO | -> VM 1.5 | | IYES | IYES | IYES | -> VM 1.6 | ===== main method == public static void main(String[] args) {} public static void main(String[] args) throws XXXException {} * arg[0] ist the first argument, not the name of the application! * There is no int return value like in c or c++ * Normally 0 is returned to the calling environment. * If you want to indicate an error, use System.exit() (preferred) or throw an exception, e.g.: public static void main(String args[]) { //throw new RuntimeException(); System.exit(3); } ===== Declaration modifiers == ==== Mini Glossary == ^ ^ nonstatic ^ static ^ ^ variable | instance variable | class variable | ^ method | instance method | class method | See also [[javatut>java/javaOO/classvars.html]] ==== static == * In an static method, there is no ''this'' referece! (from Scjp Book) * Static methods can only be hidden by subclasses, not overwritten ([[http://java.sun.com/docs/books/tutorial/java/IandI/override.html|source]]) ==== final (or const) == * final primitives: cannot change from its initialized value * final objects: Like constant pointer to modifiable data in C, see [[java#final objects|below]] * final methods: cannot be overridden * final classes: cannot be subclassed (from Java Tutorial Sun) The concept of const objects and const methods is missing in Java. A workaround is to use an Interface, see Faqs of de.comp.lang.java === final objects == public class Tester { public int i= 1; public static void main(String args[]) { final Tester b = new Tester(); Tester c = new Tester(); b.i = 2; // works always //b = c; // Error: cannot assign a value to final variable b c = b; // works } } ===== Rich Internet Applications == FIXME Whole secton is obsoete. See [[java plumbing]] instead! ==== Java Web Start == This might help: http://www.developer.com/java/web/article.php/3828811 ==== Applets == === Embedding in HTML == Easiest is to use the [[javatut>uiswing/components/applet.html#plugin|applet tag]] See also: * [[http://www.developer.com/java/article.php/3841566/|Java ARchive (JAR) Files]] tutorial * [[javaref>technotes/guides/plugin/developer_guide/using_tags.html|Using applet, object and embed Tags]] * [[http://java.sun.com/products/plugin/versions.html|Encountering OBJECT, EMBED, and APPLET Tags With Different Plug-in Versions and Browsers]] * The CODEBASE-attribute of the applet-tag has a different meaning of the CODEBASE-attribute of the object-tag! * [[javaref>technotes/guides/plugin/developer_guide/java_js.html|Java-to-Javascript Communication]] (needs plugin.jar) === Code Template == It is [[javatut>deployment/applet/|recommended]] to use ''JAppled'' instead of ''Applet''. Therefore the rest of this section is obsolete. An example for the use of ''JAppled'' is provided [[java#deploy_both_as_applet_and_jws|below]]. import java.applet.Applet; // *1 public class HelloWorld extends Applet { // *1 public void init() { . . . } // *2 public void start() { . . . } // *2 public void stop() { . . . } // *2 public void destroy() { . . . } // *2 public void paint(Graphics g) { g.drawString("Hello world!", 50, 25); } // *3 } - has to be subclassed from Applet - called by the browser, may be overwritten - inherited from java.awt.Container see also Java Tutorial Sun: Lesson: Overview of Applets ===== Events == ==== General == * EventTarget passes Object XxxListener-Interface by calling addXxxListener() of EventSource * When the action occurs, EventSource calls appropriate method of XxxListener The folling example code is part of the constructor of a subclass of JFrame: JButton jb= new JButton("Click me"); jb.addActionListener( new ActionListener() { // an anonymous object is passed here public void actionPerformed(ActionEvent e) { System.out.println("'jb' button pressed"); } } ); To find the appropriate addXxxListener() method of the event source, see [[http://doc.novsu.ac.ru/oreilly/java/javanut/ch07_03.htm|Java in a Nutshell]] (maybe obsolete) or search for such methods in the reference documentation of the event source and its superclasses or look at "Using Swing Components" in the Java Tutorial FIXME Any better idea? ==== canClose() == public class Klasse extends JFrame { public Klasse() { setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); // see apiSpecSun/api/javax/swing/JFrame.html & javaTutSun/uiswing/compontents/frame.html addWindowListener(new MyAppCloser()); } // Event handler for closing the application window as inner class: class MyAppCloser extends WindowAdapter { public void windowClosing(WindowEvent we) { if ( JOptionPane.OK_OPTION == JOptionPane.showConfirmDialog( null, // default Frame "confimation question", "Title", JOptionPane.YES_NO_OPTION ) ) System.exit(0); } } } ===== Strings == ==== general == Class String // constant string, can't be changed Class StringBuffer // mutable string, thread save Class StringBuilder // mutable str., for single thread only, faster, since V1.5 ==== String2Number Conversion == byte ix= Byte.parseByte("47"); int ix= Integer.parseInt("4711"); String s= ""+ 4711; String s= new Integer(4711).toString(); String s= String.valueOf(4711); ===== Inheritance == FIXME * see inherit.java * StaticAndInheritance.java * Static methods can't be overwritten, only hidden, see http://java.sun.com/docs/books/tutorial/java/javaOO/override.html ===== Constructors and Initialisation == ==== Default Constructor == If any constructor is provided, than also the default constructor (= constructor without arguments) has to be provided. Tested 2005-09-09 on JDK 1.5 ==== Multiple Constructors ===== public class Klasse { private int i, j; public Klasse(int i, int j) { this.i=i; this.j=j; } public Klasse() { this(0,0); } } ==== Static Initialization Block == Acts like a constructor for class members\\ See Java tutorial for more info\\ Further example at http://java.sun.com/j2se/1.5.9/docs/guide/language/enums.html Layout: class Example { static { // static initialization block: // This code runs, AFTER super() return, and before the code in the constructor } } For initializing instance members the constructor should be used! It would also be possible to use an intstance initializer instead of a constructor, but it is not recommended: class Example { { // intstance initialization block instead of constructor: // code } } ==== Cloning Objects (Copy Constructor) == FIXME See Java Kochbuch p 223 ===== I/O Streams ====== ==== Byte Streams ====== | [[javaref>api/java/io/InputStream.html|InputStream]] || [[javaref>api/java/io/OutputStream.html|OutputStream]] || | FileInputStream | ObjectInputStream | FileOutputStream | ObjectOutputStream | ==== Character Streams ====== | abstract [[javaref>api/java/io/Reader.html|Reader]] || abstract [[javaref>api/java/io/Writer.html|Writer]] ||| | BufferedReader | InputStreamReader | BufferedWriter | OutputStreamWriter | PrintWriter | | | FileReader | | FileWriter | | // Abstract class Writer: Writer append(char c) throws IOException; void write(int c) throws IOException; // same as above! void write(String str[, int off, int len]) throws IOException; BufferedWriter(Writer out); void newLine() throws IOException;// Write a line separator. FileWriter(File file[, boolean append]) throws IOException; FileWriter(String fileName[, boolean append]) throws IOException; PrintWriter(File file) throws FileNotFoundException; PrintWriter(String fileName) throws FileNotFoundException; PrintWriter(Writer out, boolean autoFlush); PrintWriter(OutputStream out); PrintWriter printf([Locale l, ]String format, Object... args); // same as format void print(allPrimitivesAndObject o); void println(allPrimitivesAndObject o); // Abstract class Reader: int read() throws IOException; BufferedReader(Reader in); String readLine() throws IOException; FileReader(File file) throws FileNotFoundException; FileReader(String fileName) throws FileNotFoundException; BufferedReader(Reader in); String readLine() throws IOException ===== Collections == ==== Overview == [[javatut>reallybigindex.html#collections|Chapter in the Java tutorial]] | //[[javaref>api/java/util/Collection.html|Collection]]// |||| //[[javaref>api/java/util/Map.html|Map]]// || | //[[javaref>api/java/util/Set.html|Set]]// || //[[javaref>api/java/util/List.html|List]]// | //[[javaref>api/java/util/Queue.html|Queue]]// | || | | //[[javaref>api/java/util/SortedSet.html|SortedSet]]// | | | | //[[javaref>api/java/util/SortedMap.html|SortedMap]]// | | HashSet LinkedHashSet | TreeSet | LinkedList Vector ArrayList | LinkedList, PriorityQueue | HashTable LinkedHashMap HashMap | TreeMap | ==== Implementations == * [[javatut>collections/implementations/|Overview]] * [[http://www.developer.com/java/article.php/3829891|Selecting the Best Java Collection Class for Your Application]] * [[javatut>collections/implementations/map.html|General purpose map implementations]] ==== Methods == // important methods of List: boolean add(E e) void add(int index, E element) boolean contains(Object o) E get(int index) int indexOf(Object o) Iterator iterator() E remove(int index) boolean remove(Object o) // Removes the first occurrence Object[] toArray() T[] toArray(T[] a) // important methods of Map boolean containsKey(Object key) boolean containsValue(Object value) V get(Object key) Set keySet() // Returns a set of the keys V put(K key, V value) // there is no add! V remove(Object key) // important methods of Queue: boolean offer(E o) // Inserts the specified element at the end; also add() possible E peek() // Retrieves, but does not remove, E poll() // Retrieves and removes from the beginning; remove() also possible * Set: has no special order and no duplicates are permitted, not indexed; methods ar a subset of List (no index operations) * List: ordered, duplicates are permitted, indexed * Map does not implement the collection interface * 'Sorted' is a subset of 'Ordered' * Ordering: * //Lists// are always ordered by index * //Linked// collections are always ordered by insertion or last access * //Tree// collections are always sorted * List can made thread-save by Collections.synchronizedList() * Tutorial: Vector is a legacy class; API: Vector is a normal class; Hashtable is similar; Vector also implements List * HashSet & LinkedHashSet: Overwrite hashCode() so that equal objects provide the same hashcode * LinkedList implements //List// and //Queue// * //Queue// has Fifo (not stack) behaviour! * All Interfaces have a size() method * PriorityQueue sorts Elements by natural order using Comparable * Elements for SortedSet/TreeSet, SortedMap/TreeMap PriorityQueue must implement the Comparable interface! * String implements interface Comparable and Integer implements Comparable -> Trying to add both Types to any untyped (old style) Tree-Container results in a ClassCastException * Whereas adding only the same Type (eg Strings) works but gives a compiler warning. (I assume the type is detected at run time by reflection and the Object to compare is casted to String before compareTo() is called.) ==== Sorting and Searching == === Sorting with the Comparable Interface == To sort a //List// (eg ArrayList) or an array use: static void Collections.sort(List list); static void Arrays.sort(allPrimitivesAndObject[] a); The List interface has no sort method! All elements in the List or array must implement the Comparable interface: Interface Comparable { int compareTo(T o); } Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Keep in mind that compareTo accepts Type T (the generic of the List) wheras equals always only accepts type Object! === Sorting with the Comparator Interface == static void Collections.sort(List list, Comparator c); static void Arrays.sort(T[] a, Comparator c); // T is an Object, no primitives! Interface Comparator { int compare(T o1, T o2); } === Searching == static int Collections.binarySearch(List list, T key[, Comparator c]); static int Arrays.binarySearch(allPrimitivesAndObject[] a, allPrimitivesAndObject key); static int Arrays.binarySearch(T[] a, T key, Comparator c); Call binarySearch() with the array or List as first param, the key as second, and, if not all items implement the Comparable interface, provide a Comparator as 3rd parameter. List or array has to be sorted before binarySearch can be called, otherwise the result is not predictable! If the element is not found, binarySearch returns -length-1 ===== Threads == ==== Basics == A thread owns the locks on one or more objects. The lock of an object can only have one thread as owner. Only one thread can access the code in a syncronized method or code block at one time. ''syncronized'' refers always to an object, not to code; the lock is acquired per object. ==== Thread States == Waiting/Blocking/Sleeping ↓ ↑ New → Runnable ↔ Running → Dead Verify: As a rule of thumb, only the current thread can bring itself from state Running to another state, other threads can't. ==== Creating a Thread == Two techniques for providing a run method for a thread: * [[http://java.sun.com/docs/books/tutorial/essential/threads/simple.html|Subclassing Thread and Overriding run]] (seems to be easier) * [[http://java.sun.com/docs/books/tutorial/essential/threads/clock.html|Implementing the Runnable Interface]] by instantiating a Thread instance and passing itself in as the target (prefered if your class must subclass some other class and therefore can't subclass Thread; prefered by Jens Hartwig Sun Heimstetten 2005-09) public class MyRunner implements Runnable { public void run() {...} public static void main(String args[]) { (new Thread(new MyRunner())).start(); } } ==== Important Methods of Class Thread ===== public void run() To be overwritten! Called by JVM and Should not be called directly. It is possible but doesn't create a real new tread. Represents the main loop of the thread. === Operations on Threads different from the current Thread ==== public void start() Tell the thread to begin with the execution, i.e. transfer the thread from state New to Runnable. The JVM then calls the run method of this thread. public void interrupt(); * Usually used to request a different thread to termniate. * The interrupted thread must support its own interruption: * Methods like ''sleep()'' and ''join()'' (in the main loop of ''run()'') throw an InterruptedException if this method is called from another thread. This can be used to return from ''run()'' * The main loop in ''run()'' can check periodically ''Thread.interrupted()'' See also [[javatut>essential/concurrency/interrupt.html|JavaTut:Interrupts]] public final void join() throws InterruptedException t.join(); // Example Causes the //current// thread to pause execution until thread t terminates. Tread state is Waiting/blocked/sleeping. === (Static) Operations on the current Thread ==== public static void sleep(long millis) throws InterruptedException; public static void yield(); These methods Cause the currently executing thread to temporarily pause and allow other threads to execute. A call to those functions affects only the own thread, other threads can't be controlled. sleep() transfers the thread to state Wating/blocked/sleeping whereas yield() transfers the thread only to Runnable. This means that after calling yield() on the current thread, the VM can immeditatly re-select the thread to run whereas calling sleep(millis) will really stop the thread for at least the millis specified sleep() does not relaese any locks from objects ⇒ A sleeping threads locks are not available for other treads! public static boolean interrupted() Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. See also ''interrupt()'' above and isInterrupted(). === Example ==== import java.io.IOException; class HelloThread implements Runnable { public void run() { while (true) { System.out.println("Hello from HelloThread!"); try { Thread.sleep(500); } catch (InterruptedException e) { System.out.println("Got exception in HelloThread!"); return; } } } } class SlaveThread implements Runnable { Thread m_master; SlaveThread(Thread master) {m_master= master;} public void run() { System.out.println("Im SlaveThread and waiting for HelloThread to terminate"); try { m_master.join(); } catch (InterruptedException e) { return; } System.out.println("Good bye from SlaveThread!"); } } public class ThreadTest { public static void main(String args[]) throws IOException { System.out.println("Press Return to stop"); Thread ht= new Thread(new HelloThread()); (new Thread(new SlaveThread(ht))).start(); ht.start(); System.in.read(); // blocks & waits for a linefeed ht.interrupt(); } } Prints: Press Return to stop Im SlaveThread and waiting for HelloThread to terminate Hello from HelloThread! Hello from HelloThread! Hello from HelloThread! [Return] Got exception in HelloThread! Good bye from SlaveThread! ==== Important Methods of Object (thread related) ===== An object in the context of threads means data, which is shared among the differnt threads. See also [[wpde>Semaphor_(Informatik)|Concept of Semaphores]] === Description of the Methods ==== public final void wait() throws InterruptedException public final void wait(long timeout) throws InterruptedException Causes the currently executing thread thread to wait (thread state: running -> Waiting/blocked/sleeping) until another thread invokes the notify() method or the notifyAll() method for this object, or, in the second version, a specified amount of milliseconds has elapsed. A call to those functions affects only the own thread, other threads can't be controlled. public final void notifyAll() public final void notify() The first version wakes up all threads that are waiting on this object's monitor (Standard use). The second notification method, wakes up a single thread. Because notify doesn't allow you to specify the thread that is woken up, it is useful only in massively parallel applications. See [[javatut>essential/concurrency/guardmeth.html|JavaTut > Guarded Blocks]] synchronized aMethod() { /* method definition */ } synchronized (anObject) { /* a code block */ } The code segments within a program that access the same object from separate, concurrent threads are called critical sections. In the Java language, a critical section can be a block or a method and are identified with the synchronized keyword. The Java platform then associates a lock with every //object// that has synchronized code. === Example ==== import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; class SharedText { private String text= null; public synchronized void setText(String text) { while(this.text != null) { try{ this.wait(); } catch(InterruptedException e) { } System.out.println(Thread.currentThread().getName()+ ":setText wakes up"); } this.text= text; this.notifyAll(); } public synchronized String getText() { String t; while((t=this.text) == null) { try{ this.wait(); } catch(InterruptedException e){ } System.out.println(Thread.currentThread().getName()+ ":getText wakes up"); } this.text= null; this.notifyAll(); return t; } } class Stdin implements Runnable { private SharedText sharedText; public Stdin(SharedText sharedText) {this.sharedText= sharedText;} public void run() { BufferedReader stdin= new BufferedReader(new InputStreamReader(System.in)); while (true) { String t= null; try { t= stdin.readLine(); } catch(IOException e){ System.exit(1); } if (t != null) this.sharedText.setText(t); else System.exit(0); } } } class Stdout implements Runnable { private SharedText sharedText; public Stdout(SharedText sharedText) { this.sharedText= sharedText; } public void run() { while (true) { System.out.println("Stdout: "+ this.sharedText.getText()); } } } public class ThreadTest { public static void main(String args[]) { SharedText text= new SharedText(); (new Thread(new Stdin(text), "StdinThread")).start(); (new Thread(new Stdout(text), "StdoutThread")).start(); } } ==== Misc == * Possibly useful: [[ibm>java/library/j-javadev2-7.html|Kilim]] //actors// instead of threads for concurrent programming * [[http://www.developer.com/design/article.php/3680701|Thread local static variables]] (Threads Versus The Singleton Pattern) * Possibly useful: Simple thread control with [[http://www.developer.com/java/article.php/3713031|CountDownLatch]] * Possibly useful: [[http://www.developer.com/java/other/article.php/3723501|Managing Long-Running Tasks in a Swing App]] ===== Access Specifiers ====== Default specifier: package ^ ↓Specifier / access from→ ^ same class ^ same package ^ a subclass ^ the world ^ ^ private | IYES | INO | INO | INO | ^ package | IYES | IYES | INO | INO | ^ protected | IYES | IYES | IYES | INO | ^ public | IYES | IYES | IYES | IYES | ===== Inner Classes ====== | nested class |||| | inner class ||| | | (regular) inner class | method-local inner class | anonymous inner class | static nested class | class EnclosingClass{ static class AStaticNestedClass { } class InnerClass { } // inner classes are non-static nested classes } * Use it when (see also [[http://www.javaworld.com/javaworld/javaqa/2000-03/02-qa-innerclass.html|Javaworld]]): - you need something like a callback function (in java there is no function pointer, so you need a class reference) - The callback needs access to your class members, i.e. if function pointers would be possible it would be a member function of your class * A nested class makes sense only in the context of its enclosing class or when it relies on the enclosing class for its function. * A nested class has unlimited access to its enclosing class's members, even if they are declared private. * access specifiers--private, public, protected, and package may be used * most nested classes that you write will be inner classes ===== Arrays, Lists and Loops ====== ==== Defining an Array ====== int[] anArray; // declare an array of integers anArray = new int[10]; // create an array of 10 integers int[] anArray= new int[10]; // composed form: declare & create an array of 10 integers DateFormat[] dfa = new DateFormat[6]; // composed form String[] colNames = { "Text", "Topic" }; // shortcut for creating and initializing an array anArray.length // get the size of an array, not length() ! To copy an array use ''System.arraycopy()'' (see [[javatut>java/nutsandbolts/arrays.html|Tutorial]], [[javaref>api/java/lang/System.html|API]]) or use ''Arrays.copyOf()'' (see [[http://www.developer.com/java/data/article.php/3680241|developer.com]]) ==== Walking through ====== import java.util.*; class TestArrayAndList{ public static void main(String[] args){ String[] myArr= {"eins", "zwei"}; System.out.println("Array: Obsolete: Using length property:"); for (int ix=0; ix myList = new ArrayList(); myList.add("one"); myList.add("two"); System.out.println("\nList: Obsolete: Using an iterator:"); Iterator i = myList.iterator(); while (i.hasNext()) { System.out.print(" "+i.next()); } System.out.println("\nList: Better: Using Foreach:"); for (String pos : myList) { System.out.print(" "+pos);} } } It is expected that the use of Iterators will diminish: http://www.developer.com/java/print.php/10922_3631061_2 ==== List methods ====== List list= new ArrayList(); /** Appends the specified element to the end of this list */ boolean add( e); /** Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices). @return the element that was removed from the list. */ E remove(int index); /** Replaces the element at the specified position in this list with the specified element. @return the element previously at the specified position */ E set(int index, E element); ===== Assertions ====== ==== Syntax Example ===== assert a < b; // or: assert a < b : "a="+a+" is too big"; see JavaDocSun ==== When to use ===== Do not use assertions to check the parameters of a public mehod, throw an IllegalArgumentExcetption intead. (from Java Tutorial) ===== Generics ====== ==== Normal "is a" relationship ===== public void someMethod(Number n){/*...*/} someMethod(new Integer(10)); // OK someMethod(new Double(10.1)); // OK ==== Subtyping and Wildcards ===== Example: (ERROR means compiler error, not runtime error) class Gen { public void take(T t) {} } class NumGen { public void take(T t) {} } public class GenericsTest { public static void takeNumGen0(Gen numGen) {} public static void takeNumGen1(Gen numGen) {} public static void main(String[] args) { Integer i= new Integer(1); Double d= new Double(1.1); Gen numGen = new Gen(); Gen intGen = new Gen(); Gen strGen = new Gen(); numGen.take(i); // OK: Integer is a Number numGen.take(d); // OK: Double is a Number //intGen.take(d); // Obvious ERROR: Double d is not an Integer takeNumGen0(numGen); // OK //takeNumGen0(intGen); // ERROR: Gen is not a Gen ! takeNumGen1(numGen); // OK takeNumGen1(intGen); // OK: Gen is Gen //takeNumGen1(strGen); // Obvious ERROR: Gen is not Gen NumGen numNumGen = new NumGen(); NumGen intNumGen = new NumGen(); //NumGen strNumGen = new NumGen(); // Obvious ERROR: String is not a Number } } ===== Enum Usage ====== class Tribool { public enum State { UNKNOWN, TRUE, FALSE } public State state; public Tribool(State state){this.state= state;} public Tribool and(Tribool other) { Tribool r= new Tribool(State.UNKNOWN); if (this.state == State.TRUE) { r.state= other.state; } else if (this.state == State.FALSE) { if (other.state != State.UNKNOWN) r.state= State.FALSE; } return r; } public String toString() {return state.toString();} } public class EnumTest { public static void main(String[] args) { Tribool t0 = new Tribool(Tribool.State.UNKNOWN); Tribool t1 = new Tribool(Tribool.State.UNKNOWN); System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.UNKNOWN; t0.state= Tribool.State.TRUE; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.UNKNOWN; t0.state= Tribool.State.FALSE; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.TRUE; t0.state= Tribool.State.UNKNOWN; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.TRUE; t0.state= Tribool.State.TRUE; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.TRUE; t0.state= Tribool.State.FALSE; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.FALSE; t0.state= Tribool.State.UNKNOWN; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.FALSE; t0.state= Tribool.State.TRUE; System.out.println((t0.and(t1)).toString()); t1.state= Tribool.State.FALSE; t0.state= Tribool.State.FALSE; System.out.println((t0.and(t1)).toString()); } } ===== Further Reading / 2do == * Intro to the [[ibm>java/library/j-5things9.html|Java Scripting API]] with [[jrunscript]] * Doc general Java strategy: Use [[Apache Pivot]] for the GUI, [[JUnit]] for testing, [[Apache Ant]] for building, JWS for distribution and [[Groovy]] for coding * [[http://www.linux-magazin.de/Heft-Abo/Ausgaben/2008/08/Reiches-Angebot|Webentwicklung mit Java]]: An Overview (german) * [[http://www.ibm.com/developerworks/opensource/library/os-lombok/|Eliminate Java verbosity with Lombok]] * REST (with AJAX): * Wink is a framework for building RESTful Web services * [[ibm>web/library/wa-aj-jackson/|Wink with Jackson]], a [[http://jackson.codehaus.org/|Java JSON-processor]] * [[ibm>web/library/wa-aj-richjava/|Build rich Java Web applications with Apache Wink and Ajax]] * [[ibm>web/library/wa-apachewink1/|RESTful Web services with Apache Wink]] * [[http://www.developer.com/article.php/3843846|JAX-RS]]: The Java API for RESTful Web Services * [[http://www.developer.com/article.php/3841046|Real World REST]] using Jersey, AJAX and JSON * [[http://www.developer.com/java/article.php/3837316/|Non-Blocking I/O Made Possible in Java]] * Dick Wall [[http://www.developer.com/java/ent/print.php/10933_3813031_1|recommends]] to create a reusable genericized ''Pair'' (and ''Triple'') class (like in the C++ Standard Library) for the main purpose of being able to conveniently and typsave return more values at once from a method. * [[http://www.developer.com/java/ent/print.php/3623781|Internationalization in Java]] using string resource referencesis better than ResourceBundle's (?) * Do we have to make classes final to optimize? see [[http://www.ibiblio.org/javafaq/javafaq.html#xtocid1902957]]