Title: Using Classes
Course: CPS 161: An Intro to Programming with Java - DL MM MASTER

Using Classes Provided by Java

Java Provides many libraries of ready to use programs. In this lesson we are going to go over using existing classes.

String Class

The String class is a very important class in Java. Because of this, the String class has some built in optimizations that don't occur in other classes.

Declaring variables has to do with defining the types and names of variables to the Compiler.

Consider the following piece of code which declares 2 variables:

int num;
String name;

Here we have created 2 variables that are unitialized. Java will often discourage creating variables that are unitialized, however, it is possible to have declarations as shown above. In this case:

num will have a default value of 0
name will have a default value of null

The null value is a reserved word in Java which indicates that this class has not be created yet.

To initialize the above variables we would have statements like:

num = 0;
name = new String("James Gosling");

We can also combine the notion of declaration with initialization with the statements:

int num = 0;
String name = new String("James Gosling");

The variable name now has a handle (I am avoiding the term Pointer here) to a hunk of memory which has the contents for the name String. This hunk of memory was allocated from the Java Heap. In the case of Java, we are not responsible for returning this memory back to the Heap.

As long as we have a variable name that references this hunk of memory Java will allow us to keep the memory. As soon as we have no variables which reference a hunk of memory, the Java environment can put the memory back into the Heap.

What actually happens is that Java will wait until sometime later (perhaps when it is running short on memory) to enter something called:
Garbage Collection. Garbage Collection is process where Java goes through your program and marks all of the hunks of memory allocated from the heap that are still referenced. Any hunk that is not referenced by one of your variables will be thrown back into the available memory in the Heap. Consider the following piece of code:

String name1 = new String("James Gosling");
String name2 = new String("Cabrera");
name1 = name2; // At this point the hunk of memory containing "James Gosling" has no reference

Note that once we set name1 = name2, we no longer have a handle to the first heap allocation ("James Gosling"). Consequently, this hunk of memory will be reclaimed later as part of the next Garbage Collection operation.

Notes:

- Because of Garbage Collection, you don't have to worry about memory leaks and other pointer related problems that occur in languages like C/C++
- Because of Garbage Collection, you probably don't want to use Java in applications that require predictable real time performance like needing to respond to some hardware every 4 milliseconds.

Methods and String Optimizations:

Because the String is a class it has a wide range of methods. You can look at the list of methods available for the String class by going to the Java API documentation. Pick the Java.lang package and the click on the String class. We will go over a few of the methods now and others later.

First of all, we will start out with a few Java optimizations. These optimizations are available to the String class because the String class is very important to Java (i.e. other classes don't have optimizations like the String class).

The following do exactly the same thing:

String name1 = new String("abcd");
String name1 = "abcd";

String Concatenation:

String name1="Clem ";
String name2="Hasselbach";
String name3 = name1 + name2; // String concatentation

name3 = name1 + " has " + 4 + " children"; // You can concatentate with Primitive data types

SomeClass x = new SomeClass(); // Some arbitrary class
String str = " x = " + x; // You can concatenate with Non-String Classes

The Reason why you can concatenate anything to a String is because every class has a method called
toString()
When Java needs to take an arbitrary class and create a String from it, it calls the toString method. Most of the Java library classes have reasonable toString methods. If you create your own class, you can provide your own toString method are stick with the default one provided by Java (the default might not print out anything useful to you).

String Methods:

String name="abcdef";
int len;

len = name.length(); // len now contains 6

char c;

c = name.charAt(0); // c contains 'a'
c = name.charAt(1); // c contains 'b'
c = name.charAt(5); // c contains 'f'

String name_upper = name.toUpperCase(); // name_upper contains "ABCDEF"

String name_lower = name_upper.toLowerCase();// name_lower contains "abcdef"

if (name.equals(name_lower))
System.out.println("name does contain the same value as name_lower");
else System.out.println("This shouldn't print");

// Note that the following does not work the way you think

if (name == name_lower)
System.out.println("This shouldn't print");
else System.out.println("name is not == to name_lower ---- Why?");

String s= "be Good";
String s2 = s.substring(3,5);
// s2 contains "Go"

s2 = s.substring(3); // s2 contains "Good"

String Mutation Example


public class StringMutation
{
   //-----------------------------------------------------------------
   //  Prints a string and various mutations of it.
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      String phrase = "Change is inevitable";
      String mutation1, mutation2, mutation3, mutation4;

      System.out.println ("Original string: \"" + phrase + "\"");
      System.out.println ("Length of string: " + phrase.length());

      mutation1 = phrase.concat (", except from vending machines.");
      mutation2 = mutation1.toUpperCase();
      mutation3 = mutation2.replace ('E', 'X');
      mutation4 = mutation3.substring (3, 30);

      // Print each mutated string
      System.out.println ("Mutation #1: " + mutation1);
      System.out.println ("Mutation #2: " + mutation2);
      System.out.println ("Mutation #3: " + mutation3);
      System.out.println ("Mutation #4: " + mutation4);

      System.out.println ("Mutated length: " + mutation4.length());
   }
}



