CSCI E-50b: Practice Final Exam Key

HOME

Practice Final Exam Answers
PART A:
For each of the following three questions, indicate precisely what will be printed (or drawn) when the program is executed. HINT: Each of these programs does compile! For possible partial credit, show all of your work in the limited space provided.
[1]
class P1
{
    public static void main (String args [])
    {
        int arr[] []  = { {24, 0, 19}, {21, 6, -5},
                          {10, 16, 3}, {1, -1, 0} };
  
        for(int j = 0; j < arr[0].length; j++)
            for(int k = 0; k < arr.length - 1; k++)
                System.out.println( arr[k][j] );
    }
}
 
The answer to this is:

   24
   21
   10
    0
    6
   16
   19
   -5
    3
The array looks like this:

24 0 19
21 6 -5
10 16 3
1 -1 0

You are used to setting up your nested for loops to have the outer loop control the row, and the inner loop the column. In this case, however, the two have been reversed; the outer loop controls the columns (note its boundary condition is arr[0].length), and the inner one the rows. Additionally, the inner loop (controlling the rows) is bounded by length - 1, so the last row elements will not print.
  In the print statement, they are also reversed, but the inner loop of rows increments before the column loop, thus printing out the first three elements in column 1 first, then column 2, etc. Note also that we are using println, not simply print, so each number is on its own line.
 
[2]
import javax.swing.*;
import java.awt.*;

public class Prob2 extends JFrame
{
public static void main(String [] args)
{
Prob2 c1 = new Prob2();
}

Prob2()
{
JPanel p = new JPanel();
Container c = getContentPane();
p.setBackground(Color.pink);
p.add(new JButton("One"));
p.add(new JTextField("Two"));
p.add(new JButton("Three"));
c.add(p, "Center");
c.setLayout(new FlowLayout());
setSize(300, 300);
setVisible(true);
}
}
 
The key here is to note that changing the layout is legal, and will reposition all the elements in the frame. In FlowLayout (which is the default layout already on JPanels), items are simply placed from top to bottom and left to right in the order in which they are added to the JPanel. By default, also, they will center within the larger space.

Also, with nothing specified for sizes, the items take their minimum size, so that the JTextField is only large enough to hold its text, and the JPanel becomes only large enough to hold the two buttons and the textfield. Since the size of the JFrame is set specifically, it takes that larger dimension and the remaining area is blank space.
 
[3]
class P3
{   
    public static void main (String [] args)
    {
        A b = new B();
        b.whoAmI();
    }
}
 
class A
{
    public void whoAmI()
    {
        System.out.println("I'm an A object!");
    }
}
 
class B extends A
{
    public void whoAmI()
    {
        System.out.println("I'm a B object!");
    }
}
  This program outputs the text: "I'm a B object!"

Although the reference in main is declared with type A, the actual object that's created is of type B ( a subclass of A). Therefore, since the two method signatures are identical (think overridden methods - and see [4c] below), the method which is more specific for the object's actual type (based on the constructor that was used) is the one that is used.
 
PART B:
Answer each of the following by writing between 2 and 5 clear, unambiguous English language sentences.
[4a] The following code does not compile. Why not? Explain how to fix it!
     ArrayList<int> numbers = new ArrayList<int>();
     numbers.add(7);
     numbers.add(19);
     System.out.println( numbers );	 	 	 
  This code does not compile, because you cannot make an ArrayList (which holds kinds of Objects) with a primitive type - int - as its declared type. To fix it, replace the <int> with the Object equivalent <Integer>, and the code will then work.
 
[4b] Explain two uses of the Java keyword this.
  1) In a constructor, using this() with parentheses (and with or without arguments) will call another constructor in the same class which has a matching argument list.

2) When this is used without parentheses, either in a constructor or in another method, it refers to the object calling the method; it is most commonly seen when arguments being passed to the method have the same names as instance variables which belong to the class, or are objects of the same class. Using this.variableName will access the instance variable or instance method.

