JAVA-HOWTO PREPARE FOR SUN CERTIFIED JAVA PROGRAMMER EXAM Java Study Note: Jan 4 - Mar 4, 2002 These are the study notes I made while preparing for my SCJP2 Exam. When I find the time, I will convert it to an HTML doc with links and diagrams, hopefully my note 'as-is' can be of service to others preparing for the SCJP2 Exam. To give these notes some perspective, they are written from someone with a professional development background in C++ as such it may have some omissions! Best of luck!! :^D - Rajinder Yadav In following with the Linux/OpenSource/OpenDoc philosophy, I am making my java notes available for free to the public under the GNU FDL (GNU Free Documentation License). JAVA-HOWTO PREPARE FOR SUN CERTIFIED JAVA PROGRAMMER EXAM Copyright (c) 2002 Rajinder Yadav Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with the no Front-Cover Texts, and with no Back-Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License". A copy of the GNU FDL can be obtained at, http://www.gnu.org/licenses/fdl.html If you have signed the SUN CERTIFIED JAVA PROGRAMMER EXAM Non-disclosure form, please do not make changes or modifications to this document other than for personal use. You are still granted to make copies and redistribute the document. This restriction has been added to assure that this document is allowed to be freely available without any legal restriction to others. If you have not signed the SUN CERTIFIED JAVA PROGRAMMER EXAM Non-disclosure form and would like to contribute to the growth of this document by adding, correcting, or modifying this document, you are free to do so. To get the latest copy of this document please visit: http://www.rajindery.com/javacert/jnotes.txt If you have come across this document from another source, please send me an email stating where you obtained your copy, thank you. You may send your comments, suggestions and corrections to: Rajinder Yadav email: rajindery@yahoo.com +--------------------------------------------------------+ | Table of Content | +--------------------------------------------------------+ 1) How to use my notes 2) How to help out and give back Part I 3) fundamentals 4) classes 5) exception handling 6) string immutability & garbage collection Part II 7) AWT components 8) AWT events 9) AWT layout event listeners Part III 10) java.lang 11) threading 12) Collections 13) java.oi +--------------------------------------------------------+ | How to use my notes | +--------------------------------------------------------+ I would suggest that you print out a copy of my notes and use them along with other reading material. I have done my best to give each topic it's own section so you can use my notes as a quick refresher. Once you are able to read my notes in it's entirety, I would suggest that you take a look at my java questions, they are designed to test you on what you already know from my notes and your reading. My review question can be picked up at: http://www.rajindery.com/javacert/jtest.txt I suggest that you save my review questions for the last week before taking your exam, you can then use my answer sheet which also contains the questions, together they will provide you a way to refresh your memory and keep you sharp! I've taken my free time to make this available for you, now please take some time to give back.... in the immortal words of Jerry Maguire, "Help me help you!" +--------------------------------------------------------+ | How to help out and give back | +--------------------------------------------------------+ First please read the FDL agreement contained in this document. If you found these notes to be helpful, please share them with others so they may also benefit in their preparation for the SCJP2 Exam, better yet direct them to this site so they can pick up the latest copy. To give back, I would encourage you strongly to come up with a few 'tough' questions of your own, and send them to me for inclusion in my review questions document. Please do not send me copies of someone else's original work! Other ways to help, * help translate these documents and test questions to another languages * proof read for typos, errors, clarification * review information for technical accuracy * help maintain all information current, advise on deprecated APIs, etc. btw, when you make your first million, please don't forget about me :^D +--------------------------------------------------------+ | fundamentals | +--------------------------------------------------------+ With references to Java Language Specification (2nd ed) http://java.sun.com/docs/books/jls/second_edition/html/jTOC.doc.html foo.java --->(javac) --->foo.class ---> JVM sourcecode java bytecode * a valid source code filename contains the .java suffix * the name of the source file must be the same name used by the public top-level class * only one top-level class within a source file can be public * a source file may contain many non public top-level classes * a valid empty source file will compile without an error * a valid java source file has three optional parts, in the following order > single package declaration > one or more import statement > one or more class declaration NOTE: one or more comment may appear before the package name // file: MyClass.java package com.mydomain.myutils; import java.awt.*; import java.util.*; public class MyClass {...} class MyHTTPClient {...} * all the packages under java.lang are imported implicitly by javac * all classes which reside in the same file belong to the same package and are placed in the same directory > classes with the 'default' access modifier are only visible within the same package * java primitives data-type and their wrapper classes wrapper data-type classes bits value range --------- ------- ---- ----------- byte Byte 8 -2^7 to (2^7)-1 short Short 16 -2^15 to (2^15)-1 int Integer 32 -2^31 to (2^31)-1 long Long 64 -2^63 to (2^63)-1 float Float 32 double Double 64 char Character 16 '\u0000' to '\uffff' boolean Boolean na false, true * java 'implicit' up-casting rule is byte -> short \ +--> int -> long -> float -> double / char * integer types: byte, short, int, long are signed values * negative numbers in java are stored in two's compliment --> ~a = -a-1 * valid java comments // this is a single line comment /* this comment line can span many lines */ /** this is a javadoc comment line */ * all java keywords are in lowercase * a valid java identifier has the following rules: > can begin with $, an underscore '_' or a letter [a-z, A-Z] > identifiers are not length limited > cannot begin with a number > must start with a valid unicode char > cannot contain the special java control char like, ':', ';', '#', '%' > cannot be a java keyword ref: http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#40625 * valid java keywords ref: http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308 abstract default if private this boolean do implements protected throw break double import public throws byte else instanceof return transient case extends int short try catch final interface static void char finally long strictfp volatile class float native super while (*)const for new switch continue (*)goto package synchronized NOTE: const and goto are reserved java keywords NOTE: null, true, false are java literal values (not java keywords) From the JLS 3.10.3 Boolean Literals: The boolean type has two values, represented by the literals true and false, formed from ASCII letters. 3.10.7 The Null Literal: The null type has one value, the null reference, represented by the literal null, which is formed from ASCII characters. A null literal is always of the null type. ref: http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308 * java operators: the bitwise shift operators '>>' is a signed right shift operator, the sign of the value is not changed the bitwise operator '>>>' is a unsigned right shift operator, it fills the MSB(most significant bit) with a zero int i = 1; i = i<<31; i = i>>31; ---> i == -1 int j = 1; j = j<<31; j = j>>>31; ---> j == 1 int x = -1; y = x>>1; // sign remain negative z = x>>>1; // sing become positive, value is some large number all arithmetic operations are promoted to at least an int value byte b1 = 10; byte b2 = 5; byte sum = b1 + b2; // will not compile without casting! dividing a value by zero, or taking a modulus '%' with a zero will cause a "java.lang.ArithmeticException" exception to be thrown * with the operators '>>' and '<<' if the r-value is greater then the bit depth of the value, java will use the following rules to interpret the result 1<<35 == 1<<(35%32) == 1<<3 == 8 (since interger literals are 32-bit) * short-circuit operators '&&' and '||' work with boolean values only > operator '&&' will not need to evaluate the r-value if the l-value is false > operator '||' will not need to evaluate the r-value if the l-value is true > given that X can has either a true or false value false && X is always false true || X is always true * dividing a floating point value by zero will not result is an exception import java.util.*; public class Test { public static void main(String[] args) { double f = 1.0/0; double g = -1.0/0; double h = Math.sqrt(-1.0); System.out.println(f); System.out.println(g); System.out.println(h); } } output displays special identifiers for floating point arithmetic errors yadav@sandbox: javac Test.java yadav@sandbox: java Test Infinity -Infinity NaN * the comparison operator '==' works with java primitives values, and does a superficial comparison of references with objects * a literal value of '10' is interpreted as a integer * a literal value of '10.2' is interpreted as a double * all hexadecimal value begin with a 0x or 0X * all octal values begin with a zero int i = 10; // decimal value 10 int j = 0x0a; // hex value of 10 int k = 012; // octal value of 10 * valid char literal values must be in the range of 0 to (2^16)-1, or '\u0000' to '\uffff' // valid char literals char a = 'a'; char b = 10; char c = 0xaa; char d = '\u0001'; NOTE: a char literal must appear inside a single quote, not a double quote ref: http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#48272 * valid ways to declare an array reference int[] a; int b[]; int b[][]; int []c[]; int[] a, b; // declares two array references int a, b[]; // only b is an array reference * you don't declare the array size inside the square brackets as in C\C++ int a[5]; // compile time error * an array object has a length field (property) not a length() method * valid ways to declare and initialize an array reference int []j = {1,2,3}; int q[][] = {{1,1},{2,3,4},{5,5,5,5}}; int k[] = new int[]{1,2,3,4}; Object[] o = { new Object(), new Object(),new Object() }; * arrays values are always initialized to default values * an array's size is determined using it's length field public class Test { public static void main(String[] args) { boolean[] b = new boolean[5]; for(int i=0; i < b.length; ++i) { System.out.println(b[i]); } } } output shows how to get the array's size and proves arrays are initialized to a default value yadav@sandbox: javac Test.java yadav@sandbox: java Test false false false false false ref: http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#27805 +--------------------------------------------------------+ | classes | +--------------------------------------------------------+ * top-level class declaration has the following format: | class name { } where: <...> indicates optional | indicated an or binding indicates an xor binding NOTE: abstract and final cannot be used together * by default a class in not visible outside of it's package * no restriction on the ordering of public, abstract or final * class field declaration has the following format: | ||| type name; * class method declaration has the following format: | |||| * class fields can be assigned a default value when they are declared * the access modifiers are public, protected, private and "default" if not specified * the volatile modifier is used to tell the JVM not to cache the value for optimization purpose, but rather to use a single reference to access it's "real-time" value * the protected access modifier is less restrictive then the 'default' access modifier since it also adds the provision for subclasses in other packages to be able to access member fields and methods of thier parent class * all classes implicitly derive from java.lang.Object * to subclass use the 'extends' keyword * java only allows single inheritance (only one class can be extended) class A {} class B extends A {} * the 'super' keyword is used to reference superclass members * super(); is used to call the superclass ctor * a default constructor (ctor) will be included in the class if no other ctor is defined within the class * a ctor is required to allow a class object to be created class A { A(int n) {} } class B extends a { } B b = new B(); // will not compile! the following error message is reported by javac 1.3.1 on linux yadav@sandbox: javac Test.java Test.java:15: cannot resolve symbol symbol : constructor A () location: class A class B extends A { ^ 1 error there are two ways to correct the code i) declare a default no argument ctor within class A class A { A() {} // no argument ctor A(int n) {} } ii) declare a default ctor within class B to make a call to a "defined" ctor in the superclass A class B extends a { B() { super(10); // make call to superclass ctor } } * ctor's don't have a return value * ctor's have the same name as the class * it's valid to have a method with the same name as the class with a return value // example of a method name looking like a ctor class A { void A() {} // watch out this is not a ctor, has a return type of void } * a call to another ctor using the 'this' or 'super' operator must be the first statement inside a ctor, otherwise a compiler error will result 01 public class Test { 02 public static void main(String[] args) 03 { 04 B b = new B(); 05 } 06 } 07 08 class A { 09 A(int n) {} 10 } 11 12 class B extends A { 13 B() { 14 int i=10; 15 super(10); 16 } 17 } javac 1.3.1 on linux report the following error message when this file is compiled yadav@sandbox: javac Test.java Test.java:13: cannot resolve symbol symbol : constructor A () location: class A B() { ^ Test.java:15: call to super must be first statement in constructor super(10); ^ 2 errors * all superclass are created before their subclasses public class Test { public static void main(String[] args) { C c = new C(); } } class A { A() { System.out.println("Class A created"); } } class B extends A { B() { System.out.println("Class B created"); } } class C extends B { C() { System.out.println("Class C created"); } } output for this code is yadav@sandbox: javac Test.java yadav@sandbox: java Test Class A created Class B created Class C created * a ctor with no access modifier has the same access privilege as the class * class static members can be accessed without creating an object public class Test { public static void main(String[] args) { StaticCls.who(); } } class StaticCls { static String name = "me that's who!"; static void who() { System.out.println(name); } } output: yadav@sandbox: javac Test.java yadav@sandbox: java Test me that's who! * all class member (instance) fields are initialized with their default values type default value ---- ------------- byte (byte)0 short (short)0 int 0 long 0L float 0.0F double 0.0D char '\u0000' boolean false * all instance fields are initialized when an object is created * all static fields are initialized once when the class is loaded by the JVM * static fields belong to the class, instance fields below to each object * a look at static and instance initializers public class Test { public static void main(String[] args) { StaticCls.who(); } } class StaticCls { static String name; StaticCls() { System.out.println("inside the ctor"); } static { System.out.println("inside the static initializer"); name = init(); } static String init() { System.out.println("inside the static init() method"); return "me that''s who!!!"; } static void who() { System.out.println("inside the static method who()"); System.out.println(name); } } when the following code is compiled and run, here is the output you get yadav@sandbox: javac Test.java yadav@sandbox: java Test inside the static initializer inside the static init() method inside the static method who() me that''s who!!! NOTE: 1) static initializer is executed when the class is loaded 2) static field is set using a method call to a static method 3) static methods are called using a reference to the class name * non-static methods and fields cannot be accessed from inside a static method public class Test { String s = "Hello!"; public static void main(String[] args) { System.out.println(s); } } javac 1.3.1 on linux reports the following error message with a static/non-static access yadav@sandbox: javac Test.java Test.java:4: non-static variable s cannot be referenced from a static context System.out.println(s); ^ 1 error * an interface is declared using the 'interface' keyword * a class can support one or more interface using the 'implements' keyword * all interfaces are abstract by default * all fields in an interface are 'public static final' by default * all methods in an interface are 'public abstract' by default * an interface can subclass one or more interface using the 'extends' keyword * the following will not compile since class A implements MyInterface but declares method myMethod1() as default which has a narrower access scope then public public class Test { public static void main(String[] args) { A a = new A(); } } interface MyInterface { int j=10; void myMethod1(); // this is public, not default } class A implements MyInterface { void myMethod1() {} // declared as default } javac 1.3.1 on linux report the follow compiler error yadav@sandbox: javac Test.java Test.java:1: myMethod1() in Test cannot implement myMethod1() in MyInterface; attempting to assign yadav@sandbox: javac Test.java Test.java:12: myMethod1() in A cannot implement myMethod1() in MyInterface; attempting to assign weaker access privileges; was public class A implements MyInterface { ^ 1 error NOTE: to fix this declare myMethod1() as public within class A class A implements MyInterface { public void myMethod1() {} } * a class declared with a private ctor cannot be created * ctor's are not inherited * sub-classing is known as a 'is-a' relationship, key words to look for are 'extends' and 'implements' * in the diagram below we can say the following about class Test > class Test 'is-a' subclass of class Object > class Test 'is-a' implementation of interface Runnable +---------------+ +--------+ | <> | | Object | | Runnable | +--------+ +---------------+ ^ ^ | | | | | | +------+ | +-| Test |-----+ +------+ public class Test extends Object implements Runnable { public void run() {} public static void main(String[] args) { Test t = new Test(); Object o = new Object(); System.out.println("t instanceof Object : " + (t instanceof Object)); System.out.println("t instanceof Runnable: "+ (t instanceof Runnable)); System.out.println("o instanceof Test : " + (o instanceof Test)); } } output shows t is-a subclass of Object and t is-a subclass Runnable, but o is not a subclass of Test yadav@sandbox: javac Test.java yadav@sandbox: java Test t instanceof Object : true t instanceof Runnable: true o instanceof Test : false * containment is known as a 'has-a' relationship class A {} class B { A a; // class B contains a ref of type class A } * all classes directly or indirectly derive from class Object * the following class members are inherited from class Object protected Object clone() throws CloneNotSupportedException public boolean equals(Object obj) public int hashCode() public String toString() protected void finalize() throws Throwable public final Class getClass() public final void notify() throws IllegalMonitorStateException public final void notifyAll() throws IllegalMonitorStateException void wait() throws IllegalArgumentException, IllegalMonitorStateException, InterruptedException void wait(long millisec) throws IllegalArgumentException, IllegalMonitorStateException, InterruptedException void wait(long millisec, int nanosec) throws IllegalArgumentException, IllegalMonitorStateException, InterruptedException * a cloneable class must implement the the Cloneable interface * a shallow clone operation copies java primitives values and only makes a copy of reference values * a deep clone creates new objects from the references in the class being copied * inner class declaration has the following format: | || class name {} class Outer { class Inner {} } // two step process for inner class creation Outer o = new Outer(); Outer.Inner i = o.new Inner(); // one step creation of an inner class Outer.Inner c = new Outer().new Inner(); * An inner class is a nested class that is not explicitly or implicitly declared static. * Inner classes may not declare static initializers or member interfaces. * Inner classes may not declare static members, unless they are compile-time constant fields * Member interfaces are always implicitly static so they are never considered to be inner classes. * an non-static inner class requires that the outer class exist before it can be created * an inner class has full access to 'all' fields of it's outer class * a static inner class doesn't require an instance of the outer class for it's creation // how to create a static-inner class object class Test { public static void main(String[] args) { A.B b = new A.B(); } } class A { static class B { B() { System.out.println("Hello from static inner class!"); } } } output yadav@sandbox: javac Test.java yadav@sandbox: java Test Hello from static inner class! * an abstract class may contain non-abstract methods * a class with an abstract method must be declared as abstract * method overloading requires the following conditions: 1) the method name is the same 2) the argument list is different 3) method is declared in the same class (class level scope) * overloaded methods can have different return types * overloaded methods have no restrictions on the exceptions they may throw * overloaded methods can have any access modifier * method overriding requires the following conditions: 1) the method name is the same 2) the return type is the same 3) the argument list is the same 4) the method is declared in the subclass * overridden method have these restrictions: 1) may not throw any new 'checked' exception 2) may not throw a broader 'checked' exception than the superclass 3) may throw a narrower 'checked' exception than the superclass 4) the access modified can be less restrictive class A { void init() {} } class B extends A { protected void init() {} } NOTE: protected is less restrictive then the default access modified * restriction level of access modifiers (most restrictive to least): private--->(default)-->protected--->public Modifier Method Variable class ======== ====== ======== ===== public yes yes yes private yes yes nested protected yes yes nested abstract yes no yes final yes yes yes transient no yes no native yes no no volatile no yes no * static initialization code block is executed once when the class is loaded * instance initialization code blocks are executed each time an object is created public class test { static public void main(String[] agr) { System.out.println("Inside class static method: main()"); foo f1 = new foo(); foo f2 = new foo(); } static { System.out.println("Static initializer executed in class test"); } } class foo { int i; foo() { System.out.println("Object getting created"); } static { System.out.println("Static initializer executed in class foo"); } // instance initializer block { System.out.println("instance initializer executed when object foo is created"); i=10; } } Output C:\temp>java test Static initializer executed in class test Inside class static method: main() Static initializer executed in class foo instance initializer executed when object foo is created Object getting created instance initializer executed when object foo is created Object getting created +--------------------------------------------------------+ | exception handling | +--------------------------------------------------------+ * java provides built in exception handing support (unlike C++) * there are two type of exceptions, 1) checked exception and 2) unchecked exceptions * checked exception are checked by the compiler, a sourcefile will not compile if the checked exception is not handled correctly * unchecked exception are subclasses of 'RuntimeException' or 'Error' * an exception causes the thread to stop executing and do a search for an exceptional handler * all uncaught exception are passed up the call stack until a handler is found, otherwise the thread is terminated * an exception can be caught in a try/catch block * there are three causes of an exception 1) an abnormal condition occurred (i.e divide by zero) 2) a throw statement was executed 3) an internal error occurred in the JVM * java provides a try/catch/finally block, where the either catch or finally block is optional, but not both * the finally block is always executed, even if there is a return statement in the try / catch block * a try block cannot appear alone public class Test { public static void main(String[] args) { try { int i=0; System.out.println(i); } } } the following error is reported by javac 1.3.1 on Linux yadav@sandbox: javac Test.java Test.java:3: 'try' without 'catch' or 'finally' try { ^ 1 error * the root class of exception is 'java.lang.Throwable' java.lang.Throwable | +-Error {unchecked exception} | +-Exception {checked exception} | +-RuntimeException {unchecked exception} | +-ArithmeticException +-IllegalMonitorStateException +-IndexOutOfBoundsException +-NullPointerException, * if an exception is caught, execution continues after the handler block try { int i = 10/0; } catch(ArithmeticException e) { } finally { // always executes! } * the order exception handlers are listed is important, all specific/narrower exceptions must be listed before the general/broader exception, otherwise an error will result public class Test { public static void main(String[] args) { try { int i=10/0; } catch(Exception e) { // general handler } catch(ArithmeticException e) { // specific handler } } } javac 1.3.1 on linux reports the following error message since a more general exception handler is listed before a more specific handler (see exception class hierarchy above) yadav@sandbox: javac Test.java Test.java:8: exception java.lang.ArithmeticException has already been caught catch(ArithmeticException e) { ^ 1 error +--------------------------------------------------------+ | string immutability & garbage collection | +--------------------------------------------------------+ * java String is immutable, what this means is that it cannot be modified String s = "Hello"; s.concat(" World!"); System.out.println(s); output will be "Hello" not "Hello World!" * String.concat() creates a new string object on the heap while leaving the original string un-altered public class Test { public static void main(String[] args) { String s = "Hello"; String s1 = s.concat(" World!"); String s2 = s.concat(" World!"); System.out.println(s1 == s2); } } when compiled and run the output indicated s1 and s2 are difference objects! yadav@sandbox: javac Test.java yadav@sandbox: java Test false * all string literals are converted into java String object and placed in the 'java runtime constant string pool' public class Test { public static void main(String[] args) { String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); String s4 = new String("Hello"); System.out.println("s1 == s2 :" + (s1 == s2)); System.out.println("s1 == s3 :" + (s1 == s3)); System.out.println("s3 == s4 :" + (s3 == s4)); System.out.println("s1.equals(s3) :" + s1.equals(s3)); System.out.println("s3.equals(s4) :" + s3.equals(s4)); } } yadav@sandbox: javac Test.java yadav@sandbox: java Test s1 == s2 :true s1 == s3 :false s3 == s4 :false s1.equals(s3) :true s3.equals(s4) :true +------------------+ +---------------+ | runtime constant | | heap | | string pool | | | | | |"Hello" "Hello"| | "Hello" | | | | | +-------|----------+ +---|-------|---+ | | | +---+---+ | | | | | | (s1 == s2) != (s3 != s4) {references} the output shows s1 and s2 reference the same object from the 'constant string pool', but objects created on the heap will be unique objects, and thus s3 and s4 will reference different objects * the String.equals() method overrides class Object.equals() to compare each character, the default base class implementation does a superficial comparison of object references boolean equals(Object obj) { return this == obj; } * the StringBuffer class does not override the Object.equals() method public class Test { public static void main(String[] args) { StringBuffer s1 = new StringBuffer("Hello"); StringBuffer s2 = new StringBuffer("Hello"); System.out.println("s1.equals(s2) :" + s1.equals(s2)); } } output: yadav@sandbox: javac Test.java yadav@sandbox: java Test s1.equals(s2) :false * only objects created on the heap can be garbage collected * garbage collection (gc) 'cannot be forced' * garbage collection may or may not occur * calling System.gc() will not force gc to occur * an object becomes 'eligible' for gc when all reference to it are removed String s1 = new String("xxx"); String s2; s2 = s1; s1 = null; // not yet eligible for gc, s2 still has a // reference to String "xxx" created on the help s2 = null; // String "xxx" is now eligible for gc * an object's finalize() method is only called when the object is 'actually' garbage collected * an object's finalize() method will be called at most one time, it is possible to save a reference inside the finalize() method, doing this will prevent the object from being GCed, so the next time the object is GCed the finalize() method will not be called NOTE: don't ever use the finalize() method since there is no guarantee if an object will be GCed or when that will happen * there is no guarantee that a java application will not run out of memory +--------------------------------------------------------+ | AWT components | +--------------------------------------------------------+ * class Component is the base class for all visible GUI widgets * the Component class provides general methods for things like: > setting the background colour > setting the foreground colour > setting the font > to specify size and min/max constraints > setting visibility > to enable/disable the component * all components have a graphic's context that can be obtained with Component.getGraphics(); * with the graphic's context you can > set the clip region > get/set current colour attributes > get/set the font > get/set drawing mode (i.e XOR is one drawing mode) > render graphics primitives like line, circle,... > render text * Applets have 4 'lifetime' methods you can override init() // called once start() // called each time applet is started stop() // called each time applet is stopped destroy() // called when applet is unloaded * the basic GUI components are derive from the Component class Component | +-Button +-TextComponent | | | +-TextField | +-TextArea | +-Label +-Canvas +-Checkbox +-List +-Choice +-ScrollBar +-ScrollPane * GUI components are added to containers with Container.add() * class Container is a subclass of Component * Containers may contain other containers Component | +-Container {abstract} | +-Panel | | | +-Applet | +-Window | +-Frame +-Dialog | +FileDialog * Menus et. al belong to the MenuComponent class MenuComponent | +-MenuBar +-MenuItem | +-CheckboxMenuItem +-Menu | +-PopupMenu * menu components cannot be added to a container * a menu component is added to the Frame window using Frame.setMenuBar() * CheckboxGroup is not a container, it is a logical group * Panel, Applet and Window have no title bars, menu bar or close/min/max boxes * Applet container designed to appear within a web-browser * a Frame compoment has a title bar, menu bar, close/min/max boxes * the following code shows how to create a Frame application with a menubar import java.awt.*; public class Test { public static void main(String[] args) { Frame f = new Frame("Test"); MenuBar bar = new MenuBar(); Menu menu = new Menu("File"); menu.add(new MenuItem("Open...")); menu.add(new MenuItem("Close")); bar.add(menu); f.setMenuBar(bar); f.setSize(400,200); f.setVisible(true); } } * to draw inside a component override the paint method() public void paint(Graphics g); * to perform tasks before a paint operation, override the update() method public void update(Graphics g); * call Component.repaint() to cause an update to occur, which in turn calls the paint method * the Button component is a simple push button Button b1 = new Button(); Button b2 = new Button("Click"); * the TextField component is a single line input field TextField t1 = new TextField(); TextField t2 = new TextField(30); // 30 char field limit TextField t3 = new TextField("Default Text"); // default text in field TextField t4 = new TextField("Text", 30); * the TextArea component is a multi-line input field, vertical and horizontal scrollbars can be added > defined constants are: TextArea.SCROLLBARS_VERTICAL_ONLY TextArea.SCROLLBARS_HORIZONTAL_ONLY TextArea.SCROLLBARS_BOTH TextArea t1 = new TextArea(); TextArea t2 = new TextArea(row, col); TextArea t3 = new TextArea("default text"); TextArea t4 = new TextArea("text", row, col); TextArea t5 = new TextArea("text", row, col, TextArea.SCROLLBARS_BOTH); * the Label component is a read-only text field Label l1 = new Label(); Label l2 = new Label("Name:"); * the Canvas component provides a surface to draw on as well as track mouse clicks and movements Canvas c = new Canvas(); * the Checkbox component can be used for single boolean selection: Checkbox c1 = new Checkbox("label", true, null); * the Checkbox component can be used in a group to provide exclusive boolean selection options: CheckboxGroup sex = new CheckboxGroup(); Checkbox c1 = new Checkbox("male", true, sex); Checkbox c2 = new Checkbox("female", false, sex); * the List component show a list of items that can be selected > multiple selection can be enabled > the number of visible items is set via the ctor > a scrollbar is provide if there are many items List l = new (5); // make 5 items visible List m = new (3, true); // allow multiple selections l.add("one"); l.add("two"); * the Choice component provides a single drop-down list where the selected item is visible by default Choice c = new Choice(); c.add("Toronto"); c.add("New Delhi"); c.add("Seoul"); * the ScrollBar component provides both vertical and horizontal oriented range selection > defined constants are: ScrollBar.HORIZONTAL and ScrollBar.VERTICAL ScrollBar sb = new ScrollBar(ScrollBar.HORIZONTAL, position, slider_size, min_val, max_val) * the ScrollPane provides a scrollable surface and handles the scrolling for you > can be used as a container for other components > defined constants are: ScrollPane.SCROLLBARS_ALWAYS ScrollPane.SCROLLBARS_NEVER ScrollPane.SCROLLBARS_AS_NEEDED ScrollPane sp = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); * the layout manager for components are: FlowLayout GridLayout BorderLayout GridBagLayout CardLayout * the default layout manager for Panel derived classes is FlowLayout * the default layout manager for Window derived classes is BorderLayout * the FlowLayout manager tries to maintain the component's preferred size * FlowLayout adds components left to right and top to bottom * GridLayout manager honors the row setting and adds new columns when more components are added beyond the initial size * BorderLayout manager has five regions a component can be placed in, they are: BorderLayout.CENTER BorderLayout.NORTH BorderLayout.SOUTH BorderLayout.WEST BorderLayout.EAST +-----------------+ | N | <-- N/S regions runs the entire width +-----------------+ | | | | | W | C | E | | | | | +-----------------+ | S | +-----------------+ * components added to BorderLayout without specifying a region are placed in the center, one on top of the other, the component also ends up taking the entire area * the layout manager can be changed with Container.setLayout() +--------------------------------------------------------+ | AWT events | +--------------------------------------------------------+ * AWTEvent objects contains information about the source of the event * java.util.EventObject is the super class of all event objects java.util.EventObject | +-AWTEvent | +-ActionEvent +-AdjustmentEvent +-InputMethodEvent +-ItemEvent +-TextEvent +-ComponentEvent | +-ContainerEvent +-InputEvent | | | +-KeyEvent | +-MouseEvent | +-FocusEvent +-PaintEvent +-WindowEvent Event Type Mask ---------- ----- ActionEvent ACTION_EVENT_MASK AdjustmentEvent ADJUSTMENT_EVENT_MASK InputMethodEvent INPUT_METHOD_EVENT_MASK ItemEvent ITEM_EVENT_MASK TextEvent TEXT_EVENT_MASK ContainerEvent CONTAINER_EVENT_MASK KeyEvent KEY_EVENT_MASK MouseEvent MOUSE_EVENT_MASK FocusEvent FOCUS_EVENT_MASK PaintEvent PAINT_EVENT_MASK WindowEvent WINDOW_EVENT_MASK * events are enabled with Component.enableEvents(eventmask) * to process the event, the appropriate event handler methods need to be overridden > the method signature will the form: public void ProcessXEvent(XEvent e) where X is one of the event types listed above // example for processing events using event handlers // class MyButton enables ActionEvent and provides // the overridden event handler for it import java.awt.*; import java.awt.event.*; class MyButton extends Button { MyButton(String s) { super(s); enableEvents(AWTEvent.ACTION_EVENT_MASK); } public void processActionEvent(ActionEvent e) { System.exit(0); } } public class Test { public static void main(String[] args) { Frame f = new Frame("Event Enabled App"); MyButton b = new MyButton("Close"); f.add(b); f.setSize(300,300); f.setVisible(true); } } * ActionEvent is generated by the following components Button - button is clicked List - item is double clicked MenuItem - menu item is selected TextField - return key is hit * ItemEvent is generated by the following components CheckBox - state of check is changed CheckBoxMenuItem - state changed Choice - selection is changed List - item selection changed * AdjustmentEvent is generated by the following components ScrollBar - when position is changed * TextEvent is generated by the following components TextArea - when text is updated TextField - when text is updated * FocusEvent is generated by the following components Component - gains/looses focus * KeyEvent is generated when key is pressed and release * MouseEvent is generate when mouse button is pressed and released mouse pointer is moved * WindowEvent is generate when Window - open/close, activate/deactivate window * PaintEvent is generate when Component - on repaint notification * ComponentEvent is generated by the following components Component - when it's hidden,shown,moved,resized * ContainerEvent is generated by the following components Container - when components are added/removed +--------------------------------------------------------+ | AWT layout event listeners | +--------------------------------------------------------+ * java has a second way of handling events using event listeners * event listeners allow event notification to be delegate to other objects * event listeners are classes that implement one more listener interface * java.util.EventListener is the superclass for the listener interfaces java.util.EventListener | +-ActionListener +-AdjustmentListener +-ComponentListener +-ContainerListener +-FocusListener +-InputMethodListener +-ItemListener +-KeyListener +-MouseListener +-MouseMotionListener +-TextListener +-WindowListener * interface ActionListener { public void actionPerformed(ActionEvent e); } * interface AdjustmentListener { public void adjustmentValueChanged(AdjustmenEvent e); } * interface ComponetListener { public void componentHidden(ComponentEvent e); public void componentMoved(ComponentEvent e); public void componentResized(ComponentEvent e); public void componentShown(ComponentEvent e); } * interface ContainerListener { public void componenAdded(ContainerEvent e); public void componenRemoved(ContainerEvent e); } * interface FocusListener { public void focusGained(FocusEvent e); public void focusLost(FocusEvent e); } * interface InputMethodListener { public void caretPositionChanged(InputMethodEvent e); public void inputMethodTextChanged(InputMethodEvent e); } * interface ItemListener { public void itemStateChanged(ItemEvent e); } * interface MouseListener { public void mouseClicked(MouseEvent e); public void mouseEntered(MouseEvent e); public void mouseExited(MouseEvent e); public void mousePressed(MouseEvent e); public void mouseReleased(MouseEvent e); } * interface MouseMotionListener { public void mouseDragged(MouseMotionEvent e); public void mouseMoved(MouseMotionEvent e); } * interface TextListener { public void textValueChanged(TextEvent e); } * interface WindowListener { public void windowActivated(WindowEvent e); public void windowClosed(WindowEvent e); public void windowClosing(WindowEvent e); public void windowDeactivated(WindowEvent e); public void windowDeiconified(WindowEvent e); public void windowIconified(WindowEvent e); public void windowOpened(WindowEvent e); } * steps required to add a listener interface 1) create component object 2) create listener object 3) add listener object to component * a listener is added to the component with addXListners(); where X is one of the event listener above // example of event delegation using an event listener // a event listener is added to the button object import java.awt.*; import java.awt.event.*; class MyActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { System.exit(0); } } public class Test { public static void main(String[] args) { Frame f = new Frame("Event Listener"); Button b = new Button("Close"); MyActionListener h = new MyActionListener(); b.addActionListener(h); f.add(b, BorderLayout.SOUTH); f.setSize(300,400); f.setVisible(true); } } +--------------------------------------------------------+ | java.lang | +--------------------------------------------------------+ * from JDK 1.3.1 - Provides classes that are fundamental to the design of the Java programming language. * the java.lang package is imported implicitly by javac * the java.lang.Math package contains many useful function * the Math class define two constants: Math.E and Math.PI * the Math class define the following public static methods: * the abs() function double abs(double n); float abs(float n); int abs(int n); long abs(long n); From JDK 1.3.1 If the argument is negative, the negation of the argument is returned. Special cases: > If the argument is positive zero or negative zero, the result is positive zero. > If the argument is infinite, the result is positive infinity. > If the argument is NaN, the result is NaN. * the round() function long round(double n); int round(float n); From JDK 1.3.1 Returns the closest long to the argument. The result is rounded to an integer by adding 1/2, taking the floor of the result, and casting the result to type long. In other words, the result is equal to the value of the expression: Special cases: > If the argument is NaN, the result is 0. > If the argument is negative infinity or any value less than or equal to the value of Long.MIN_VALUE, the result is equal to the value of Long.MIN_VALUE. > If the argument is positive infinity or any value greater than or equal to the value of Long.MAX_VALUE, the result is equal to the value of Long.MAX_VALUE * double floor(double n); From JDK 1.3.1 Returns the largest (closest to positive infinity) double value that is not greater than the argument and is equal to a mathematical integer. Special cases: > If the argument value is already equal to a mathematical integer, then the result is the same as the argument. > If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument. * double ceil(double a) From JDK 1.3.1 Returns the smallest (closest to negative infinity) double value that is not less than the argument and is equal to a mathematical integer. Special cases: > If the argument value is already equal to a mathematical integer, then the result is the same as the argument. > If the argument is NaN or an infinity or positive zero or negative zero, then the result is the same as the argument. > If the argument value is less than zero but greater than -1.0, then the result is negative zero. Note that the value of Math.ceil(x) is exactly the value of -Math.floor(-x). * double sqrt(double a) From JDK 1.3.1 Returns the correctly rounded positive square root of a double value. Special cases: > If the argument is NaN or less than zero, then the result is NaN. > If the argument is positive infinity, then the result is positive infinity. > If the argument is positive zero or negative zero, then the result is the same as the argument. Otherwise, the result is the double value closest to the true mathematical square root of the argument value. * the max functions int max(int a, int b); long max(long a, long b); float max(float a, float b); double max(double a, double b); From JDK 1.3.1 If either value is NaN, then the result is NaN. Unlike the the numerical comparison operators, this method considers negative zero to be strictly smaller than positive zero. If one argument is positive zero and the other negative zero, the result is positive zero * the min functions int min(int a, int b); long min(long a, long b); float min(float a, float b); double min(double a, double b); From JDK 1.3.1 If either value is NaN, then the result is NaN. Unlike the the numerical comparison operators, this method considers negative zero to be strictly smaller than positive zero. If one argument is positive zero and the other is negative zero, the result is negative zero. * double random() From JDK 1.3.1 Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range. This method is properly synchronized to allow correct use by more than one thread. * java.lang.System provides three useful stream classes > System.err - standard error output stream (usually console) > System.in - standard input stream (usually keyboard) > System.out - standard output stream (usually console) * to get system properties use System.getProperties(); * to end the process call System.exit(int status); * to run the garbage collector use System.gc(); public class Test { public static void main(String[] args) { System.out.println("abs(-0.0) " + Math.abs(-0.0)); System.out.println("abs(NaN) " + Math.abs(Double.NaN)); System.out.println("floor(-0.0) " + Math.floor(-0.0)); System.out.println("floor(-1.2) " + Math.floor(-1.2)); System.out.println("ceil(-0.0) " + Math.ceil(-0.0)); System.out.println("ceil(-1.2) " + Math.ceil(-1.2)); System.out.println("round(-1.3) " + Math.round(-1.3)); System.out.println("round(1.5) " + Math.round(1.5)); System.out.println("round(NaN) " + Math.round(Double.NaN)); } } output yadav@sandbox: javac Test.java yadav@sandbox: java Test abs(-0.0) 0.0 abs(NaN) NaN floor(-0.0) -0.0 floor(-1.2) -2.0 ceil(-0.0) -0.0 ceil(-1.2) -1.0 round(-1.3) -1 round(1.5) 2 round(NaN) 0 NOTE: NaN cannot be represented as a integer so a zero is return from the round function -3 -2 -1 0 1 2 3 +---+---+---+---+---+---+ ceil---> <---floor +--------------------------------------------------------+ | threading | +--------------------------------------------------------+ * a thread is an independent path of execution within a given process * a process may have many threads working independently * all threads in a process share process global data * each thread will have it's own call stack and copy of local variables * there are two ways to make a class multi-threaded: 1) subclass the java.lang.Thread class 2) implement the java.lang.Runnable interface * a thread may be in one of the following state: > newly created > ready to run > running > waiting > blocked > sleeping > dead +-------+ +---------+ |created|-->(start)-->| ready |<-----<-----<-----+<--------+ +-------+ +---------+ | | (thread) | ^ | | v | ^ | +---------+ | ^ |scheduler| | | +---------+ ^ | CPU time| ^ CPU time | | granted | | spent +--------+ ^ | | +-->|sleeping| | v | | +--------+ | +----+ +-------+ | | |dead|<----(exit)---|running|-->(sleep)-+ +-->(notify)-->+ +----+ thread +-------+ | | finishes ||| +-------+ | ||+-->(wait)->|waiting| | || +-------+ | +-------+ |+--->(yield)--->----->---->------+ | |<--(operation call)-+ ^ |blocked| | | |-->(call returns)----->-------->-------->-------------+ +-------+ NOTE: with a blocked thread, if control returns to the thread before the CPU time is used up the thread will return to the running state, otherwise the scheduler will have swapped it out meaning the thread will be put into the ready state when control return from the blocked call (the blocked call may be running in a separate thread or process) * a thread is started by calling the Thread.start() method * a threaded class must override method, public void run(); * a process dies when the last non-daemon thread exists or terminates // threading support by sub-classing Thread public class Test { public static void main(String[] args) { MyThread t1 = new MyThread("One"); MyThread t2 = new MyThread("Two"); t1.start(); t2.start(); } } class MyThread extends Thread { String m_msg; MyThread(String s) { m_msg = s; } public void run() { while(true) { System.out.print(m_msg); } } } // threading support using interface Runnable public class Test { public static void main(String[] args) { MyRunner r1 = new MyRunner("One"); MyRunner r2 = new MyRunner("One"); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); } } class MyRunner implements Runnable { String m_msg; MyRunner(String s) { m_msg = s; } public void run() { while(true) { System.out.print(m_msg); } } } * if your class needs to extend another class, then using the Runnable interface is your only choice for thread support * the synchronized keyword is used to sync access to shared resources and gain the object's monitor lock * a synchronized object can only be accessed by a single thread at a time * the synchronized keyword can be added to a method > synchronized void foo() {...} * the synchronized keyword can be used within a block > synchronized(this) {...} * method wait(), notify() and notifyAll() must be called on an object that we have a monitor lock * the following example shows how to sync the output of two threads // two threads are created, one prints "Ping" and the other prints "Pong" // shows how to get the two threads to co-operate to print "PingPong" // both threads are synchronized on the PingPongTest object 't' // class PingPongTest { public static void main(String[] argv) { PingPongTest t = new PingPongTest(); t.play(); } public void play() { Thread m_ping = new Thread(new Ping(this)); Thread m_pong = new Thread(new Pong(this)); m_ping.start(); m_pong.start(); } } // class Ping class Ping implements Runnable { PingPongTest m_ppt; Ping(PingPongTest ref) { m_ppt = ref; } public void run() { synchronized(m_ppt) { for(int i=0; i<100; ++i) { try { System.out.print("Ping"); m_ppt.notify(); m_ppt.wait(); } catch(InterruptedException e) { } } // for() m_ppt.notify(); } // sync } } // class Pong class Pong implements Runnable { PingPongTest m_ppt; Pong(PingPongTest ref) { m_ppt = ref; } public void run() { synchronized(m_ppt) { for(int i=0; i<100; ++i) { try { System.out.println("Pong"); m_ppt.notify(); m_ppt.wait(); } catch(InterruptedException e) { } } // for() m_ppt.notify(); } //sync } } output: yadav@sandbox: javac PingPongTest.java yadav@sandbox: java PingPongTest PingPong PingPong PingPong PingPong ... * non-atomic treatment of long and double From JLS 2ed (17.4 Nonatomic Treatment of double and long) >If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write actions they are treated as if they were two variables of 32 bits each: wherever the rules require one of these actions, two such actions are performed, one for each 32-bit half. * the volatile keyword assure that the master value of a variable is processed on and not a local cached value +--------------------------------------------------------+ | Collections | +--------------------------------------------------------+ * a Collection can be viewed as a container for object grouping * a Collection work by grouping objects such that they can be operated on independent of their data structure * a Collection has the following intefaces << interface >> Collection | +-List +-Set | +-SortedSet << interface >> Map | +-SortedMap * the Set collection is used for storing 'unique' elements within the group * the List collection stores elements is a sequentian order allowing dupilcated of elements * the SortSet collection is an ordered Set * a Map collection associates 'key' references with a data 'value' * there is a 1-to-1 mapping of key to value, this implies that key's must be unique, but values can be non-unique * the java.util.*; package provided the following concrete classes collection data structure class interface -------------- ----- ---------- Dynamic Array ArrayList List Dynamic Array Vector List Balanced Tree TreeSet SortedSet Balanced Tree TreeMap SortedMap Linked List LinkedList List << class >> ---> << interface >> java.util.AbstractCollection ---> Collection | +-java.util.AbstractSet ---> Set | | | +-java.util.HashSet ---> Set | | | +-java.util.TreeSet ---> Set | +-java.util.AbstractList | +-java.util.AbstractSequentialList ---> List | | | +-java.util.LinkedList ---> List | +-java.util.Vector | +-java.util.ArrayList --> List java.util.AbstractMap | +-java.util.HashMap ---> Map +-java.util.TreeMap ---> SortedMap +-java.util.WeakHashMap +--------------------------------------------------------+ | java.oi | +--------------------------------------------------------+