|
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
When you compile your class file (the blueprint), you don't actually create objects. The only way to create objects is by calling their constructor method. A constructor is a slightly odd method; it's called not by walking up to an object and asking it something (after all, there aren't any objects in existence when you start!), but rather by the keyword new:
new PizzaServer() new Emcee() |
We could add yet another field for PizzaServers, one which told which high school they graduated from. (High school graduation is a requirement for Krust-eaze Pizza Ink.) The problem is, what initial value should be given this field?
class PizzaServer { double balance = 0; String almaMater = /* ??? */; // ...other fields, and methods, go here ... } |
One approach might be to say “well, set a PizzaServer's
alma mater to "unknown", and then after creating
a new PizzaServer,
we'll hope that the person immediately calls setAlmaMater
to be the correct value.”
But that's begging for trouble.
A better solution: Whenever somebody uses new to create a new object, force them to provide the high school at that moment. We do this by writing a constructor ourselves, which takes an argument:
PizzaServer( String _almaMater ) { this.setAlmaMater( _almaMater ); } |
We already know that to call the constructor, we use new:
new PizzaServer( "South" ) PizzaServer jo; jo = new PizzaServer( "North" ); |
You might be wondering, why we have been calling new all semester long, passing it zero arguments, without ever writing a constructor. It turns out, if you don't write a constructor explicitly, then Java secretly writes a “zero-argument constructor” for you. We've been relying on that fact up 'til now, with PizzaServer and all our other classes.
There are two unusual things to remember, about the constructor's signature:
A constructor is a method whose purpose is to make sure all fields get initialized.(The code inside the constructor runs immediately after fields are initialized.)
Example
People who call our constructor over and over
(that is, the person in charge of hiring at Krusteze Pizza Korp.)
probably are tired of typing in the words “High School”
every single time they call the constructor.
As a favor to them, let's
modify our constructor so it adds those words automatically.
How to do this?
Solution:
/** The PizzaServer constructor. * @param _almaMater The highschool graduated from. * Don't include a suffix " High School"; that suffix is assumed. * Example: * new PizzaServer( "Radford" ) */ PizzaServer( String _almaMater ) { this.setAlmaMater( _almaMater + " High School" ); } |
Create a class Dog. What fields might a Dog have? Write the constructor. (We'll defer brainstorming about other methods Dog can do, besides set/get its fields.)
class Dog { String name; String breed; int age = 0; // Age in years. boolean hasShots; /** Constructor needs to initialize the name and breed: * @param name The name of this Dog (e.g. "Rex") * @param breed The breed of this Dog (e.g. "Collie") */ Dog( String _name, String _breed ) { this.setHasShots( false ); // We could also have init'd the field `hasShots` when we declared it. this.setName( _name ); this.setBreed( _breed ); } } |
sneak peak:
class PizzaServer { double salary = 5.15; // In $/hr. boolean isManager = false; double balance = 0.0; String almaMater; // Name of the highschool graduated from. /** The PizzaServer constructor. * @param _almaMater The highschool graduated from. * Don't include a suffix " High School"; that is * automatically added. * Example: * new PizzaServer( "Radford" ) */ PizzaServer( String _almaMater ) { this.almaMater( _almaMater + " High School" ); } /* method definitions omitted ... */ } |
Something sneaky: When you write "hello", that's actually shorthand for new String("hello"). That's why we can call methods on Strings, and it's how we made Strings that had different states from each other.
Type each of the following in Code Pad. Explain what each line is doing.
PizzaServer jo; jo = new PizzaServer("West"); jo.pizzaArea(20); // We can have an object, even if we don't // use a local variable to remember it for later: (new PizzaServer("Skyline")).pizzaArea(20); // Fine, although we now have no way to ask // that particular PizzaServer any more questions. String greeting; greeting = new String("Howdy!"); greeting.length() (new String("hi")).length() "bye".length() // Odd, but otherwise just like above. // Relies on the fact that behind our backs, // Java re-writes `"bye"` to be `new String("bye")`. |
The syntax for a constructor's signature:
Signatureconstructor ::= Nameclass ( paramater-declaration-list ) constructor-call ::= new Nameclass( argument-list ) |
There are two unusual things about the constructor's signature:
What exactly1 happens, when you call a constructor, like new Blarg(…)?
Constructors rarely do anything interesting, besides accept some values which (almost always) are directly put into fields. Note that there are two common naming conventions: You can use parameter names which start with underscores (but otherwise have the meaningful name corresponding to the field):
class Blarg { int blargNum; String blargName; double blargDub = Double.MIN_VALUE: boolean blargTF; /** * Construct a Blarg, given an initial value for blargNum and blargName. * @param _blargNum The initial value for blargNum. * @param _blargName The initial value for blargName. */ Blarg( int _blargNum, String _blargName ) { this.setBlargNum( _blargNum ); this.setBlargName( _blargName ); this.setBlargTF( false ); // This initial value could have been provided when // the field was declared, as with blargDub. } |
While it's technically legal to call a method (in the same class) from a constructor, you should be very careful about doing this: People writing the other methods always assume the object being worked with (this) is in a valid, fully-initialized state. But if you call it from the middle of a constructor, you're only half initialized! Even getters and setters should be avoided in this one situation.
That's all good and well, but what if this warning conflicts with our princicple of avoiding repeated code? That is, what if you have code which needs to be performed both in the constructor and in regular methods? It's an annoying conflict of interest. There is a solution, but we don't yet have the tools: static methods. Fortunately, this situation doesn't arise too often; constructors are usually extremely boring: they just initialize fields more-or-less directly from their parameters.
1 Well, this isn't the whole story, as we ignore initialization blocks, as well as not mention static (class) initializon nor superclass constructors. ↩
2Actually, they are set to a zero-ish value
(0.0 for float,
false for boolean,
).
But even if you want some field to have the value 0 initially,
you should set it yourself explicitly, so others reading your
code know what you really intended, and don't have to guess whether
you have a bug of uninitialized variables.
For this course, you'll be required to initialize every field.
↩
home—info—exams—lectures—labs—hws
Recipe—Laws—lies—syntax—java.lang docs—java.util docs
©2008, Ian Barland, Radford University Last modified 2008.Feb.27 (Wed) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |