Chapter 4: Method decomposition – Static Variables & methods

From Java Software Solutions by Lewis, Loftus, and Cocking
Static Keyword youtube Video

Static Keyword Video

Assignments:
1. Explain why a static method cannot refer to an instance variable.
2. Can a static method be referenced with the “this” operator? Explain
3. What is the purpose of static variables since a static variable belongs to the class, not to an object?
4. How are static variables and methods used?
5. Modify the PigLatinTranslator class so that its translate method is static. Modify the PigLatin class so that it invokes the method correctly.

Method decomposition

Sometimes it is useful to decompose a method into multiple methods to create a more understandable design. As an example, let’s examine a program that translates English sentences into Pig Latin.

Pig Latin is a made-up language in which each word of a sentence
is modified, in general, by moving the initial sound of the word to the end and adding an “ay” sound. For example, the word happy would be written and pronounced appyhay and the word birthday would become irthdaybay. Words that begin with vowels simply have a “yay” sound added on the end, turning the word enough into enoughyay. Consonant blends such as “ch” and “st” at the beginning of a word are moved to the end together before adding the “ay” sound. Therefore the word grapefruit becomes apefruitgray.

The real workhorse behind the PigLatin program is the PigLatinTranslator class. An object of type PigLatinTranslator provides a method called translate, which accepts a string and translates it into Pig Latin. Note that the PigLatinTranslator class does not contain a constructor because none is needed.

//********************************************************************
//  PigLatin.java       Author: Lewis/Loftus
//
//  Demonstrates the concept of method decomposition.
//********************************************************************

import java.util.Scanner;

public class PigLatin
{
   //-----------------------------------------------------------------
   //  Reads sentences and translates them into Pig Latin. 
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      String sentence, result, another;
      PigLatinTranslator translator = new PigLatinTranslator();
      Scanner scan = new Scanner (System.in);

      do
      {
         System.out.println ();
         System.out.println ("Enter a sentence (no punctuation):");
         sentence = scan.nextLine();

         System.out.println ();

         result = translator.translate (sentence);
         System.out.println ("That sentence in Pig Latin is:");
         System.out.println (result);

         System.out.println ();
         System.out.print ("Translate another sentence (y/n)? ");
         another = scan.nextLine();
      }
      while (another.equalsIgnoreCase("y"));
   }
}


 

//********************************************************************
//  PigLatinTranslator.java       Author: Lewis/Loftus
//
//  Represents a translator from English to Pig Latin. Demonstrates
//  method decomposition.
//********************************************************************

import java.util.Scanner;

public class PigLatinTranslator
{
   //-----------------------------------------------------------------
   //  Translates a sentence of words into Pig Latin.
   //-----------------------------------------------------------------
   public String translate (String sentence)
   {
      String result = "";

      sentence = sentence.toLowerCase();

      Scanner scan = new Scanner (sentence);

      while (scan.hasNext())
      {
         result += translateWord (scan.next());
         result += " ";
      }

      return result;
   }

   //-----------------------------------------------------------------
   //  Translates one word into Pig Latin. If the word begins with a
   //  vowel, the suffix "yay" is appended to the word.  Otherwise,
   //  the first letter or two are moved to the end of the word,
   //  and "ay" is appended.
   //-----------------------------------------------------------------
   private String translateWord (String word)
   {
      String result = "";

      if (beginsWithVowel(word))
         result = word + "yay";
      else
         if (beginsWithBlend(word))
            result = word.substring(2) + word.substring(0,2) + "ay";
         else
            result = word.substring(1) + word.charAt(0) + "ay";

      return result;
   }

   //-----------------------------------------------------------------
   //  Determines if the specified word begins with a vowel.
   //-----------------------------------------------------------------
   private boolean beginsWithVowel (String word)
   {
      String vowels = "aeiou";

      char letter = word.charAt(0);

      return (vowels.indexOf(letter) != -1);
   }

   //-----------------------------------------------------------------
   //  Determines if the specified word begins with a particular
   //  two-character consonant blend.
   //-----------------------------------------------------------------
   private boolean beginsWithBlend (String word)
   {
      return ( word.startsWith ("bl") || word.startsWith ("sc") ||
               word.startsWith ("br") || word.startsWith ("sh") ||
               word.startsWith ("ch") || word.startsWith ("sk") ||
               word.startsWith ("cl") || word.startsWith ("sl") ||
               word.startsWith ("cr") || word.startsWith ("sn") ||
               word.startsWith ("dr") || word.startsWith ("sm") ||
               word.startsWith ("dw") || word.startsWith ("sp") ||
               word.startsWith ("fl") || word.startsWith ("sq") ||
               word.startsWith ("fr") || word.startsWith ("st") ||
               word.startsWith ("gl") || word.startsWith ("sw") ||
               word.startsWith ("gr") || word.startsWith ("th") ||
               word.startsWith ("kl") || word.startsWith ("tr") ||
               word.startsWith ("ph") || word.startsWith ("tw") ||
               word.startsWith ("pl") || word.startsWith ("wh") ||
               word.startsWith ("pr") || word.startsWith ("wr") ); 
   }
}


 

The act of translating an entire sentence into Pig Latin is not trivial. If written in one big method, it would be very long and difficult to follow. A better solution, as implemented in the PigLatinTranslator class, is to decompose the translate method and use several other support methods to help with the task.

The translate method uses a Scanner object to separate the string into words.

The Scanner class is to separate a string into smaller elements called tokens. In this case, the tokens are separated by space characters so we can use the default white space delimiters. The PigLatin program assumes that no punctuation is included in the input.

