RU beehive logo ITEC Department logo
ITEC 120
2007spring
ibarland,
jpittges

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

lect11b
static methods and fields
lect11b

java source, all files (source), all files (.jar).

Recall the first methods we wrote, which were part of class PizzaServer: the method pizzaArea, as well as methods like crustArea and wedPizzaArea. Those methods were a bit odd, because it didn't matter which PizzaServer was asked; they all gave the same answer. That is, the answer didn't depend on the PizzaServer's state. We could make a million PizzaServers, and they'd all ask the same thing. (In fact, we might want that question answered even before any PizzaServers are created.)

Actually, it is possible to write methods which aren't tied to a particular instance.

A static method is a method which is not called through an individual instance. Instead, it is associated only with a class (but no instances of that class). This means you can call that method even if an instance has never been created.
Really, pizzaArea should have been a static method:
class PizzaServer {
  public  double MINIMUM_WAGE = 5.15;
  private double salary = MINIMUM_WAGE;
  private double balance = 0;
  private String almaMater;

  // ...Constructors, setters omitted


  public static double pizzaArea( double diam ) {
    double radius = diam/2;
    return 3.14 * radius * radius );
    }

  }
We can call these methods in BlueJ, by right-clicking directly on the class, even though we haven't created any PizzaServer instances! Notice which methods are shown when you right-click on the class, and (after you do create an instance) which methods are shown when you right-click on the instance.

Then, from the code pad, we can now write:

PizzaServer.pizzaArea(12)
PizzaServer.pizzaArea(1)
PizzaServer.pizzaArea(0)
Think of static methods as being methods where you walk up to the PizzaServer-factory, not a particular PizzaServer.

Or, consider Math.sqrt. It's natural question to ask what the square root of some number is; but it's odd to say you must ask some particular Math object. I'd lied earlier; there is no Math object (we never called new, so there couldn't have been an object!). Instead, Math is just a class chock full of static methods.

Or, consider: when writing Explorer methods, we really wish we had a method createNewLint(). Clearly, such a method would belong in class Treasure. But: it seems odd that you walk up to one Treasure (say, a chocolate egg) and ask it to create a Lint for you.
Really, we want a method which we can call even if no (other) Treasures have been created yet.

warning: The Java keyword “static” means “associated with the class, not a particular instance”. It does not mean “unchanging”.

Limitations of static methods

You cannot mention this in a static method.
This means you can't call (non-static) methods from inside a static method: you can't say this.getSalary(). (This further means that you can't even write getSalary, because

Note that you can certainly might have object-references that were passed in as arguments; you can certainly invoke methods on those parameters:

  static Treasure theBetterOf( Treasure t1, Treasure t2 ) {
    if (t1.getWeight() < t2.getWeight()) {
      return t1;
      }
    else {
      return t2;
      }
    }
What you cannot do from a static method is to write “getWeight()” since Java rewrites it as this.getWeight() which then triggers “cannot access method from a static context”.

Remember, the solution to the error message “cannot access method/field from a static context” is probably not making the method or field static. Although that gets rid of the error message, it's almost certainly not what you to do, if the enclosing method (“context”) really was meant to be static. The proper solution is to

Optional: calling methods from constructors

We currently have tension between a law of programming, and a rule-of-thumb:

Here's an example of tension between these two:
class PizzaServer() {
  /** The wage, in $/hr. */
  private double salary;

  /** The minimum wage (in $/hr). */
  public static double MINIMUM_WAGE = 5.15;

  /** Constructor.
   * @param The initial salary (in $/hr)
   */
  PizzaServer( double _startSalary ) {
    if (_salary < MINIMUM_WAGE) {
      this.salary = MINIMUM_WAGE;
      }
    else {
      this.salary = _salary;
      }
    this.startSalary = _startSalary;
    }


  /** Set this PizzaServer's salary (subject to federal minimum wage).
   * @param _salary The new salary rate.
   *   If _salary is below the min.wage ({@value MINIMUM_WAGE}), we use that instead.
   */
  void setSalary( double _salary ) {
    if1 (_salary < MINIMUM_WAGE) {
      this.salary = MINIMUM_WAGE;
      }
    else {
      this.salary = _salary;
      }
    }

  }
Do you recall the rationale for not wanting to call methods from a constructor? Nothing inherently wrong, except that writing (or modifying) a method, it's deeply ingrained to assume that the object is in a valid state (fully initiailized). But when called from a constructor, the object is still partway through being initialized; bugs can be easy to introduce and very difficult to locate. But this restriction doesn't apply to static methods, since there is no object involved with a static method. So it's fine to call a static method from a constructor.

Thus we have an easy solution to the above tension: write static methods to do the work which you want to call from a constructor as well as other places:

  /** Return the 
   * @param The proposed salary.
   */
  static double legalSalary( double _salary ) {
    if (_salary < MINIMUM_WAGE) {
      return MINIMUM_WAGE;
      }
    else {
      return _salary;
      }
    }

  /** Constructor.
   * @param The initial salary (in $/hr)
   */
  PizzaServer( double _startSalary ) {
    this.startSalary = legalSalary( _startSalary );
    }


  /** Set this PizzaServer's salary (subject to federal minimum wage).
   * @param _salary The new salary rate.
   *   If _salary is below the MINIMUM_WAGE, we use that instead.
   */
  void setSalary( double _salary ) {
    this.salary = legalSalary( _salary );
    }


1This if-statement could expressed more concisely using Java's conditional operator: this.salary = (_salary < MINIMUM_WAGE) ? MINIMUM_WAGE : _salary;. Actually, computing the smaller of two numbers is so common there is even a built-in method which will do this for us: this.salary = Math.min( _salary, MINIMUM_WAGE );. Note that Math.min happens to itself be a static method.      

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2007, Ian Barland, Radford University
Last modified 2007.Aug.27 (Mon)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme