 |
|

|
 |

09/10/09 - Variables, constants, overloaded methods, String processing and user-input from the keyboard
|
 |
 |
 |
  | "Controlling complexity is the essence of computer programming." - Brian Kernighan, co-creator of C.
|
 |
 |
 |
 |
  | Variables are used in three places in Java programs to hold and move data.
|
 |
 |
 |
 |
  | Local variables are declared inside a function
|
 |
 |
 |
 |
  | public class Arithmetic { public static void main(String [] args) { int a = 5; int b = 7; int sum = add(a,b); int difference = subtract(b,a); System.out.println(a + " + " + b + " = " + sum); System.out.println(b + " - " + a + " = " + difference); } public static int add(int x, int y) { return x+y; } public static int subtract(int q, int r) { return q-r; } }
|
 |
 |
 |
 |
  | In the main method of the code above, we have declared 4 local variables: a, b, sum and difference. What local means is that those variables can only be accessed (that is, their values can be examined or changed) only within the main method. When we move to the add and subtract methods, the variables a, b, sum and difference are out of reach.
|
 |
 |
 |
 |
  | The values of a and b, are copied into the parameter variables x and y when we call the add method. The variables x and y are created when the add method is called. x and y are local to the add method and exist only while that method is active. When we exit the add method, only the sum of the x and y values is returned and the variables x and y are discarded.
|
 |
 |
 |
 |
  | The fact that local variables have limited accessibility (scope or visibility) is actually a good thing. The variables are created only when we need them, and they are discarded when we're done with them.
|
 |
 |
 |
 |
  | Variables are created when they are declared (memory is allocated) inside a block. Blocks usually, but not always, begin with { and }. Variables have block scope, which means they can only be accessed inside the block where they are declared.
|
 |
 |
 |
 |
  | When we declare a variable inside a for-loop as in the following:
|
 |
 |
 |
 |
  | for (int i = 0; i < 10; ++i) { System.out.println(i); }
|
 |
 |
 |
 |
  | the scope of the variable i is the for loop. The variable i only exists while the loop is running. After we've finished the loop, the variable i is discarded.
|
 |
 |
 |
 |
  | So far, we've discussed variables declared inside a method or as the parameters in a function call. In the example above, we say the use of parameters as a way to send copies of information (the values of a and b) to another method, in this case, add or subtract.
|
 |
 |
 |
 |
  | Variables can also be declared outside of a method. In this case they are called instance variables, and they are declared just inside the class, before any of the methods.
|
 |
 |
 |
 |
  | For example, in the code shown below from the Circle class, variables relevant to a circle are declared just inside the class: diameter, xPosition, yPosition, color and isVisible. Since these variables are declared at the beginning of the block { } for the class, they have class-scope. That is, they are accessible from anywhere inside the class, in other words, from inside any method in the entire class. They are essentially "global" inside the class. So their values can be used and modified without needing to pass them in to methods as parameters.
