Java Tutorial for Beginners

 

Working with Objects

When we looked briefly at object oriented programming at the beginning of this tutorial, we said that programs should be built from a collection of objects. Classes are the blueprint, or mould, from which objects are made. Up till now, we have looked at very simple programs that are defined in a single class. Now we need to know how to make use of other objects in our programs. 

We’ll use the Java Library class BigDecimal to look at how to incorporate and use objects within our program. Objects created from the BigDecimal class are used to store and work with decimal fractions. As I mentioned earlier, the double and float data types store numbers as binary fractions. These don’t always convert exactly to decimal fractions, and tend to give rounding errors. This can drive an accountant crazy, as they like things to balance right down to the last cent! 

To make use of an object in your program, you need to know a few things about the class from which the object will be created. Firstly, you need to know whether it expects any data to be supplied when it is created. Secondly, you need to know what methods it has, what type of data they expect, and what type of data they will return.  

Again, for the Java library classes, your source of information will be the Java documentation on http://java.sun.com/javase/6/docs/api/ . Have a look at the documentation for the BigDecimal class by choosing java.math, then choosing BigDecimal. 

There are a few things that are worth noting from the documentation, before looking at how a BigDecimal object can be used in a program. 

At the top of the documentation, you will see the following: 

java.math
Class BigDecimal

java.lang.Object
  |
  +--java.lang.Number
        |
        +--java.math.BigDecimal

java.math is the package to which the Bigdecimal class belongs. Packages are a way of grouping classes together. The core java libraries contain several packages, including java.lang, java.util (utility classes), java.math (mathematical classes), java.sql (classes for working with databases) etc.  

Underneath the class name is an inheritance hierarchy, showing that BigDecimal is a subclass of the class Number, which again is a subclass of the class bject. This means that it inherits data and methods from the Number class and also from the Object class. 

Next, you will see a description of the BigDecimal class, followed by a field summary. The field summary shows constants that are defined in the BigDecimal class. Of interest to us is the following: 

static int ROUND_HALF_UP
Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up

 

 Many of the Java classes define constants that are ‘codes’ understood by the class, and can be used to control the way certain methods work. ROUND_HALF_UP is one of them. We will refer back to this later. 

Next we see a section headed “Constructor Summary”. This shows the data that will be required when creating an object from this class. There are usually several different options. We will take note of one of them, which we will use in the next example program. 

BigDecimal(java.lang.String val)
          Translates the String representation of a BigDecmal into a BigDecimal.

This tells us that a BigDecimal can be created by supplying the number that it will store, in String format. 

Next we see a Method summary. This gives a list of all the methods defined in the class, showing the type of data to be supplied to them, and the type of data returned. For example, there is a method for adding together two BigDecimal numbers as follows: 

java.math.BigDecimal add(java.math.BigDecimal val)
Returns a BigDecimal whose value is (this + val), and whose scale is max(this.scale(), val.scale())

 This tells us that the method is named add; it needs to be supplied with an object of class BigDecimal which it refers to as val; and it will return another object of class BigDecimal containing the sum of the number stored in this object, and the number supplied as val. 

We will also make use of the multiply, divide and subtract methods. Have a closer look at the definition of the divide method:

java.math.BigDecimal divide(java.math.BigDecimal val, int scale, int roundingMode)
Returns a BigDecimal whose value is (this / val), and whose scale is as specified.

 Note that this method needs three arguments: the first is the divisor, the second defines the number of decimal points to be held in the answer (the scale), and the third defines how to deal with any rounding that will take place. This is where we would use the constant ROUND_HALF_UP that we took a note of earlier. 

Now that we’ve looked at the documentation for the BigDecimal class, let’s learn how to create an object from a class in our program. There are two steps in creating an object. Sometimes we can shortcut and carry out both steps in one statement. At other times, we may need to carry out the two steps separately. 

The first step is to create a reference to the object. This is done by stating the classname from which the object is to be created, and the name by which it will be known in your program. This doesn’t create an object: all it does is create a memory area that can store a pointer to the object. For example, coding the following line in you program: 

BigDecimal num1; 

creates a pointer called num1 that will be used to point to an object of class BigDecimal. 

To actually create the object, you need to call the constructor of the class, supplying te required data. The BigDecimal class, as we saw from the documentation, needs to be supplied with a number that will be stored in the new object. To create the object num1 containing the number 5.37, the coding is: 

num1 = new BigDecimal(5.37); 

This can, in fact, be done in a single step as follows: 

BigDecimal num1 = new BigDecimal(5.37); 

The following program is an amended version of the program calc that we saw in an earlier example. This one uses BigDecimal objects instead of doubles to store the numbers and do the calculations.

 

// *******************************************************
// * This program will carry out a calculation
// * entered on the command line. The calculation
// * should be entered as a number, followed by a
// * space, followed by an operand, followed by a
// * space and a number. Valid operands are +,-,x
// * and /.
// ******************************************************
//
// * Modified version - uses BigDecimal class to
// * store the numbers and perform the arithmetic
// ******************************************************
import java.math.*;
public class calcdec
{

public static void main(String[] args)
{
BigDecimal Num1, Num2, Ans;
char Op;
Num1=new BigDecimal(args[0]);   //First argument is a number
Op=args[1].charAt(0);                  //First character of second
                                                    //argument is the operand
Num2=new BigDecimal(args[2]); //Third argument is a number 

Ans=new BigDecimal(0); 

// ******************************************************
// Decide on the correct calculation depending on
// the operand entered
// ****************************************************** 

switch(Op)
{

case '+':
      Ans= Num1.add(Num2);
      break;
case '-':
      Ans= Num1.subtract(Num2);
      break;
case 'x':
      Ans= Num1.multiply(Num2);
      break;
case '/':
      Ans= Num1.divide(Num2,2,Num1.ROUND_HALF_UP);
      break;
default:
       System.out.println("Can't do that - I'm only a cheap calculator");
        break;
}
System.out.println("Answer is " + Ans);
}
}

Notes:

Have a look at the following line that appears just before the class header:
import java.math.*;
This is needed to tell the compiler to look for classes in the java.math package. If there are no import statements, the compiler will only look for classes in the package that holds the class you are working on, and in the java.lang package. 

When calling the methods add, multiply etc, they are prefixed with the object name (Num1) rather than the class name (BigDecimal). The rule is that the method name must be prefixed with the object name, if one has been created from the class, or the classname where no object has been created. 

Writing classes from which objects can be created 

Up to now, we have created objects from library classes. If you write a class that is to be used to create objects, there are a few things that need to be included in the class. Objects consist of data and methods. The class from which the object is created defines what data will be stored, and what methods will be available for use with the object. It can also define constructors, which are special methods used when creating a new object from the class. These classes will usually not contain a main method. 

The Instance Variables define the data to be stored by the object. Instance Variables are not the same as local variables used by an object’s methods. They are defined outside of any method, usually at the front of the class. Whereas the local variables of methods do not retain their value outside of the method, the instance variables are retained throughout the lifetime of the object, and can only be modified by the methods of the object. They can’t be modified by other classes. 

They can be of any valid data type, and can also be objects themselves. They should always be given the modifier private to enforce the encapsulation rule of OOP. 

The following is an example of the definition of instance variables for a class named Loan: 

class Loan
{
// * Instance Variables
// ********************* 

private String Customer;
private double CurrentBalance;
private double Rate; 

…… methods etc. would be defined here
} 

If an object is to be created from a class, it needs one or more special methods known as constructors. 

The purpose of a constructor is to place initial values in the instance variables. The constructor method will usually require parameters, in order to be able to get the initial values from the process which created the object. 

The constructor method must have the same name as the class. Unlike other methods, it does not have a return data type. 

Many classes provide more than one constructor, in order to allow flexibility in the number and type of parameters supplied. For example, if one of the parameters is a date, two constructors can be provided, one of which requires the date as a parameter, and one of which defaults to today’s date. 

Again, if one of the instance variables is an integer, two constructors may be provided. The first will expect this parameter in the form of an integer. The second will expect the parameter in the form of a string, and will convert it to an integer. 

Since all constructors have the same name, being that of the class, the run time environment decides which of the constructors to invoke, depending on the number and type of arguments supplied. 

The following example shows the constructors for the Loan class described in the previous example. The first constructor expects the amount of the loan and the rate as data type double; the second expects them as strings, and converts them to doubles. 

public Loan(String Cust, double Amt, double Rt)
{

Customer = Cust;
CurrentBalance = Amt;
Rate = Rt / 100;
} 

public Loan(String Cust, String Amt, String Rt)
{

Customer = Cust;
CurrentBalance = Double.parseDouble(Amt);
Rate = Double.parseDouble(Rt) / 100;
} 

Public methods in a class can be used by the process which created the object in order to initiate an action. Typically, these will include accessor methods, which return data stored in the object, and mutator methods, which change the values of data stored within the class. 

The return expression statement is used to return a value to the process which invoked the method, eg
return Balance;
This should be the last logical statement within the method. 

Additionally, a class may have its own private methods which may be called from within other methods of the class, but may not be called from outside the class. 

The full coding for the sample Loan class is shown below. 

As well as the two constructor methods, Loan contains the methods:
MthlyInterest : Calculates monthly interest on the loan, adds it to the balance, and returns the amount of interest calculated
Payment: Retrieves a payment amount as a parameter, and subtracts this from the balance
getBalance: Returns the balance 

Here’s the full code for the class Loan: 

public class Loan
{
// * Instance Variables
// ********************* 

private String Customer;
private double CurrentBalance;
private double Rate; 

// Constructors
// *********** 

public Loan(String Cust, double Amt, double Rt)
{

Customer = Cust;
CurrentBalance = Amt;
Rate = Rt / 100;
} 

public Loan(String Cust, String Amt, String Rt)
{

Customer = Cust;
CurrentBalance = Double.parseDouble(Amt);
Rate = Double.parseDouble(Rt) / 100;
} 

// Other public methods
// *******************
public double MthlyInterest()
{

double Interest;
Interest = CurrentBalance * Rate / 12;
CurrentBalance = CurrentBalance + Interest;
return Interest;
} 

public void Payment(double Pay)
{

CurrentBalance = CurrentBalance - Pay;
DateLastTran=new GregorianCalendar();
} 

public double getBalance()
{

return CurrentBalance;
} 

} 

If you write a class that will be used to create objects, you will also need to write another class that uses the object, so that you can test that it works correctly. Here is a program that tests the Loan class by creating objects from it with sample data, calling its methods, and displaying the results. 

// *************************************
// public class to test the Loan class
// ************************************* 

public class loancalc
{

public static void main(String[] args)
{
double Interest, Balance;
Loan CarLoan = new Loan("Fred", "120000", "25");
Interest=CarLoan.MthlyInterest();
CarLoan.Payment(3000);
Balance = CarLoan.getBalance();
System.out.println(+ Interest + " " + Balance);
}
} 

Try this out as follows: First, type in and save the loan class. Then create a new class called loancalc, type it in, save it and run it.