|
Object-Oriented Design & Patterns (ISBN: 978-0-471-74487-0)
Object-Oriented Design & Patterns ISBN: 978-0-471-74487-0 p5 BlueJ example p6 Use javadoc to build code from your source code comments between /** ... */ The first sentence of each method is used for a summary table of all methods of your class. javadoc also looks for comment lines that starts with @param paramName or @return. p10 Primitive Types
Type | Size | Range | | int | 4 bytes | -2,147,483,648 ... 2,147,483,647 | | long | 8 bytes | -9,223,372,036,854,775,808L ... 9,223,372,036,854,775,807L | | short | 2 bytes | -32768 ... 32756 | | byte | 1 byte | -128 ... 127 | | char | 2 bytes | '\u0000' ... '\uFFFF' | | boolean | | false, true | | double | 8 bytes | approximately ±1.79769313486231570E+308 | | float | 4 bytes | approximately ±3.40282347E+38F |
Escape characters
Escape Sequence | Meaning | | \b | backspace (\u0008) | | \f | form feed (\u000C) | | \n | newline (\u000A) | | \r | return (\u000D) | | \t | tab (\u0009) | | \\ | backslash | | \' | single quote | | \" | doucle quote | | \un1n2n3n4 | unicode encoding - four hexadecimal digits |
p13 // Cast (Date) is necessary in below cod snippet because clone() is a generic method with return type object. Date myDate = ... Date anotherDate = (Date) myDate.clone(); p16 Java uses call by value when passing parameters for both premitive and object types (note object reference is passed by value). p17 Java classes can be grouped into packages. Place a class inside a package by simply adding a package statement as the first statement of the source file: // Class files are stored in subdirectories that match package name. // Therefore, always compile from base directory. For example: /// javac edu/sjsu/cs/cs151/alice/Greeter.java package edu.sjsu.cs.cs151.alice; public class Greeter {....} You can import classes using wildcard in an import statement import edu.sjsu.cs.* Any class without a package statement is in the "default package" with no package name. p19 If you call a method that might throw a checked exception, then you must either declare it or catch it. Checked exception is caused by elements outside programmer's control (i.e. closed socket handle). Unchecked exception are usually programmer's fault (i.e. NullPointerException). If your code will cause an exception, then you must either 1) Declare the exception in the method header, or 2) Handle or catch the exception. p20 public void read( String filename) throws FileNotFoundException, IOException, ClassNotFoundException { FileRead reader = new FileReader( filename ); ... } p21 try { read( "myfile" ); // code that may throw exceptions } catch (IOException e ) { // corrective action } finally { // executed during normal processing or when an exception is thrown. } p22 Empty string ("") length 0 is different than null (no reference to a string object) use equals method to compare strings. == only comperes the referencee if ( "there".substring(3,4).equals( "re" ) ) ... Convert string to number using Integer.parseInt and DoubleparseDouble p23 Use scanner class to read input from file or stdio. Methods and exceptions to consider: nextInt(), nextDouble(), hasNextInt(), hasNextDouble(), InputMismatchException Scanner in1 = new Scanner( new FileReader( "input.txt" ) ); scanner in2 = new Scanner( System.in ); int counter = in2.nextInt(); while (in1.hasNextLine() ) { String s = in1.nextLine(); ...} p23 ArrayList (in java.util package) allows you to collect a sequence of objects, but not premitives (i.e. ArrayList<int> is NOT allowed). Common methods and exception: add(), set(), size(), IndexOutOfBounds ArrayList<String> countries = new ArrayList<String>(); countries.add( "Italy" ); for (int i=0; i< countries.size(); i++) System.out.println( countries.get(i) ); for (String c : countries ) System.out.println ( c ); // For Each Loop p24 Inserting and removing data in ArrayList is not efficient; therefore, use the LinkedLists data structure, and use the ListIterator to reference elements LinkdedList<String> countries = new LinkedList<String>(); countries.add( "Italy" ); ListIterator<String> iterator = countries.listIterator(); if (iterator.hasNext() ) iterator.next(); iterator.add( "France" ); while ( iterator.hasNext() ) System.out.println( iterator.next() ); p25 When array is constructed, its elements are set to zero, false, or null. Use the length property to reference number of elements in an array. You can create anonymous arrays without declaration by putting your array elements in curly braces {1,2,3,4} int [][] table = new int [9][9]; public double sum( int... values ); // ... denotes variable number of parameter for array "values" p28 static field in a class variable, is a single variable for the entire class. static methods are used for factory methods; that is, methods that return an object, similar to constructor. static methods can acces static fields but not instance fields. Use final keyword to insure that variable is not changed. private static Random gen = new Random(); // Methods nextInt, nextDouble, nextBoolean public static final double PI = 3.14; // Constant public class A { public static A newClass() { return new( A ); } // Factory method }
p29 Class name should always start with uppercase letters. Package names should always be lowercase letters. Field and method names should always start with lower case. Underscores are NOT commonly used in class or method names. Constants should be in all uppercase with occasional underscore (MAX_VALUE). It is not considered good style by most Java programmers to use prefix for fields (ie. _name or m_name). For setting and retrieving object methods use get and set prefix (i.e. setDate, getDate). For setting and retrieving boolean methods us is and set prefix (i.e. isPolite, setPolite). Except for public static final fields, all fields shold be declared private. If you omit the access specifier, the field has package visibility (all methods of class in the same package can access it - an unsafe practice). From OOP point of view, it makes more sense to list the public interfaces first Avoid c++ array declaration (int number[]); Use int[] numbers becuase it clearly shows int[] is the data type. Put spaces after binary operators, but not after methods. Good | Bad | | x > y | x>y | | if (x > y ) | if(x > y) | | Math.sqrt(x) | Math.sqrt (x) |
p31 CheckStyle program automatically checks the quality of your code. It reports misaligned braces, missing documentation comments, and many other style errors. http://checkstyle.sourceforge.net Ch2 p36 Functional specification is a detailed textual description of the problem that software system needs to carry out. It has the following characteristics: Completely defines the tasks to be performed Free from internal contradictions Readable both by experts in the problem domain and software developers Reviewable by diverse interested parties Can be tested against reality
p37 Analysis document format can be in different forms; such as: User Manual, Use Cases, Object-Oriented techniques. Use Cases - a sequence of actions that yields a benefit for a user of a system. Analysis phase concerns itself with the description of what needs to be done, not how it should be done. It is possible to use Object-Oriented techniques in the analysis phase as well as the desighn phase. It's adantage is that the object model of the analysis phase can be carried forward to the design phase. It's disadvantage is that customers of of software product are generaly not familiar with terminology of object orientation; and clients may not be able to tell if the product design satisfies their needs. Design phase - Create interrelated classes. Each class must be specified precisely, listing both its responnsibilities and its relationship to other classes. Design phase goals: Identify classes Identify responsibilities of these classes Identify relationship among classes Programming Language and exact choice of data strcture (ie. hash, binary tree, etc) are NOT part of the analysis decision.
p38 Outcome of the design process Textual description of the classes and their most important responsibilities Diagrams of the relationships among classes Diagrams of important usage scenarios State diagrams of objects whose behavior is highly state-dependent
Object-oriented design is particularly suited for prototyping p39 Objects are charracterized by state, behavior, identity. State - Collection of all information held by an object. Object's state may change over time (only after an operation). Behavior - the operations (methods) an object can carry out. Identity - two or more objects can have same operations, and states; yet, are different from eachother (have own identity). p40 Class describes a collection of related objects. It includes: 1) operations that are allowed on the object of the class 2) Possible states for the objects of the class An instance of a class is an object that belongs to the a class (objects conforming to a class description) p41 A simple rule of thumb for identifying classes is to look for nours in the functional specification. Class names should be nouns in a singular form (i.e. Message, MailBox). Sometimes nouns need to be prefixed by an adjactive (i.e. BufferedReader, RectangularShape). Don't use "object" in the class name (i.e. MailboxObject). If you name your classes after a verb, you are probably on a WRONG track (i.e. Deliver, Printing) p43 Tangible thinkgs are the easiest classes to discover becuase they are visible in the problem domain (i.e. Mailbox, Message, Footnote). Sometimes it is helpful to change an operation into an agent. For example: change "computer page breaks" operation into a class Paginator. Agent classes often end with "er" or "or" (i.e. Paginator, Scanner, etc) User and Role classes are stand-ins for actual users of the program. System classes model a subsystem or overall system being built. Their roles are typically the initialization/shutdown (i.e Mailsystem) System interface classes model interfaces to host operating system (i.e. File class) Foundation classes (i.e. Date, String, Rectangle) encapsulate basic data types with well-understood properities. Assume these types are readily available just as undamental types (integer, float, etc) p45 Just as nouns in the problem correspond to Classes, the verb correspond to responsibilities. When you find a responsibility, you must find one class (and only one class) that owns that responsibility (operation) When assigning responsibilities, respect the natural layering of abstraction levels; and the class should stay at one abstraction level. Mid-level abstraction should not deal with processing keystrokes, low level responsibility, initialization, or high level responsiblities. A class depends on another class if it manipulates objects of the other class in any way. One important design goal is to minimize the number of dependency relationships; that is, minimize the coupling between classes. A low degree of coupling tends to make it easier to implement changes in the future; otherwise, the changes in one can force changes in the other(s). p47 Aggregation - When one class contains objects of another class over a period of time. For example, MessageQueue has Message objects, and we say that the MessageQueue class aggregates the Message class. Aggregation is a special case of dependancy; it is ofter informally described as the "has-a" relationship. In aggregation, It is useful to keep track of multilicities (1:1 or 1:n)f Simple or Foundational types (number, string, date) are considered attributes; where as, a complex object (i.e. MailBox) is an aggregation. p48 superclass is a general class, and a specialized class is a subclass A class inherits from another if it incoperates the bhavior of the other class. Inheritance is often called the "is-a" relationship. "has-a" and "is-a" help in distinguashing between inheritnace and aggregation. For example: a forwarded message is a message (inheritance) while a mailbox has a greeting (aggregation). Each "Use Case" focuses on a specific scenario, and describes the steps that are necessary to bring it to successful completion. A use case lists a sequence of actions that yields a result that is of value to an actor. For example, "Leave a message" has a value because the message is deposited in the mailbox; however, dialing a telphone number and listening to a menu is NOT considered a valid use case because it does not by itself have a value to anyone. p49 A use case should include variations that describe different situations. It should atleast contain: 1) name that describes the problem 2) main sequence of the actions 3) if appropriate, variants of mainsequence. http://www.usecases.org contains a template for elaborate use case formats. http://www.pols.co.uk/use-case-zone has many useful links to articles that report on experiances with use cases; including cautionary tales. Here is a quick tutorial on Use Case diagrams http://www.cragsystems.co.uk/SFRWUC/index.htm p50 CRC card is an index card that describes a class, its high-level responsibilities and its collaborators. The card is small; thus, it prevents you from piling too much responsibility into a single class For CRC card 1) Write class name at the top of the card. Below it 2) On the left side, describe responsibilities 3) On the right side, list other classes that need to collaborate with this class to fullfillits responsibilities.  Responsibilities on the CRC card should be at a high level. Many programmers equate responsibilities with method; however, a responsiblity can correspond to several methods. If you find that you have many responsibilities on an index card, try to think of a higher level responsibility. Beware of the ominpotent system class. You often need a class that is responsible for coordinating the working of the system that you are buidling, but there is a tremendous danger of overburdening that class with too many responsibilities. p52 Avoid "mission creep". If a class acquires too many responsibilites, then consider splitting it in two. Ideally, a class should not have more than three high-level responsibilities Watch out for unrelated responsibilites. A class hsould repersent a coherent concept, with related responsibilites. For example, if the MailBox class gets charged with storing messages and parsing input, make a new class and split the responsibilities. Resist the temptation to add responsibilites just because they can be done. For example, someone may have suggested a Mailbox responsibility "sort messages". But that task at hand requires no sorting, and you shouldn't collect unused responsibilites. A class with no responsibilites sureley is not userful. Eleiminate classes that don't seem to contribute to solving the problem at hand. Typical candidates are vuge mechanisms such as Connector and Data. p53 Arrange CRC cardson the table so that classes are physically close to their collaborators. If you work on your own, become "Jekyll and Hde" and challange your design. CRC cards are a dood tool for proposing designs, but they are not particularly suited for documenting them. These cards should be discarded afrter a design has been found. They are meant as a discovery tool, not as archival information. UML diagram illiustrates an aspect of an object-oriented design, using stardaized notation. p54 Free UML drawing programs: ArgoUML https://argouml.tigris.org Dia http://www.gnome.org/projects/dia and windows version at: https://hans.breuer.org/dia Violet http://hosrtmann.com/violet A Class diagram shows classes and the relationships among them. Classes are drawn as boxes, which contan the class name, and when appropriate, attributes and methods in additional compartments. If you have lots of attributes, see if you can goup them into classes (i.e. ContactInfo) In a class diagram you can specify attribute type (notation name : type ) and method return types (notation: method( param:type ) : returnType ). For example: Mailbox | newMessages savedMessages | add( ) getCurrentMessatge() : Message |
Often, types of attributes, parameters, and return values are omitted in class diagrams to conserve space. Thus, for a method without marameters, you may NOT assume that there are no parameters. Use UML connectors to draw the relationships among the class diagrams.
 Note: Compisition is a sronger form of aggregatino. In composition, the object never resides outside the object (i.e. MessageQueue class is never used outside Mailbox class) Use UML connectors to draw the relationships among the class diagrams. You have to be carefule about the shapes of the arrow tips. The inheritance arrow is closed, whereas the dependancy arrow is open. Also note that the arrow tips for inheritance and dependancy are at the end of the dependent class, but the diamond for aggregation is at the end of the aggregating class. You may need to show the multilcipity for "has-a" relationship at the end of the connector end points. Any number: * one or more: 1..* zero or more: 0..* exactly one: 1  p56 Use aggregation (or composition ) only if a class actively manages objects of another class. Some designers do not like the aggregation relationship because they feel it is too implementation-specific. UML defines a more general association between classes by using a simple solid line. You can write roles at the end of connector lines p57 An interface type describes a set of methods, but it contains no implementation at all. In the UML notation, you denote an interface by adding the stereotype descriptor «interface» above the interface name. (The « and » characters are called guillemets). If a class implements an interface, you draw a dotted arrow with closed arrow tip (see image above). p58 The most important relationship to control is the dependency or "uses" relationship. Too many dependencies make it difficult to evolve a design over time. You should NOT aim for a comprehensive diagram that shows all classes and relationships in the system. A diagram with too much information becomes just a blur. The reason for drawing diagrams is to communicate design decisions. To achieve this purpose, each UML diagram should focus on a particular aspect of the design and it should be accompanied by text that explains its relevence. When drawing a diagram, you should only include those elements that are needed to make a particular point, and omit all distractions. Class diagrams are static. They display relationship among the classes that exist throught the lifetime of the system. Sequence diagrams show the dynamics of a particular scenario. it descibes the communication patterns among objects. In UML, you use underline to distinguish object rectangles from class rectangles. The text inside the object rectengle has the following three formats: objectName : ClassName (full description) objectName (class not specified) : ClassName (object not specified)