A Few more String Methods

Method | Notes
int length( )
String s = "be Good";
int len;
len = s.length();
//len contains 7
String substring(int start) | String s = "be Good"; String s2 = s.substring(3); // s2 contains "Good"
String substring(int start, int end) | String s= "be Good"; String s2 = s.substring(3,5); // s2 contains "Go"
boolean equals(Object y) | Normally, this is what you want to use to compare 2 strings.
boolean equalsIgnoreCase(String y) | Case Insensitive String Comparison.
int indexOf(int ch)
int lastIndexOf(int ch)
String s="day by day";
int index, index2;
index = s.indexOf('y');
index2 = s.lastIndexOf('y');
// index contains 2
// index2 contains 9
index = s.indexOf('z');
index2 = s.lastIndexOf('z');
// index and index2 contain -1
int indexOf(int ch, int fromIndex)
int lastIndexOf(int ch, int fromIndex)
String s="day by day";
int index, index2;
index = s.indexOf('y', 3);
index2 = s.lastIndexOf('y', 8);
// index contains 5
// index2 contains 5
int indexOf(String str)
int lastIndexOf(String str)
String s="day by day";
int index, index2;
index = s.indexOf("day");
index2 = s.lastIndexOf("day");
// index contains 0
// index2 contains 7
index = s.indexOf("days");
index2=s.lastIndexOf("days");
// index and index2 contain -1
int indexOf(String str, int fromIndex)
int lastIndexOf(String str, int fromIndex)
String s="day by day";
int index, index2;
index = s.indexOf("day",1);
index2 = s.lastIndexOf("day",6);
// index contains 7
// index2 contains 0
index = s.indexOf("days",1);
index2=s.lastIndexOf("days",7);
// index and index2 contain -1

More Classes

Random Class:

Method | Description
Random() | Constructor: creates a new pseudorandom number generator
float nextFloat() | Returns a random number between 0.0(inclusive) and 1.0 (exclusive)
int nextInt() | Returns a random number that ranges over all possible int values (positive and negative)
int nextInt(int num) | Returns a random number in the range 0 to num-1

Note that Random is in the java.util package

See if you can find it in the Java API documentation

Java contains many packages --- just look at the Java API documentation. Here are a few packages that you might find useful at some point:

Package Name | Provides support to
java.applet | Create programs that run in a browser
java.io | Perform a wide variety of input and output functions
java.net | Communicate across a network
java.text | Format text for output
java.util | General utilities
java.awt | Draw graphics and create grphical user interfaces; AWT stands for Abstract Windowing Toolkit
javax.swing | Create graphical user interfaces with components that extend the AWT capabilities

You can import just the class with:

import.java.util.Random;

or you can be lazy and import all classes in the java.util package:

import.java.util.*;


import java.util.Random;

public class RandomNumbers
{
   //-----------------------------------------------------------------
   //  Generates random numbers in various ranges.
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      Random generator = new Random();
      int num1;
      float num2;

      num1 = generator.nextInt();
      System.out.println ("A random integer: " + num1);

      num1 = generator.nextInt(10);
      System.out.println ("From 0 to 9: " + num1);

      num1 = generator.nextInt(10) + 1;
      System.out.println ("From 1 to 10: " + num1);

      num1 = generator.nextInt(15) + 20;
      System.out.println ("From 20 to 34: " + num1);

      num1 = generator.nextInt(20) - 10;
      System.out.println ("From -10 to 9: " + num1);

      num2 = generator.nextFloat();
      System.out.println ("A random float (between 0-1): " + num2);

      num2 = generator.nextFloat() * 6;  // 0.0 to 5.999999
      num1 = (int)num2 + 1;
      System.out.println ("From 1 to 6: " + num1);
   }
}



