Passing handles around

Bruce Eckel's Thinking in Java Contents | Prev | Next

//: PassHandles.java
// Passing handles around
package c12;
 
public class PassHandles {
  static void f(PassHandles h) {
    System.out.println("h inside f(): " + h);
  }
  public static void main(String[] args) {
    PassHandles p = new PassHandles();
    System.out.println("p inside main(): " + p);
    f(p);
  }
} ///:~ 

The method toString( ) is automatically invoked in the print statements, and PassHandles inherits directly from Object with no redefinition of toString( ). Thus, Object’s version of toString( ) is used, which prints out the class of the object followed by the address where that object is located (not the handle, but the actual object storage). The output looks like this:

p inside main(): PassHandles@1653748
h inside f(): PassHandles@1653748

You can see that both p and h refer to the same object. This is far more efficient than duplicating a new PassHandles object just so that you can send an argument to a method. But it brings up an important issue.

Aliasing

//: Alias1.java
// Aliasing two handles to one object
 
public class Alias1 {
  int i;
  Alias1(int ii) { i = ii; }
  public static void main(String[] args) {
    Alias1 x = new Alias1(7);
    Alias1 y = x; // Assign the handle
    System.out.println("x: " + x.i);
    System.out.println("y: " + y.i);
    System.out.println("Incrementing x");
    x.i++;
    System.out.println("x: " + x.i);
    System.out.println("y: " + y.i);
  }
} ///:~ 

In the line:

Alias1 y = x; // Assign the handle

a new Alias1 handle is created, but instead of being assigned to a fresh object created with new, it’s assigned to an existing handle. So the contents of handle x, which is the address of the object x is pointing to, is assigned to y, and thus both x and y are attached to the same object. So when x’s i is incremented in the statement:

x.i++;

y’s i will be affected as well. This can be seen in the output:

x: 7
y: 7
Incrementing x
x: 8
y: 8

One good solution in this case is to simply not do it: don’t consciously alias more than one handle to an object at the same scope. Your code will be much easier to understand and debug. However, when you’re passing a handle in as an argument – which is the way Java is supposed to work – you automatically alias because the local handle that’s created can modify the “outside object” (the object that was created outside the scope of the method). Here’s an example:

//: Alias2.java
// Method calls implicitly alias their
// arguments.
 
public class Alias2 {
  int i;
  Alias2(int ii) { i = ii; }
  static void f(Alias2 handle) {
    handle.i++;
  }
  public static void main(String[] args) {
    Alias2 x = new Alias2(7);
    System.out.println("x: " + x.i);
    System.out.println("Calling f(x)");
    f(x);
    System.out.println("x: " + x.i);
  }
} ///:~ 

The output is:

x: 7
Calling f(x)
x: 8

The method is changing its argument, the outside object. When this kind of situation arises, you must decide whether it makes sense, whether the user expects it, and whether it’s going to cause problems.

In general, you call a method in order to produce a return value and/or a change of state in the object that the method is called for . (A method is how you “send a message” to that object.) It’s much less common to call a method in order to manipulate its arguments; this is referred to as “calling a method for its side effects .” Thus, when you create a method that modifies its arguments the user must be clearly instructed and warned about the use of that method and its potential surprises. Because of the confusion and pitfalls, it’s much better to avoid changing the argument.



Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: August 20, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT When you look at natural user interfaces as a developer, it isn't just fun and games. There are some very serious, real-world usage models of how things can help make the world a better place – things like Intel® RealSense™ technology. Check out this upcoming eSeminar and join the panel of experts, both from inside and outside of Intel, as they discuss how natural user interfaces will likely be getting adopted in a wide variety …

  • Managing your company's financials is the backbone of your business and is vital to the long-term health and viability of your company. To continue applying the necessary financial rigor to support rapid growth, the accounting department needs the right tools to most efficiently do their job. Read this white paper to understand the 10 essentials of a complete financial management system and how the right solution can help you keep up with the rapidly changing business world.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds