Concepts / Method Parameters in Java

Method Parameters in Java

An interface declares a set of methods that implementing classes must provide, and a variable of the interface type can refer to any implementing object.

  • Programming

When a Method Needs Behavior, Not Just Data

Most method parameters carry data: a number, a string, or a reference to an object. Sometimes a method needs something different. It needs a piece of behavior from its caller, meaning the caller must decide what happens when the method asks for work to be done. Java lets you express that need with an interface. An interface names a set of methods that a caller must supply, and the method that receives the behavior never needs to know which concrete class supplies it. It only needs to know that the object promises the required methods.

This article follows one small scenario. A method has to draw a figure into two different graphics contexts. The figure itself is supplied by the caller. Before reading further, pause and ask yourself what the caller must hand over so that the method can do its job, and where that object would come from if you did not want to write a separate named class for it.

The Drawable Promise

Definition

An interface declares a set of methods that implementing classes must provide, and a variable of the interface type can refer to any implementing object.

Read the declaration as a promise. The interface Drawable says that anything claiming to be a Drawable has a draw method that accepts a Graphics object. The declaration contains no body for draw. The body belongs to whichever class implements the interface. Classes are allowed to implement interfaces, and that is the mechanism this whole article depends on.

java
Notes on the code
  • Drawable is the interface: it declares draw but gives no body
  • drawTwice receives the figure through a parameter typed as Drawable
  • render builds the anonymous implementation at the call site

The method that consumes a Drawable takes two graphics contexts and one drawable figure, then asks the figure to draw itself into each context in turn. The listing above reconstructs that shape in its essential form. The method drawTwice never mentions a concrete class. It only calls draw on figure, and that call is legal because figure is declared as a Drawable.

Predict Before You Read the Code

Notice what a prediction about drawTwice depends on. You do not need to know the name of the class behind figure. You only need the fact that figure is a Drawable, so calling draw on it is legal. This is the point of the design: the caller decides what the figure does, and drawTwice decides how many times it happens and in which contexts.

What do you think happens?

When drawTwice runs, in what order does the figure draw into the two graphics contexts?

  • Into g2 first, then g1

  • Into g1 first, then g2

  • Into both at the same time, because they are passed together

Reveal answer
Answer:

Into g1 first, then g2

drawTwice contains two sequential calls: figure.draw(g1) appears first and figure.draw(g2) appears second. Java runs statements in order, so the figure draws into g1 and then into g2.

Reading the Anonymous Expression

An anonymous class is a class without a name that is declared and instantiated in one expression. It can implement an interface by supplying the required method body. Read the expression from left to right. The keyword new asks for an object. Drawable() names the interface the object will satisfy, and the empty parentheses work the same way they do in any instance creation. Because no class name appears, the braces that follow supply the entire class body.

newasks for a new objectDrawable()interface the objectsatisfies{ ... }entire class body, no classnamepublic voiddraw(Graphics g)the method body theinterface left outcreates instance ofbody followscontains
Which parts of the anonymous class expression name the interface, request the object, hold the class body, and supply the overridden method, and what job does each part do?

Inside those braces, the method draw is written with the parameter g, and its body is the work the figure performs. The anonymous class exists only as this expression, so you use it exactly where the object is needed. You cannot refer to it by name later in the file, because it was never given one.

Following an Argument Into a Parameter

Anonymous classes are often used as actual parameters, meaning the values supplied at a call site rather than declared variables. In the scenario, the third argument to drawTwice is not a variable declared earlier. It is the anonymous Drawable, created directly inside the argument list. Each actual argument is bound to the parameter in the same position. The first two arguments are graphics contexts, so they land in g1 and g2. The third argument is the anonymous object, so it lands in figure.

render call sitedrawTwice(a, b, newDrawable)g1receives argument afigure.draw(g1)runs the anonymous drawbodyg2receives argument bfigure.draw(g2)runs the same body againfigurereceives the anonymousDrawableargument 1argument 2argument 3first callsecond call
When render calls drawTwice with a new Drawable as the third argument, where does each object go, what does each parameter name refer to, and how does the call reach the overridden code?

Inside drawTwice, the name figure refers to the anonymous object, and the method never mentions the anonymous class by name. Each call figure.draw(...) runs the implementation supplied at the call site. The name g inside the anonymous draw method is a parameter of that method, separate from g1 and g2 in drawTwice. The two methods use different names for their own parameters. The value that connects them is the argument passed on each call. If you lose track of which graphics context is in use during a run, check the argument in the call that is currently executing, not the names you see elsewhere in the file.

Worked example

Tracing one call to drawTwice

render calls drawTwice(a, b, new Drawable with draw body g.drawLine(0, 0, 10, 10)). Trace where each value goes and what runs.

  1. 1
    Bind the arguments

    a is bound to g1, b is bound to g2, and the new Drawable object is bound to figure, because each argument takes the parameter in its position.

  2. 2
    First call

    drawTwice runs figure.draw(g1). Because figure refers to the anonymous object, control enters the anonymous draw method, where the parameter g now refers to the same graphics context as g1, namely a.

  3. 3
    Body runs

    The anonymous body calls g.drawLine(0, 0, 10, 10) on that context. When the body finishes, control returns to drawTwice.

  4. 4
    Second call

    drawTwice runs figure.draw(g2). The same anonymous body runs again, this time with g referring to b.

  5. 5
    Return

    After the second call finishes, drawTwice ends and control returns to render.

Result

The figure is drawn into a first and then into b, using the single anonymous implementation written at the call site.

Mistakes That Block Compilation

Most problems with anonymous interface implementations come from breaking the promise the interface makes. The compiler checks that promise, so many errors appear before the program runs. The mistakes below are the ones most likely to stop the code from compiling or from behaving as you intended.

  • Common mistake

    Leaving out the draw method

    What it looks like

    new Drawable() { } passed as the third argument, with no draw body inside the braces.

    Why it fails

    The interface declares draw and requires implementing classes to provide it. An anonymous class that omits the method does not satisfy the promise, so it cannot be used as a Drawable.

    Do this instead

    Write a draw method with a body inside the braces, matching the interface signature.

  • Common mistake

    Writing the wrong method signature

    What it looks like
    void draw(Graphics g, int n) inside the braces of a Drawable.
    Why it fails

    The interface promises a draw method that accepts a single Graphics object. A method with a different parameter list is a different method, so draw is still missing as far as Drawable is concerned.

    Do this instead

    Match the declared signature exactly: draw takes one Graphics parameter and returns void.

  • Common mistake

    Putting a semicolon after the closing brace of the class body

    Why it fails

    The anonymous expression is part of a larger statement, the call to drawTwice. The statement ends with a semicolon after the call's closing parenthesis, not after the brace that closes the class body.

    Do this instead
    End the whole call with one semicolon: drawTwice(a, b, new Drawable() { ... });
  • Common mistake

    Looking for the anonymous object by name later in the file

    Why it fails

    An anonymous class has no name and exists only as the expression where it was created. A later reference to it has nothing to refer to.

    Do this instead

    Use the object through the parameter it was passed into, such as figure inside drawTwice.

Practice: Tracing Two Calls

MEDIUM

Suppose render is changed so that drawTwice receives the same graphics context for both arguments, and the anonymous draw body is unchanged. Without running the program, describe which graphics context figure.draw uses on each call and how many times the body runs in total.

Hints
  • Each argument is bound to the parameter in its own position, so check what the first and second arguments are.
  • drawTwice makes exactly two calls on figure, one per statement.
  • Count the calls, not the distinct contexts.

Wrap-Up

  1. 1
    An interface declares methods that implementing classes must provide, and a variable of the interface type can refer to any implementing object.
  2. 2
    An anonymous class is declared and instantiated in one expression, using new, the interface name, and a braced body that supplies the required method.
  3. 3
    When an anonymous object is passed as an actual parameter, it is bound to the parameter in the same position, and each call on that parameter runs the anonymous implementation.
  4. 4
    Compilation errors such as a missing method or a wrong signature break the interface promise, while the statement must end with one semicolon after the whole call.

Key Takeaways

  • An interface is a promise: a variable of the interface type can refer to any object whose class supplies the declared methods.
  • An anonymous class is a nameless class declared and instantiated in one expression, with a braced body that supplies the interface method.
  • Passing an anonymous object as an argument binds it to a parameter by position, and each call on that parameter runs the anonymous implementation.
  • Missing methods and wrong signatures break the interface promise, and the statement ends with a semicolon after the entire call.