Math Class

Consider calculating:

We are assuming a polynomial of the form of:

a*x^2 + b*x + c

The following program calculates the roots according to the above equation:



import java.util.Scanner;

public class Quadratic
{
   //-----------------------------------------------------------------
   //  Determines the roots of a quadratic equation.
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      int a, b, c;  // ax^2 + bx + c
      double discriminant, root1, root2;

      Scanner scan = new Scanner (System.in);

      System.out.print ("Enter the coefficient of x squared: ");
      a = scan.nextInt();

      System.out.print ("Enter the coefficient of x: ");
      b = scan.nextInt();

      System.out.print ("Enter the constant: ");
      c = scan.nextInt();

      // Use the quadratic formula to compute the roots.
      // Assumes a positive discriminant.

      discriminant = Math.pow(b, 2) - (4 * a * c);
      root1 = ((-1 * b) + Math.sqrt(discriminant)) / (2 * a);
      root2 = ((-1 * b) - Math.sqrt(discriminant)) / (2 * a);

      System.out.println ("Root #1: " + root1);
      System.out.println ("Root #2: " + root2);
   }
}



Note that we don't have any import statement for the Math class. This is because the Math class is part of java.lang which defaults as being available for you.

Also note that we didn't create any instances of a class like with did with String and Scanner. Remember:

String s = new String("abc");

This is because all of the methods in the Math class are static.

Most things in Java require creating an instance of a class like we do with the String class. However, static methods are the closest thing we have to standard functions as they have always existed in traditional languages like C, Fortran, etc. Methods that are static don't require user data that needs to stay around between calls.

Note that the Math class contains a static method called random. This can be used to create random doubles. Here are a few more notes on the Math class:

All of the classes in Math are static --- this means you can just call the methods without creating an instance of the Math class first.

double Math.random( ) - this is very handy to know about because it returns numbers
>= 0 and < 1.0
This means that you can easily create random numbers between 0 and some Max. Let's say you want numbers between 0 and 100, then you would create an expression something like:
x = 101 * Math.random( );

Note that 101 will never be created because Math.random( ) never returns 1.00

abs, min, and max

There are many overloaded methods for routines like:
abs, min, and max. You might want to review how methods are chosen by going over the overrloading discussion in the oop section.

ceil, floor, and Round

double Math.ceil( double inVal) - returns the next larger whole number

double Math.floor(double inVal) - returns the next smaller whole number

long Math.Round (double inVal) - Rounds a double to the nearest integer.


  // For example:
  double outVal, inVal;
  long outLong;

  outVal =  Math.ceil(13.12);  // outVal now = 14.0
  outVal =  Math.floor(13.12); // outVal now = 13.0
  outLong = Math.Round(13.12); // outLong now = 13
  outLong = Math.Round(13.5);  // outLong now = 14


Formatting Output:

In the java.text package you will find some routines that allow you to take a number and format it as currency, percentage, or just as a number with a fixed number of digits to the right of the decimal place. The following example shows a few simple techniques available. There are many others if you pursue the details in this software package:



import java.text.NumberFormat;
import java.text.DecimalFormat;

import java.util.Scanner;

public class FTest
{
   public static void main (String[] args)
   {
        Scanner scan = new Scanner (System.in);
        double test;

        NumberFormat fmtc = NumberFormat.getCurrencyInstance();
        NumberFormat fmtp = NumberFormat.getPercentInstance();
        DecimalFormat fmtd = new DecimalFormat ("0.###");


        do
        {
            System.out.println("Enter double to format:");
            test = scan.nextDouble();
            System.out.println("Currency: " + fmtc.format(test));
            System.out.println("Percent: " + fmtp.format(test));
            System.out.println("Decimal: " + fmtd.format(test));
         } while (test >= 0.0);

   }

}



Another Formatting Program:




import java.util.Scanner;
import java.text.NumberFormat;

public class Purchase
{
   //-----------------------------------------------------------------
   //  Calculates the final price of a purchased item using values
   //  entered by the user.
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      final double TAX_RATE = 0.06;  // 6% sales tax

      int quantity;
      double subtotal, tax, totalCost, unitPrice;

      Scanner scan = new Scanner (System.in);

      NumberFormat fmt1 = NumberFormat.getCurrencyInstance();
      NumberFormat fmt2 = NumberFormat.getPercentInstance();

