Chapter 15 Abstract Classes and Interfaces CIS265/506 Cleveland State University – Prof. Victor Matos Adapted from: Introduction to Java Programming: Comprehensive Version, Eighth Edition by Y. Daniel Liang 1 More specialized More general Abstract Classes and Abstract Methods 2 2 This example was introduced in Chapter 11. Abstract Classes and Abstract Methods Aside - Useful links: An UML Tutorial http://www.ibm.com/developerworks/rational/library/content /RationalEdge/sep04/bell/ Google’s Draw-io: A free-ware UML drawing tool https://www.draw.io/ 3 3 Example1:Superclasses and Subclasses public abstract class GeometricObject { 1 2 2 private String color = "white"; private boolean filled; private java.util.Date dateCreated; // Return TRUE is object is filled public boolean isFilled() { return filled; } // Construct a default geometric object protected GeometricObject() { dateCreated = new java.util.Date(); } // Set filled to either: true/false public void setFilled(boolean filled) { this.filled = filled; } // createa obj with color and filled value protected GeometricObject(String color, boolean filled) { dateCreated = new java.util.Date(); this.color = color; this.filled = filled; } // Get dateCreated public java.util.Date getDateCreated() { return dateCreated; } // Return a string representing this object public String toString() { return "created on " + dateCreated + "\ncolor: " + color + " and filled: " + filled; } // Return color public String getColor() { return color; } // Set a new color public void setColor(String color) { this.color = color; } // Abstract method getArea public abstract double getArea(); // Abstract method getPerimeter public abstract double getPerimeter(); } 4 4 5 Example1: Superclasses and Subclasses public class Circle4 extends GeometricObject { private double radius = 1; /** Return diameter */ public double getDiameter() { return 2 * radius; } 1 2 3 3 public Circle4() { } public Circle4(double radius) { super(); this.radius = radius; } public Circle4(double radius, String color, boolean filled) { super(color, filled); this.radius = radius; //setColor(color); //setFilled(filled); } /** Return perimeter */ public double getPerimeter() { return 2 * radius * Math.PI; } /* Print the circle info */ public void printCircle() { System.out.println(toString() + " Circle created on: " + getDateCreated() + " and the radius is " + radius); } /** Return radius */ public double getRadius() { return radius; } /** Set a new radius */ public void setRadius(double radius) { this.radius = radius; } 5 /** Return area */ public double getArea() { return radius * radius * Math.PI; } 4 public String toString() { return ">>> Circle " + getColor() + "\n" + super.toString() + "\n>>> Radius: " + getRadius() + " Perimeter: " + getPerimeter() + " Area: " + getArea(); } } 5 Example1: Superclasses and Subclasses 1 public class Rectangle extends GeometricObject { private double width; private double height; 2 3 3 /** Return height */ public double getHeight() { return height; } public Rectangle() { } /** Set a new height */ public void setHeight(double height) { this.height = height; } public Rectangle(double width, double height) { super(); this.width = width; this.height = height; } /** Return area */ public double getArea() { return width * height; } public Rectangle( double width, double height, String color, boolean filled) { super(color, filled); this.width = width; this.height = height; // setColor(color); // setFilled(filled); } /** Return perimeter */ public double getPerimeter() { return 2 * (width + height); } public String toString() { return "\n>>> Rectangle " + getColor() + "\n" + super.toString() + "\n>>> Height: " + getHeight() + " Width: " + getWidth() + " Perimeter: " + getPerimeter() + " Area: " + getArea(); // Return width public double getWidth() { return width; } // Set a new width public void setWidth(double width) { this.width = width; } 6 4 } } 5 Abstract Classes and Abstract Methods • An abstract class, like any other Java class, consists of class variables, constructors, mutators, and user-defined (concrete and abstract) methods. • Unlike concrete classes they cannot be instantiated . • Abstract classes are good for: • specifying virtual methods via signatures, those methods must be implemented by descendents of the abstract class. • Providing some concrete although very general methods and variables for subclasses to use Example: public abstract double computeTaxes(int ssn, int w2Nbr) ; One of my subclasses must compute taxes using SSN andW2 form. If returned value is positive then “you owe”, a negative value means “a refund” 7 7 abstract method in abstract class Some regulations: 8 8 • An abstract method cannot be contained in a non-abstract class (concrete classes must have concrete methods). • If a subclass of an abstract superclass does not implement all the abstract methods, the subclass must be defined abstract. • In other words, in a non-abstract subclass extended from an abstract class, all the abstract methods must be implemented, even if they are not used in the subclass. object cannot be created from abstract class More rules: 9 9 • An abstract class cannot be instantiated using the new operator. • However you can still define its constructors, which are invoked in the constructors of its subclasses. • For instance, the constructors of GeometricObject are invoked in the Circle class and the Rectangle class. superclass of abstract class may be concrete A subclass can be abstract even if its superclass is concrete. Example: The Object class is concrete, but its subclasses, such as GeometricObject, may be abstract. 10 10 abstract class as type Although you cannot create an instance from an abstract class, an abstract class can be used as a data type. The following fragment is correct: Concrete subclass GeometricObject g1 = new Circle(2, "RED", true); System.out.println( g1.toString() ); System.out.println( g1.getClass() ); System.out.println( g1 instanceof GeometricObject ); Output: 11 11 >>> Circle RED created on Fri Feb 03 17:11:00 EST 2012 color: RED and filled: true >>> Radius: 2.0 Perimeter: 12.566370614359172 Area: 12.566370614359172 csu.matos.Circle true Example: The Abstract Calendar and the Date class An instance of java.util.Date represents a ‘concrete’ specific instant in time with millisecond precision. java.util.Calendar is an abstract base class for extracting detailed information such as year, month, date, hour, minute and second from a Date object. Subclasses of Calendar can implement specific calendar systems such as 12 12 Gregorian calendar, Lunar Calendar, Jewish calendar, and Chinese calendar. Currently, java.util.GregorianCalendar for the Gregorian calendar is supported in the Java API. Example: The Abstract Calendar and the Date class Java.util.Date Aside-1 Date Class 13 13 Dates are represented as a signed long that counts the number of milliseconds since midnight, January 1, 1970, GMT Time. Java.util.Date Recommended approach is to use a java.text.DateFormat object to obtain a meaningful string out of a date has many deprecated methods to manipulate date/time Example: The Abstract Calendar and the Date class Java.text.DateFormat Aside-2 DateFormat Class Date now = new Date(); DateFormat df = DateFormat.getDateInstance(); String s = df.format(now); System.out.println("Today is " + s); DateFormat DateFormat DateFormat DateFormat String String String String String s0 s1 s2 s3 s4 df1 df2 df3 df4 = = = = = = = = = DateFormat.getDateInstance(DateFormat.SHORT); DateFormat.getDateInstance(DateFormat.MEDIUM); DateFormat.getDateInstance(DateFormat.LONG); DateFormat.getDateInstance(DateFormat.FULL); df.format(now); df1.format(now); df2.format(now); df3.format(now); df4.format(now); System.out.println("(Default) System.out.println("(SHORT) System.out.println("(MEDIUM) System.out.println("(LONG) System.out.println("(FULL) Today Today Today Today Today is is is is is " " " " " + + + + + s0); s1); s2); s3); s4); // old deprecated style, bad-habit int hour = now.getHours(); int min = now.getMinutes(); int sec = now.getSeconds(); System.out.println ( hour + ":" + min + ":" + sec ); 14 14 Today is Feb 16, 2012 (Default) Today is Feb 16, 2012 (SHORT) Today is 2/16/12 (MEDIUM) Today is Feb 16, 2012 (LONG) Today is February 16, 2012 (FULL) Today is Thursday, February 16, 2012 15:43:50 Example: The Abstract Calendar Class and Its GregorianCalendar subclass Aside 3- A note from Wikipedia http://en.wikipedia.org/wiki/Hebrew_calendar http://en.wikipedia.org/wiki/Pope_Gregory_XIII Lunar calendars differ as to which day is the first day of the month. For some lunar calendars, such as the Chinese calendar, the first day of a month is the day when an astronomical new moon occurs in a particular time zone. For others, such as some Hindu calendars, each month begins on the day after the full moon or the new moon. Others were based in the past on the first sighting of a lunar crescent, such as the lunisolar Hebrew calendar (19-years cycle). 15 15 Pope Gregory XIII ordered in 1582 adoption of a new calendar to replace the Julian calendar (in use since 45BC).The average length of a year under the Julian system was 365days and 6 hours.This was about11 minutes longer than the correct value (365d 5h 49m 12s). In 13 centuries this error grew up to be ten days.The Pope decreed on 24 February 1582, that the day after Thursday, 4 October 1582 would be not Friday, 5 October, but Friday, 15 October 1582. Hindu Calendar Maya Apocalypse Calendar Gregory XIII 1582 Example: The Abstract Calendar Class and Its GregorianCalendar subclass No. Name Aside 4- A note from Wikipedia http://en.wikipedia.org/wiki/Gregorian_calendar The Gregorian solar calendar counts days as the basic unit of time.Years have 365 or 366 days; and repeats completely every 400 years. Of these 400 years, 303 common years have 365 days and 97 leap years have 366 days. A calendar mean year has exactly 365+ 97/400 days = 365.2425 days = 365 days, 5 hours, 49 minutes and 12 seconds. Month length is L = 30 + { [ M + floor(M/8) ] MOD 2 }, where L is the month length in days and M is the month number 1 to 12. The expression is valid for all 12 months, but for M = 2 (February) adjust by subtracting 2 and then if it is a leap year add 1. 16 16 Days 1 January 31 2 February 28 or 29 3 March 31 4 April 30 5 May 31 6 June 30 7 July 31 8 August 31 9 September 30 10 October 31 11 November 30 12 December 31 Example: The Abstract Calendar Class and Its GregorianCalendar subclass 17 Example: The GregorianCalendar Class You can use new GregorianCalendar() to construct a default GregorianCalendar with the current time. Calendar calendar = new GregorianCalendar(); Use new GregorianCalendar(year, month, date) to construct a GregorianCalendar with the specified year, month, and date. Calendar calendar = new GregorianCalendar(2525, 0, 31); Date d = cal.getTime(); System.out.println ( d ); // Mon Jan 01 00:00:00 EST 2525 18 18 The month values are 0-based, days are not 0 is for January, 11 for December. 1 for Sunday, 7 for Saturday Example: Fields contained in the Calendar class Constant Description YEAR The year of the calendar. MONTH The month of the calendar with 0 for January. DATE The day of the calendar (1-31). HOUR The hour of the calendar (12-hour notation). HOUR_OF_DAY The hour of the calendar (24-hour notation). MINUTE The minute of the calendar. SECOND The second of the calendar. DAY_OF_WEEK The day number within the week with 1 for Sunday. DAY_OF_MONTH Same as DATE. DAY_OF_YEAR The day number in the year with 1 for the first day of the year. WEEK_OF_MONTH The week number within the month. WEEK_OF_YEAR The week number within the year. AM_PM Indicator for AM or PM (0 for AM and 1 for PM). Usage: Calendar calendar = new GregorianCalendar(); int minute = int year = calendar.get(Calendar.MINUTE); calendar.get(Calendar.YEAR); int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); 19 Example: Getting Date/Time Information from Calendar import java.util.*; public class TestCalendar { public static void main(String[] args) { // Calendar calendar1 = new Calendar() // ERROR!!! Calendar is abstract // Construct a Gregorian calendar for the current date and time Calendar calendar = new GregorianCalendar(); System.out.println("Current time is " + new Date()); System.out.println("YEAR:\t" + calendar.get(Calendar.YEAR)); System.out.println("MONTH:\t" + calendar.get(Calendar.MONTH)); System.out.println("DATE:\t" + calendar.get(Calendar.DATE)); System.out.println("HOUR:\t" + calendar.get(Calendar.HOUR)); System.out.println("HOUR_OF_DAY:\t" + calendar.get(Calendar.HOUR_OF_DAY)); System.out.println("MINUTE:\t" + calendar.get(Calendar.MINUTE)); System.out.println("SECOND:\t" + calendar.get(Calendar.SECOND)); System.out.println("DAY_OF_WEEK:\t" + calendar.get(Calendar.DAY_OF_WEEK)); System.out.println("DAY_OF_MONTH:\t" + calendar.get(Calendar.DAY_OF_MONTH)); System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR)); System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.DAY_OF_YEAR)); 20 20 Example: Getting Date/Time Information from Calendar System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH)); System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR)); System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM)); // Construct a calendar for September 11, 2001 Calendar calendar2 = new GregorianCalendar(2001, 8, 11); System.out.println("September 11, 2001 is a " + dayNameOfWeek(calendar2.get(Calendar.DAY_OF_WEEK))); } public static String dayNameOfWeek(int dayOfWeek) { else else else else else else else } } 21 21 if(dayOfWeek if(dayOfWeek if(dayOfWeek if(dayOfWeek if(dayOfWeek if(dayOfWeek if(dayOfWeek return null; == == == == == == == 1) 2) 3) 4) 5) 6) 7) return return return return return return return "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday"; Example: Getting Date/Time Information from Calendar Console Current time is Fri Feb 03 20:18:09 EST 2012 YEAR: 2012 MONTH: 1 DATE: 3 HOUR: 8 HOUR_OF_DAY: 20 MINUTE: 18 SECOND: 9 DAY_OF_WEEK: 6 DAY_OF_MONTH: 3 DAY_OF_YEAR: 34 WEEK_OF_MONTH: 1 WEEK_OF_YEAR: 5 AM_PM: 1 September 11, 2001 is a Tuesday 22 22 What is an interface? Why is an interface useful? 23 23 An interface is a special Java class that contains only constants and abstract methods. Like abstract classes, they cannot be instantiated using new. The intent of an interface is to specify behavior for objects. For example, you can indicate that the objects are: Comparable Cloneable Serializable Fulfilling any other user-define forms of behavior UML Representation of Classes and Interfaces 24 24 Java classes use single inheritance. An interface is depicted with a relatively similar UML notation. A Match-Making app may want Client to extend person and implement the interface: LoveCompatible as well as Comparable A banking app may want its Client class to extend Person implement Comparable and ignore the LoveCompatible interface. Define an Interface To distinguish an interface from a class, Java uses the following syntax to define an interface: public interface InterfaceName { constant declarations; method signatures; } Example: public interface Edible { /** Describe how to eat */ public abstract String howToEat(); } 25 25 Example: Using Interfaces The Edible interface specifies whether an object is edible and if so, it recommends the best way to eat the object. This behavior is accomplished by letting the class for the object implement the Edible interface using the implements keyword. In the example, the classes Chicken and Fruit implement the Edible interface, however DeadlySpider does not. public interface Edible { /** Describe best way to eat it */ public abstract String howToEat(); } 26 26 Example: Using Interfaces public class TestEdible { public static void main(String[] args) { Object[] objects = {new DeadlySpyder(), new Chicken(), new Apple()}; for (int i = 0; i < objects.length; i++) if (objects[i] instanceof Edible) System.out.println(((Edible)objects[i]).howToEat()); } } class Animal { // Data fields, constructors, and methods omitted here } class Chicken extends Animal implements Edible { public String howToEat() { return "Chicken: Fry it"; } } class DeadlySpider extends Animal { } abstract class Fruit implements Edible { // Data fields, constructors, and methods omitted here } class Apple extends Fruit { public String howToEat() { return "Apple: Make apple cider"; } } 27 27 class Orange extends Fruit { public String howToEat() { return "Orange: Make orange juice"; } } Omitting Modifiers in Interfaces In an interface All data fields are public final static and all methods are public abstract. For this reason, these modifiers can be omitted, as shown below: public interface T1 { public static final int K = 1; public abstract void p(); } Equivalent public interface T1 { int K = 1; void p(); } A constant defined in an interface can be accessed using syntax InterfaceName.CONSTANT_NAME (e.g., T1.k ). 28 28 Example: The Comparable Interface • • Assume you need to compare two Circle objects. You could use a Java fragment such as: if ( circle1.getArea() == circle2.getArea() ){ // do something here... } • However to compare two Client objects you may say if ( client1.getId() == client2.getId() ){ // do something here... } • 29 29 Previous ideas are OK, but perhaps a more general way of comparing objects is needed. For example if ( circle1.compareTo(circle2) == 0 ){ // do something here... } 29 The Comparable Interface When you try to contrast two arbitrary objects, they should be comparable. The Java interface supporting object comparisons is defined as follows: // interface for comparing objects defined in the java.lang package package java.lang; public interface Comparable { public int compareTo(Object o); } Example: int result 30 30 result = firstObject.compareTo(secondObject); 0 if firstObject == secondObject > 0 if firstObject > secondObject < 0 if firstObject < secondObject Why the Comparable Interface ? The fundamental goal of the Comparable interface is to decide how to arrange two objects from an arbitrary class according to an intuitive notion of a ‘natural ordering’, sequencing, or arrangement of those kind of elements. For instance, consider the following sets of objects Integers: Strings: Dates: Rectangles: 31 31 -n < … <-2 < -1 < 0 < 1 < 2 < … n < n + 1 Unicode (alphabetic) collating sequence Jan < Feb < … < Dec < String and Date Classes are Comparable Many classes (e.g., String and Date) in the Java library implement Comparable to define a natural order for the objects. If you examine the source code of these classes, you will see the keyword implements used in the classes, as shown below: public class String extends Object implements Comparable { // class body omitted public class Date extends Object implements Comparable { // class body omitted } } All the following expressions are true new new new new 32 32 String() instanceof String String() instanceof Comparable java.util.Date() instanceof java.util.Date java.util.Date() instanceof Comparable Defining Classes to Implement Comparable Notation: The interface name and the method names are italicized. The dashed lines and hollow triangles are used to point to the interface. GeometricObject Rectangle «interface» java.lang.Comparable +compareTo(o: Object): int ComparableRectangle - The Rectangle class does not provide a method to compare rectangles. However, you can define a new subclass of the Rectangle class that implements Comparable. The instances of this new class are therefore comparable. ComparableRectangle Rectangle = new ComparableRectangle(4, 5); ComparableRectangle rectangle2 = new ComparableRectangle(3, 6); System.out.println( Rectangle,compareTo(rectangle2) ); 33 33 Example: Implement Comparable Rectangles public class ComparableRectangle extends Rectangle implements Comparable { // Construct a ComparableRectangle with specified properties public ComparableRectangle(double width, double height) { super(width, height); } // Implement the compareTo method defined in Comparable public int compareTo(Object obj ) { ComparableRectangle otherRectangle = (ComparableRectangle) obj; if (this.getArea() > otherRectangle.getArea()) return 1; else if (this.getArea() < otherRectangle.getArea()) return -1; else return 0; } 34 34 Example: Implement Comparable Rectangles 1 2 3 4 ... ComparableRectangle cr1 = new ComparableRectangle(10, 20); ComparableRectangle cr2 = new ComparableRectangle(20, 10); ComparableRectangle cr3 = new ComparableRectangle( 4, 50); Rectangle r4 = new Rectangle(10, 20); int int int int int c12 c13 c23 c14 c41 = = = = = cr1.compareTo(cr2); cr1.compareTo(cr3); cr2.compareTo(cr3); cr1.compareTo(r4); r4.compareTo(cr1); // // // // // c12 is 0 c13 is 0 c23 is 0 produces run-time error syntax error Observation: In this example the ComparableRectangles cr1, cr2, and cr3 are equal (they all have different width and height but they have a similar area -which is the criteria used for establishing the comparison among them). 35 35 The Cloneable Interface A class that implements the Cloneable interface is designated cloneable, and its objects can be duplicated using the clone() method defined in the Object class. package java.lang; public interface Cloneable { } Aside: Observe that this interface is empty. A marker interface does not contain constants or methods. 36 Example: Implementing Cloneable Interface We will make a better Rectangle class by allowing it to implement the Clonable and Comparable interfaces. public class Rectangle extends GeometricObject implements Cloneable, Comparable { 1 // variables, constructors, and other methods omitted for editing 2 @Override public int compareTo(Object obj) { Rectangle otherRectangle = (Rectangle) obj; if ( this.getArea() == otherRectangle.getArea() ) return 0; else if ( this.getArea() > otherRectangle.getArea() ) return 1; else return -1; } @Override 3 37 37 } // Override the protected clone method defined in the Object class public Object clone() throws CloneNotSupportedException { return super.clone(); } Example: The Cloneable Interface public static void main(String[] args) throws CloneNotSupportedException { Rectangle r1 = new Rectangle(10, 20, "blue", true); Rectangle r2 = (Rectangle) r1.clone(); System.out.println(" r1==r2 is " + (r1 == r2)); ⟵ prints false System.out.println(" r1.equals(r2) is " + r1.equals(r2)); ⟵ prints false System.out.println(" r1.compareTo(r2) is " + r1.compareTo(r2)); ⟵ prints 0 } Rectangles r1 and r2 are two different objects with identical contents. The clone method in the Object class copies each field from the original object to the target object. If the field is of a primitive type, its value is copied. For example, the value of area ( double type) is copied from r1 to r2. If the field is of an object, the reference of the field is copied. For example, the field dateCreated is of the Date class, so its reference is copied into r2. This process is referred to as a shallow copy rather than a deep copy, meaning 38 that if the field is of an object type, the object’s reference is copied rather than its contents. Example: Overriding the Equals method public class Rectangle extends GeometricObject implements Cloneable, Comparable { // variables, constructors, and other methods omitted for editing ... @Override public boolean equals(Object obj) { Rectangle other = (Rectangle) obj; if ( this.getColor().equals(other.getColor() ) && this.getDateCreated().equals(other.getDateCreated() ) && this.getHeight() == other.getHeight() && this.getWidth() == other.getWidth() ) return true; else return false; } } You may override the Equals method of the Rectangle class to return true each time the contents of the two compared objects are the same. After this change is made the test code in previous page produces: 39 r1==r2 is false r1.equals(r2) is true r1.compareTo(r2) is 0 Interfaces vs. Abstract Classes In an interface, the data must be constants; an abstract class can have all types of data. Each method in an interface has only a signature without implementation; an abstract class can have concrete methods. Variables Constructors • Abstract class No restrictions • All variables • • Interface must be public static final 40 40 Methods Constructors are invoked by subclasses through constructor chaining. An abstract class cannot be instantiated using the new operator. No restrictions. No constructors. An interface cannot be instantiated using the new operator. All methods must be public abstract instance methods Whether to use an interface or a class? In general, a strong is-a relationship that clearly describes a parent-child relationship should be modeled using classes. A weak is-a relationship, also known as a ‘is-kind-of’ relationship, indicates that an object possesses certain property. A weak is-a relationship can be modeled using interfaces. 41 41 For example, a Staff Member is a Person. So their relationship should be modeled using class inheritance. For example, all strings are comparable, so the String class implements the Comparable interface. You can also use interfaces to circumvent single inheritance restriction if multiple inheritance is desired. Becoming a Better IT Professional ACM Code of Ethics and Professional Behavior* Rule 2.1 Strive to achieve the highest quality, effectiveness and dignity in both the process and products of professional work. Excellence is perhaps the most important obligation of a professional.The computing professional must strive to achieve quality and to be cognizant of the serious negative consequences that may result from poor quality in a system. Translating the rule to our context Whenever you write a Java class try to make your ‘best effort’; each professionally crafted Java class is expected to implement the following interfaces: Comparable, Comparator, Cloneable, Serializable 42 42 * For a complete list of rules of conduct see: http://www.acm.org/about/code-of-ethics Wrapper Classes 1. Primitive data types (int, long, float,…) are not used as objects in Java (objects add extra processing overhead). 2. However, many Java methods require the use of objects (not primitive types) as arguments. For example, the add( object) method in the ArrayList . 3. Java offers a convenient way to wrap a primitive data type into an object ( e. g., wrapping int into the Integer class, and wrapping double into the Double class). 4. The corresponding class is called a wrapper class. 5. Java provides Boolean, Character, Double, Float, Byte, Short, Integer, and Long wrapper classes for primitive data types. 43 43 Wrapper Classes 1. The wrapper classes do not have zero-argument constructors. 2. The instances of all wrapper classes are immutable, i.e., their internal values cannot be changed once the objects are created. 44 44 Wrappers: The toString, equals, and hashCode Methods Each wrapper class overrides the toString, equals, and hashCode methods defined in the Object class. 45 45 With the exception of Boolean all the wrapper classes implement the Comparable interface. Therefore the compareTo method is implemented in the wrapper classes (all but Boolean). The Number Class 1. Each numeric wrapper class extends the abstract Number class, which contains the methods doubleValue, floatValue, intValue, longValue, shortValue, byteValue byteValue, shortValue 2. These methods “convert” objects into primitive type values. 3. Subclasses of Number support other methods such as 46 46 valueOf(string) SIZE MAX_VALUE MIN_VALUE Example: Using Class-Wrapper Methods Integer n1 = new Integer(111); Integer n2 = new Integer("111"); Integer n3 = 111; Integer n4 = Integer.MAX_VALUE; Integer n5 = Integer.MIN_VALUE; Integer n6 = Integer.SIZE; Integer n7 = Integer.decode("1234"); Integer n8 = Integer.parseInt("1234"); Integer n9 = Integer.valueOf("1234"); String s1 = String.valueOf(1234); 47 47 Example: Largest Rectangle in a List Objective: Various rectangles are placed in a list. Find the location of the largest . Assume the class Rectangle implements Comparable 1 public static void main(String[] args) { Rectangle rectangle; ArrayList list.add( list.add( list.add( list.add( list.add( list = new ArrayList(); new Rectangle(10,20) ); new Rectangle(10,21) ); new Rectangle(11,15) ); new Rectangle(12,21) ); new Rectangle(15,10) ); for (int i=0; i<list.size(); i++) { rectangle = (Rectangle)list.get(i); System.out.println( "Loc: " + i + "\t" + rectangle.toString() ); } 2 int locBiggest = FindPositionBiggestRectangle(list); rectangle = (Rectangle)list.get(locBiggest); System.out.println ( "\nSolution\n" + locBiggest + "\n" + rectangle.toString() ); }//main 48 48 Example: Largest Rectangle in a List Objective: Various rectangles are placed in a list. Find the location of the largest . Assume the class Rectangle implements Comparable private static int FindPositionBiggestRectangle(ArrayList list) { int position = -1; if (list.size() == 0 ) return position; Rectangle largest = (Rectangle) list.get(0); Rectangle current; for (int i=1; i<list.size(); i++){ current = (Rectangle) list.get(i); if ( current.compareTo(largest) > 0){ position = i; largest = current; } } return position; } 49 49 Example: Largest Rectangle in a List 1 2 50 50 Console Loc: 0 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 20.0 Width: 10.0 Perimeter: Loc: 1 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 21.0 Width: 10.0 Perimeter: Loc: 2 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 15.0 Width: 11.0 Perimeter: Loc: 3 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 21.0 Width: 12.0 Perimeter: Loc: 4 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 10.0 Width: 15.0 Perimeter: 60.0 Area: 200.0 62.0 Area: 210.0 52.0 Area: 165.0 66.0 Area: 252.0 50.0 Area: 150.0 Solution 3 >>> Rectangle white created on Sat Feb 04 22:19:21 EST 2012 color: white and filled: false >>> Height: 21.0 Width: 12.0 Perimeter: 66.0 Area: 252.0 BigInteger and BigDecimal If you need to compute with very large integers or high precision floating-point values, you can use the BigInteger and 51 51 BigDecimal An instance of BigInteger can represent an integer of any size. The largest integer of the long type is Long. MAX_ VALUE ( i. e., 9223372036854775807). Both are part of the java.math package, they extend the Number class and implement the Comparable interface. Case Study: The Rational Class ( your turn ! ) java.lang.Number +byteValue(): byte +shortValue(): short +intValue(): int +longVlaue(): long +floatValue(): float +doubleValue():double java.lang.Comparable compareTo(Object): int Rational -numerator: long -denominator: long +Rational() +Rational(numerator: long, denominator: long) +getNumerator(): long +getDenominator(): long +add(secondRational: Rational): Rational +multiply(secondRational: Rational): Rational +subtract(secondRational: Rational): Rational +divide(secondRational: Rational): Rational +toString(): String -gcd(n: long, d: long): long 1 52 52 1 Add, Subtract, Multiply, Divide JSON Encoding JSON Encoding 53 53 • JSON stands for JavaScript Object Notation. This is a text-based “human-readable” and “open-format” standard intended for the representation of structured data. JSON’s original purpose is to act as a language-independent data interchange vehicle. • Objects are written in JSON as a curly-braced ({ }) delimited string. The various properties inside the object are recursively annotated as a comma separated set of ‘key:value’ pairs. • Array elements are enclosed in square brackets ([ ]) and separated by commas. • JSON is language and platform independent and it is available for a large number of programming environments [Jackson, Gson, Jayrock-Ref-Microsoft]. JSON Encoding Why JSON ? Positive features: (1) transparency – the developer can see objects as plain text, (2) it can be used on cross-platform applications involving a variety of operating systems and programming languages, (3) It is relatively easy to use and understand, (4) No need to posses original source code to add Serializable annotation support, (5) The technology is already well understood, diffused, and supported . 54 54 CAUTION is needed when JSON is used as a data-interchange vehicle over the data network, because as any plain-text message, there are some risks of eavesdropping. JSON Encoding 1. Encoding Simple Data Types // Create an instance of a Gson-JSON encoder Gson gson = new Gson(); // must import com.google.gson.* API // PART1. serialize primitive data elements (strings, numbers) String jsonString = gson.toJson("Game of Thrones"); String javaValue1 = gson.fromJson(jsonString, String.class); System.out.println(javaValue1); // prints “Game of thrones” // PART2. deserialize primitive data elements String jsonString2 = gson.toJson(4321); Integer javaValue2 = gson.fromJson(jsonString2, Integer.class); System.out.println(jsonString2); // prints 4321 55 55 Download API (Jar) from: https://code.google.com/p/google-gson/downloads/list Download JSON Encoding 2. Encoding Simple Objects // PART1. Serialize a single Person object Gson gson = new Gson(); Person person0 = new Person("Daenerys Targaryen", 18); jsonString = gson.toJson(person0); System.out.println("Json string: " + jsonString ); // PART2. Deserialize a single Person object Person personDecoded = gson.fromJson(jsonString, Person.class); System.out.println("Java object: " + personDecoded ); The previous fragment produces the following output: Json string: {"name":"Daenerys Targaryen","age":18} 56 56 Java object: Person(name=Daenerys Targaryen, age=18) JSON Encoding 3. Encoding a List of Objects // PART1. create a (Generic) list of Person objects ArrayList<Person> lstPerson = new ArrayList<Person>(); lstPerson.add(new Person("Daenerys Targaryen", 17)); lstPerson.add(new Person("Tiryion Lannister", 30)); lstPerson.add(new Person("Arya Stark", 11)); // convert Java collection to JSON string String jsonList = gson.toJson(lstPerson); System.out.println("Json list: " + jsonList ); // PART2. use Java reflection to find the list's type Type arrPersonType = new TypeToken<ArrayList<Person>>(){}.getType(); ArrayList<Person> lst2 = gson.fromJson(jsonList, arrPersonType); System.out.println("Java list:" + lst2 ); The list of Person objects is encoded as follows: Json list: 57 57 [ {"name":"Daenerys Targaryen","age":18}, {"name":"Tiryion Lannister","age":30}, {"name":"Arya Stark","age":11} ] JSON Encoding 3. Encoding a List of Objects Json list • • • • 58 58 (cont.) [ {"name":"Daenerys Targaryen","age":18}, {"name":"Tiryion Lannister","age":30}, {"name":"Arya Stark","age":11} ] A JSON array is delimited by square-braces ([ ]). Each element in the array is a Person object including the attributes “name” and “age”. Objects are enclosed inside curly-braces({ }) and separated by commas. The Gson TypeToken class is used to extract the collection’s generic type information JSON Encoding 4. Encoding a Subclass Assume the PersonHouse class is an extension of the Person class. It contains the additional house attribute. Consider the following example: // PART1. Encode subclass PersonHouse person4 = new PersonHouse("Jon Snow", 23, "Stark"); String jsonPerHome = gson.toJson(person4); System.out.println("Json subclass: " + jsonPerHome); // PART2. Decode string PersonHouse person4again = gson.fromJson(jsonPerHome, PersonHouse.class); System.out.println("Java subclass: " + person4again); The output produced by this fragment is 59 59 Json subclass: {"House":"Stark","name":"Jon Snow","age":23} Java subclass: PersonHouse( House=Stark Person(name=Jon Snow, age=23) ) JSON Encoding 5. Encoding a 1:Many Relationship Assume the existence of a House class including the properties: houseName and characters (represented as a dynamic list of Person objects). ArrayList<Person> theStarks.add(new theStarks.add(new theStarks.add(new theStarks = new ArrayList<Person>(); Person("Catelyn Stark", 40)); Person("Sansa Stark", 14)); Person("Bran Stark", 9)); //PART1. Encoding complex 1:m class House starkHouse = new House("Stark", "Winterfell", theStarks); String jsonHouse = gson.toJson(starkHouse); System.out.println("\nJson House: " + jsonHouse); //PART2. Decoding complex 1:m class House javaHouse = gson.fromJson(jsonHouse, House.class); System.out.println("Java House: " + javaHouse); The output produced by this example is: Json House: 60 60 {"houseName":"Stark","location":"Winterfell", "personLst":[{"name":"Catelyn Stark","age":40}, {"name":"Sansa Stark","age":14}, {"name":"Bran Stark","age":9}]} JSON Encoding Alternative Decoding based on traversing the JSON data structure looking for jsonElements (which could be: jsonObject, jsonArray, or jsonPrimitive tokens) private static void jsonHouseNodeParsing(String jsonHouseStr) { String result = ""; try { JsonElement jelement = new JsonParser().parse(jsonHouseStr); JsonObject jobject = jelement.getAsJsonObject(); String jHouseName = jobject.get("houseName").toString(); String jLocation = jobject.get("location").toString(); // JsonPrimitive jLocation = jobject.getAsJsonPrimitive("location"); System.out.println(jHouseName + "\n" + jLocation); JsonArray jarray = jobject.getAsJsonArray("personLst"); 61 61 for (int i = 0; i < jarray.size(); i++) { jobject = jarray.get(i).getAsJsonObject(); result = jobject.get("name").toString() + " " + jobject.get("age").toString(); System.out.println(" " + result); } } catch (Exception e) { System.out.println(e.getMessage()); } }// jsonNodeParsing JSON Encoding Alternative Decoding Approach (continuation) Example using alternative decoding JSON encoded string {"houseName":"Stark", "location":"Winterfell", "personLst":[ {"name":"Catelyn Stark","age":40}, {"name":"Sansa Stark","age":14}, {"name":"Bran Stark","age":9} ] } 62 62 Decoded Nodes "Stark" "Winterfell" "Catelyn Stark" 40 "Sansa Stark" 14 "Bran Stark" 9