Algorithms and OOD (CSC 207 2014S) : Labs

Java Generics


Summary: We explore some basic use of generic values in Java.

Prerequisite Knowledge: Classes and interfaces

Preparation

Fork and clone the repository at https://github.com/Grinnell-CSC207/lab-generics.

Exercises

Exercise 1: Simple Expandable Arrays

The reading on generics shows how we build a generic “expandable array” class. You'll find that generic class in the repository for this lab.

a. Read through SEAExpt.java and predict what the output will be.

b. Compile and run SEAExpt.java to see what the output is.

c. Create an expandable array of strings, assign some values to it, and print them out. Here's a start.

  ExpandableArray<String> strings =
      new SimpleExpandableArray<String>();
  ...
  for (int i = 0; i < 10; i++)
    {
      pen.println("strings[" + i + "] = " + strings.get(i));
    } // for

d. What do you expect to happen if you assign a string to an element of numbers or a number to an element of strings??

e. Check your answer experimentally.

f. What do you expect to happen if we leave out the type when we construct numbers, as in the following?

  ExpandableArray<BigInteger> numbers =
      new SimpleExpandableArray();

g. Check your answer experimentally.

h. What do you expect to happen if we leave out the type when we declare strings, as in the following?

  ExpandableArray strings =
      new SimpleExpandableArray();

i. Check your answer experimentally.

j. Summarize what you've learned in these exercises.

Exercise 2: Searching, Revisited

The reading on generics shows how we build a generic search method. You'll find that code in the repository.

a. Read through SearchExpt.java and predict what the output will be.

b. Compile and run SearchExpt.java to see what the output is.

d. What do you expect to happen if you try to search strings with odd or numbers with small?

e. Check your answer experimentally.

f. What do you expect to happen if we try to generalize the declaration of strings, as in the following?

    Object[] strings = new Object[] { ... };

g. Check your answer experimentally.

h. Revise the short predicate so that it takes an object as a parameter, converts it to a string, and sees if it has fewer than five characters. Do you expect that new predicate to work with the updated strings?

i. Check your answer experimentally.

j. Summarize what you've learned in these exercises.

Exercise 3: Predicates, Continued

a. What do you expect to happen if we restore the original declaration of strings and use the new version of small?

    String[] strings = new String[] { ... };
    ...
    Predicate<Object> small = 
      new Predicate<Object>()
        {
          @Override
          public boolean holds(Object val)
          {
            return (val.toString().length() < 5);
          } // holds(Object)
        }; // new Predicate<Object>
    ...
    pen.println("A small string: " + SearchUtils.search(strings, small));

b. Check your answer experimentally.

c. What do you expect to happen if we use the new small predicate to search numbers?

    pen.println("A small integer: " + SearchUtils.search(numbers, small));

d. Check your answer experimentally.

e. Summarize what you've learned in this exercise.

Exercise 4: A Box

As you've noted, when two variables refer to the same mutable object, we can change the object through one variable and see the effect through the other variable. At times, that effect is undesirable, but at others it is desirable.

Unfortunately, if the two variables refer to the same immutable object, such as a string, we can't propagate the change to one variable to the other variable. The typical solution to this problem is to have what is typically called a “box”. You can set the value in a box or get the value in a box.

  Box<String> s1 = new Box<String>("Hello");
  Box<String> s2 = s1;
  pen.println(s1.get());        // Prints "Hello"
  pen.println(s2.get());        // Prints "Hello"
  s1.set("Goodbye");
  pen.println(s1.get());        // Prints "Goodbye"
  pen.println(s2.get());        // Prints "Goodbye"
  s2.set("Whatever");
  pen.println(s1.get());        // Prints "Whatever"
  pen.println(s2.get());        // Prints "Whatever"

  Box<Integer> i1 = new Box<Integer>(42);
  Box<Integer> i2 = i1;
  pen.println(i2.get() + 3);          // Prints 45
  i2.set(21);
  pen.println(i1.get() * 2);          // Prints 42

Implement Box using generics. You should include a constructor that sets the initial value; a mutator, set, that changes the value; and an observer, get, that extracts the value.

For Those With Extra Time

Finish the following alternate implementation of ExpandableArray

public class VectorBasedExpandableArray
{
  Vector<T> values;
  ...
} // class VectorBasedExpandableArray

Copyright (c) 2013-14 Samuel A. Rebelsky.

Creative Commons License

This work is licensed under a Creative Commons Attribution 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.