Radford University ITEC

ITEC120-ibarland (incl. office hrs)infolectureslabshws

lect12

int x = 16.0;
Math.sqrt(x)
x
It's no surprise that x still has the value 16.0, even though we happened to give That is because we wrote down 16.0 on a piece of paper and gave the paper to Math.sqrt; (If you thought Math.sqrt(x) should change the value of x, what should it do when given Math.sqrt(x+3) or Math.sqrt(x+2*y)?)

Note that while the parameter itself cannot be changed, the fields of that parameter can be. Assigning to the parameters doesn't actually modify what value was passed in:

  void addSevenTo( int n ) { n += 7; }  // A useless method.
  
  int addSevenTo_v2( int n ) { n += 7; return n; }  // Still bad practice.
  
  
  int zz = 5;
  addSevenTo(zz);    // zz is still 5.
  addSevenTo(zz+3);  // zz+3 is still 8.
  addSevenTo(19);    // 19 is still 19.
  
  addSevenTo_v2(zz)     // returns 12; zz is still 5.
  addSevenTo_v2(zz+3)   // returns 15; zz+3 is still 8.
  addSevenTo_v2(19)     // returns 26; 19 is still 19.
  
Similarly, it is impossible to write a function void swapInts(int,int), or void swapDogs(Dog,Dog)!. (The closest we could get in the second case is a method void swapDogNameAndAge(Dog,Dog).)
  Dog d1 = new Dog( "rintintin", 3 );
  Dog d2 = new Dog( "lassie", 7 );
  Dog bestDog = d1;
  swapDogs(d1,d2);
  (d1 == bestDog)   // MUST be true, even if d1's name and age have both changed.
  

We say: "Java passes arguments by value" with the addendum "object-references are values". Some languages allow you to "pass arguments by reference", a special language-feature that would let you write something like swapInts(int,int). However, this has fallen out of favor recently, and is commonly viewed as something which can add obscure bugs without really giving much more power. Just write methods which return a (reference to) the new items, and assign your variables explicitly.

null

null is a dirty word in this class, and you should never use it. … However, you'll see it in other code and in books, so we'll talk about what it does, and also give some strategies on how to avoid it.

First, let's back up, to ints: What does the following code do?

  int zz;
Easy: It declares a variable, named zz, of type int. (If this line is inside a method, it's creating a local variable; if this line is at the top level of a class, then it's creating a field.) Either way, zz is not initialized at this point. If you try to use zz without initializing it, you might get a compiler error “zz may not have been initialized.”. We've already discussed:
Always initialze your variables; if you don't know what value a field should have before the constructor is called, then the constructor's job is to make sure that field gets initialized.

Here's a dirty little secret: If you don't initialize a field, Java secretly initializes it for you. The int zz actually starts off with the value 0. But just because Java does that, don't rely on it: If you want a value initialized to zero, then do this yourself. That way, other people reading your code (like the grader!) don't have to stop and wonder whether there might be some bug involving an uninitialized field.

Okay, now that we've seen that talked about int, what happens with objects?

  Treasure tt;
As before, this code declares tt to be a reference-to-Treasure. And like before, Java secretly initializes tt for you. But it can't use 0, because that's not of type reference-to-Treasure. Instead, Java uses null: a reference-to-no-Treasure-at-all.

This is dangerous. Consider:

Treasure someFunction() {
  Treasure tt;
  //...
  tt.getWeight();
  //...
  }
If the first part of code doesn't assign a real reference-to-Treasure to tt, then tt.getWeight() will result in “Null pointer exception”. If you see that error, look for fields (or variables) which were never initialized.

Thorough testing is important:

Treasure someFunction() {
  Treasure tt;
  if ( /* some condition */ )
    tt = new Treasure( /*... */);

  tt.getWeight();

  //...
  }
If your test cases aren't careful, you might think they all pass without any error, but in truth your test cases all happened to match the condition of line 3. In the above example, when the error does occur (line 5), it's easy to figure out. But sometimes null-pointer-exceptions can occur long long after the faulty code is run. Consider:
Treasure someFunction() {
  Treasure tt;
  if ( /* some condition */ )
    tt = new Treasure( /*... */);

  return tt;
  }
Here, the person who called someFunction() could have taken the (possibly-null) result, tucked it away in some field/variable, and only 10hrs later does somebody actually take that result and call its getWeight method. The moral of the story:
Make sure you initialize your fields and variables to non-null values!

Now, what if people want to represent a reference to nothing at all? For example: Consider Explorers who have two Treasure fields (one for each pocket). Initially, an explorer starts with no treasures. So, you might be inclined to say that those fields should be null. But a better solution — which is required no the homework — is to have an actual Treasure which somehow corresponds to “a nothingness treasure” — in our case, lint.

What difference does it make, if we use null or a nothingness-treasure? There are some pros and cons:

ITEC120-ibarland (incl. office hrs)infolectureslabshws


2006.Nov.Vote (Tue)

Lists

A list is a very handy thing. Today we'll look at a built-in Java class for lists. What behavior would we like to see, from a list of doubles, which is named dubs?

