Wednesday July 5, 2000


Quiz 15


1. What are the five primary components in a class definition?

2. What are the four primary components in the signature of a method?

3. What is the signature of the constructor of a class? How many constructors can a class have?

4. What keyword indicates that we are calling the constructor of a class?
































Before we proceed there are a few things that need to be mentioned.

Deprecated Features

If you look at a Java book that was written a few years ago, then you will probably find that there are methods mentioned in that book that are not mentioned in the current documentation. The reason for this is that Java is an evolving language and is still under development. Features that are part of the language today may be replaced later.

These features are called deprecated features. They have been replaced by other features as Java has evolved. Usually the compiler will still recognize those features but will give you a warning.

null

Recall that when we give an identifier a name, that name refers to some location in memory.

For example, in the declaration int a = 3;, the identifier a refers to 4 bytes in memory in which the value 3 is stored.

When we create a new instance of a class, the name of the object we create also refers to some area in memory. We can say that it "points" to some area in memory.

There is a special value that we can give to an object reference. That value is the Java keyword null. When an object reference is set to null it means that that reference points to nothing. So essentially we create an object reference that we will use later but initialize it to point to nothing.

Note that this is not the same as assigning an object an empty value.

For example, consider the following two statements.

String a = null;

String a = "";
There is a great difference between these two statements. In the first statement we are creating a reference to a String object and having it refer to nothing. In the second statement we are creating a reference to a String object but having it refer to an empty String. It is a valid String object that takes up space in memory.

Instance Methods and Instance Variables and Class Methods and Class Variables

Let's be more specific about the interaction between these four things. Recall that the difference between a class method and an instance method is that the instance methods are called by instances of the class, whereas class methods are called by the class itself.

This implies a couple of things.
  1. The keyword this has no meaning inside of a class method since this refers to the instance of the class calling the method.

  2. Instance variables and methods cannot be referred to within a class method since they have no meaning to the class.
For example consider the following class definition.

public class Test {
   int a;
   static int b = 3;

   public Test() {
      a = 4;
   }

   public int return_a() {
      return(a);
   }

   public static int return_b() {
      return(b);
   }

   public void display_b() {
      int c = return_b();
      System.out.println(c);
   }

   public static void display_a() {
      int d = return_a();
      System.out.println(d);
   }

   public static void main(String[] args) {
      Test myTest = new Test();

      myTest.display_b();
   }
}
When this program is compiled the following error is reported.

tsunami:/home/lynn/summer2000/cis120{61}% javac Test.java
Test.java:23: Can't make static reference to method int return_a() in class Test.
      int d = return_a();
                      ^
1 error
This tells us that class methods can't refer to instance methods. Likewise class methods can't refer to instance variables.

When the method public void display_b() is removed from the class definition, the compile is successful. Why?

The answer is that instance methods can refer to class methods. Recall that we are creating a new instance of the class and instance methods are meant to be called by instances of the class. However, methods associated with a class are also available to instances of the class.

Condition Execution

Let us examine in more detail the constructs we have for conditional execution.

if without an else

if (condition)
   statement
if with an else

if (condition)
   statement1
else
   statement2
nested if with an else

if (condition1)
   statement1
else if (condition2)
   statement2
else if (condition3)
   statement3
...
else
   defaultstatement
The conditions in each of these constructs is a boolean value. Recall that a boolean value is either true or false.

We have seen several operators which produce boolean results.
<
<=
>
>=
==
!=
&&
||
The operator ! can also be used to negate a boolean value.

Don't confuse the == with =.

Any expression which produces a boolean result is a valid condition.

A shortcut for if with an else

There is a very nice shortcut to an if with an else.

Consider the following if statement.

if (a == 3)
   b = 4;
else
   b = 1;
A shortcut to this statement is the following.

b = (a == 3) ? 4 : 1;
the switch statement

Recall the syntax of a switch statement.

switch (variable) {
   case value1 : statement1; break;
   case value2 : statement2; break;
   case value3 : statement3; break;
   ...
   default; defaultstatement;
}
This is equivalent to the following nested if with an else.

if (variable == value1)
   statement1;
else if (variable == value2)
   statement2;
else if (variable == value3)
   statement3;
...
else
   defaultstatement;
So the switch statement can be implemented as a nested if with an else.

However we cannot always replace a nested if with an else with a switch statement.

