This activity requires the file: money.txt
Static class members
Often we need to have a global information that is visible to everybody in a program. These “global” variables must be defined as static class members.
In our example, the department of treasury creates certain number of dollars per year. This information is public and visible to the public. Therefore, it is needed to have a variable to keep track of how many times the department of treasury prints a dollar bill. We introduce this variable as a counter in Dollar:
public class Dollar{
// define the fields
private int denomination;
private String face;
private String serial;
private int year;
public static int counter;
}
The variable counter is:
public, which means that every entity outside of the class Dollar can access it
static, which means that can be reachable in any context, including the main on the DepOfTreasury
int, since we will keep track of each print of Dollar, must be a whole number
We have seen this behavior in the following:
> Math.PI
3.141592653589793
> Math.pow(2,3)
8.0
In addition to create this variable, every time we create a new instance of the Dollar, that counter must increase by one. Therefore, in all the constructors we need to add the statement:
counter++;
For example, in our default constructor, it will look as follows:
// default constructor
public Dollar(){
denomination = 0;
face = null;
serial = null;
year = 0;
counter++;
}
By going to the DepOfTreasury, we can add the following statements
Dollar d1 = new Dollar(1,"Washington","F54931740C",2006);
System.out.println("Total: "+d1.counter);
Dollar d2 = new Dollar(20,"Jackson","MK35065653B",2013);
System.out.println("Total: "+d2.counter);
These statements will print the following:
Total: 1
Total: 2
If we change the code as follows:
Dollar d1 = new Dollar(1,"Washington","K75719608D",2013);
Dollar d2 = new Dollar(5,"ML12944865C",2002);
System.out.println("Total: "+d1.counter);
This will generate the following:
Total: 2
Regardless of which object you are calling the static class member; it will reflect the changes that has been done by the same static members. Since we are in the same static context, we keep adding counter++ every time we run the program.
Dollar d1 = new Dollar(1,"Washington","F54931740C",2006);
Dollar d2 = new Dollar(20,"Jackson","MK35065653B",2013);
System.out.println("Total: "+Dollar.counter);
In the department of treasury, we can perform several operations. Since in this class we are creating Dollar objects and probably we will create more than two instances, then we need a holder to store all the instances of Dollars. The natural and human way to store the Dollars into a wallet. We have the following:
1. public static void main(String [] args){
2. Dollar d1 = new Dollar(1,"Washington","K75719608D",2013);
3. Dollar d2 = new Dollar(5,"ML12944865C",2002);
4. Dollar d3 = new Dollar(10,"B19811820K",2005);
5. Dollar d4 = new Dollar(100,"C98798451S",1999);
6. Dollar[] wallet = {d1,d2,d3,d4};
7. }
Notice that from Line 2 to 5, we define 4 different instances of Dollars. Now we will store them in a wallet (by defining an array of Dollars) as shown in Line 6.
d1 d2 d3 d4
0 1 2 3
Now that we know how to store Dollar objects into an array, we can now create a method called getTotal(). The method will take as an argument an array of Dollars and it will calculate the total amount of dollars we have in the wallet. The first attempt to create the method looks as follows:
1. public static int getTotal(Dollar[] array){
2. int total = 0; // variable to accumulate
3. for(int i = 0; i < array.length; i++){// BFF of arrays
4. total += array[i]; // add each value into sum
5. }
6. return total; // report back the sum
7. }
If we attempt to run the previous code, it will generate the following syntax error as:
1 error found:
File: ...\DepOfTreasury.java [line: 4]
Error: bad operand types for binary operator '+'
first type: int
second type: Dollar
The error is suggesting that on Line 4 we are trying to perform an operation with an object and an int. Which is not possible. Remember that the array wallet contains Dollar objects inside of each subscript. Therefore, we need to check the denomination in each subscript from the array. Then we can use the power of the getters to extract specific information, i.e., getDenomination().
The resulting method now looks as follows:
1. public static int getTotal(Dollar[] array){
2. int total = 0; // variable to accumulate
3. for(int i = 0; i < array.length; i++){// BFF of arrays
4. total += array[i].getDenomination();// add each value into sum
5. }
6. return total; // report back the sum
7. }
Textual Representation of the Dollar Object.
Let us try to write a method called getWalletInfo(). This method will take an array of Dollars as a parameter, and it will print the content of each Dollar that is in the wallet. The representation that we would like to have for each dollar object is:
"$"+denomination face serial #, year and is ## years old!";
Let us try to print what is inside the wallet just by using the simple for loop.
public static void getWalletInfo (Dollar[] array){
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
}
If we attempt to run the program, we will get:
Dollar@6759e5b2
Dollar@16d86ead
Dollar@957f5c9
Dollar@3f40b923
This is the hexadecimal memory address location for each object Dollar. We have seen this when you try to print an array.
Solution: We can use the method printInfo() that we implemented in Dollar. However, there is a more natural way to solve this situation. This is by overwriting the toString() method.
The toString() method is one of the eleven methods that is inherited from the ancestor Object in Java. Inheritance is another feature of OOP that will be discussed in the next section. The toString() method provides the textual representation of your object.[7]
From the above list, we recognize the equals method, when we compare two Strings (i.e., two objects). By overwriting the method toString() in the class, will allows to provide our own textual representation for the specific object we are implementing. In our case, Dollar.
Therefore, we can now go to the Dollar and overwrite the method inherited from the class Object as follows:
public String toString(){
String s = "$"+denomination+" Face: "+
face+" #"+serial+" Y:"+year+" and is "+
getAge()+" years old!";
return s;
}
Since we overwrote the method toString() in the class Dollar, now we have the following result:
$1 Face: Washington Y: 2006 and is years old!
$20 Face: Jackson Y: 2013 and is years old!
$10 Face: Hamilton Y: 2011 and is years old!
$5 Face: Franklin Y: 1998 and is years old!
Help us to identify members from a specific class. It also helps us to avoid conflict of variable names. The book calls it shadowing. It also helps to exercise the power of method overloading (a.k.a. polymorphism).
Variable Names. Recall the setters. We used a different name for the parameter that belongs to the fields.
E.g.,
public void setDenomination(int denomination){
denomination = denomination;
}
The left side of the = signs refers to the field. The right side of the = refers to the parameter. In order to avoid any confusion in identifying which variable is which, we use the word this to identify the field that belongs to THIS class.
public void setDenomination(int denomination){
this.denomination = denomination;
}
Method/Constructor overloading
Notice that we have several constructors. All of them basically do the same functionality – i.e., initialize all the fields of the class. We noticed that there is a redundancy of coding in the constructors. For example, let us examine customized constructor #1 and customized constructor #2.
// customized constructor #1
public Dollar(int d, String f, String s, int y){
denomination = d;
face = f;
serial = s;
year = y;
counter++;
}
// customized constructor #2
public Dollar(int d, String s, int y){
denomination = d;
serial = s;
year = y;
if(d == 1){
face = "Washington";
// … code omitted for space …
counter++;
}
}
There is a lot of redundancy between both constructors. We can avoid redundancy by using the keyword this. The keyword “this” will identify/map inside of THIS class a method/constructor that satisfies the number of parameters you are passing through.
For example, in customized constructor #1
// customized constructor #1
public Dollar(int newDenomination, String newFace, String newSerial, int newYear){
this(newDenomination, newSerial, newYear);
}
AP CS A
[Using Methods]
MOD-3.B Create an inheritance relationship from a subclass to the superclass.
MOD-3.B.1 A class hierarchy can be developed by putting common attributes and behaviors of related classes into a single class called a superclass.
MOD-3.B.2 Classes that extend a superclass, called subclasses, can draw upon the existing attributes and behaviors of the superclass without repeating these in the code.
MOD-3.B.3 Extending a subclass from a superclass creates an “is-a” relationship from the subclass to the superclass.
MOD-3.B.4 The keyword extends is used to establish an inheritance relationship between a subclass and a superclass. A class can extend only one superclass.
MOD-3.C.3 If S is a subclass of T, then a reference of type T can be used to refer to an object of type T or S.
MOD-3.C.4 Declaring references of type T, when S is a subclass of T, is useful in the following declarations— ● Formal method parameters ● arrays — T[] var ArrayList<T> var.
MOD-3.D Call methods in an inheritance relationship.
MOD-3.D.1 Utilize the Object class through inheritance.
MOD-3.D.2 At compile time, methods in or inherited by the declared type determine the correctness of a non-static method call.
MOD-3.D.3 At run-time, the method in the actual object type is executed for a non-static method call.
MOD-3.E Call Object class methods through inheritance.
MOD-3.E.1 The Object class is the superclass of all other classes in Java.
MOD-3.E.4 Subclasses of an Object often override the equals and toString methods in class-specific implementations
MOD-3.E.2 The Object class is part of the java.lang package.
MOD-3.E.3 The following Object class methods and constructors—including what they do and when they are used—are part of the Java Quick Reference— ● boolean equals(Object other) ● boolean equals(Object other)
[Superclass Constructor and Methods]
MOD-3.B.5 Constructors are not inherited.
MOD-3.B.6 The superclass constructor can be called from the first line of a subclass constructor by using the keyword super and passing appropriate parameters.
MOD-3.B.7 The actual parameters passed in the call to the superclass constructor provide values that the constructor can use to initialize the object’s instance variables.
MOD-3.B.8 When a subclass’s constructor does not explicitly call a superclass’s constructor using super, Java inserts a call to the superclass’s no-argument constructor.
MOD-3.B.9 Regardless of whether the superclass constructor is called implicitly or explicitly, the process of calling superclass constructors continues until the Object constructor is called. At this point, all of the constructors within the hierarchy execute beginning with the Object constructor.
MOD-3.B.10 Method overriding occurs when a public method in a subclass has the same method signature as a public method in the superclass.
MOD-3.B.11 Any method that is called must be defined within its own class or its superclass.
MOD-3.B.12 A subclass is usually designed to have modified (overridden) or additional methods or instance variables.
MOD-3.B.13 A subclass will inherit all public methods from the superclass; these methods remain public in the subclass.
MOD-3.B.14 The keyword super can be used to call a superclass’s constructors and methods.
MOD-3.B.15 The superclass method can be called in a subclass by using the keyword super with the method name and passing appropriate parameters.
MOD-3.C Define reference variables of a superclass to be assigned to an object of a subclass in the same hierarchy.
MOD-3.C.1 When a class S “is-a” class T, T is referred to as a superclass, and S is referred to as a subclass.
MOD-3.C.2 If S is a subclass of T, then assigning an object of type S to a reference of type T facilitates polymorphism.
[Random Numbers]
CON-1.D.4 The values returned from Math.random can be manipulated to produce a random int or double in a defined range
[Documentation Comments]
MOD-2.C.3 A precondition is a condition that must be true just prior to the execution of a section of program code in order for the method to behave as expected. There is no expectation that the method will check to ensure preconditions are satisfied.
MOD-2.C.4 A postcondition is a condition that must always be true after the execution of a section of program code. Postconditions describe the outcome of the execution in terms of what is being returned or the state of an object.
MOD-2.C.5 Programmers write method code to satisfy the postconditions when preconditions are met.
Explain the importance of algorithms in the problem-solving process.
Demonstrate how a problem may be solved by multiple algorithms, each with different properties.
Read a given program, and explain what it does
Trace the flow of control during the execution of a program (both correct and incorrect).
Use appropriate terminology to identity elements of a program (e.g., identifier, operator, operand)
Reading and explaining code
Basic concepts such as variables, primitive data types, expression evaluation, assignment, etc.
Apply basic programming style guidelines to aid readability of programs such as comments, indentation, proper naming of variables, etc.
Basic testing (perhaps using suitable frameworks) including test case design
Basic concepts such as variables, primitive data types, expression evaluation, assignment, etc.
Key modularity constructs such as functions (and methods and classes, if supported in the language) and related concepts like parameter passing, scope, abstraction, data encapsulation, etc.
When and how to use standard data structures
Structured data types available in the chosen programming language like sequences (e.g., arrays, lists), associative containers (e.g., dictionaries, maps), others (e.g., sets, tuples) and when and how to use them.