FUNDAMENTAL JAVA STUFF MEMBERS = FIELDS + METHODS STREAMS vs. READERS/WRITERS vs. PRINT* classes Readers/Writers are for reading "characters". Non-reader streams are for reading "bytes". Readers always use a character encoding. FileReaders/Writers use system default character encodings. To specify your own, use new InputStreamReader(new FileInputStream(...), "ISO-8859-1") and analogous Writer. streams/Readers generally read return count or -1 for EOD and throw for all other non-successes (incl. closes). Exceptions are ObjectInputStream+DataInputStream reads and BufferedReader.readLine() which throw or return null (correspondingly) for EOD. All streams/Writers write ALL supplied bytes and throw for all non-success EXCEPT Print* classes have print*()/format()/println*() methods and have .checkError() instead of throwing (with all write/print methods I/O-failing silently). PrintStream is a bastardization since these methods are clearly character-specific. FLUSHING is very idiosyncratic. Default PrintStreams (with no Buffer class involved) seems to flush even when newlines not written. PrintWriters, even with a Buffer class involved, requires a .checkError() or .flush() even after a println(). ??? http://www.phrantic.com/scoop/tocint.htm And Sun (actually Jguru I think) Fundamentals trail. Current time in milliseconds (saved in a long internally): new Date(). To print time with time zone and 24-hour hour, just print new Date(). To print with am/pm hour and no time zone, use the default Format (below). java.text FORMATTING Critical classes are all java.text.Format subclasses. Categorically { DateFormat, MessageFormat, NumberFormat } (the first and last are abstract) Single-quote to escape pattern characters in formats. '' for '. The (default) pattern characters like , are US-English-specific (and will be converted automatically). GENERALLY Get formatter instance with AbstractFormat.get*Instance(...[Locale]) and for cust. pat.: ((SpecificClass) formatter).applyPattern(pattern) OR new SpecificClass("pattern"[, Locale]) Except that DecimalFormat doesn't have the Locale param in previous); and that the type-specifiers for DateFormat.get*Inst(...) get clobbered. Method is uniform for specifying pattern for default locale OR for specifying a locale. DateFormat: SimpleDateFormat.format(java.util.Date) => String java.util.Date SimpleDateFormat.parse(String) throws ParseException: like sdfYMDHMS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.LLL"); Can get default SimpleDateFormat or several others with DateFormat.get*Instance([int style...][, Locale]) where * is Date+/Time or "" Date string: java.text.DateFormat.getDateTimeInstance().format( new java.util.Date()) ); If doing it multiple times, get the DateFormat only once (output of get...). NumberFormat: xFormat = new DecimalFormat("##0.0##"); String xFormat.format(d) or String.xFormat(l); // double or long Number xFormat.parse(String) throw ParseException Locale-Specific Formats: NumberFormatter.get*Instance([locale]); //* Number Integer Currency Percent To apply a locale-specific pattern, then do ((DecimalFormat) nf).applyPattern("pattern"); Compare Strings: "string".equals("otherstring"); BECAUSE String vars + concatenated generate Strings != to the normal constants. Beeping: comp.getToolkit().beep(); Anonymous subclassed class: Superclass varname = new Superclass(args){ imp }; Anonymous interface-impling class: Ifname varname = new Ifname(args){ imp }; Anonymous variable: new Classname(args) Anonymous variable w/ anonymous class: new Superclass/If(args){ imp }; NOTE: You can only use final or member vars in inner class impls. You can not give a constructor with an anonymous class, because you can't name it with the class name (there is none). Use "local inner classes" if you need that. (You can also give cons code via instance initializer blocks). atoi convertsion: Integer.parseInt(String s); atoi convertsion: Float.parseFloat(String s); itoa conversion: String.valueOf(int i); str-to-char-arr: String.toCharArray(); DOCS: http://java.sun.com/j2se/1.3/docs/api/index.html As of Java 1.1, the Java method naming convention is: get*: method that retieves the value of an object's property set*: ... sets is*: tests [ heap is for dynamic memory. Stack for static memory? ] No ; after closing block }. I don't know if this is just for the main block of a class def, or always. THREE WAYS TO RUN A JAVA PROGRAM Applet must be invoked by a HTML APPLET tag. May be run by appletviewer or a Java-capable browser. The HTML has to specify the window size to allocate for the Applet to run in. Application. public class method "main" of class is invoked. Applets can do this too if they have the method. Applications run wide open. Servlet. Can run standalone or from a web server. Main signatures MUST declare the String array. java.lang.System.out.println: System is a class. System.out is a class variable; and it is an instance of some other type (PrintStream). out happens to be instantiated when the System class is loaded into an app. println is an instance method of the PrintStream class. print is just like println, but doesn't append a newline. write is like print but writes bytes, in case you have binary data. IMPORTANT: Stream == bytes; Reader/Writer == characters. The abstract class InputStream provides read() for bytes; The abstract class Reader provides read() for characters. Ditto for writing bytes and chars, but Writer also writes Strings. (Both reads/writes work with a single int in order to differentiate eof). java.lang.System.err is the error byte PrintStream. java.lang.System.in is the stdin byte InputStream. /** Javadoc comments look like this */ All methods and variables must be defined INSIDE a class definition. NO FREESTANDING methods or global variables. Every class results in a class file. MEMBER = attribute = variable static = class Instance vars and instance methods can only be accessed through an object of the class. (Must ref as obj.name.thing). Class vars and instances can be specified by objname, classname, or default to classname: obj.thing, Class.thing, thing. SIGNATURE: visibility type datatype name (args...) public static void thing (...) Datatype void means: Doesn't return any value array_object.length # NOTE THAT THIS ISN'T A METHOD BUT A DATA MEMBER I guess you cant get the script name from Java. STANDARD GUI APP: The main creates a class instance. The main class is a Frame ("extends Frame"). Do mostly everything in constructor. Use locals unless something outside of the cons needs to access something. Overriding methods. Can override any method, except may not change the return type or visibility for a superclass method of same name+params. (With C++ can only override a virtual method). (With v. 5+, can change return type to a superclass of the overridden return type). You can synchronize overridden methods. Overriding fields. Can do, and can change visibilities. Every object is an Object. (Object is the base class). New classes are direct subclasses of Object, by default. (I.e, "extends Object" is the default parent specifier). APPLETS. Must extend the Applet class (public!). Must override at least one of the following methods: init(), start(), paint(). init & start are Applet class methods paint is a component method. It must take a Graphics object as an arg. Making a main for an Applet. make a frame instance. make an instance of your Applet class. add the Applet to the frame. make it visible. add a window listener to the frame to override the windowClosing event. Importing entire package(s) slows down compile time but not run time. Casts work just like C. "char" is actually a 16 bit Unicode. All integers are signed. boolean type. Object wrappers for primitive types: Begin with capital letter. To output a primitive value, need to use a method, like var.doubleValue(). Creation example: Double d = new Double(5.5); Standard wrappers are NOT WRITABLE! Have to write your own for that. Legal java identifiers: start with case-sensitive letter or _ or $, plus any numer of Unicode chars. Legal Java variable name. Legal identifier; not a keyword or true or false. Can't re-declare a variable name of same scope. However, an arg param or local var may override a member var of same name; and you may "override" variable names (even with different visibility settings). Unlike C++, can initialize vars just like you should be able to. Scope is exactly what you would think. There are local for vars. Primitive types contains a single value. (Arrays/vectors are objects) AUTO VARIABLE INITIALIZATION: By default, instance and class "member" variables are initialized to 0 (or equiv) (C++ does not initialize instance member variables at all) Local variables are not initialized OPERATORS string + thing converts item on right to a string and concats pre/postfix operators. Done before/after expression evaluated. var = object just sets a reference to the object. To make a copy, use object.clone(). no comma operator (except in first clause of a for statement) Constants: final datatype name = value; // Must initialize with a value! commas allowed in 1st and 3rd clause of for. switch statement: the expression must be of datatype byte, char, short, or int or the corresponding Wrapper Objects, + enums. N.b. WILL NOT WORK WITH floats, longs, etc. labelled break & labelled continue. Tutorial says that it "appears" you can only use a label that would be the default behavior anyways. label:s are pretty much allowed anywhere, but are only honored for break, etc. statements if they are really at a direct ancestor scope. "return 3;", not "return (3);". "this" is available in instance methods. "this" is just a pointer (ref) to the object (just like C++) . Since Java tracks all references, you don't have to worry about the object being deallocated. Doc says that it may be used to access "instance members"-- I suspect that it can also be used to access class (static) members. Code in class methods may not access instance methods or vars. (Though they may create objects of their own class and may access that object's members). PRIMITIVES ARE VERY DIFFERENT FROM OBJECTS. Primitivetype name; Allocates space for name Classtype name; Allocates only a reference You can not "new" primitive types. "myArray = new int[25];" is only newing "references", not integers. ARRAYS + System.arraycopy(...) Array instantiator must be explicit, like "new int[] { 1,2,3 }" EXCEPT FOR when initialized with a declaration, in which case the "new int[]" may be omitted. Declare a multidim array ref: "int[][] myArray;" array1 == array2 only compares references array1.equals(array2) generally will not do what you want it to Arrays.equals(array1, array2); <== THAT DOES what you want it to! FOLLOWING STATIC METHODS INDISPENSIBLE: Arrays.equals(ar1, ar2); // deepEquals if nested arrays may be present Arrays.asList(el1, el2,...); Arrays.toString(ar); // deepToString if nested arrays may be present Arrays.sort(ar); // in-place sort. Unlike Collectsions.sort() only natur. N.b. binarySearches require array to be sorted before-hand, and if absent returns negative insertion index (offset by -1 so it will always be negative). A Comparator may be supplied to use instead of natural ordering. (Alternative declaration syntax: int myArray[]; There some danger with making arrays of Strings?? Object arrays in Java are really object ref (pointer) arrays. The underlying objects must be created by multiple new's (one for each object). It appears that "this.member" (where this is the current "object") is equivalent to "member".? Don't know about class members yet. Strings cannot be changed. StringBuffer's can. In many cases, you can generate another String and set your reference to point to it. Strings are much more efficient than StringBuffers. StringBuffer -> String: stringobj.toString() One StringBuffer constructor is "new StringBuffer(length);", but the length is only for efficiency purposes, as the size will change to accommodate the current StringBuffer contents. Current allocated size is StringBuffer.capacity(). Plus there is .append(), .insert() (you specify index before which to insert), subst-like methods, etc. append returns a StringBuffer, so you could chain them like new StringBuffer().append("alpha").append(stringobjname).append("gamma")); You must obviously instantiate a StringBuffer before you can append to it. Strings can be instantiated without the new operator. String s = "helo"; In general, DO NOT USE new TO CREATE STRINGS. It is a waste: "helo" is already a string, so 'new String("helo");' just creates an second string. Since Strings are array objects, you can do "hello".length. stdin/stdout. read() reads a single byte but returns an integer in order to differentiate eof (-1). I guess that read is a "byte stream operator". reader/writer subs are just like the byte stream operators, but work with 16-bit Unicode characters. JAVA BUG!!! If stdin is closed, System.in and even Readers made from it will actually read GARBAGE! (and .available() is ~ 3,000,000 on my Linux system for both Sun and openjdk). Printing refs. When you print an obj ref, obj.toString() is invoked. By default, this identifies the class and hex address (direct or indirect address) of the OBJECT pointed to (not the class of the ref!). Primitives are allocated statically at compile time. Objects are allocated dynamically at run time. (Object wrappers for primitives are provided). Refs can point to its class OR TO ANY SUBCLASS. Object obj = new Subobject; There are no real object variables in Java, only refs (pointers). When a ref points to a subclass object, you have to cast to a subclass in order to access any subclass fields. Anonymous Objects. Identified by a "new" without assigning the output of new to a reference. Just like perl, memory can be reclaimed when there are no refs to it. Can cause this by setting refs to point elsewhere (like null). Unfortunately, Java will not invoke anything "automatically" upon object destruction. Even calling System.gc() does not guarantee that unrefed objects will be collected. Object.finalize() gets invoked automatically when memory is "collected", but there is no way to know when that will be (between unref time and infinity). System.runFinalization() does not "guarantee" tha finalize will run. At the end of your finalize method, you should run super.finalize() to make sure that ancestors get deallocated. You can specify for finalize() to run "sometime before program terminates". System.runFinalizersOnExit(boolean). DEPRECATED. All method defs are inside class def. There is no concept of "inline" methods. CONVENTION: Classes begin with a cap. Variables begin with lc. Interfaces begin with a cap. CLASS DECL: public abstract final class NAME extends SUPERNAME implements if1, if2 { DEFAULT is a non-final, non-public, non-abstract "implements Object" that implements nothing. Can't use the combination abstract + final. Doesn't make sense. FINAL CLASSES are for instantiating objects, not for subclassing. Unlike C++, you can not modify access specifiers to inherited methods. Classes which implement an interface. Must implement ALL methods of the interface according to the signatures in the interface (this includes return type). By default, a class can be used only by the objects of other classes in the same package (what about by other classes directly?). Public overrides this. ABSTRACT CLASSES are for subclassing, not for instantiating objects. They MAY contain class signatures, but may not implement any method. Additionally, an abstract is the only class that may inherit abstract methods without implementing them. All objects inherit the following behaviors from Object. equal(): ability to compare oneself to another object toString(): ability to convert to a string wait(): ability to wait on a condition variable notify(),notifyAll(): ability to notify other objects that a condition variable has changed, etc. getClass(): ability to create a new object that is the clone of an existing object finalize(): ability to define code that will be executed immediately prior to garbage collection of an object instanceof: ability to identify the class type for an existing object FQ inheritance is java.lang.Object. A member variable and a method may have the same name. Support of volatile and transient are suspect. VARIABLE DECLARATION public|private|protected static final transient volatile TYPE VARNAME If no method params, just use empty parens (no optional "void" like in C++). Return values "returned by value". (Object "references" are returned by value). Args are "passed by value". (Object "references" are passed by value, so pointing parameter reference to something else is generally counterproductive). Direct changes (ie. not to reference object) to args "passed by value" have no effect on the original variable. To change a passed primitive, you need to write your own WRITABLE primitive wrapper class. Unlike C++, returned item can be of a SUBCLASS of the specified return type. Return type can be an interface type, in which case returned object must implement it. Just like C++, you can overload methods as long as the arg #Xtypes differ. Return types don't matter! "overloading" is just the triviality that different parameters in a declaration make a method "different". CONSTRUCTORS. method name = class name. No return type specified. No return statement permitted. Unlike C++, can only call constructor as "new" (NOTE: Interm & Advance courses explain that explicit call to new isn't always neede). Default constructor. System provides a "NoArg" constructor ONLY IF YOU PROVIDE NO CONSTRUCTOR AT ALL. So, if you make any constructor, you must make a NoArg contructor if you want one. (Same as C++) METHOD DECLARATION accessSpecifier static abstract final native synchronized returnType methodName( paramList ) throws exc1, exc2 {... final prevents method from being overridden. No direct support for passing a method to a method for execution. Can only kludge it by inheritance. "super" means to bypass the local method/var and use the overridden one in a superclass. super() + initializer blocks {} is done silently as first thing in constructors. (Unless you code your own super(...) or this(...) which will eliminate the implicit super()). NOTE THAT THIS BEHAVIOR IS INVISIBLE. super(parameters) must be the first executable statement in the constructor. The super()-chaining is called "constructor chaining". Unlike C++, you can have no static vars that are not member vars. Doesn't make sense. CLASSPATH contains directory names and/or zip file names and/or jar file names. Each directory is a peer "default" package location and each subdir thereof corresponds to a package. To be able to invoke an application with "java -jar jarfile", you have to write "Main-Class: Classname" in a file (of any name) and then create the jar file with "jar cmf manfile file.jar...". The Main-Class keyword is case insensitive, but there must be exactly one "space" on the entire line or things won't work right. The Java installation should append your Java home + /class to your CLASSPATH. CLASSPATH contains directory names and/or zip file names and/or jar file names. Ditto for "." ($PWD). Package statements must be the first nonwhitespace in a java source file. *I think* that every file in any one source directory must have the same "package" statement. That statement just gives the current directory path, relative to a base dir (in someone's CLASSPATH). Import statements must come before any class or interface declarations. Import statements specify class files, either singly or with wildcard *. The argument to import is CLASS FILES, not packages or directories. The class names (or object name obviously) must still be specified when using them. Compiling. javac the controlling class source file. This will also compile all clases that this depends on. Invocation. Controlling classes inside packages must be invoked from a base directory with the full path down to the class. VISIBILITY/ACCESS CONTROL. Applies to class and ALL OBJECTS of the class. Each visibility level EXTENDS the previous level, and 'protected' extends default/package level! (therefore it is also visible to all other classes in the same package). CLASS ACCESS (access and instantiation capability). Same package by default. Any if "public". Can further refine instantiation access control by applying member access controls to the constructor method. PRIVATE MEMBERS are only accessible from that one class (not to a subclass). Note that private members of objects are visible to the class and to all other objects of that class. (As I see it, this means that private members are not "inherited", but the author doesn't see it that way). PACKAGE MEMBERS are accessible only from that package (not to a subclass in another package). Remember that this applies to where the member was originally DEFINED. PROTECTED MEMBERS are accessible (The asshole keeps talking about access "from objects", but I suspect that this applies to access from class methods too). AS subclass.member: only from subclasses (regardless of package). AS superclass.member: only if member originally DEFINED in same package No functionality corresponding to "friend" in C++ (C++ aside: class vars in C++ must be redeclared at the global level. Both C++ and Java allow access from object like object.varname, but access by class differs. Classname::varname in C++; Classname.varname in Java). Member variable constants are usually finals, since there is no reason to use memory on multiple copies. Instance methods may access both instance and class vars (same in C++). Java will throw a OutOfMemoryError if a new object can't be allocated. Overriding Object.equals(). Arg is Object, so must cast it down. Don't know what the default equals does to user-defined classes. Class (subclass of Object) has no public constructors, they are created automatically. But Class methods return instances. Some useful methods newInstance() (see CLONING below), getName(), getSuperclass(). DESCRIPTOR: An object that describes another object or class. Example: Class objects. CLONING: origobj.getClass().newInstance(); RETURN TYPE IS Object. This is a way to create an object without invoking "new". Interfaces. Can not instantiate an object of the interface type. There is no "new" for the interface. Variables of this type may only access methods declared in the interface (or a superinterface). INTERFACE DECLARATION: public interface NAME extends if1, if2 {... As you can see, unlike a class, an interface can extend multiple other interfaces. A interface may only extend other interfaces. Interface method declarations. All are implicitly public and abstract. Can not specify transient, volatile, private, protected, synchronized. As the interfaced method is public, it's impossible to broaden visibility. Just like for any other method overriding, it's illegal to narrow an overriden method's return type. ? They will use Object datatypes where the self type is normally. ? You can synchronize overridden methods. # I THINK THIS IS WRONG. AUTHOR DOESN'T KNOW HOW TO IMPLEMENT INTERFACES. # Routines that use interface types (this is the purpose for interfaces) # should run instanceof to test that args really implement the interface. Routines that use interface types (this is the purpose for interfaces) should take args of the interface TYPE. Interface related implementations should check the Classes with instanceof where necessary. instanceof: (X instanceof B) is a boolean. Returns true if X is a class or an implementation of B (don't know about subclass or subimplementation). DOES NOT WORK WITH nulls, since null has no class. GOTCHA! Precedence of instanceof operator is non-intuitively low! If use in an expression, you must put parens closely around the instanceof operation, like: !(x instanceof Y) Null values are not 'instanceof' anything. Looks like Instances contain only OBJECT methods and public constants. public, final, static keywords are not necessary. You can implement constructor-like subs by calling an outside method in a constant assignment expression. Interfaces must be in their own source file??? (Funny requirement) List system properties: System.getProperties().list(System.out); java.lang.System. Properties. Create a Property. save to output stream with store(), retrieve with load(). store removes all other comments. propCust.store(new FileOutputStream ("blaine.props"), "Idunno"); It writes the required comment to 1st line plus a data stamp comment. For detailed file syntax, see API for java.util.Properties.load(InputStream). # or ! comment lines and blank lines permitted Leading and trailing whitespace trimmed from keyword. Leading whitespace trimmed from values. Generally: " KEYWORD [:=]? Value " (Final whitespace preserved) Program does not have access to its name. The arg array begins (arg[0]) with the first (not zeroth) arg. java.lang.System controls system resources in a platform-independent manner. Contains only CLASS variables and methods. Final class with only private constructors. getProperty(one arg) returns a null ref if the given key is not found. getProperty(two, args) returns the 2nd arg if a key of the first arg is not found. setProperties overwrites the entire properties list with the Properties object that you supply. Note that this sets them for this process instance only. System.setProperty("name", "value") works on live system properties. MISC. SYSTEM METHODS public static void arraycopy(Object src, int src_position Object dst, int dst_position, int length); Dest array must be completely pre-allocated. arraycopy only creates objects, not array elements. I.e. shallow copy. System.exit() or System.exit(value). This may cause a SecurityException in an applet. setSecurityManager() and getSecurityManager(). Can only set the security manager once in an Application. Browsers do this, so that means that if an Applet tries to do it, it will cause a SecurityException. Runtime Object. Platform-dependent resources and capabilities. Includes capability to use UNIX getenv and setenv. System.getenv("string") is deprecated. Exceptions. try, throw, catch, finally (C++ does not have "finally"). catch block runs if you (or the system) throws the event. finally block is executed whether or not an exception occurred. Exceptions are "thrown". They are objects descendeded from class Throwable. User defined exceptions must be descended from Throwable. Throwable has 2 subclasses: Error, Exception. Errors "should not be caught". Errors SHOULD NOT BE CAUGHT. (Sun tutorial incorrectly calls Errors a "type" of Exception, when they are in fact Throwables). All Throwable.Exception.* objects other than Throwable.Exception.RuntimeException (so this excludes Error.*) must either be caught or declared. Also called "checked" exceptions. RuntimeExceptions "most applications shouldn't throw runtime exceptions or subclass RuntimeException", but I think that is extremely oversimplified! Apps should throw them, but in such a way that APPS should avoid their generation. "preconditions on public methods are enforced by explicit checks that throw particular, specified exceptions", incl. example IllegalArgumentException. "If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception." MY WORDS: When the caller SHOULD prevent it from ever being thrown, throw a RuntimeException. If the caller has not prevented it from being thrown, the results will be admittedly unrecoverable. Checked Exceptions must be either caught or "specified". Note that you can still trap and handle unchecked exceptions if you want to (the distinction is that you don't *have to*). Throwable methods. getMessage(), printStackTrace(), toString(). Try/Catch/Finally syntax: Try block followed immediately by at least one catch or finally block. Catch (aThrowableObjectType varName) {...} The type in the Catch param could be a specific class (leaf) or a class with subclasses (node). The second will catch all subclasses. CONVENTIONS. Subclasses under Exception should end with "Exception". Subclasses under Error should end with "Error". USER DEFINED EXCEPTIONS: Override getMessage() or it will return null. (I think this is set by the arg to the exception constructor). Finally block is even run if a "return" is run. (I don't know about System.exit() though). Catch blocks handling more specific (leafy) exceptions should come earlier. As you would think, you can specify files with absolute paths or paths relative to the $PWD. I don't know how to find out the directory from which the current object/class is in. SECURITY MANAGER ENABLE A SECURITY MANAGER System.setSecurityManager(new PasswordSecurityManager("Booga Booga")); SYSTEM ALREADY CALLS checkXXX wherever necessary. Only need to do it if write a new checkXXX method. SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkExit(status); } SecurityManager.checkExit(?) (instance method) thorws a SecurityException if exit not permitted. checkAccess() for thread accesses, checkpropertyAccess(). There is a checkXXX() for every operation or group of operations. Default SecurityManager checkXXXX methods prohibit everything: public void checkXXX(. . .) { throw new SecurityException(); } So, if you enable the SecurityManager, you need to override many checkXXX methods if you want to permit much. CREATING A NEW SECURITY MANAGER. Create a SecurityManager subclass. Override or create some methods. DataInputStream?? Has DataInputStream.readLine(); (DEPREC. instance method) DataOutputStream?? Has DataOutputStream.writeBytes(data); (instance method) THROWING EXCEPTIONS. In this case at least, the arg is printed with the terminating traceback: throw new SecurityException("Not Even!"); You can avoid the hassle of handling exceptions that you throw by throwing only unchecked exceptions, or by putting a "throws Throwable" in your main method declaration. long System.currentTimeMillis(); returns mulliseconds since 01/01/1970. (NOTE: currentTime and nowMillis are obsolete). To prevent "variable may not be initialized" errors, set refs (objects vars) to null. THREAD SUBCLASS. Constructor java.lang.Thread(String name) should be overridden to supply a name. Override the void run() method. Here's a simple create & invoke: new SimpleThread("Jamaica").start(); Thread.currentThread(); self-explanatory Thread.getName(); self-explanatory (works for thread groups too). Threads are "destroyed" by dereferencing the pointer(s). When done with a thread, you should stop() and destroy it. THREAD IMPLEMENTATION. Call thread with first arg a "runnable" object. "Runnable"" objects implement java.lang.Runnable: implements public void run(). (Note that you still make a Thread instance, but instead of subclassing Thread, you give it an arg of a Runnable type). In Applet example: Applet itself implements Runnable. public void start() creates (w/ arg "this") and starts the thread. public void stop() causes run() to return. Keep in mind that Applet start and stop can be invoked multiple times (by revisiting web page), so prepare for one object to handle multiple thread objects (from multiple "new Thread..."s. Everytime Applet.start() is invoked, an ADDITIONAL thread is run. Threads. Rule of thumb: Implement interface if your class is a non-direct-Object subclass. This is because your object can not extend Thread and something else (like Applet) too. (I.e., no multiple inheritance) Unlike perl, can have empty block: {} Thread.isAlive() only tells if the thread's "run" is "running". Other distinctions are impossible (i.e.., could be a "new" thread). Thread priority. Higher the better priority. Thread.MIN_PRIORITY to Thread.MAX_PRIORITY. Thread.setPriority(val). In general, only threads of "equal" priority will share the processor. Otherwise higher priorities will hog it until idle*. Higher pri's will pre-empt. A thread can Thread.yield() to permit other equal-pri threads to run. Java runtime will not stop any thread to run an equal or lower process thread, but the underlying thread implementation *may* timeslice to other equal pri threads. * THIS IS NOT GUARANTEED DEFAULTS: main() gets Thread.NORM_PRIORITY New threads supposedly inherit from parent thread, but I see new Thread()s getting Thread.NORM_PRIORITY+1 ??? May have to do with the ThreadGroup. See mt.txt file SNYNCHRONIZATION. Critical sections identified by "synchronized" keyword. CubbyHole objects are shared. They are like a non-appendable (scalar) fifo. There is one lock per "object". Locks are "reentrant" in that the holder may reenter, just non non-holders. Reads and writes block, just like on a fifo. Object.wait() waits for a notification (signal), and relinquishes lock while it waits. Object.notifyAll() signals ALL waiters (to this object) (they then compete for the lock). Object.notify() arbitrarily wakes up one waiting thread (to this object). There are also wait(long) and wait(long,int) to specify max time in milliseconds or milli+nanoseconds. Thread.sleep() will not awaken before the timeout-- cannot be interrupted like waits can. Can also specify in millis or milli+nanos: Thread.currentThread().sleep(10000); Thread groups decided upon creation and cannot be changed. By default, the thread group is the same as its parent's thread group. java.lang.ThreadGroup myThreadGroup = new ThreadGroup( "My Group of Threads"); Thread myThread = new Thread(myThreadGroup, "a thread for my group"); theGroup = myThread.getThreadGroup(); Thread groups can belong to other thread groups (just like a thread can). ThreadGroup methods can give count or enumerate threads; get/set max/min priories, name,parents,string of GROUP; resume, stop, suspend ALL, access restrictions using a SecuritManager. Both Thread and ThreadGroup have checkAccess() methods which call the security manager's checkAccess before runnin their own secured methods. java.alang.ThreadDeath is a throwable. Throw at a thread to kill it. Threads may catch that before dying. All streams are automatically opened when created; garbage collector can close it. CAN NOT DEPEND ON THIS AUTOMATIC CLOSE!!!! (nor flush) Need to work with characters, because they are portable. However, System.in, System.out, System.err are all streams, so need to do lots of conversion to work with them. DEPRECATED: (new DataInputStream(in)).readLine(); Should not read streams directly into characters. CONVERTING CHAR STREAM (Stream) TO/FROM Reader/Writer: InputStreamReader, outputStreamWriter I/O WRAPPING BufferedReaders are at the very top and you call to get chars, etc. BufferedWriters intercede between PrintWriters and underlying Writers. READING LINES OF TEXT INPUT FROM A STREAM: (new BufferedReader(new InputStreamReader(in))).readLine(); "in" could be System.in or (new FileInputStream("X")) readLine is supposed to return null at eof, but it is not doing so! CAN WRITE TO OUTPUT STREAMS DIRECTLY WITH CHARACTERS. (WHY??????) Just use PrintStream System.out (or System.err) READING/WRITING TEXT FILES FileReader and FileWriter only use the platform default encoding. To specify, use an *StreamReader/Writer. PrintStream (such as System.out) similarly use platform default for output. PrintStreams are really a violation of the char vs. byte bifurcation, since this is a stream that converts supplied characters to bytes (i.e. a Print*Stream* corresponds to a File*Writer*). Print* classes are the only ones that have the print*()/format()/println*() methods. BufferedReader br = new BufferedReader(new FileReader("in.file")); System.out.println("Read attempt: (" + br.readLine() + ")\n"); PrintWriter pw = new PrintWriter(new FileWriter("out.file")); pw.println("New line"); pw.flush(); pw.close(); OBSOLETE: ? WRITING LINES OF TEXT OUTPUT TO FILE: PrintWriter pw = new PrintWriter(new OutputStreamWriter( new FileOutputStream("Y"))); pw.println("Text"); pw.flush(); (Note that System.out is already a PrintStream, so you can println to that) DataInputStream & DataOutputStream use BINARY byte streams, not char files. Input & Output implement lots of readXxx and writeXxx methods. Ditto for Object*Streams, which implements DataOutput and DataInput (so you can also use the writeXxx or readXxx methods) . OBJECT SERIALIZATION. Use ObjectOutputStream.writeObject(); Member refs are followed and stored recursively. If any non-transient instance field object does not implement Serializable interface, a NotSerializableExeption is thrown. ObjectInputStream.readObject() returns an Object, so you must cast. Serializable. The Serializable interface is empty. If you want to ADD something, then override writeObject() and readObject(), invoking ObjectOutputStream.defaultWriteObject() or ObjectInputStream.defaultReadObject(). writeObject() and readObject() methods are only responsible for saving/storing the immediate object (not the ancestors). To really do everything yourself, implement the Externalizable interface. There is a serious security concern with others accessing the serialized objects: Either verify contents or (safer) do not implement either Serializable or Externalizable. CONSTRUCTION: Upon reconsititution (readObject), NO CONSTRUCTOR IS USED FOR ANY serializable instance or serializable superclass. However, no-param constructors are used AND REQUIRED for all non-serializable superclasses. VERIFY: I believe Serializables.readObject() always uses no-arg constructors for every Object all the way up the ancestor chain (and ancestor privileges must allow this). By default stores only and all instance non-transient FIELDS, BUT you may do whatever the hell you want by overriding readObject()/writeObject(). Window.readObject(), fore example, overwrites many Component fields explicitly. Following looks totally wrong, as these methods are for object REPLACEMENT. ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException; can make any modifications between reconstitution and returning it to caller. (Works for both Serializable and Externalizable). java.bean.XMLEncoder/Decoder No requirement to implement anything. The class you writeObject(it) must have the required public constructor. No non-API constructor requirements for null constructor, superclass constructors et. al. Designed just like Serializable, but only writes PUBLIC members, and in terms of operations. Just calls persistenceDelegate.writeObject() for each "new" == special name for constructor method. Object being persisted. THERE ARE NO readObject() methods involved! The XMLEncoder class itself has custom PersistenceDelegates registere for all of the J2SE classes which need them. (packaged in java.beans.MetaData). DefaultPersistenceDelegate.writeObject() requires either *I no-param **public** cons + traditional **public** getters/setters OR *II cons w/ property values + traditional **public** getters/setters ?? Consequently, if there is no cons param or getter+setter, the property will not be persisted. ?? It determines the values to persist (or not) by using the getters on supplied Object. It then determines the dflt prop values by using the specified constructor and invoking the getters (and setters in order to initialize derived values in sequence. Due to this, the sequence of getters and setters is significant). Can't simply use transient modifier to ignore a property. Must use: static { try { for (PropertyDescriptor pd : Introspector.getBeanInfo(Bean2.class).getPropertyDescriptors()) if (pd.getName().equals("x")) pd.setValue("transient", Boolean.TRUE); } catch (IntrospectionException ie) { throw new RuntimeException(ie); } } To do II, you specify the list of properties corresp to cons params: encoder.setPersistenceDelegate(MyClass.class, new DefaultPersistenceDelegate(new String[] { "prop1", "prop2",,,})); Unfortunately, there is no provided way to efficiently share these delegs. TRY extending XMLEncoder!!! Any other persistence customization requires subclassing PersistenceDelegate or DefaultPersistenceDelegate for your class, implementing: PersistenceDelegate.initialize(..., out) { // THIS IS RUN WHEN THE OUTPUT IS GENERATED!!! // To cause anything to happen at initialization, you must write method // invocations, etc. here! super.initialize(..., out); out.writeStatement(new Statement(inst, "method", new Object[] {params})); ... // Beware that the newInstance param may be partially constructed already OR PersistenceDelegate.instantiate(), returning new Expression(oldI, aClass, "new", new Object[] { paramVals... }); The paramVals will normally be derived from oldI somehow. I don't know what aClass is, but it's a target for something. List/Map/HashTable impls WHICH DO NOT SUBCLASS the J2SE impls. must have delegate set to encoder.getPersistenceDelegate(List.class), etc. But subclasses of List/Map, etc. can not just extend the PersistenceDelegate, since they are private/package. SUCKS!!! Still must always add custom fields like by adding writeStatements to Delegate.initialize() as instructed above. Tricks are needed for factory methods and singletons. XML SYNTAX: Inside an the items are done in sequence. (For static methods, use class="x" attr). returns an Object (may be a method or constructor). Default methodname = "new" = Constructor, therefore construct with . The Object will not be instantiated until after all require cons params are specified, so the params MUST BE FIRST. A param, val void means to ignore the returned value. classname attrib means a static method (which here incl. constructor "new"). Shortcut for <... method="get">3... ==> < index="3"/> Shortcut for <... method="set">3... ==> < index="3">... /res.txt Unfortunately, pretty dumb wrt expressions. Can't do any math, and can't input any but decimal radixes. Validation leaves something to be desired. If types are wrong, sometimes the method call is silently ignored. RANDOM ACCESS FILES Does not implement InputStream or OutputStream, so can't use most filters. Does implement DataInput and DataOutput, so filters that work with DataInput or DataOutput will work with all random access files. Example: new RamdomAccessFile("name", "rw"); Methods: readXXX, writeXXX, skipBytes (relative), seek (absolute), getFilePointer. Note that unlike Streams and Reader/Writers, one sink objet works for read and write. To write your own random access file filter, instead of extending Filter*, you implement DataInput or DataOutput. OTHER IMPORTANT java.io CLASSES AND INTERFACES File. Can query for stuff like full pathname FileDescriptor. Pretty useless in Java StreamTokenizer. FilenameFilter. Used by File.list() to match file names. CheckInputStream &c. Checksums as reading/writing GZIPInputStream &c. (Ditto for Deflater/Inflator and Zip) I see no easy way to sort elements of an Enumeration, Vector, or Hashtable. ENUMERATION INTERFACE Appears pretty useless. Object s of class S is a set of some subobjects o (of type O). Enumeration objects e of class E control traversal of the o objects. This is the sole purpose of e/E. E implements Enumeration by implementing hasMoreElements() and nextElement(). s generally provides something like getEnum() which will return an e. So, to use it... S s = new S(); Enumeration e = s.getEnum(); while (e.hasMoreElements()) { O o = (O) e.nextElement();... } VECTOR CLASS java.util.Vector Like a runtime-growable array. elementCount is obvious (protected var). capacity is current size and increments by capacityIncrement. Methods addElement(o) contains(o) insertElementAt(o,int) removeElement(o) elementAt(int) isEmpty() removeElementAt(int) elements()* lastElement() capacity() firstElement() size() * returns an enumeration object HASHTABLE CLASS java.util.Hashtable Keys use their hashCode() and equals() method. Object has a default hashCode() and equals() methods. Whole purpose is to provide put() and get(). Values are treated as Objects. Can tune performance by using capacity and load factor args of constructor. Methods. contains(o) keys()* isEmpty() containsKey(o) get(o) put(o,o) elements()* remove(o) * returns an enumeration object remove(key) returns the value of the removed key/val, or null. get(o) doesn't remove anything. java.util.StringTokenizer. (By default, delims do not count as tokens). StringTokenizer(hasMoreTokens() and StringTokenizer.nextToken(). The delimiter string contains all of the delimiters. Default is "\t\n\r\f". String.trim() trims leading and trailing whitespace. EXECUTING EXTERNAL PROGRAMS Runtime.exec() returns a process. You can get input and output streams from a process. Process proc = Runtime.getRuntime().exec ( "/usr/lib/sendmail support"); PrintWriter std = new PrintWriter (proc.getOutputStream()); BufferedReader br = new BufferedReader(new InputStreamReader( proc.getInputStream())); There is also a getErrorStream() (pretty cool!) Note that doing System.setProperty("user.dir", "/dir") doesn't work for subsequent exec's. You have to use one of the exec forms where you specify a current working directory, e.g. proc.exec("ls", (String[])null, new java.io.File("/tmp")) TOOLKIT CLASS Get toolkit with either comp.getToolkit() or Toolkit.getDefaultToolkit(). beep() prepareImage() getScreenResolution() getImage() getFontList() getScreenSize() checkImage() getFontMetrics() getSystemClipboard() createImage() getPrintJob() getSystemEventQueue() Finding out what host an applet came from: String getCodeBase().getHost(); SIGNALS: See Ppp.java for example. Uses sun.misc.Signal and sun.misc.SignalHandler classes. By default QUIT will cause the running program to dump a thread report. When using Arrays.asList(), sorts of either the List or the Array do change ordering of the peer structure. When using Collection.toArray(...), sorts of either DO NOT affect the peer structure. (Also for adding or removing elements; however the individual elements are shared and mutations get shared). SORTING NATIVE ARRAYS java.util.Arrays.sort(*) COLLECTIONS: I don't know if all, but certain Maps can not contain primitive values. static methods: obj = Collections.max(mycol); or ....min(mycol); Perl "Arrays" correspond to Java Lists (but you can also have Java HashSets or TreeSets which are just Lists that prohibit duplicate entries-- notice that HashSets are like Perl Arrays NOT LIKE PERL HASHes) Perl "Hashes" correspond to Java Maps. To use them, you have to decide which Collection class to use: (1) List/Set or Map (i.e., like a Perl Array or a Perl Hash)? (2a) If Map, then do you need sorted? ==> HashMap OR TreeMap (sorted) (2b) If List/Set, then permit duplicate elements? If Permit duplicates, then List; if prohibit duplicates then Set. (3a) If List, then do you need to be able to add or remove elements from the middle of the List? (You can always add/remove elements from the very beginning or end of any kind of List). ==> ArrayList to just add/del at begin/end OR LinkedList to add/del anywhere (Sort lists with static method "Collections.sort(mylist);". Rewrites mylist.) (3b) If Set, then do you need random-access or sorted? ==> HashSet or TreeSet (rand-acc/sorted) Implementation detail: For sorted Sets or Maps, it's generally better to make an unsorted variant (HashSet or HashMap), then convert to a sorted variant (TreeSet or TreeMap) to get the elements in sorted order. Read-only: After creating collection, replace original ref with corresponding unmodifiable*: Collection unmodifiableCollection(origcollect); etc. (Note that read- only's are thread safe and are more efficient than synchronized*s. Thread-safes. Instead of standard constructors, use Set set = Collection.synchronizedSet(new HashSet()); .singleton constructor create single-element immutable collections. Immutable list of repeated elements: List l = Collection.nCopies(10, null); Can then change with: List m = new ArrayList(Collection.nCopies(10, null)); Constants: EMPTY_LIST, EMPTY_SET, EMPTY_MAP. Not type-safe. There are methods like Collections.emptySet() which somehow automagically cast to the variable being assigned to, like Set s = Collections.emptySet(); To sort collections of user-defined-type elements (or Maps with keys of user-defined-type elements), must implement the Comparator interface, which must define public int Comparator.compare(obj, obj). Either use as arg to Tree constructor (then addAll()), or use as 2nd arg to Collections.sort(alist, comparator). Sorting lists Collections.sort(myList) rewrites myList. (Can specify a comparator) Sorting arrays (incl. primitives): Arrays.sort(myarray) rewrites myarray. String.compareTo() has some unexpected consequences, as it sorts by unicode value. All capital letters sort lower. Treemaps are sorted by the keys, not the values Encrypting passwords: http://developer.java.sun.com/developer/qow/archive/28/index.html To create a new object of class determined at runtime. Ifacename newobj = (Ifacename) Class.forname("classname").newInstance(); (where only Ifacename, newobj, and classname change). Can not cast from (Object[]) to (String[]). Have to convert all of the elements. SYNCHRONIZATION Need to synchronize ALL class and instance vars (i.e., non-local vars) in multithread code because JVM's can give separate "copies" of the vars to each thread. Normally there is a single lock for an entire object instance. So, if you have "synchronized a()" and "synchronized b()" in class c, then they are both locked with the same lock. This is the same lock used elsewhere when you do "synchronized(this) {...". THROWABLES (java.loang.Throwable) java.lang.Exception: Normal exception (Throwable subclass) java.lang.RuntimeException: Need not be caught (Exception subclass) (Make these for "unrecoverable errors"). java.lang.Error: Should not be caught (Throwable subclass) J2EE apps should throw RuntimeExceptions for non-recoverable errors, but the Java Trail says that throw RuntimeExceptions "hardly ever": when hyou are creating an error in the virtual machine runtime. (Java tutorial trail says to rarely throw Runtimes, but J2EE apps throw them in order to isolate implementation details from user). Class.forName() initializes static stuff in class. ClassLoader.loadClass() does not. Sequence of static initializers. They initialize in the order they are in the source file, regardless of whether they are variable settings or "static {" blocks. Variable settings to null, like "static org.apache.log4j.Category lgr = null;", do not static-initilize classes. Static initializers DEFINITELY DO RUN for all superclasses upon first access to class X. nullobj.staticMethod() works (is equivalent to ClassName.staticMethod()) (this is discouraged, but works). nullobj.staticVar works. nullobj.finalInstanceVar works. nullobj.instanceVar doesn't work (unless var is final, see previous). nullobj.instanceMethod() doesn't work. Empty array: new Object[0] s, "my method(new Object[0]);" order. Appears that "static {...}" and static variable initializers all run in the order in which they appear in the source file. Can not "return" from clinit "methods" (not really methods apparently). Constructor chaining. Constructors may contain other constructors of this, like "this(arg1, arg2)". The this() commands probably must be the very first thing in the method. INTERFACES Can extend MULTIPLE super-interfaces! May not define static methods. May only define abstract instance methods WITH NO IMPLEMENTATION (all are public with or without specification). variables (all are public static final, with or without specification). SUBCLASSING You can't NARROW the visibility of a parent's methods. E.g., you can't make a type-safe subclass of HashMap. You can make new get and put methods with more specific classes, but that will not stop users from calling these methods with other classes and reaching the parent's methods, since they are public. As a result, to really restrict classes of ArrayList, HashMap, etc., you must make a new class with a HashMap field and wrap selected methods. You can, however, BROADEN visibility of a parent's methods. Instances can not access overridden ancestor methods EXCEPT FOR overridden parent methods (with super.*()). DOES NOT WORK: ((GrandParentClass) anInstance).overriddenMethod(); This is bizarre since it does work for fields!!! It's called "virtual method invocation". Overriding Fields. This does not suffer from the limitations of method overriding. You can widen or narrow visibility, and you can access the implementation-class-specific values with ClassName.x (assuming the class provides visibility). super.x and super.x() can only be called from inside instance methods. (Not 100%. This is by my empirical tests). CAN enter multiple NULLs into an ArrayList. Can't enter multiple nulls (maybe no nulls) as keys into a map. CONVERTING BETWEEN STREAMS AND READER/WRITERS THERE IS NO GOOD WAY TO CONVERT FROM A READER TO AN INPUT STREAM. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4094886 new InputStreamReader(new ByteArrayInputStream(Result.getBytes()) WORKAROUNDS. OutputStream -> String: ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); store(outputStream, "StyleReport preferences"); String s = outputStream.toString(); String -> InputStream load(new ByteArrayInputStream(String.getBytes())); JUNIT assert() methods always have EXPECTED parameter before test-parameter. In-line array constants: x.somemethod(new String[] { str1, str2, str3 }); JAVA-5 SPECIFIC Gotchas Enums: If try to convert an invalid String, including "", to an enum constant, get the very misleading message: No enum const class Class$Enum. Can't subclass enums. Can shut up compiler warnings by putting @SuppressWarnings("type") right before method (or class) definitions. Good list of types at http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm http://dev.eclipse.org/newslists/news.eclipse.tools.jdt/msg15624.html !!! But note the typo on this page. It's "@SuppressWarnings", not "@SuppressWarning"! Gotcha: Some cast warnings actually need "unchecked" suppressed instead of "cast". Some @SuppressWarnings may be placed over individual statements, and others cause compilation warnings unless placed at the method declaration level. My strategy is to always try above the target statement, then fall back to method scope if necesssary. ANNOTATIONS @SuppressWarnings is documented above. Other important ones are: @Deprecated Prefix method declaration and put a @deprecated in the method Javadoc too. DOES NOT WORK FOR Java 5! For Java5 just use JavaDoc @deprecated. @Override Prefix method decl. Just helps the compiler catch failures to override. Great to use whenever overriding anything, EXCEPT THAT OVERRIDING INTERFACE METHODS IS Java 6-specific! String.split(). Always use "String.split(regex, -1);" if you want well-behaved, normal splitting. I.e. don't clump all remaining text into last limited cap like for limit>0. I.e., don't want to throw away (numerous) trailing empties like for limit==0. java.util.regex. MOST IMPORTANT THING TO KNOW!!!: Matcher.matches() has implicit ^ and $. find() does not!!!!!!!!!!!!!!!! Consequently, it only makes sense to do a single .matches(), which can populate .group(), groupCount(), group(int), etc. This is completely different from find(), which is repeatable, with each find() populating a new set of .group(), groupCount, group(int), etc. To Matcher.replaceAll(), you do no match/find, etc., you just replaceAll directly. Mistake in API spec. The output for the "(a(b)?)+" example is not as shown. m.group() === m.group(0) (and for match() method this will always be the entire input string). Non-capturing or capturing nulls is entirely fucking inconfuckingsistent!!!! Must always check both capture count and for nulls!!!!! I think that capture count SHOULD always be the same and should be equal to the number of non-? () in the pattern. This may have been fixed in 5 or in 6. (x?) will ALWAYS be non-null, with "" if x absent (x)? will be null if x absent (but remember that a previous capture from quantification would be retained). GOTCHA: Unlike StringBuffer.replace(), java.util.regex replacement Strings do special processing to \ and $ characters. If you have Java 1.5, you can literalize replacement strings with Matcher.quoteReplacement(String). If don't need regexp, use Java 5's: String.replace(String, String); Number of groups returned is always <= number of non-? parens in your pattern. (So far unable to verify w/6 that this can go lower for negative () matches). "(?...)" is the magic indicator of a non-capturing spec. With no punctuation or just punctuation of -, consumes 0 length. See file "doc/tech/re.txt" about Regular Expressions. It is always ok to get substrings beginning 1 character past the last character of a String. I.e, "s.substring(s.length())" always evaluates to "", not to null, and it it will not throw. I.E. SAFE where s == "s": System.out.println('(' + s.substring(1) + ')'); N.b. Acording to Jar spec, manifest attributes should "work" regardless of attribute name capitalization, but authors SHOULD CAPITALIZE ACCORDING TO THE NAMES IN SPEC, and they are like Main-Class, Class-Path. Jar file Class-Path may contain only jar files and ".". All relative to dir containing the Jar file. The Manifest Class-Path setting used EXCLUSIVELY if run like "java -jar..." (i.e. the classpath may contain nothing else); if run without "-jar", then the Class-Path settings are effectively inserted into the classpath alongside the containing jar (probably right after). STATICS Methods can't be both static + abstract. : Exec DOS cmd: http://www.jguru.com/faq/view.jsp?EID=118872 Testing for runtime classes. Don't know how I could not have figured it out, but for native types, do .class, like "int.class". Testing for Generic classes. ? (Most of the following also applies to the other direction with Collection.toList). Converting from array to Collection: Arrays.asList(array); Absolutely no typing needed. Just Param-type the variable assigning to. This is funny when an array has primitive elements. Instead of auto-boxing, it somehow stores refs to the primitives, and this results in a List that does not toString() as expected. Collection initialization: List stooges = Arrays.asList("Larry", "Moe", "Curly"); N.b.!! These lists are FIXED-SIZE with shared references. Therefore, you can't add or remove elements, but elements themselves may be modified. In this direction (asArray), sorts are reflected in peer; that is not so in the other direction with Collection.asList(...). But asList() is even more useful than this to initialize lists, since it is var-args: generifiedList = Arrays.asList(el1, el2,...) This last will magically generate element type most specific as possible to satisfy all specified elements, as determinable at build time? ? And according to the type of the var being assigned to. Can't initialize generic arrays directly. Must cast. COLLECTIONS Collections.singleton*() are great maps for instantiating immutable Collections with single elements. Collections.min(Collection...) and max(). Collections.sort(List) Collections.binarySearch(List...) works exactly like Arrays.binarySearch(). The java.text.*Formatters ROUND, not truncate. Just like you would want them to do. Java 5 for-each requires Iterable. Therefore does not work with either Enumerations or Iterators. Works great with Sets and EntrySets. Enumeration can't (use enum.values!!!) Set can native[] can Great candidates that work. enum.values, EnumSet.of(), EnumSet.range(). I don't understand how primitive arrays can implement Iterable, but they apparently do. Escaping other than built-ins like \t and \\, are easiest accomplished with unicode literals: \u exactly 4 hex characters. Can use in both char and String specifications: '\u0002' and "x\u0002y". The index param of String.charAt(index) is strict in that the position must be valid. The index param of String.indexOf(char, index) is not strict and works great. java.io.File File objects are very separated from the file system, except for the methods which obviously modify the underlying file. In particular, setting file privileges and modification dates will have no effect at all if there is no corresponding underlying file (and NO INDICATION WILL BE GIVEN IF THERE IS NO UNDERLYING FILE). File(String, String) constructor is very liberal in that the 1st dir param may be null, and the 2nd "name" param may contain any number of directory levels; but getFile() ALWAYS contains just the final directory element (WITH NO IMPLICATION ABOUT EXISTENCE!). getParent*() may be null or may be relative. The getParent* methods really return the parent dir of the file, not the left portion of the File(left, right) constructor. getPath() may be relative or absolute. It will return absolute if file.isAbsolute(). You can force that by file = origFile.getAbsoluteFile(); hashCode/equals/... new File('x').equals(new File('x')) is true. Object.hashCode (Concerned just with equality, not ordering) [Intended for use with Hash* objects. Yet must be updated to comply with:] *** equal() objects must return the same hashCode. Should uniquely identify an INSTANCE. JVM-execution-specific. Reconstituted object in a different JVM run may make a different hashCode. Generally just convert instance's memory addr. The critical thing is, the hashCode impl. must accommodate saving of multiple instances in sets. Object.equals(Object) (Concerned just with equality, not ordering) Object.equals(Object) implementation is just x == y. Does not need to be as specific as hashCode (but is so for direct Objects) x.equals(null) => false NATURAL ORDERING: java.lang.Comparable { int compareTo(T) throws NPE ; } "consistent with equals": Returns 0 if .equals(). RECOMMENDED :( java.util.Comparator.compare(T, T) + java.util.Comparator.equals(Object) Does not need to throw NPE if either T is null. (The latter is a usually useless override to compare the Comparator itself). Do implement Serializable if Collections of your data types will be serd. (Same definition of 'consistent with equals'). java.util.concurrent java.util.concurrent.Callable is a J2SE5 Runnable-like that can throw Exceptions and can return a value: V call() throws Exception I don't know yet how to implement a queue executor. Here is how to work the submittor side: Future future = .getQueue(q).enqueue( new Callable() { public Type call() throws Whatever { ... return ignoredObject; } } ); future.cancel(immediate); future.isCancelled(); future.isDone(); Type type = o.get(); // Synchronous (Perhaps executor side subclasses ThreadPoolExecutor?) null isinstance X is always false. So, there is no need to test for null before doing an isinstance. Unfortunately, need to specify presedence in: !(x instancecof y). Precedence of ! is high, so can do !x && y. Instance and static variables are initialized to null or 0. Local variables must be initialized manually. Interfaces should generally not extend Serializable due to serialVersionUID issues. Classes should implement Serializable directly. "final" variables may not be modified AFTER CONSTRUCTION. NIO. I believe that the only way that you will use less RAM than your buffer capacity is with FileChannel.map(). (or perhaps with .allocateDirect()?) Several excellent lessons about NIO at http://www.dickbaldwin.com/tocadv.htm position is unaffected by absolute (index-specifying) operations. All offsets are byte-based; EXCEPT FOR View Buffers! mark is for manual resetting capacity. Real buffer length remaining (== .length when available?). = limit - position limit. Before get()ing, you need to set this to max initialized data. Limit should generally be set to capacity before writing to buffer. AND to EOD before writing to the sink. Initialized to capacity, but set to position by flip(). Therefore, if you don't do something to change "limit" get()s will read uninitialized bytes. ByteChannels (incl. FileChannel) are I/O objects that support ByteBuffer I/O. .read()/.write() operate upon Buffer.pos() and modify position but not limit .read(ByteBuffer) of -1 == EOF .close() STOPS all I/O using the channel. Once you get a MappedByteBuffer from a channel, you should close the Channel and just use the MappedByteBuffer. "From the standpoint of performance it is generally only worth mapping relatively large files into memory". I think this just applies to MappedByteBuffer. DIRECT: I think that DIRECT means that the underlying physical object is directly mapped (NOT a memory area). "wrapped" ByteBuffers are NOT direct. MappedByteBuffers ARE direct. Allocation of Directs much more expensive; but usage native. Non-Direct buffers GENERALLY have backing arrays. duplicate()/slice() duplicates the Buffer but SHARES the backing array/physical data. View buffers obtained by ByteBuffer.as*Buffer(). Views of the primary buffer from position to limit. View buffer offsets are in the non-byte-type units. (This is very different from the absolute offsets of type-specific ByteBuffer getters and setters where we have bb.getFloat(byteOffset), etc. Since Views are independent, after using one Buffer, you must adjust the other Buffer's position/limit/etc. manually accordingly. FileChannel. long .position(), void .position(long); long .size(). .force() means flush. .transferTo() / .transferFrom() seems to use DMA with some other Channel. FileChannels only deal with pysical files via the ByteBuffer. Therefore, prepare the ByteBuffer and use FileChannel.read/write(ByteBuffer). Seems that both Channel and Stream should be closed. For SocketChannels, see http://java.sun.com/developer/TechTips/txtarchive/2004/Sept14_JohnZ.txt and http://www.javafaq.nu/java-article1102.html SHUTDOWNHOOKS See my agf game programs for examples. N.b. some classes, like Commons logging, at least, DO NOT WORK in the shutdown runnable. Apparently, some of the piping is already shut down at this point. SAME APPLIES about half the time to writing to System.out and System.err, even when explicitly flushing and sleeping afterwards! Looks like shutdown hooks are just no good for reporting purposes! PERSISTENCE XML exporters do save "bound" if present. Upon import, a worldBound is generated IFF "bound" is present. It seems the Nodes never update world bounds. WEBSTART SETTINGS: $HOME/.java/.../deployment.properties. deployment.log deployment.user.logdir GENERICS GENERALLY (not generic-specific) assignments, incl. arrays, may only broaden. Same for array-slot assignment. Object[] objects = new Shape[] {...}, but not But generic assignments without wildcards may not change typing at all: REQUIRED: List n = new ArrayList; ILLEGAL: List nL = new ArrayList(); RHS above may be an Arrays.asList(). Can't instantiate arrays of generics. Therefore, instantiate arrays of non-generics and cast that array to the generified class, like: arrayOfLists = (ArrayList[]) new ArrayList[] {....}; Can't construct with wildcards. I.e. no: new *List collection elements are Objects collection elements are X's, the same as for collections. GENERIC METHODS AND CONS public static void fillBoxes(U u, List> boxes) { N.b. instead of declaring the generic type immediately after the class name, it comes before the method type. TYPE INFERENCE: Normally the param type is not specified in invocations since it is automatically determined by checking the parameter classes. "allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type." Generally if there is no need for associations in the sign., don't. (otherwise use wildcards) CRITICAL APPLICATION is setting the Generic Method type according to supplied .class: public static Collection methName(Class c,...) { ... T item = c.newInstance; BOUNDED TYPES. Simple "" in the Generic class. + GenClass actually means "a GenClass for ALL X's" == "ALL-X GenClass". PROHIBITED: GenClass xgc = GenClass ygc; can't narrow because obviously (cause latter may contain a dog) GenClass catGc != GenClass mammalGc; Can't broaden because with GenClass mammalGc = GenClass catGc; would allow mammalGc.add(dog) to add non-cats into catGc. Same thing with an array causes a runtime casting error. + GenClass means "a GenClass for SOME X" == "SOME-X GenClass". + GenClass means "a GenClass for SOME X superclass"? ("lower" bound) == Collections X and X have elements of type Object, but only a X can match the first. GUESSING HERE: For inserting, create a normal typed collection like List. For handling of multiple existing typed collections, use Bounded types. (definitely can't add to these). ERASURE Compile generation of RAW (de-generifice) classes. CONSTRUCTORS Seems that you never not specify before a constructor for the class type params, but only for Generic Method purposes. Must always invoke with new X() to indicate you want a non-raw version. Back and forth from Collections to arrays: arrays[] = Collection.toArray(new Type[0]); primitives[] = org.apache.commons.lang.ArrayUtils.toPrimitive(intObjArray); List = Arrays.asList(new Type[] {...}); Collection.toArray() is NON-GENERIC. Use the following instead. T[] collection.toArray(T[] a) N.b. no <>-spec required, since the output type is determined by the param type. To toString() native arrays, use Arrays.deepToString(arr); What about plain old Arrays.toString(arr)??? To simply get elements from an unknown Collection implementation class, you don't need to iterate or anything, just collection.toArray(new ElType[0])[3]. INDEXED IMAGES IndexedColorModel.getRGBs seems to get an int for each .getMapSize(), in sequence ARGB. Excellent troubleshooting device, including native stuff, dumps, stack traces: http://java.sun.com/developer/technicalArticles/Programming/Stacktrace/ VARARGS. The declared param is actually a real array. May be called with individual elements like: call("one", "two"); OR with real array like call(new String[] { "one", "two" }); BUT can't call with a collection. Seems to smartly choose the most specific constructor between traditional and var args constructors. "... emulated by a synthetic accessor method" means that an inner class method should not use private visibility since the class will compiled to a separate class. RESOURCE BUNDLES Basenames are always absolute and independent of calling class (just need the ClassLoader to give visibility). Leading "/" is not allowed (and is unnecessary, as they are always absolute). "Basenames" of form supdir/subdir/base and supdir.subdir.base both work. INITIAL VALUES. From the lang spec: Each class variable, instance variable, or array component is initialized with a default value when it is created (secion 4.12.5 specifies what the vals are). FILE HANDLERS and Stream/Reader/Writer buffer allocations. Definitely do not use anonymous file input streams of any variety. A close() of any Reader above a Stream (e.g. InputStreamReader or BufferedReader) has the same effect as directly closing the Stream). ByteArray*/CharArray* .closes() have no effect EXCEPT FOR CharArrayReader()! However, the following are necessary to free buffers: CharArrayReaders must be set to null or .closed() (can also close() a super-reader like a BufferedReader()). ALL OTHERS (ByteArray/CharArray) must be set to null. In some cases, just going out of scope will free the buffer the same as setting to null. Pipes Reading and Writing streams/RWs must be set to null to free buffer. From my email to Fred: The only close() method which has any effect on ByteArray*/CharArray* classes is CharArrayReader(). As this is according to even old API specs, it's a waste of time closing these. close() methods have no effect on file-handle allocation or buffer allocation for Piped* classes. ByteArray*Stream.close() are totally useless. However, close() are VERY IMPORTANT for CharArray* and Piped* classes, because they signal EOD, etc. Where close()s do have effect, closing a wrapping/filter Reader/Writer has the same effect as closing the underlying Stream, if there is one. Freeing of ByteArray*/CharArray*/Piped* buffers is dependent upon GC, and therefore Java-implementation-specific. In Linux I find that the buffers are freed immediately only in a few situations unless the references are explicitly set to null. Therefore, programs should create Stream/Reader/Writer references and set them to null in a finally block. In the case of all Piped* classes, both the reading and writing Stream/Reader/Writers must be set to null. TYPE-SAFE ENUMS The useful switches unfortunately can't match null, so must test for null separately. The Enum "class" corresponds to the enum elements = constants, not the 'enum'. E.g. we have enum.values() but Enum.name() and Enum.ordinal(). Therefore, we would have Planet.values() but Planet.MERCURY.name(). Sample enum of: Planet Sample element/constant of Planet: MERCURY Planet.values() is an ARRAY of all of the elements, suitable for for/each. I.e. there is no reason to do ArraySet.allOf(En.class).toArray(new En[0]); Planet.values().length ... obviously By default, simply listing a element theoretically invokes a null constructor, so: public enum Planet { MERCURY, VENUS } is equivalent to: public enum Planet { MERCURY(), VENUS(), } To add Class members (a.o.t. enum elements), just add a ; after the last element and add the fields, methods, constructors, (but not since there is no enum "instance"). The JVM will not invoke main() methods as for classes, however. * The class element list must come first. To perform any field population pro instance setup, implement a cons. Elements may themselves have methods declared in {} right after them. But these are useless unless the enum itself has a method that is overridden (the enum method may be just an abstract declaration and overriding behaves exactly as it should). EnumSet: Holds an arbitrary set of enum elements in specified order. GENERAL SYNTAX IS: visibility enum EnumName { ELEMENT1[(...)] [ { methods() {...}...}],... ; cons(...)... fieldDef... methodDef... } Great for for/each. EnumSet.of(Planet.MERCURY, Planet.MARS); EnumSet.range(Planet.MERCURY, PLanet.EARTH); EnumMap: new EnumMap(KeyClass.class); Enum.valueOf(yourEnum.class, string) generates a real enum constant. INSTANCE INITIALIZER BLOCKS { }. Same as putting the code into every constructor. INNER CLASSES Static inner classes are same as standalone classes it seems, but with the visibility limits. Reference like Outer.Inner (what about from inside of Outer?). The nested class name in the definition must be unqualified. Perhaps for this reason, can't use same class name in any level of nesting. I.e. every class name must be distinctive among its ancestors/descendants. Can not re-use a class name. Normal Inner Classes can't define static members, exc. static final. Normal Inner classes must be instantiated within the outer class. However, contrary to Sun's tutorial, it doesn't exist only within the Outer instance, since it can be passed out. Just as you would want, both types of inner classes can be referenced absolutely like Outer.Inner, or line Inner from insider of Outer. (This even though the class files are like (Outer$Inner.class"). Normal Inner classes may access super-instance like Outer.this. Public outer classes must be declared in a class of that name, hence there may only be one of these in each source code file. LOCAL INNER CLASSES No such thing as Local Interface. anony inner classes may have instance initializers but no constructors. "local inner class" Cool! Doesn't have the limitations on anonies. Whether static or instance depends on whether in a static or instance method (allowed in static and instance initializer blocks). May use final local vars just like an anony class. Contrary to what it says in the O"Reilly book, you CAN override a class at the same level. (My test class pkga.LocalClass proves this). static import statements still begin with "import" and must use abs. names. Legal var names: unlimited length. Unicode letters+digits and not a keyword. \w = letter + digit + underscore [\l$_][\w\d$]* EXCEPT THAT letter here is any Unicode letter in any language (I.e. only difference for first character is that it can't be a digit). General looping statements are either "while" or "do...while", period. (No "until". No "goto"). ASSERTIONS can throw non-end-user Errors (with stack trace available). DISABLED BY DEFAULT. assert boolExpr [: exprForErrorToStringObject]; To always trigger: assert false [: expr]; To avoid the conditionality, throw an AssertionError instead. Enabling/disabling: -ea, -da, esa, -dsa (s = system) or the very long analogs (n.b. the longs are ALL LOWERCASE WITH NO DELIMITING WHATSOEVER OF WORDS). (System classes are exempt by default). !1.4-ONLY! Must use compiler switch "-source 1.4" or compiler will be completely assert-ignorant. ! "the % operator is not a true module operator". It returns a remainder which may be negative. AUTO-BOXING danger. int == int is very different from Integer == Integer, so khow which it is you use. Not for performance-intensive usage or where the type distinction is important. Even destination wrapper type can be automatically determined, like Number iger = 3.14; instantiates a Double. Wildcard narrowing Gen g = new Gen(): or same with "Gen" is allowed, but usage of the params isn't working for me. List generates for-each elements of type Object. Strings vs. StringBuffers vs. StringBuilders. Strings are immutable. StringBuffer === StringBuilder except *Buffer has synchronized methods. Therefore, StringBuilder should always be used in single-thread settings. (E.g. where it is instantiated and used exclusively with local variables). java.io.Console System.console() # Need to know for Java 6 cert. Provides char-based stream stuff. N.b. you get an instance with System.console(), not System.console (like in/out) I/O commands are synchronized and may cause blocking in MT apps. closes on the reader()/writer() will not actually close. After something closes the reader()/writer() on the Console side, like with CTRL-d, it can auto-open when new characters are written. No-echo password-reading ops. N.b.: PrintWriter writer(); // not PrintStream like System.out! // Funny in that bulk reads will not read beyond one line. Formatted prompted readLine, like shell read commands. Ant does not give the console to the JVM. System.arrayCopy() useful. java.util.Locale("la", "CO"|""[, "REGION"]); specify language and country. (Docs "say" that CO param may be "null", but it must actuall be ""!). or predefined Locale.XXXXXXs's for languages (with "null" CO) and countries. (Note they are all-caps countries and languages spelled out IN ENGLISH). N.b. there are huge formatting differences if language but not country specd. Locale.toString() of format la_CO. Locale.getDisplayName() is user-friendly. All Locale.specific classes provide a Locale[] getAvailableLocales() method which seems to not be a part of any interface. I guess just by convention. static Locale Locale.getDefault()/setDefault(Locale). But they discourage you from changing this default??? Fucking ridiculous. Several java.util. and java.text method look in the JVM for a locale-satisfying implementation first, then look for registered Locale-Sensitive Services SPI implementations. Java 5 finally has static String.format(), which is just like C printf. EVERY printf variant (only in Console and Print* classes) are exactly equal to the corresponding "format" method in the same class. All of the .format() methods have an optional 1st parameter for Locale. Except for %< and %n (%+integer), all format specifiers must match an argument. LINE DELIMITERS: %n for platform-independent. \n means a real Newline. Great! Width specifier is the OUTPUT length and therefore includes punctuation, etc. Optional argument index is "\d$" and must be first. < means to re-use arg used by previous specifier. Use "<" in place of "\d$". - flag does not mean to display "-" (which will ALWAYS be done for negative numbers), but to pad on the RIGHT. I.e., left-justify. f decimal vs. e scientific-notation vs. g values-specific (these require doubles, not floats). java.util.Formatter aggregates a sink object that it appends to. It may be a file, stream, Writer, StringBuilder/Buffer. Most of the conversion letters have lower-case and cap variant. t* is a multi-character date/time conversion. c requires characters, but Java casts automatically from an int (only) as you would want. Can always supply wrapper objects instead of primitives. java.util.Scanner since java 5. Scanner scanner = new Scanner(src[, charSetName]); scanner.useLocale(x); scanner.useDelimiter(Pattern re); OR scanner.useDelimiter(String re); try { while (scanner.hasNext()) { // It's an iterator if (scanner.hasNextDouble()) ... scanner.nextDouble(); else scanner.next(); } finally { scanner.close(); } interfaca java.util.NavigableSet extends SortedSet { descendingIterator, descendingSet, floor, headSet(E[ bool]), higher, pollFirst, subSet(E, incl, E, incl), SortedSet subset(E, E)... } interfaca java.util.NavigableMap extends SortedMap { similar with many of those methods like *Entry(K) or *Key(K) instead of *Map } An "invariant" the word for a state that must always be so. Java Assertions should now be used for invariants. inputStream.available() don't work with ServletInputStreams. Normal method overloading is runtime-driven. inst.meth(object); // will invoke most specific method available according to the runtime type of 'object'. Case-insensitive sorting: Arrays.sort(teams, String.CASE_INSENSITIVE_ORDER) Determine compatibility of Java classes: javap -classpath CP -verbose org.MyClass | grep major See mapping of major version to JVM version at http://thiamteck.blogspot.com/2007/11/determine-java-class-file-version.html Can URL.openStream() or URLConnection.getInputStream() return null? I'd say no. Clas.getSimpleName is the unqualified class name. Comparing null (o1 == o2) will be true if both are null and false if their null-ness differs. Properties files. White space rules are consistent so that x= (lots of whitespace after) still sets x to empty string. "x=" in a Properties file does define property with value of empty String. Maps certainly can not hold native type values.