A dashed verticla line that emanates from object is called the lifeline. In some OOP langagues, objects can be explicitly destroed, which causes their lifeline to end at the of destruction. p59 The rectnagles along the lifeline are called activation bars. The show when the object has control, executing a method. The activation bar ends when the method returns. Additionally, it should also be smaller than that of the calling method. Draw the activation bar of the called method over the one of the calling method when the methods are inside the same object. If a method constructs a new object, you can use the stereotype «create» to indicate the timing of the creation. When drawing a sequence diagram, you omit a large amount of detail. Generally, you do not indicate branches or loops. The principle purpose of a sequence diagram is to show the objects taht are involved in carrying out a particular scenario and the order of the methods calls that are executed. p60 If you played through a use case when using CRC cards, then it is probably a good idea to use a sequence diagram to document that scenario. A state diagram shows the states of an object and the transitions between states. The state has a noticble impact on the behavior. States are particularly common with objects that interact with the program user. 
p 61 You can use javadoc to document your design. Simply write a skeleton class with no fields and leav all methods implementation blank. Ofcourse, supply the class methods and comments. Do NOT compile the skeleton file (the compiler will complain about unkinonw types and methods with no return statements). Simply run javadoc program to extract the HTML documentation. /** A mailbox contains message that the mailbox owner can manage. */ public class Mailbox { /** Adds a message to the end of the new message. @param aMessage a message */ public void add( Message aMessage ) { } /** Returns the current message. @param the current message */ public Message getCurrentMessage() { } }
p62 In the analysis phase, define behaviors through a set of use cases. Note that the "use cases" by themselves are not a full specification of a system. The functional specification also needs to define system limitations, performance, and so on. p71 An aggregation relationship "wins" over a dependency relationship. If a class aggregates another, it clearly uses itt, and you don't need to record the latter. p72 There is no advantage in modeling a repetition of sequence diagram. You do not see parameters and return values in the sequence diagrams. You have to keep track of the objects yourself and realize that the object to the right is meant to be the object returned by the corresponding method call. Chapter 3 p91 Total Ordering - relation between elements in a set that fullfils certain properties. Transitivity: If x <= y and y <= z, then x=y Reflexivity: x <= x Antisymmetry: If x<= y and y <= x, then x= y Totatility: For any x and y, x<= y or <= x
Partial ordering - a relation that fullfils only the first three properties from above. For Date object x and y, you can define x<=y as: x.before(y) || x.equals(y) p93 The responsibility of the GregorianCalendar class is to assign descriptions to points in time. Defining the GregorianCalendar class separate from the Date class is goode class design. There are many possible descriptions of a point in time. For example: * Annee 209 de la Republique Mois de Pluviose Decade 2 Jour du Quitidi in the French Reveolution calandar * 12.19.7.17.1 in the Mayan Long Count Java library designers provide a superclass Clendar that is supposed to help implementors of other calendars. 
Often times the existence of a mathematical structure can be used to define the behavior of a class ina precise and unambiguous manner. For example: (d + n ) - d is same as n, which transelates to d.addDays(n).daysFrom(d) p96 ISO 8601 standard specifies that format as 4 digit year, 2 digit month, and then two digth day. That is 2/4/06 is written as 20060204 p98 Three reasons to be cautious of public helper methods: they can clutter up the public interface, making it harder for class users to understand Sometimes, helper methods require a special protocol or calling order. You may not trust your class users to understand the subtleties, or you may not want to document them as carefully as you documnt the public interface Sometimes, helper methods depend on a particular implementations
p110 A mutator method modifies the state of an object. An accessor method leaves the state unchanged. Objects of an immutable class cannot be changed after they have been constructed. Providing set method for every instance ins not advisable. Consider the following: Day deadline = new Day( 2006, 1, 31); ... deadline.setMonth( 2 ); // This is a disaster waiting to happen (31 days in february!). One major advantage of non-mutator classes is that object references can be freely shared. Thus, it is dangerous to give out a reference to a mutable instance field. p113 An accessor method should never return a reference to amutable instance field. Instead, clone the field; however, it is safe to return primitve types and references to immutable objects. Immutability is a valuable feature. If you can make your class immutable, you should. final keyword is a good way of expressing immutable class. Though finaly will not allow contents of a variable change, it has no control to the state of the object that it may reference. For example: private final ArraayList elements; // does not prevent changes to the contents of the array lis. p114 When you have a class that has both accessors and mutators, then it is a good idea to keep their roles separate. A method that returns information about an object should ideally not change the object state. A method that changes the object state should ideally have return type void. A mutator can return a value for a the user's convenience, but there should also be an accessor that gets the same value, so that the class user isn't forced to mutate the object. An example of this violation can be seen in the Scanner object where there is no getCurrent(), rather the next() mutates the instance. p115 Generally, users of your class expect thtat its methods do not modify the explicit parameters that they supply. p117 Some researchers believe that object promiscuity (return object that is mutable) is a sign of poor organization that is likely to lead to maintencance headaches. Law of Demeter states that method should only use: * instance fields of its class * parameters * Objects that it constructs with new A method that follow the law of Demeter does not operate on global objects or objects that are a part of another object. The law of Demeter tells you what not to do, but it doesn't tell you what to do instead. You should not ake the Law of Demeter as a natrual or mathematical law. Simply consider it, together with other and possibly conflicting design guidelines, when you design your program. Law of Demeter implies that a class should not return a rerence to an object that is a part of its internal implementation. See Karl J. Lieberherr and Ian Holland "Assuring Good Style for Object-Oriented Programs" and details and tools at http://www.ccs.neu.edu/research/demeter Interface design needs to consider the users, who want a set of operations that is large enough to solve their programming tasks, yet small enough to be comprehensible. Cohesion - A class is cohesive, if all of its methods are related to a single abstraction. All class operations must logically fit together to support a single coherent purpose. For example: public class Mailbox { public void addMessage( Message m ) {...} public Message getCurrentMessage() {...} public Message removeCurrentMessage() {...} public void processCommand(String command) {...} // How/What/in what format } p119 Completeness - A class interface should be complete, and support all operations that are a part of an abstraction that the class repersents. For example, the designers of the Date class included before() and after() method; however, they did not include a difference() method. Thus, the users must make use of t1.getTime()-t2.endTime() and then convert the time units accordingly. Convenience - The interface should provide a convenient way to accomplish common tasks. Programmers should have to jump through hoops to solve conceptually simple task. Before Java 5.0, you had to wrap System.in into an InputStreamReader and then into a BufferedReader, which was vary inconvenient. Clarity - The interface design should be clear to programmers without generating confusion. Whenever the explanation of a method is complex, you should pause and think whether the complicity is necessary. For example: LinkedList add() method inserts a node before current element; however, the remove() method requires the user to advance over the "current" node, and then call remove. It would have been straightforward to implement a rmove operation that removes the element to the left of the iterator, rather than the righ. p121 Coinsistancy - the operations in a class should be consistent with each other with respect to names, parameters, return values, and behaviors. For example, String object provides equals() and equalsIgnoreCase() , yet it has a set of compareTo/compareToIgnoreCase methods that break consistancy by looking at an explicit parameter for the case sensativity comparision (i.e. regionMatches method). Why use one schem for equals() and a different schem for compareTo? As with any engineering task, you need to use your judgment to balance the conflicts between cohesion, completeness, convenience, clarity, and consistancy. p122-3 No operation should waste a lot of time checking for invalid objects; because of the precondition contract (methods). A precondition of a method is a condition that must be fullfilled before the method may be called. Specify javadoc @precondition by using custom tag as if it were a valid java doc tag. Then include it during javadoc build using option -tag precondition:cm:"Precondition:" where the cm instructs javadoc to look for this tag only in constructor and methods p126-7 Class user mut be able to check the precondition of a method. Preconditions of public methods must only involve public methods of the class. Use assertion to check conditions that you believe should be true in the course of the program. assert condition : explanation; Where the operation will proceed as long as the condition is true; otherwise, an error message is displayed that contains the file and line number of the failed assertion statement. Assertion can be turned off completely after tetsting. Some computer scientists think that assertions shouldn't be turned off after debugging is completed. After all, would you wear a life vest only while sailing close to the shore? To enable java assertion use -enableassertions or -ea flag when running the java program. Rather than returning null, use the tough love approach of terminating the program with an assertion error, which makes it ppossible to locate error percisely. p128 You can also selectively enable and disable assertions in different classes and packages. See http://java.sun.com/j2se/1.4/docs/guide/lang/assert.html A common strategy for dealing with problem cases is throwing an exception. Unlike an assertion test, exception checks cannot be turned off, and therefore always inur a small performance penalty. That does not mean that you shold stay away from exceptions. In fact, exceptions are part of the contract description (i.e. @trows ...) There is a an important distinction between a precondition and a contractually specified exception. When a method is violated, it may do anyting (unknown behavior); however, with exception precondition, the outcome is explicit. p129 A post condition of a method is a condition that holds after the method has completed. It is useful to document postconditions that go beyond the description of the method purpose and @return tag by using @postcondition like earlier @precondition. Note that you should not repeat the @return comment in a @post condition comment. Class Invariants - is a contion that is fulfilled by all objects of the class after the completion of any constructor or method, exept possibly those that are undergoing mutation. In other words, the condition must be true before and after every method call, but it can be temporarily violated inside a method call. To prove an invariant, you need to check: 1) It is true after every constructor has completed execution 2) It is preserved by every mutator. That means, if it is true at the start of the mutator, then it is agin true when the mutator returns. We don't worry about accessor operations because they don't change the object state. For example: In a messageQueue class head >=0 and head < elements.length() p131 Invariants are useful for bringing out thoese properties of your classes that ensure freedom from bad casts, null pointers, or arry bounds errors. Using theorem-proving technology, it is even possible to automate some of these checks. Checkout Compaq Extended Static Checker for Java (ESC/Java) from http://reserarch.compaq.com/SRC/esc/ to see this technology in action. A unit test of a class test the class in isolation. Programmers are much less reluctant to improve the implementation when they have a collection of test cases that they can use to validate their changes. A popular tool for unit testing is JUnit (https://junit.org). To test a class, you need to design a companion class that contains the test cases. Each test case needs to be placed in a method whose name starts with test. Follow this template: import junit.framework.*; public class DayTest extends TestCase { public void testAdd() {...} public void testDaysBetween() {...} } Each test cases checks some code and uses assertTrue expression. When compiling test class, you need to add the junit.jar file to the class path: javac -classpath .:junit.jar DayTest.java To run all tests in the graphical test runner, execute: java -classpath .:junit.jar junit.swinggui.TestRunner DayTest Chapter 4 p137-8 A class defines a set of operations (interface) and statements that specify how to carry out the operations and how to represent object state (the implementation). You can display dialog box with: JOptionPane.showMessageDialog(null, "Hello, World!"); You can include custom icon in dialog box via: JOptionPane.showMessageDialog( null, //parent window "hello World!" //message "Message", // window title JOptionPane.INFORMATION_MESSAGE, //message type new ImageIcon( "globle.gif" )); If a method has a parameter of an interface type, then ou can supply an object of any class that implements the interface type (i.e. any class that implements the Icon interface type). An interface type specifies a set of methods, but does not implement them. public interface Icon { int getIconWidth(); int getIconHeight(); void paintIcon( Component c, Graphics g, int x, int y); } p140 All methods of an interface type are automatically public. A class implements the interface type by providing an implements clause and supplying for the methods that are declared in the interface type. p141 import java.awt.*; import java.awt.geom.*; import javax.swing.*; /** An icon that has the shape of the planet Mars */ public class MarsIcon implements Icon { /** Constructs a Mars icon of a give size. @param aSize the size of the icon */ public MarsIcon( int aSize) { size = aSize; } public int getIconWidth(){ return size; } public int getIconHeight(){ return size; } public void paintIcon( Component c, Graphics g, intx, int y) { Graphics 2D g2 = (Graphics2D) g; Ellipse2D.Double planet = new Ellipse2D.Double(x, y, size, size); g2.setColor( Color.RED); g2.fill(planet); } private int size; } p142 When you implement a method that has been defined in an interface that has been defined in an interface type, you need not supply a javadoc comment if the comment in the interface type is sufficient. the javadoc utility automatically inserts links to the documentation of the interface type. If the interface type belongs to the standard library, you should run the javadoc utility with the -link option and supply a URL for the standard library documentation. For example: javadoc -link http://java.sun.com/j2se/1.5.0/docs/api *.java An interface type cannot specify any implementation details; and never specifies instance variables. It does however, allow declaration of variables, but are automatcially declared public static final variables: public interface ImageObserver { int ABORT = 128; // a public static final constant .... } An interface type can extend another byaddition additional requirements. i.e. public interface MoveableIcon extends Icon { void translate( int x, int y ); } p143 If a class implements an interface type, its objects can be assigned to variables of the interface type. The type of an object is never an interface type. However, the type of a variable can be an interface type. Such a variable contains a reference to an object whose class implements the interface type. Polymorphism refers to the ability to select different methods according to the actual methods of an object. An important use of polymorphism is to promote loos coupling. Another important use of polymorphism is extensibility. By using the Icon interface type, the designers of the JOptionPane class don't lock you into the use of bitmap icons. You can suply icons of your own design. The Collection.sort method can sort objects of any class that implements the Comparable interface type. public interface Comparable<T> { int compareTo (T other); } If you design a class whose objects need to be compared to each other, your class should implement the Comparable interace type p147 Instead of compareTo you can implement Comparator and its compare method so that you can designate your own sort orders. For example: Collections.sort( mylist. myCompareObject) You can sort collection in any sort order by supplying an object of a class that implements the Comparator interface type. public class CountryComparator implements Comparator<Country> { private int direction; public CountryComparator(boolean sortAscending) { direction=sortAscending ? 1 : -1; } public int compare( Country c1, Country c2 ) { return direction * c1.getName.compareTo( c2.getname ); } } ... Comparator<country> c = new CountryComparator(true); Collections.sort( countries, c ); // where "c" parameter is the function object. Collections.sort( countries, new CountryComparator(flase) ); // using anonymous object
Anonymous object is an object that is not stroed in a variable. Anonymous class is a class without a name. When defining an anonymous class, you must also consttruct an object of that class. Comparator<Country> comp = new // put new on a line by itself so you // can quickly recognize something is different. Comparator<Country>() // Note that there is no "class <name> implements". { public int compare(Country c1, Country c2) { return c1.getName.compareTo( c2.getName ); } }; //Note the ending semicolon, because this is an assignment expression.
Most programmers find it easier to learn about anonymous classes by rewriting the code and explicitly introducing a class name. p150 Consider creating oner or more static methods that returns an annonymous class. For example: public class Country{
publice static Comparator<Country> comparatorByName() { return new Comparator<Country>() { public int compare( Country c1, Country c2) { return c1.getName.compareTo( c2.getName() ); } } } publice static Comparator<Country> comparatorByArea() {...} } ... Collections.sort( countries, Country.comparatorByName() );
The above design allows for serval comparisons that can be referenced when needed p151-2 You specify actions for buttons, menus, etc. to ccur upon activation by defining classes that implement the ActionListener interface type. A frame window is a top-level window, usually decorated with borders and a title bar. Even though the main() thread will quit, the setVisible() method spwns another thread so that the GUI stays active until user terminates it. listnener class - In Java user interface toolkit, the code that executes when a button is clicked. Thus, the code can attache itself to a component's action listener (i.e. button's action listener). A button or other objects that support action listeners can hav have any number of action listener objects. The listener objects must belong to classes that implement the ActionListener interface. public interface ActionListener { void actionPerformed( ActionEvent event ); }
Here is a sample code with an annonymous action listener class JFrame = new JFrame(); frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); // exits when user closes the window frame.setLayout( new FlowLayout() ); // FlowLayout lines up components side by side. // Because the following textfield is accessed from an inner class // (annonymous action listener), we must declare it as final. final JTextField t = new JTextField( 20 /* field width */ ); frame.add( t ); JButton b = new JButton( "hello" ); b.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent event ) { t.setText("Hello World"); } } ); frame.add( b ); frame.pack(); //set the size of frame to the smallest size needed to display its content. // Alternatively, you can use frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setVisible( true );
A layout manager sets the positions and dimensions of components. Flow layout lines up components side by side. Methods of inner classes can access variables that are visible in the enclosing scope; therefore, in the above example, the annonymous class has access to the JTextField variable "t". If you access a local variable from an inner class, you must declare it as final. p156 Recall that you can put modularize the annonymous action listener by putting it in a static method, and then call it with a parameter, if applicable (similar to above Country Comparator example. p157-8 Timer class in javax.swing package generates a sequence of action events, spaced apart at equal time intervals, and notifies a designated action listener. Timer t = new Timer ( 1000 /* miliseconds */ , new ActionListener() {...} ); There are two classes named Timer in the Java library: one in the javax.swing and the other in java.util package. To resolve ambiguity, you can declare timer as: javax.swing.Timer t = new javax.swing.Timer( DELAY, listener ); p159 Here is what the graphics paintIcon() method looks like: public void paintIcon( Component c, Graphics g, int x, int y ) {...} The Graphics parameter "g" of a paint() method carries out drawing operations. The Graphics object is a graphics context. You invoke methods on that object whenever you want to draw a shape or change the current color or font. In general, a "context" object is usually an object that has some specialized knowledge of how to carry out omplex tasks. For historical reasons, most moethods still use the older Graphics parameter, even though a Graphics2D object is always passed into the methods. To use the powerful 2D drawing operations, you need to cast it to the Graphics2D type. For example: public void paintIcon( Component c, Graphics g, int x, int y ) { Graphics2D g2 = (Graphics2D) g; ... } You can draw objects of any class that implements the Shape interface type, such as rectangles, ellipses, and line segments. More complex shapes can be drawn by using arbitrary quadratic and cubic curve segments. // ellipse is bound inside of rectangle dimensions Shape ellipse = new Ellipse2D.Double(x, y, width, height); Shape rectangle = new Rectangle2D.Double( x, y, width, height ); g2.draw( rectangle ); // draw a shape g2.fill( ellipse ); // fill a shape g2.drawString( "hi", x, y ); // draw string 
p163 Typographical measurements to describe the vertical and horizontal extendt of text: ascent - is the height of the largest letter above the base line descent - is the depth below the baseline of the letter with the lowest descender 
monospace font - all letters have the same width proportionally spaced fonts - different letters have different widths To measure the size of a string, you need to construct a FontRenderContext object, which you obtain from the Graphics2D object by calling getFontRenderContext() method. To get the size of a string, you call getStringBounds method of the Font. String text = "Message"; Font font = g2.getFont(); FontRenderContext context = g2.getFontRenderContext(); Rectangle2D bounds = font.getStringBounds( text, context ); double ascent = -bounds.getY(); double descent = boudns.getHeight() - ascent; double extent = bounds.getWidth();
p164-166 Whenever you design a mechanism that asks someone else to supply an object of a class, you should consider whether it would be more appropriate to specify an interface type instead. By using interface types, you give added flexibility to the programmers that use the service that you provide. Desing your own interface types to decouple general mechanisms from specific implementation details. Consider the below classes: public class ShapeIcon implements Icon { public ShapeIcon( MovaleShape s, width, height ) { this.myShape = s; w=width; h=height;} public void paintIcon( Component c, Graphics g, intx, int y ) {myShape.draw( (Graphics2D) g );} public void getIconHeight() {return h;} public void getIconWidth() {return w;} } ... public interface MoveableShape { void draw( Graphics2D g2); void translate( int dx, int dy ); } ... ShapeIcon icon = new ShapeIcon(...); final JLabel myLabel = new JLabel ( icon ); // final because it is referenced via inner class javax.swing.Timer t = new javax.swing.Timer( 1000 /* milliseconds */ , new /* annonymous ActionListener class */ ActionListener() { public void actionPerformed( ActionEvent e ) { myShape.translate(1,0); myLabel.paint(); } ); ... |