      System.out.print ("Enter the quantity: ");
      quantity = scan.nextInt();

      System.out.print ("Enter the unit price: ");
      unitPrice = scan.nextDouble();

      subtotal = quantity * unitPrice;
      tax = subtotal * TAX_RATE;
      totalCost = subtotal + tax;

      // Print output with appropriate formatting
      System.out.println ("Subtotal: " + fmt1.format(subtotal));
      System.out.println ("Tax: " + fmt1.format(tax) + " at "
                          + fmt2.format(TAX_RATE));
      System.out.println ("Total: " + fmt1.format(totalCost));
   }
}



Exercises:

1. Write an application that prompts for and reads the user's first and last name (separately). Then print a string composed of the first letter of the user's first name, followed by the first five characters of the user's last name, followed by a random number in the range of 10 to 99. Assume that the last name is at least five letters long. Similar algorithms are sometimes used to generate usernames for new computer accounts.
2. Create a program that converts a String into an number. You might be aware of Integer.parseInt(we will cover this in future lessons) which accomplishes this job and wonder why write your own. Integer.parseInt is quite picky about strings with none-digits. For example, a leading space or trailing space on the string results in an error.
3. Assume you want to have a program that prints out the words that it finds in a String. Your program will prompt the user for a line of input. If the line of input has 0 characters (i.e. the user just hit the enter key), then terminate. If the user provides a string like:

She sells sea shells down by the sea shore.

Your output will be:
She
sells
sea
shells
down
by
the
sea
shore

Continue prompting the user for more strings until you see a string of 0 length.
4. Write a program that takes in a text string and replaces all single digits (i.e. 0, 1, ... 9) with the words one, two, ... nine. You might find a case statement useful here.
5. A common string processing algorithm is the global replace function found in every word processor. Write a method that takes three String arguments: a document, a target string, and a replacement string. The method should replace every occurrence of the target string in the document with the replacement string. For example, if the document is "To be or not to be, that is the question" and the target string is "be" and the replacement string is "see", the result should be "To see or not to see, that is the question.".
6. Write a program that tries out the abs, min, and max methods in the Math class. Note that each of these functions is overloaded. Also prompt the user for a double and then call the ceil, round, and floor functions on this input --- print results. Put in logic to allow your program to prompt the user multiple times until the user enters in a negative number.
7. Write an application that creates and prints a random phone number of the form XXX-XXX-XXXX. Include the dashes in the output. Do not let the first three digits contain an 8 or 9 (but don't be more restrictive than that), and make sure that the second set of three digits is not greater than 742. HINT: Think through the easiest way to construct the phone number. Each digit does not have to be determined separately.
8. Write an application that reads the lengths of the sides of a triangle from the user. Compute the area of the triangle using Heron's formula(below), in which s represents half of the perimeter of the triangle, and a, b, and c represent the lengths of the three sides. Print the area.

Area = sqrt (s(s-a)(s-b)(s-c))
9. Newton's method for calculating the square root of N starts by making a (non-zero) guess at the square root. It then uses the original guess to calculate a new guess, according to the following formulat:

new_guess = ((N/guess) + guess)/2;

No matter how wild the original guess is, if we repeat this calculation, the algorithm will eventually find the square root. Write a square root method based on this algorithm. Your program should keep iterating until 2 successive guesses are within .00001. Compare your answer with the answer calculated from Math.sqrt().
10. For those who love Math: Write a program that computes the Sine or Cosine function. Prompt the user for whether he wants sin or cos. Then prompt the user for an angle in degrees. Your java program then prints out the value of sin or cos. Sine and Cosine can be computed from the following :
sin(x) = x - x**3/factorial(3) + x**5/factorial(5) - x**7/factorial(7) + ...
cos(x) = 1 - x**2/factorial(2) + x**4/factorial(4) - x**6/factorial(6) + ...
x needs to be in radians. Converting from degrees to radians can be done by multiplying by
3.1416/180.0 or Math.PI/180.0

You can also use some methods that are now available in the Math package. See if you can find them in the Math class. Also you can find a good value for PI (Again check the Math class documentation)
The error of any partial total is less than the absolute value of the last term. You might consider passing in an optional third parameter that specifies the desired accuracy.
To test your sin and cosine, call your functions with 30, 45 and 60 degrees.

Last Modified: January 30, 2008 10:15 AM