The methods:

  • translateWord
  • beginsWithVowel
  • beginsWithBlend

Note that instead of checking each vowel separately, the code for this method declares a string that contains all the vowels, and then invokes the String method indexOf to determine whether the first character of the word is in the vowel string. If the specified character cannot be found, the indexOf method returns a value of 1.

The UML class diagram for the PigLatin program if drawn below. Note the notation showing the visibility of various methods.

uml

Static Variables

  • We’ve used static methods. For example, all the methods of the Math class are static. Recall that a static method is one that is invoked through its class name, instead of through an object of that class.
  • Not only can methods be static, but variables can be static as well. We declare static class members using the static modifier.
  • Deciding whether to declare a method or variable as static is a key step in class design.
  • So far, we’ve seen two categories of variables: local variables that are declared inside a method, and instance variables that are declared in a class but not inside a method. The term instance variable is used, because each instance of the class has its own version of the variable. That is, each object has distinct memory space for each variable so that each object can have a distinct value for that variable.
  • A static variable, which is sometimes called a class variable, is shared among all instances of a class. There is only one copy of a static variable for all objects of the class. Therefore, changing the value of a static variable in one object changes it for all of the others.
  • The reserved word static is used as a modifier to declare a static variable as follows:
                       private static int count = 0;
  • Well you are right public static variables are used without making an instance of the class but private static variables are not. The main difference between them and where I use the private static variables is when you need to use a variable in a static function. For the static functions you can only use static variables, so you make them private to not access them from other classes. That is the only case I use private static for.

    Here is an example:

    Class test {
       public static String name = "AA";
       private static String age;
    
       public static void setAge(String yourAge) {
           //here if the age variable is not static you will get an error that you cannot access non-static variables from static procedures so you have to make it static and private to not be accessed from other classes
           age = yourAge;
       }
    }
    
    

    screen-shot-2016-10-21-at-7-43-43-am

  • Memory space for a static variable is established when the class that contains it is referenced for the first time in a program.
  • A local variable declared within a method cannot be static.
  • Constants, which are declared using the final modifier, are often declared using the static modifier. Because the value of constants cannot be changed, there might as well be only one copy of the value across all objects of the class.

Static Methods

  • A static method is also called a class method. Static methods can be invoked through the class name. We don’t have to instantiate an object of the class in order to invoke the method. We know that all the methods of the Math class are static methods. For example, in the following line of code the sqrt method is invoked through the Math class name:

                      System.out.println (“Square root of 27: ” + Math.sqrt(27));

  • The methods in the Math class perform basic computations based on values passed as parameters. There is no object state to maintain in these situations; therefore, there is no good reason to create an object in order to request these services.
  • A method is made static by using the static modifier in the method declaration.
  • As we’ve seen many times, the main method of a Java program must be declared with the static modifier; this is done so that main can be executed by the interpreter without instantiating an object from the class that contains main.
  • Because static methods do not operate in the context of a particular object, they cannot reference instance variables, which exist only in an instance of a class. The compiler will issue an error if a static method attempts to use a nonstatic variable.
  • A static method can, however, reference static variables, because static variables exist independent of specific objects. Therefore, the main method can access only static or local variables.
  • The program below, SloganCounter instantiates several objects of the Slogan class, printing each one out in turn. At the end of the program it invokes a method called getCount through the class name, which returns the number of Slogan objects that were instantiated in the program.
//********************************************************************
//  SloganCounter.java       Author: Lewis/Loftus
//
//  Demonstrates the use of the static modifier.
//********************************************************************

public class SloganCounter
{
   //-----------------------------------------------------------------
   //  Creates several Slogan objects and prints the number of
   //  objects that were created.
   //-----------------------------------------------------------------
   public static void main (String[] args)
   {
      Slogan obj;

      obj = new Slogan ("Remember the Alamo.");
      System.out.println (obj);

      obj = new Slogan ("Don't Worry. Be Happy.");
      System.out.println (obj);

      obj = new Slogan ("Live Free or Die.");
      System.out.println (obj);

      obj = new Slogan ("Talk is Cheap.");
      System.out.println (obj);

      obj = new Slogan ("Write Once, Run Anywhere.");
      System.out.println (obj);

      System.out.println();
      System.out.println ("Slogans created: " + Slogan.getCount());
   }
}


  • The next program shows the Slogan class. The constructor of Slogan increments a static variable called count, which is initialized to zero when it is declared. Therefore, count serves to keep track of the number of instances of Slogan that are created.
  • The getCount method of Slogan is also declared as static, which allows it to be invoked through the class name in the main method.
  • Note that the only data referenced in the getCount method is the integer variable count, which is static.
  • As a static method, getCount cannot reference any nonstatic data.
  • The getCount method could have been declared without the static modifier, but then its invocation in the main method would have to have been done through an instance of the Slogan class instead of the class itself.

 

//********************************************************************
//  Slogan.java       Author: Lewis/Loftus
//
//  Represents a single slogan string.
//********************************************************************

public class Slogan
{
   private String phrase;
   private static int count = 0;

   //-----------------------------------------------------------------
   //  Constructor: Sets up the slogan and counts the number of
   //  instances created.
   //-----------------------------------------------------------------
   public Slogan (String str)
   {
      phrase = str;
      count++;
   }

   //-----------------------------------------------------------------
   //  Returns this slogan as a string.
   //-----------------------------------------------------------------
   public String toString()
   {
      return phrase;
   }

   //-----------------------------------------------------------------
   //  Returns the number of instances of this class that have been
   //  created.
   //-----------------------------------------------------------------
   public static int getCount ()
   {
      return count;
   }
}