Workshop: Lab 8 Engineering Software 1 Lab 8: Classes and Objects: A deeper look Learning Objectives In this lab exercise you will learn: Encapsulation and data hiding. The notions of data abstraction and abstract data types (ADTs). To use keyword this. To use static variables and methods. To import static members of a class. To use the enum type to create sets of constants with unique identifiers. How to declare enum constants with parameters. Lab Work General Note: Study every exercise and for each of them draw a structure diagram. Type in all these programs and run them inside your Java development kit. In your log-book take note of all the results from the execution of these programs and write down any problems that you had to solve. For each program of the exercises, explain clearly what each section of the program is doing. You may need to perform a walk-through, line by line, where this is appropriate. Record all your explanations in the log-book. Remember to put a date in your log-book and also to offer some discussions and a brief conclusion after every week’s work. Finally, complete the programming assignments at the end of the exercises, then enter comments in your logbook as you are doing this and save to your floppy disk/CD for submission with your logbook. Background • Every class you declare represents a new type in Java. • The public methods of a class are also known as the class's public services or public interface. The primary purpose of public methods is to present to the class's clients a view of the services the class provides. Clients of the class need not be concerned with how the class accomplishes its tasks. For this reason, private class members are not directly accessible to the class's clients. • An object that contains consistent data has data values that are always kept in range. • A value passed to a method to modify an instance variable is a correct value if that value is in the instance variable's allowed range. A correct value is always a consistent value, but a consistent value is not correct if a method receives an out- of-range value and sets it to a consistent value to maintain the object in a consistent state. Stavros Dimitriou ©London South Bank University 1 Workshop: Lab 8 Engineering Software 1 • String class static method format is similar to method System.out.printf except that format returns a formatted String rather than displaying it in a command window. • All objects in Java have a toString method that returns a String representation of the object. Method toString is called implicitly when an object appears in code where a String is needed. • A non-static method of an object implicitly uses keyword this to refer to the object's instance variables and other methods. Keyword this can also be used explicitly. • The compiler produces a separate file with the .class extension for every compiled class. • If a method contains a local variable with the same name as one of its class's fields, the local variable shadows the field in the method's scope. The method can use the this reference to refer to the shadowed field explicitly. • Overloaded constructors enable objects of a class to be initialized in different ways. The compiler differentiates overloaded constructors by their signatures. • Every class must have at least one constructor. If none are provided, the compiler creates a default constructor that initializes the instance variables to the initial values specified in their declarations or to their default values. • If a class declares constructors, the compiler will not create a default constructor. To specify the default initialization for objects of a class with multiple constructors, the programmer must declare a no-argument constructor. • Set methods are commonly called mutator methods because they typically change a value. Get methods are commonly called accessor methods or query methods. A predicate method tests whether a condition is true or false. • A class can have references to objects of other classes as members. Such a capability is called composition and is sometimes referred to as a has-a relationship. • All enum types are reference types. An enum type is declared with an enum declaration, which is a comma-separated list of enum constants. The declaration may optionally include other components of traditional classes, such as constructors, fields and methods. • enum types are implicitly final, because they declare constants that should not be modified. • enum constants are implicitly static. • Any attempt to create an object of an enum type with operator new results in a compilation error. • enum constants can be used anywhere constants can be used, such as in the case labels of switch statements and to control enhanced for statements. • Each enum constant in an enum declaration is optionally followed by arguments which are passed to the enum constructor. • For every enum, the compiler generates a static method called values that returns an array of the enum's constants in the order in which they were declared. • EnumSet static method range takes two parameters—the first enum constant in a range and the last enum constant in a range—and returns an that EnumSet contain all the constants between these two constants, inclusive. • Every class in Java has the methods of class Object, one of which is the finalize method. • The Java Virtual Machine (JVM) performs automatic garbage collection to reclaim the memory occupied by objects that are no longer in use. When there are Stavros Dimitriou ©London South Bank University 2 Workshop: Lab 8 Engineering Software 1 no more references to an object, the object is marked for garbage collection by the JVM. The memory for such an object can be reclaimed when the JVM executes its garbage collector. • The finalize method is called by the garbage collector just before it reclaims the object's memory. Method finalize does not take parameters and has return type void. • The garbage collector may never execute before a program terminates. Thus, it is unclear if, or when, method finalize will be called. • A static variable represents classwide information that is shared among all objects of the class. • Static variables have class scope. A class's public static members can be accessed through a reference to any object of the class, or they can be accessed by qualifying the member name with the class name and a dot (.). A class's private static class members can be accessed only through methods of the class. • static class members exist even when no objects of the class exist—they are available as soon as the class is loaded into memory at execution time. To access a private static member when no objects of the class exist, a public static method must be provided. • System class static method gc indicates that the garbage collector should make a best-effort attempt to reclaim objects that are eligible for garbage collection. • A method declared static cannot access non-static class members, because a static method can be called even when no objects of the class have been instantiated. • The this reference cannot be used in a static method. • A static import declaration enables programmers to refer to imported static members without the class name and a dot (.). A single static import declaration imports one static member, and a static import on demand imports all static members of a class. • In the context of an application, the principle of least privilege states that code should be granted only the amount of privilege and access that the code needs to accomplish its designated task. • Keyword final specifies that a variable is not modifiable—in other words, it is constant. Constants can be initialized when they are declared or by each of a class's constructors. If a final variable is not initialized, a compilation error occurs. • Software is constructed from existing, well-defined, carefully tested, well- documented, portable, widely available components. Software reusability speeds the development of powerful, high-quality software. Rapid application development (RAD) is of great interest today. • Java programmers now have thousands of classes in the Java API from which to choose to help them implement Java programs. The Java API classes enable Java programmers to bring new applications to market faster by using preexisting, tested components. • The client of a class cares about the functionality the class offers, but not about how the functionality is implemented. This is referred to as data abstraction. Although programmers may know the details of a class's implementation, they should not write code that depends on these details. This enables a class to be replaced with another version without affecting the rest of the system. • An abstract data type (ADT) consists of a data representation and the operations that can be performed on that data. Stavros Dimitriou ©London South Bank University 3 Workshop: Lab 8 Engineering Software 1 • Each class in the Java API belongs to a package that contains a group of related classes. Packages help manage the complexity of application components and facilitate software reuse. • Packages provide a convention for unique class names that helps prevent class name conflicts. • Before a class can be imported into multiple applications, the class must be placed in a package. There can be only one package declaration in each Java source-code file, and it must precede all other declarations and statements in the file. • Every package name should start with your Internet domain name in reverse order. After the domain name is reversed, you can choose any other names you want for your package. • When compiling a class in a package, the javac command-line option -d specifies where to store the package and causes the compiler to create the package's directories if they do not exist. • The package name is part of the fully qualified class name. This helps prevent name conflicts. • A single-type-import declaration specifies one class to import. A type-import-on- demand declaration imports only the classes that the program uses from a particular package. • The compiler uses a class loader to locate the classes it needs in the classpath. The classpath consists of a list of directories or archive files, each separated by a directory separator. • The classpath for the compiler and JVM can be specified by providing the - classpath option to the javac or java command, or by setting the CLASSPATH environment variable. The classpath for the JVM can also be specified via the -cp command-line option. If classes must be loaded from the current directory, include a dot (.) in the classpath. • If no access modifier is specified for a method or variable when it is declared in a class, the method or variable is considered to have package access. Stavros Dimitriou ©London South Bank University 4 Workshop: Lab 8 Engineering Software 1 Part A: Reinforce your understanding of key Java programming concepts Exercise 1: After reading the background above along with lecture notes, answer the given questions. The questions are intended to test and reinforce your understanding of key concepts. For each term in the left column, write the letter for the description from the right column that best matches the term. Exercise 2: Answer the following questions in your logbook. Your answers should be as concise as possible; aim for two or three sentences. 1. Why would a class provide overloaded constructors? 2. What are some advantages of creating packages? 3. What is the purpose of a constructor? 4. What is the purpose of a set method? 5. What is the purpose of a get method? 6. What is an abstract data type? Stavros Dimitriou ©London South Bank University 5 Workshop: Lab 8 Engineering Software 1 Part B: Java programs For each of the given program segments, read the code and write the output in your logbook. [ Note: Do not execute these programs on a computer.] For Exercises 1–3 use the following declaration of class Time2 : // Fig. 8.5: Time2.java // Time2 class declaration with overloaded constructors. public class Time2 { private int hour; // 0 - 23 private int minute; // 0 - 59 private int second; // 0 - 59 // Time2 no-argument constructor: initializes each instance variable // to zero; ensures that Time2 objects start in a consistent state public Time2() { this( 0, 0, 0 ); // invoke Time2 constructor with three arguments } // end Time2 no-argument constructor // Time2 constructor: hour supplied, minute and second defaulted to 0 public Time2( int h ) { this( h, 0, 0 ); // invoke Time2 constructor with three arguments } // end Time2 one-argument constructor // Time2 constructor: hour and minute supplied, second defaulted to 0 public Time2( int h, int m ) { this( h, m, 0 ); // invoke Time2 constructor with three arguments } // end Time2 two-argument constructor // Time2 constructor: hour, minute and second supplied public Time2( int h, int m, int s ) { setTime( h, m, s ); // invoke setTime to validate time } // end Time2 three-argument constructor // Time2 constructor: another Time2 object supplied public Time2( Time2 time ) { // invoke Time2 three-argument constructor this( time.getHour(), time.getMinute(), time.getSecond() ); } // end Time2 constructor with a Time2 object argument // Set Methods // set a new time value using universal time; ensure that // the data remains consistent by setting invalid values to zero public void setTime( int h, int m, int s ) { setHour( h ); // set the hour setMinute( m ); // set the minute setSecond( s ); // set the second } // end method setTime // validate and set hour public void setHour( int h ) { hour = ( ( h >= 0 && h < 24 ) ? h : 0 ); } // end method setHour Stavros Dimitriou ©London South Bank University 6 Workshop: Lab 8 Engineering Software 1 // validate and set minute public void setMinute( int m ) { minute = ( ( m >= 0 && m < 60 ) ? m : 0 ); } // end method setMinute // validate and set second public void setSecond( int s ) { second = ( ( s >= 0 && s < 60 ) ? s : 0 ); } // end method setSecond // Get Methods // get hour value public int getHour() { return hour; } // end method getHour // get minute value public int getMinute() { return minute; } // end method getMinute // get second value public int getSecond() { return second; } // end method getSecond // convert to String in universal-time format (HH:MM:SS) public String toUniversalString() { return String.format( "%02d:%02d:%02d", getHour(), getMinute(), getSecond() ); } // end method toUniversalString // convert to String in standard-time format (H:MM:SS AM or PM) public String toString() { return String.format( "%d:%02d:%02d %s", ( (getHour() == 0 || getHour() == 12) ? 12 : getHour() % 12 ), getMinute(), getSecond(), ( getHour() < 12 ? "AM" : "PM" ) ); } // end method toString } // end class Time2 Exercise 1: 1. What is the output of the following code segment? 2. What is the output of the following code segment? Stavros Dimitriou ©London South Bank University 7 Workshop: Lab 8 Engineering Software 1 3. What is the output of the following code segment? For questions 4–6 use the following declaration of class Person: Stavros Dimitriou ©London South Bank University 8 Workshop: Lab 8 Engineering Software 1 4. What is the output of the following code segment? 5. What is the output of the following code segment? 6. What is the output of the following code segment? Stavros Dimitriou ©London South Bank University 9