3) A third use, which you have learned with Swing, is that it can be used to pass the current object as a parameter to another object; an example is when your class acts as its own listener (by implementing the listener's interface) and then (this) is passed as the argument to addXXXListener() methods.
 
[4c] What is an overloaded function/method name? How is it different from an overridden function/method name?
  An overloaded method is one which has the same method name as another method in the same class, but differs in its argument list (either in sequence or type or both) from the other method. In this case, the method to be used is determined by the argument list.

An overridden method is one which has the same name AND arguments (exactly) as a method in its superclass; the subclass version will be used by objects of its type unless the superclass version is explicitly called using super.
 
[4d] In Java, all objects descent ultimately from the base class Object. State an advantage that Java derives from having all object types inherit from this class.
  Having all classes ultimately derive from Object allows for standardization of objects, sets up the overall structure and hierarchy for inheritance and polymorphism, and sees that all objects have certain identical characteristics: 1) being accessed through a reference and stored in another area of memory; 2) having a few fundamental methods (in Object) which are thus defined and inherited by all classes (you haven't seen many of these yet - toString() is probably the most familiar one; equals() is another); 3) being able to test for membership in a class (instanceof); and 4) consistent support for Thread control, to name a few.
 
[4e] A polymorphic variable is one for which the static type (the type associated with the declaration) may differ from the dynamic type (the type associated with the value currently being held by the variable at run time). How is this handled in Java? In other words, how can a programmer create polymorphic variables in this language?
  Because all objects ultimately derive from java.lang.Object, AND because any class may only have one superclass, we can set up inheritance relationships and know that a subclass object will meet all the criteria of its superclass type. Therefore, we can create the reference (the static type) to be of the superclass type (even an abstract superclass or an interface), and make the object itself from the subclass type (the dynamic type) by calling one of the subclass's constructors.

This can be predetermined within the program code, or it can be left for the user's decision at runtime; as long as the constructor called belongs to a subclass of the static type, the object will work without problems, and in fact will use its own more specific methods if they override the superclass's methods. This ability to select the appropriate method "on the fly" at runtime is known as dynamic method binding or late binding.
 
[4f] The principles of data abstraction are very important in writing complex software that is easy to maintain. How does the public/private distinction for instance variables and methods in Java class definitions help one to create abstract data types (ADTs)?
  By making class data members private, and methods public, the implementation details of the class can be kept hidden; the user never sees how the actual data is stored or manipulated. Instead, the user is presented with a public face (sometimes referred to as a public interface - not necessarily the same as a Java interface, although it may be) that identifies the methods available to the user (public methods) as an abstract data type.

Data cannot be manipulated except through these methods, thereby making error-proofing possible; it allows the methods' code (or data storage) to be modified or upgraded without the user's interaction being affected in any way; and objects of the class are much more reusable in a variety of programs or settings.
 
In answering question [5] assume the Bitset class has been defined as discussed in lecture and in a course handout. You may assume the byteArray instance variable is public (not private) in answering this question.
[5] Suppose a Bitset named setA has been declared and properly initialized to some value.

What would be the effect of the statement

setA.byteArray[0] ^= 17;

Express your answer in terms of setA's resulting "set value." For example, your answer might state something like, "The value 17 is removed from setA if that value was already present. Otherwise this statement has no effect."
  Recall that the '^' symbol indicates the operator XOR, or Exclusive OR. This operator will be true when ONE OR THE OTHER of its two operands is true, but false when both are identical (trues OR falses). The operation we are therefore performing is:

     0000 0000       // or whatever byteArray[0] contains
  ^ 0001 0001
      // 17 in binary
    -----------
     0001 0001

IF, however, either of those bits had been set in byteArray[0], XOR'ing them would have turned them off (thus removing the them from the set) instead of added them; so your answer should be that the bits or values represented by 17 (in Bitset, bits 0 and 4) will be set if they are not there, but removed if they are already present.
 
PART C: Programming Problems
[6] MIPS Assembly Language Programming

Write a MIPS subroutine named decode. This subroutine expects as its only argument a pointer to an ASCIIZ string that contains a "secret message" in lower-case alphabetic letters along with "punctuation."

This "secret code" has every letter in the original message being stored as a character that is three ahead. In other words, the letter 'a' is stored as a 'd', the letter 'b' is stored as an 'e', ..., and the letters 'x', 'y' and 'z' have been converted into 'a', 'b', and 'c' respectively. Your subroutine should convert the secret message back into ordinary English. Thus, for example, if the encoded message is:
    mdyda!!!
then your decode subroutine will return with this message now reading
    javax!!!

Note that the encoded string (and the decoded result) might contain non-alphabetic characters. Upper-case alphabetic characters can be treated as through they are "punctuation."

This subroutine is written using the standard MIPS conventions for argument passing and installing a stack frame, and so on. Most of the code is shown below. Fill in the missing pieces!

# E50b Final Exam, Spring 2001
# Decodes a message

        .text
main:             # SPIM starts by jumping to main.
                  # First read in string from the keyboard
        la     $a0,  string_space
        li     $a1, 1024
        li     $v0,  8  # load "read_string" code into $v0
        syscall
        
        la     $a0, string_space        
        jal    decode
        la     $a0, string_space
        li     $v0, 4
        syscall
        li     $v0, 10
        syscall
        
decode:   # Here is the subroutine!
        subu   $sp, $SP, 8
        sw     $ra, 4($SP) 
        SW     $fp, 
addu $FP, $SP, 8
loop: lb $t3, ($a0) beqz $t3, exit
blt $t3, 'a', incr bgt $t3, 'z', incr
  // Fill in the missing statements right here!   ##( Part A )
 
 
  incr: sb $t3, ($a0) addu $a0, $a0, 1 b loop exit: // Fill in more missing statements right here!   ## ( Part B )
 
 
 
  ## Here's where the data for this program is stored: .data string_space: .space 1024
  (A). When we get to this point in the program, we've just tested for characters less than 'a' and greater than 'z', so we know we have a valid character. We now need to change its ASCII code by three less, so that it contains the real letter, and if we end up less than 'a', correct by adding 26 to get the 'x', 'y', or 'z'.
   subu   $t3, $t3, 3    # subtract the 3 places
   bge    $t3, 'a', incr # if the letter is still greater than or 
                         # equal to 'a', go to incr; we don't need
                         # to correct for the last three letters.
   addu   $t3, $t3, 26   # The letter was less than 'a', so we need
                         # to correct it, then go on to incr.
(B). Here, we've finished dealing with the individual letter, and we need to leave the subroutine by returning to the calling location. The example you've seen of this was in the recursive Fibonacci MIPS program (Handout #11: fib-s.asm); in this program, we're not using recursion and we had no arguments, so we have less to restore.
   lw     $ra, 4($sp)    # restore the return address
   lw     $fp, 0($sp)    # restore the frame pointer
   addu   $sp, $sp, 8    # move the stack pointer down
   jr     $ra            # go back to the instruction that
                         # called the subroutine
 
[7] A Java program has been constructed to present a very simple user interface. The main program, Prob10.java, appears below:
public class Prob10
{
    public static void main (String [] args)
{
Prob10Frame f = new Prob10Frame("Prob10", 300, 300);
} }
When this program is executed, the following appears: a JFrame containing a JButton at the top and a JButton at the bottom.
The center space has been reserved for the user to draw small circles and squares simply by clicking the mouse inside a JPanel. The user can toggle between drawing circles versus squares by first clicking on one or the other JButton. Here's what the screen is supposed to look like after doing a bit of clicking:
Each circle or square is 20 pixels wide and 20 pixels high. The upper left-hand corner of each circle or square appears where I clicked the mouse. A somewhat incomplete version of this program is shown below. Your task is to fill in the missing code for the constructor
public myPanel() and the method actionPerformed(ActionEvent e).
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

class Prob10Frame extends JFrame

   JButton circleButton = new JButton("Press to draw CIRCLE!");
   JButton squareButton = new JButton("Press to draw SQUARE!");
   MyPanel mp = new MyPanel();
   boolean circleOrSquare = false;
   int xValue, yValue;
  
   public Prob10Frame(String name, int height, int width)
   {
       setTitle(name);
       setSize(height, width);
       setLocation(200, 200);

       Container c = getContentPane();
       ButtonListener bl = new ButtonListener();
       circleButton.addActionListener(bl);
       squareButton.addActionListener(bl);
          
       c.add(mp, BorderLayout.CENTER);
       c.add(squareButton, BorderLayout.SOUTH);
       c.add(circleButton, BorderLayout.NORTH);
       setVisible(true);
    }

    class MyPanel extends JPanel implements MouseListener
    {
        public MyPanel()
        {
           // missing code goes here!  Part (A).
        }

        public void mouseClicked(MouseEvent me)
        {
           Graphics g = getGraphics();
           xValue = me.getX();
           yValue = me.getY();
           if(circleOrSquare){
              g.fillRect(xValue, yValue, 20, 20);
           }
           else{
              g.fillOval(xValue, yValue, 20, 20);
           }
        }

        public void mouseReleased(MouseEvent me)
        { }

        public void mousePressed(MouseEvent me)
        { }

        public void mouseEntered(MouseEvent me)
        { }

        public void mouseExited(MouseEvent me)
        { }
    }

    class ButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
           // missing code goes here!    Part (B).
        }
    }
}
  (A). The main thing that needs to be in the MyPanel constructor is adding the MouseListener - other than that, the panel is blank until the user clicks it. Note also that the class itself is implementing the interface and acting as its own listener. As required by the interface, all of the MouseListener methods are included and defined. Your MyPanel constructor thus only needs one line of code:
        public MyPanel()
{
addMouseListener(this);
}
(B). In the ButtonListener, you are asked to define actionPerformed(ActionEvent e). You will need to look carefully at the rest of the code to see what ought to go here. You know that you have two buttons in the Frame, which add an object of this class as a listener, so your method must address what happens when either button is clicked. If you look closely at the mouseClicked() method in MyPanel, you'll see that the drawing of squares or circles is determined by a variable named circleOrSquare. When this variable is true, squares are drawn; otherwise, circles are drawn. Your actionPerformed() method thus must manage this variable, so that when the user clicks the squareButton, it is set to true, and the circleButton will change it to false. This makes writing actionPerformed much easier:
        public void actionPerformed(ActionEvent e)
        {
            if(e.getSource() == squareButton){
                circleOrSquare = true;
            }
            else{                 // must be the circleButton
                circleOrSquare = false;
            }
        }
Note that when you look at the pictures of the program, the circles and squares that are already drawn remain visible as new ones are added; therefore, you will not want to call repaint(), because that would redraw the entire panel and eliminate the previous figures.

HOME


© 2008 The President and Fellows of Harvard College
Please send comments to The Webmaster
Last modified: Saturday, 16-May-2009 09:43:03 EDT
URL: http://www.fas.harvard.edu/~libe50b/practicefinal.html