This class can do all that, and more. It's called ArrayList (though using it has nothing to do with arrays; it's just a list).

One weird thing about its name: As we've seen, Java is very type-hungry. So if we make a list of doubles, it's not enough to simply say we have an object of type ArrayList; we need to say what type of objects is the list holding? That is, we actually have types of the form ArrayList<PizzaServer> or ArrayList<Treasure> or ArrayList<Double>. Think of the <> as part of the type-name.

You can look at the official documentation. ArrayList Note that it the documentation is for “an ArrayList which has elements of type E”. Really, E is a type-variable, which can stand for any java type!

One last glitch: ArrayLists can't actually hold doubles; they may only contain objects (not primitive types like double, int, boolean etc.). But: Java actually provides, for each primitive type, a “wrapper class”: Double, Integer2, Boolean, etc.. That is, an instance of Double is nothing but an object which contains one field: a double. [Draw picture.] Wrapper classes were invented just for situations like ArrayList, which require Objects rather than primitives to work.

To type in BlueJ's code pad (note the lack of most semicolons):

import java.util.ArrayList;   /* Note: no <>. */

new ArrayList<Double>()      /* Create a list which contains Doubles. */
ArrayList<Double> dubs = new ArrayList<Double>();
dubs

dubs.add( new Double(5.4) )       
dubs.add( new Double(-1.2) ) 
dubs.add( new Double(Double.MAX_VALUE))   // a static field, inside class Double 
dubs.toString();

dubs.add(4.2)        /* Note the autoboxing: 4.2 is auto-rewritten new Double(4.2) */
dubs.add(0.0) 
dubs.toString()

dubs.get(2)         /* Provide an index (not a Double). */
dubs.get(0)         /* Indices start at 0  (in java, and most languages). */
dubs.get(3)         /* Evidence of auto-boxing: we added double, got back Double. */
dubs.size()         /* Ask the list how many elements it has. */
dubs.get(dubs.size()-1)     /* The last element. */
dubs.get(dubs.size())       /* Pay attention to this error message. */

dubs.remove(Double.MAX_VALUE)  /* Remove items. */
dubs.toString()

dubs.add(5.4)
dubs.add(-1.2)
dubs.add(5.4)      /* You can add multiple copies of an element. */
dubs.toString()
dubs.remove(-1.2)  /* Which one gets removed?   ... Not specified! */
dubs.toString()

dubs.remove( new Double(5.4) )
dubs.toString()

dubs.remove(66.6) /* Hey, this had never been in the list?! */
dubs.size()


/* Add up elements of a list, with a for-each loop. */
double totalSoFar_v1 = 0.0;
String audit_v1 = "";
for ( Double d : dubs ) {  // "for each d in dubs, ..."
  audit_v1 += d + " + ";   // (in Code Pad: shift-enter, to enter multiple lines.)
  totalSoFar_v1 += d;
  }
totalSoFar_v1 + " = " + audit_v1
// Is this correct?  No! (Why not?)
// The for-each loop isn't actually suited to this problem,
// because we want to treat the last item separately (or maybe the first item).
// For-each is only natural when we want to handle every element exactly the same.


/* Add up elements of a list, with an iterator  loop. */
double totalSoFar_v1 = 0.0;
String audit_v2 = "";
Iterator<Double> it = dubs.iterator();
while (it.hasNext()) {
  audit_v2 += it.next() + " + ";
  // How to add this item to totalSoFarForEach?
  // We musn't call it.next() twice per loop, so instead we'll have to
  // ask `it' for the next element only once, and remember `it's answer.
  //  ... The task is left to the reader ...
  }


/* Add up elements of a list, with a for-loop. */
double totalSoFar_v3 = 0.0;
String audit_v3 = "";
for ( int i = 0; i < dubs.size(); ++i ) {
  if (i != 0) audit_v3 += " + ";  // If at the first item, don't include "+".
  audit_v3 += dubs.get(i);
  totalSoFar_v3 += d;
  }
totalSoFar_v1 + " = " + audit_v1



Dog d1 = new Dog( "lassie", 15 )
Dog d2 = new Dog( "fido", 3 )
Dog d3 = new Dog( "phydeaux", 5 )

ArrayList<Dog> pound = new ArrayList<Dog>();

pound.add( d1 )
pound.add( d2 )
pound.add( d3 )
pound.toString()
pound.contains( d1 )
pound.contains( new Dog( "fido", 3 ) )   /* .equals, or == ?  See docs. */
pound.contains( "fido" )
pound.remove( new Dog( "fido", 3 ) )     /* .equals, or == ?  See docs. */
pound.toString()
pound.remove( d1 )
pound.toString()

(Thurs: write the above loop versions, in class as a group.)

1You'll often see in documentation, comments like “this method must be passed a non-null argument…”.      back

2Integer is the one wrapper class whose name isn't quite just the capitalized version of its corresponding primitive.      back

ITEC120-ibarland (incl. office hrs)infolectureslabshws


©2006, Ian Barland, Radford University
Last modified 2006.Nov.09 (Thu)
Please mail any suggestions
(incl. typos, broken links)
to ibarlandradford.edu
Powered by PLT Scheme