The variable used in a switch statement must be an ordinal type, that is a type which can put into some order or counted.

Examples of ordinal types are ints and chars.

Examples of types that are not ordinal types are real numbers and Strings.

As an example let us consider the conversion of characters into ASCII and converting ASCII into characters.

Recall that ASCII stands for American Standard Code for Information Interchange.

The ASCII code is a way of using one byte to represent all possible characters numerically. Recall that with one byte we have 256 different combinations of bits. The character `A' has ASCII value 65 and the following characters have corresponding values. That is `B' has the value 66, etc. Let us consider a method which will accept as input a character and convert it to its ASCII value.

   public static int encode(char c) {
      int ascii = 0;

      switch (c) {
         case 'A' : ascii = 65; break;
         case 'B' : ascii = 66; break;
         case 'C' : ascii = 67; break;
         case 'D' : ascii = 68; break;
         case 'E' : ascii = 69; break;
         case 'F' : ascii = 70; break;
         case 'G' : ascii = 71; break;
         case 'H' : ascii = 72; break;
         case 'I' : ascii = 73; break;
         case 'J' : ascii = 74; break;
         case 'K' : ascii = 75; break;
         case 'L' : ascii = 76; break;
         case 'M' : ascii = 77; break;
         case 'N' : ascii = 78; break;
         case 'O' : ascii = 79; break;
         case 'P' : ascii = 80; break;
         case 'Q' : ascii = 81; break;
         case 'R' : ascii = 82; break;
         case 'S' : ascii = 83; break;
         case 'T' : ascii = 84; break;
         case 'U' : ascii = 85; break;
         case 'V' : ascii = 86; break;
         case 'W' : ascii = 87; break;
         case 'X' : ascii = 88; break;
         case 'Y' : ascii = 89; break;
         case 'Z' : ascii = 90; break;
         case 'a' : ascii = 97; break;
         case 'b' : ascii = 98; break;
         case 'c' : ascii = 99; break;
         case 'd' : ascii = 100; break;
         case 'e' : ascii = 101; break;
         case 'f' : ascii = 102; break;
         case 'g' : ascii = 103; break;
         case 'h' : ascii = 104; break;
         case 'i' : ascii = 105; break;
         case 'j' : ascii = 106; break;
         case 'k' : ascii = 107; break;
         case 'l' : ascii = 108; break;
         case 'm' : ascii = 109; break;
         case 'n' : ascii = 110; break;
         case 'o' : ascii = 111; break;
         case 'p' : ascii = 112; break;
         case 'q' : ascii = 113; break;
         case 'r' : ascii = 114; break;
         case 's' : ascii = 115; break;
         case 't' : ascii = 116; break;
         case 'u' : ascii = 117; break;
         case 'v' : ascii = 118; break;
         case 'w' : ascii = 119; break;
         case 'x' : ascii = 120; break;
         case 'y' : ascii = 121; break;
         case 'z' : ascii = 122; break;
        
         default : ascii = 64;
      }

      return(ascii);
   }
Now let us consider a corresponding method for converting a number into a character.

   public static char decode(int ascii) {
      char c = ' ';

      switch (ascii) {
         case 65 : c = 'A'; break;
         case 66 : c = 'B'; break;
         case 67 : c = 'C'; break;
         case 68 : c = 'D'; break;
         case 69 : c = 'E'; break;
         case 70 : c = 'F'; break;
         case 71 : c = 'G'; break;
         case 72 : c = 'H'; break;
         case 73 : c = 'I'; break;
         case 74 : c = 'J'; break;
         case 75 : c = 'K'; break;
         case 76 : c = 'L'; break;
         case 77 : c = 'M'; break;
         case 78 : c = 'N'; break;
         case 79 : c = 'O'; break;
         case 80 : c = 'P'; break;
         case 81 : c = 'Q'; break;
         case 82 : c = 'R'; break;
         case 83 : c = 'S'; break;
         case 84 : c = 'T'; break;
         case 85 : c = 'U'; break;
         case 86 : c = 'V'; break;
         case 87 : c = 'W'; break;
         case 88 : c = 'X'; break;
         case 89 : c = 'Y'; break;
         case 90 : c = 'Z'; break;
         case 97 : c = 'a'; break;
         case 98 : c = 'b'; break;
         case 99 : c = 'c'; break;
         case 100 : c = 'd'; break;
         case 101 : c = 'e'; break;
         case 102 : c = 'f'; break;
         case 103 : c = 'g'; break;
         case 104 : c = 'h'; break;
         case 105 : c = 'i'; break;
         case 106 : c = 'j'; break;
         case 107 : c = 'k'; break;
         case 108 : c = 'l'; break;
         case 109 : c = 'm'; break;
         case 110 : c = 'n'; break;
         case 111 : c = 'o'; break;
         case 112 : c = 'p'; break;
         case 113 : c = 'q'; break;
         case 114 : c = 'r'; break;
         case 115 : c = 's'; break;
         case 116 : c = 't'; break;
         case 117 : c = 'u'; break;
         case 118 : c = 'v'; break;
         case 119 : c = 'w'; break;
         case 120 : c = 'x'; break;
         case 121 : c = 'y'; break;
         case 122 : c = 'z'; break;
        
         default : c = ' ';
      }

      return(c);
   }
