====== Objects in Methods, Objects as Class Fields, Arrays of Objects ======
----
===== Objects in Methods =====
* We will examine the topic of methods that return objects, and also objects passed to methods as input parameters.
* We will design and implement a //Fraction// class, ...
* ... and then we will write methods to add & subtract two //Fraction// objects.
* This is the way we want to be able to work with //Fraction// class objects:
// Construct one fraction and print it
Fraction f1;
f1 = new Fraction(2, 3);
System.out.println(f1);
// Add two Fraction objects to get a sum Fraction object
Fraction f2;
f2 = new Fraction(1, 6);
Fraction f3;
f3 = addFraction(f1, f2);
System.out.println(f1 + " + " + f2 + " = " + f3);
* In the code above, we use an //addFraction// method that takes two //Fraction// objects (f1, f2) as input and returns a //Fraction// object that we can assign to another //Fraction// object (f3).
* The output of the above //System.out.println()// is:
2/3 + 1/6 = 5/6
* Notice that 5/6 is a reduced fraction, meaning that somewhere in the //Fraction// class, there needs to be some kind of //reduce()// method, so the reduced form of a fraction is stored in the class.
* The //addFraction// method is shown below.
* In order to return a //Fraction// object, the //addFraction// method needs to call the //Fraction// constructor with the numerator and denominator of the //Fraction// that is the sum of //Fractions// one and two (last few lines of the code below):
public static Fraction addFraction( Fraction one, Fraction two )
{
// Compute common denominator:
int dd = one.getDenominator() * two.getDenominator();
// Cross multiply and add:
int nn = one.getNumerator() * two.getDenominator() +
two.getNumerator() * one.getDenominator();
Fraction sum = new Fraction( nn, dd );
return sum;
//
// or skip using a sum variable by doing this:
//return new Fraction( nn, dd );
}
* The //subtractFraction// method is not substantially different from //addFraction//.
----
===== Objects as Class Fields =====
* We will examine the topic of using an object of one class as a field in a different, but related class.
* Objects in the real world are often composed of smaller related objects, for example, an account holder object within a bank account object...
* We will design and implement an //AccountHolder// class, ...
* ... and then we will use an //AccountHolder// class object as a field in a //BankAccount// class.
* ... and then we will test the //BankAccount// class in a program.
* Here are the relevant sections of the //AccountHolder// class.
public class AccountHolder
{
private String firstName;
private String lastName;
private int age;
// Constructors:
/**
* Constructor #1
* @param first name
* @param last name
* @param age
*/
public AccountHolder( String fn, String ln, int ag ) {
firstName = fn;
lastName = ln;
age = ag;
}
/*
* Constructor #2 (default)
*/
public AccountHolder()
{
}
// Methods:
// Write get and set methods for firstName, lastName, age below.
...
} // end class
* The //BankAccount// class will use an //AccountHolder// object to represent an account holder:
public class BankAccount
{
private int acctnum;
private double balance;
private AccountHolder customer;
...
...
} // end class
* The //BankAccount// constructor will look like this:
/**
* Constructor#1 for objects of class BankAccount
* @param acct
* @param bal
* @param firstname of customer
* @param lastname of customer
* @param age of customer
*/
public BankAccount( int acct, double bal, String firstname, String lastname, int age )
{
// Write code to set account number, balance and customer name and age:
acctNum = acct;
balance = bal;
// Since customer is an object, initializing it requires calling a constructor;
// Use last 3 input parameters to construct the customer object.
customer = new AccountHolder( firstname, lastname, age );
}
* When a BankAccount object is constructed using the above constructor, a customer object will also be constructed.
(Code in main() method of TestBankAccount.java)
BankAccount myAccount;
myAccount = new BankAccount( 1, 8000.00, "Joe", "Chung", 56 );
// The last 3 constructor arguments, "Joe", "Chung", and 56 will
// be passed to the AccountHolder constructor to construct a
// customer object within the myAccount object.
==== Working with objects as instance variables ====
* If a class has an object instance variable, the accessor methods (get/set methods) may have to be written and used a bit differently.
* A BankAccount method to return the customer object's information might look like this:
/**
* Get method for customer's information
* @return info
*/
public String getCustomerInfo()
{
// Use get methods defined in the AccountHolder class:
String info = "Name:\t" + customer.getFirstName() + " " + customer.getLastName() + "\n" +
"Birthday:\t" + costomer.getBirthDay() + "\n" +
"Age:\t" + customer.getAge() + "\n" +;
return info;
}
* A BankAccount method can be written to return the actual customer object like this:
/**
* Get method for customer
* @return customer, an AccountHolder object
*/
public AccountHolder getCustomer()
{
return customer;
}
* The getCustomer method can then be used to access customer information using customer get methods.
* This requires an additional dot (.) to be used to access AccountHolder methods.
(Code in main() method of TestBankAccount.java)
// Get bankaccount holder's first name only:
System.out.println("Account holder's first name: " + myAccount.getCustomer().getFirstName());
// myAccount.getCustomer() returns the customer object that's in the myAccount object, and then
// .getFirstName() gets the customer object's firstname.
----
===== Arrays of Objects =====
* We will examine the topic of arrays that contain objects.
* The arrays we have looked at before were arrays of simple, primitive types, such as //int// or //double//.
* We have used an array of Strings in the //MagicEightBall// class example.
* While Strings are objects in Java, they are "special," i.e., don't require constructors to create Strings.
* We will design and implement a //Cat// class, ...
* ... and then we will use an array of //Cat// class objects as a field in a //PetStore// class.
* A //PetStore// represents a collection of //Cats// (and other animals).
* Here is the simple //Cat// class.
public class Cat
{
// instance variable
private String _name;
/**
* constructor #1
* @param name
*/
public Cat(String name)
{
_name = name;
}
// methods
/**
* Get method for _name
* @return _name
*/
public String getName()
{
return _name;
}
} // end class
* The //PetStore// class will have an array of Cats as an instance variable,
public class PetStore
{
// instance variables
// array of Cats
private Cat [] cats;
private final int MAXCATS = 15;
...
* The //PetStore// class constructor will need to "dimension" (set the length of) the array with the //MAXCATS// constant,
public PetStore()
{
// construct array of cats
cats = new Cat[MAXCATS];
}
* Every element of the //cats// array currently contains //null// as a value, by default.
* Every element of an int (or double) array would contain 0 (or 0.0) by default.
* Every element of a boolean array would contain //false// by default.
* Every element of an array of objects contains //null// by default.
* To add //Cat// objects to the //cats// array, we need to construct //Cat// objects and then assign the objects to the array elements.
* We can do this in a //addCats// method,
public void addCats()
{
// Add a new Cat using a Cat variable, c1
Cat c1 = new Cat("Miu");
cats[0] = c1;
...
// Add a new Cat without using a Cat variable
cats[3] = new Cat("Skitty");
...
}
* If we added //Cat// objects to the first 4 elements of the //cat// array, the remaining elements of the array would still contain the value //null//.
* As with any array, the //cats// array is restricted to only //Cat// type objects.
* We would not be able to add //Dog// class objects to the //cats// array.
* To access a //Cat// object as an array element, we need to use normal array syntax, i.e., array[index].
* For example, to print the name of the 4th //Cat// object in the //cats// array, we would need to write,
// Must call Cat object's getName method
System.out.println(cats[3].getName());
----
===== The ArrayList Class =====
* We will examine the //ArrayList// Class and its advantages over standard Arrays.
==== java.util.ArrayList ====
* allows for "expandable" arrays
* An ArrayList has these characteristics:
* An ArrayList automatically expands as data is added.
* An ArrayList has methods for inserting, deleting, and searching.
* An ArrayList can be traversed using a foreach loop, iterators, or indexes.
==== Arrays or ArrayList? ====
* Programmers are frequently faced with the choice of using a simple array or an ArrayList.
* If the data has a known number of elements or small fixed size upper bound, or where efficiency in using **primitive types** is important, arrays are often the best choice.
* However, many data storage problems are not that simple, and ArrayList (or one of the other [[http://download.oracle.com/javase/6/docs/technotes/guides/collections/index.html|Java Collections]] classes) might be the right choice.
==== Automatic expansion ====
* Use ArrayList when there will be a large variation in the amount of data that you would put into an array.
* Arrays should ideally be used only when there is a constant amount of data.
* For example, storing information about the days of the week should use an array because the number of days in a week is constant.
* Use an ArrayList for your email contact list because there is no upper bound on the number of contacts.
==== Objects only ====
* A possible disadvantage of ArrayList is that it holds only object types and not primitive types (e.g., int, double, character).
* To use a primitive type in an ArrayList, put it inside an object or use of the wrapper classes (eg, Integer, Double, Character, ...).
* The wrapper classes are immutable, so if you use, eg, Integer, you will not be able to change the integer value.
==== Common ArrayList methods and constructors ====
* Here are some of the most useful ArrayList methods.
* Note that E is the notation for the type of an element in a collection such as in an ArrayList.
* Constructors:
new ArrayList() Creates ArrayList of Class E objects with
initial default capacity of 10.
new ArrayList(cap) Creates ArrayList with initial int
capacity cap.
* Adding elements:
a.add(e) adds element e to the end of ArrayList a
a.add(i, e) Inserts e at index i, shifting elements up as necessary.
* Replacing an element:
a.set(i,e) Sets the element at index i to e.
* Getting the elements:
a.get(i) Returns the object at index i.
a.toArray() Returns elements in a as an array of objects.
* Removing elements:
a.clear() Removes all elements from ArrayList a
a.remove(i) Removes the element at position i.
a.removeRange(i, j) Removes the elements from positions i thru j.
* Other:
a.size() Returns the number of elements in ArrayList a.
==== Adding elements to the end of an ArrayList, getting them by index ====
ArrayList a = new ArrayList(); // Construct default size ArrayList a
E s = new E(); // Construct s object of Class E.
. . .
a.add(s); // Add object s to the end of the ArrayList a
. . .
s = a.get(i); // Assigns i-th element from a to object s.
==== To get successive elements from an ArrayList ====
* 1. Use special "foreach" loop.
* This is fast and works for all kinds of lists, but is not entirely flexible (can only go sequentially forward with no deletions, additions, or multiple references).
* foreach loops should be the first choice for ArrayLists
ArrayList a = new ArrayList();
. . .
for ( String s : a ) {
System.out.println( s );
}
* 2. Use standard //for// loop with index.
* This is fast.
* It does allow orders other than sequentially forward by one.
// Assume a is an ArrayList:
for ( int i = 0; i < a.size(); i++ ) {
System.out.println( a.get( i ) );
}
==== Sorting ====
* If the data in your ArrayList has a natural sorting order you can simply call the static //Collections.sort()// method.
Collections.sort(yourArrayList);
* Example: sort words in an ArrayList:
// Purpose: An exercise using Scanner, ArrayList, and
// Collections.sort. Read words, sort them, print
// them.
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections; // for sorting method
public class Alphabetize
{
public static void main(String[] args)
{
//... Declare variables.
Scanner in = new Scanner(System.in);
ArrayList words = new ArrayList();
//... Read input one word at a time.
System.out.println("Enter words. End with EOF (ex. CTRL-Z then Enter, or CTRL-D)");
//... Read input one word at a time, adding it to an array list.
while (in.hasNext()) {
words.add(in.next());
}
//... Sort the words.
Collections.sort(words);
//... Print the sorted list.
System.out.println("\n\nSorted words\n");
// foreach loop:
for (String word : words) {
System.out.println(word);
}
} // end main
} // end class
----