|
 |
 |
 |
 |
  | public class Circle { private int diameter; private int xPosition; private int yPosition; private String color; private boolean isVisible; public Circle() { diameter = 30; xPosition = 20; yPosition = 60; color = "blue"; isVisible = false; }
public void makeVisible() { isVisible = true; draw(); } ...
|
 |
 |
 |
 |
  | Class constants and "Magic Numbers"
|
 |
 |
 |
 |
  | In the program below, from class, the number 5 is called a "magic number" because it's particular value is not obvious. This is a very small program, if we wanted to change the number 5 to a different value, we would only have to remember to change it in two places. However, in a large program, we might have lots of different magic numbers, and if we wanted to change their values, we'd have to hunt through perhaps hundreds or thousands of lines of code and figure which ones we needed to change. It could be a nightmare and lead to lots of difficult to find errors if we missed a few.
|
 |
 |
 |
 |
  | public class Numbers { public static void main(String [] args) { for (int line = 1; line <= 5; ++line) { for (int spaces = 5-line; spaces > 0; --spaces) { System.out.print(" "); } System.out.println(line); } anotherMethod(); } }
|
 |
 |
 |
 |
  | Consequently, we should give our constant values descriptive names in all uppercase letters and initialize them once at the beginning of the code. Then we might understand their purpose, and if we needed to change them, we would change them in a single place, and all their values would be updated correctly with no hassle when we recompiled the program. By declaring them final, we make them constant. By making them static they can be used in all methods, static or not. And by declaring them outside of any method, they have class scope and can be accessed from any method in the class.
|
 |
 |
 |
 |
  | public class Numbers { public static final int LAST_ROW = 5; public static void main(String [] args) { for (int line = 1; line <= LAST_ROW; ++line) { for (int spaces = LAST_ROW-line; spaces > 0; --spaces) { System.out.print(" "); } System.out.println(line); } anotherMethod(); // call the method below to show it can access LAST_ROW }
public static void anotherMethod() { System.out.println("The value of LAST_ROW is " + LAST_ROW); } }
|
 |
 |
 |
 |
  | It's possible to have more than one method with the same name, however their parameter lists must be different for the compiler to distinguish them. The name and parameter list of a method together are called a method's signature.
|
 |
 |
 |
 |
  | For example, we could have three methods named area, one for circles, one for rectangles and one for triangles. They might look like this:
|
 |
 |
 |
 |
  | public double area(double radius)
|
 |
 |
 |
 |
  | public double area(double length, double width)
|
 |
 |
 |
 |
  | public double area(double side1, double side2, double side3)
|
 |
 |
 |
 |
  | Classes in Java are used to encapsulate all the information for an object. The class definition itself is like a blueprint that can be used to make an object, in the same way that a real blueprint (or lots of blueprints) might provide all the information you need to make a car. A class contains data relevant to a particular object and methods which manipulate that object's data. For example, the Circle class we looked at in class tonight, contains the following code excerpts. Note the instance data declarations at the top of the class. Note also the methods which manipulate the instance data. For example, the makeVisible method sets the instance variable isVisible to true. The moveHorizontal method adds its parameter, distance, to the current xPosition instance variable, thus moving the circle object to the right. Note that some methods call other methods. For example, the moveRight method calls the moveHorizontal method, passing a value of 20 for the distance parameter.
|
 |
 |
 |
 |
  | public class Circle { private int diameter; private int xPosition; private int yPosition; private String color; private boolean isVisible; public Circle() { diameter = 30; xPosition = 20; yPosition = 60; color = "blue"; isVisible = false; }
public void makeVisible() { isVisible = true; draw(); } public void makeInvisible() { erase(); isVisible = false; } public void moveRight() { moveHorizontal(20); }
public void moveLeft() { moveHorizontal(-20); }
public void moveHorizontal(int distance) { erase(); xPosition += distance; draw(); }
public void moveVertical(int distance) { erase(); yPosition += distance; draw(); }
public void changeSize(int newDiameter) { erase(); diameter = newDiameter; draw(); }
public void changeColor(String newColor) { color = newColor; draw(); } }
|
 |
 |
 |
 |
  | Java has primitive data types for numbers, single characters and booleans. But when we want to store multiple characters (letters, digits, punctuation, etc) as text, we need to use Strings. The Java library java.lang includes a String class, and the java.lang library and its classes are alway accessible by default. No import statements need to be made.
|
 |
 |
 |
 |
  | The following code declares a String object and uses some of the String class methods to manipulate it.
|
 |
 |
 |
 |
  | /** * Demo of using the String class * * @author Chuck Iverson * @version 6/25/09 */ public class StringDemo { public static void main(String [] args) { String name = "George Washington"; System.out.println("Original name: " + name); System.out.println("Name in uppercase: " + name.toUpperCase()); System.out.println("Name in lowercase: " + name.toLowerCase()); System.out.println("Name starts with \"Geo\"': " + name.startsWith("Geo")); System.out.println("Name ends with \"ton\": " + name.endsWith("ton")); System.out.println("Substring from position 7 to 11: " + name.substring(7,11)); } }
/* sample run
Original name: George Washington Name in uppercase: GEORGE WASHINGTON Name in lowercase: george washington Name starts with "Geo"': true Name ends with "ton": true Substring from position 7 to 11: Wash
*/
|
 |
 |
 |
 |
  | Note the use of the dot . in calling methods. Just as we've been typing System.out.println() to call the println method of the System.out object, to call an object's method we type the name of the object followed by a dot . followed by the name of the method we want. So, when I want to call the "toUpperCase()" method of the String class on the String object name, I type name.toUpperCase(). When I want to call the substring() method of the String class on the String object name, I type name.substring(startPosition, finalPosition).
|
 |
 |
 |
 |
  | Reading keyboard input with the Scanner class
|
 |
 |
 |
 |
  | Java provides a Scanner class which can read input from various input streams, one of which is the keyboard (System.in). The Scanner class is in the java.util library, which is not imported automatically, so when you want to use a Scanner you need to import the class as shown below:
|
 |
 |
 |
 |
  | import java.util.Scanner;
public class InputDemo { public static void main(String [] args) { Scanner keyboard = new Scanner(System.in); System.out.print("Greetings, please enter your name: "); String name = keyboard.nextLine(); System.out.print("That's great, " + name + ", how old are you? "); int age = keyboard.nextInt(); keyboard.nextLine(); // clear keyboard buffer System.out.println("That's amazing, " + name + ", you don't look a day over " + (age-10) + "."); System.out.println("Hi, " + name + ", how's it goin'? "); String status = keyboard.nextLine(); System.out.println("I'm glad you're OK."); System.out.println("\nDone!"); } }
|
 |
 |
 |
 |
  | We first import the Scanner class by writing the import statement before the class InputDemo.
|
 |
 |
 |
 |
  | Inside the main method, we declare a Scanner object named keyboard and call the Scanner constructor (using the word new) and supply the parameter System.in to indicate we want to read from the keyboard.
|
 |
 |
 |
 |
  | We then prompt the user to enter his/her name.
|
 |
 |
 |
 |
  | We read the whole line entered by the user using the Scanner's nextLine() method, including the ENTER or RETURN key (which is discarded), and store the characters in the String variable name.
|
 |
 |
 |
 |
  | We then display a message to the user and insert his/her name and ask for his/her age.
|
 |
 |
 |
 |
  | We then read whatever the user typed (but not the ENTER or RETURN key) using Scanner's nextInt() method. As long as we're reading numbers, the leftover newline characters from the ENTER or RETURN keys cause no problem because "white space" (spaces, tabs, newlines) is ignored when reading numbers. However, if we follow the reading of a number by reading of text, the leftover newline will cause the next input to be skipped. Hence, it's a good idea to flush the keyboard buffer by executing the extra keyboard.nextLine() command.
|
 |
 |
 |
 |
  | We then display a flattering message to the user and ask how they are.
|
 |
 |
 |
 |
  | We read their response but don't do anything with it.
|
 |
 |
 |
 |
  | Read from p. 117 through p. 165.
|
 |
 |
 |
 |
  | Modify your code from the previous assignment so that it could easily be modified to display a different range of numbers (instead of 1234567890) and a different number of repetitions of those numbers (instead of 60 total characters), with the vertical bars still matching up correctly. Use class constants instead of "magic numbers." Example outputs that could be generated by changing your constants would be:
|
 |
 |
 |
 |
  | | | | | | | 123401234012340123401234012340
|
 |
 |
 |
 |
  | | | | | | | 123456701234567012345670123456701234567012345670
|
 |
 |
 |
 |
  | Write a program with three different overloaded area methods as described in the notes above. The first one should take the radius of a circle as a parameter (double) and return the area of a circle as a double. The area of a circle is πr2. However, Java doesn't have an exponentiation operator to find r2. Instead, Java's Math class provides a static method called double pow(double base, double exponent). So to calculate the area of a circle you would type: Math.PI*Math.pow(r,2). The second one should take the length and width of a rectangle as parameters (doubles) and return the area of the rectangle as a double. The area of a rectangle is found by multiplying the length times the width. The third area method should take the lengths of the three sides of a triangle as parameters (doubles). To find the area of a triangle from its three sides you first need to calculate the semiperimeter: s = (side1 + side2 + side3)/2.0. The area is then found by calculating: .
|
 |
 |
 |
 |
  | There is a rumor circulating on the Internet that George Lucas (the creator of the Star Wars movies) uses a formula to create the names for the characters in his stories (Jar Jar Binks, ObiWan Kenobi, etc). The formula allegedly is this:
Your Star Wars first name:
Take the first three letters of your last name. Add to that the first two letters of your first name.
Your Star Wars last name:
Take the first two letters of your mother's maiden name. Add to this the first three letters of the name of the town or city where you were born.
And now your task: create a class named NameGenerator. This class should have a method named generateStarWarsName that generates a Star Wars name following the method described above and return it as a String. In your main method, you should get the required information (first name, last name, mother's maiden name and place of birth) from the user and pass this information to your generateStarWarsName as parameters (Strings). Inside your generateStarWarsName method you should manipulate the Strings to create the StarWars first name and last name and return them as a single string with a space separating the two names.
|
 |
 |
|


 |
 |
 |