Your programming assignment

Evariste decides that in order to gain more understanding of Object Oriented Programming he is going to write a small class called Binary. He will have five instance variables in his class.

original of type String
quadra of type String
octal of type String
hexadecimal of type String
decimal of type int

He will have four instance methods in his class.

toQuadra accepts no parameters and returns type String
toOctal accepts no parameters and returns type String
toDecimal accepts no parameters and returns type int
toHexadecimal accepts no parameters and returns type String
toString returns the String equivalent of this class (we will discuss this topic Tuesday and Wednesday)


He will have one class method called equiv that is overloaded.

The method will accept two, three or four parameters. It will return type String.

The constructor for Evariste's class will accept one parameter of type String.

The purpose of Evariste's class is to accept a binary number written as a string. Each of the instance methods will be used to convert that binary number into the appropriate number system. When the constructor is called, its job will be to give a value to original, and then call each of the four conversion instance methods to give values to the instance variables, quadra, octal, decimal, and hexadecimal.

The method equiv will be used to accept two, three, or four bits (characters) and convert that group of bits to the appropriate equivalent. For example, if the bits we send to one implementation of the method are ``1'',``1'', and ``1'', the method would recognize that since we are sending it three bits, we want the octal equivalent, so it would return the String ``7''.

The method toString will be used to prepare a formatted result. The output this method will produce will be

Binary QuadraDecimal Octal Decimal Hexadecimal
1010 22 12 10 A


Evariste has created a new number system called the quadradecimal number system which has only the digits 0, 1, 2, and 3.

He has decided that the easiest way in which to convert a binary number to other systems is to use the methods available in the String class.

He decides the easiest way to proceed with converting a binary number to a quadradecimal is with the following algorithm. Assume that there is a binary number stored in the String original.
1. Let l = the length of the string original.

2. Let n = the integer part of the quotient l/2. 
(He decides on this because like the conversion
from binary to octal and hexadecimal he must
take groups of bits. Since the base of the
quadradecimal system, 4, is 22, he must take
groups of two binary digits and convert them to
their quadradecimal equivalent).

He knows now that there are n groups of 2 bits
in original. Now he must determine is there are
any bits left over.

3. Let r = the remainder in the division l/2.

If r is 0 he knows that there are exactly n
groups of 2 bits in original and no more. If r
is 1 he knows that there are n groups of 2 bits
in original and 1 left over. If there is one left
over he must accomodate for this.

4. if (r == 1)
      get quadradecimal equivalent of ``0" and
the first character in original and store the
equivalent in an output string.

Now that he has accounted for the first character
if there is one left over, he can now go through
the rest of the string taking groups of two bits
and converting them to their quadradecimal equivalent.

If r was 1, then he will start breaking up the
 string into groups of 2 beginning with position 1.
If r was 0, then he will start breaking up the
 string into groups of 2 beginning with position 0.

5. for (initialize counter to r; as long as counter
is less than length of original; increment counter by 2) { 
      Get quadradecimal equivalent of two characters of original beginning
      at position counter.
      concatenate the equivalent into the output string.
   }

6. Return the output string.
Evariste decides he can carry out the conversion from binary to octal and hexadecimal in the same way.

He decides the conversion from binary to decimal is even easier.

Your task is to write the class Binary and have it carry out the proposed tasks. The class you write should contain a main method in which you instantiate the class, and make a call to its toString method to produce the formatted output.