Chapter 10: Class as User Defined and Constructors
In the early 1960s, two researchers at the Norwegian Computing Center in Oslo, Ole-Johan Dahl and Kristen Nygaard, were trying to write simulations — programs that imitate a real system so that decisions can be tested before money is spent on them. One of the problems they worked on was the kind of question a port authority asks: how many ships can a harbour handle in a day, how long will each wait, where does the queue build up?
The languages of that time gave them arrays and procedures. So a harbour with forty ships became a scatter of parallel arrays — one array of arrival times, one of cargo weights, one of berth numbers — and a set of procedures that had to be handed the right index every single time. Ship number seventeen was not a thing in the program. It was a subscript that several unrelated arrays happened to agree about.
Dahl and Nygaard’s answer was to let the programmer describe a ship once — everything it knows and everything it can do, kept together — and then create as many ships as the harbour needed, each carrying its own values. Their language, Simula 67, gave those two ideas the names we still use: class and object. Java inherited both, and this chapter is about how you build them yourself.
Diagram
Fig. 10.0-1 – left half: three separate labelled arrays (arrivalTime, cargo, berth) with an index 17 marked in each and dashed lines linking the three seventeenth cells; right half: three self-contained boxes each titled “Ship”, each box holding its own arrivalTime, cargo and berth values plus a list of actions (dock, unload); caption contrast: “data scattered by index” versus “data and behaviour kept together”
Keep these five questions in mind as you read. Each one is answered somewhere in this chapter, at the point where the idea behind it has been built.
10.1 The Class as a User Defined Type
Every program you wrote in Class XI worked with values that Java already knew about — whole numbers, real numbers, single characters, true and false. The language supplies those types, and it supplies the operations that go with them.
Real data is rarely a single value. A library issue is a title, an accession number, a borrower’s roll number and a due date, all describing one event. Java has no built-in type for that, and no compiler can invent one, because only you know what a library issue is.
What Java gives you instead is a way to describe such a thing yourself. That description is a class, and the rest of this chapter is about writing one well.
10.1.1 Why a Program Needs Types of Its Own
Suppose a school library program must keep, for each issued book, an accession number and the number of days it is overdue. Using only the types you already have, you would write two separate arrays and keep them in step by hand.
int acc[] = new int[200];
int overdue[] = new int[200];Nothing in that code says the two arrays are related. The connection lives only in the position: acc[17] and overdue[17] describe the same book because the programmer remembers that they do. Sort one array without the other and the data quietly becomes nonsense.
There is a second problem, and it matters more. The rule for calculating a fine belongs to an issued book as surely as the overdue count does, yet a method written separately has to be told which position to look at every time it is called.
A class solves both problems at once. It is a description you write yourself, naming the values that belong together and the operations that act on them, and Java then treats that description as a type — a user defined data type you can use much as you use int.
That last clause is worth reading twice. Writing a class reserves no memory for data, in the same way that writing the word int reserves nothing. Both are descriptions. Values appear only when something of that type is actually created, which is the subject of section 10.2.
10.1.2 Attributes and Behaviour: Data Members and Member Methods
Anything a program models can be described under two headings: what it knows, and what it can do. A bus route knows its number, its length in kilometres and its fare per kilometre; it can calculate a ticket price and print its details.
What it knows becomes the class’s data members — the variables declared inside the class. What it can do becomes its member methods — the methods declared inside the same class. Together they are called the members of the class.
The important design idea is that these two are written in one place, inside one pair of braces. The method that calculates a fine sits beside the overdue count it works on, and needs no index passed to it.
Keeping data and the methods that act on it inside a single unit is called encapsulation. When that unit is also arranged so that outside code cannot reach the data directly, but must go through the methods, the class is said to practise data hiding. Section 10.4 shows the keyword that enforces this.
A class definition can also contain a third kind of member, a constructor, which runs automatically whenever something of the class is created. Constructors are important enough to have all of section 10.8; for now, note only that they exist and that they are written inside the class like everything else. Figure 10.1-1 shows the elements a class definition may contain.
Diagram
Fig. 10.1-1 – tree diagram; single top box “Class”; three branches to “Variables (data members)”, “Constructors”, “Member methods”; the “Variables” box branches further into three boxes “Instance variables”, “Class variables”, “Local variables (declared inside a method)”; a note beside the tree reading “access specifiers control who may use each member”
Notice that local variables appear on that chart too, although they are not members of the class. They live inside a method, exist only while it runs, and are included here only so that all three kinds of variable can be told apart. Section 10.3 draws that distinction carefully.
10.1.3 Defining a Class in Java
A class definition has a header and a body. The header is the keyword class followed by the name you choose; the body is everything between the braces that follow. The general form is shown below.
class ClassName
{
type dataMember1;
type dataMember2;
returnType methodName1(parameter list)
{
// statements
}
returnType methodName2(parameter list)
{
// statements
}
}Two rules of layout are followed throughout this book, and you should follow them in your own work. The opening brace of a class or method is written on its own line below the header, and every level inside a pair of braces is indented by four spaces. Consistent indentation is how a reader — including an examiner reading a handwritten program — sees at a glance which method a statement belongs to.
The class name is an ordinary Java identifier, but convention gives it an initial capital letter, and joins multi-word names without spaces: Fare, BusFare, IssueRecord. Method and variable names conventionally begin with a small letter. Java does not enforce this; every experienced Java programmer does.
The word public may be written before class, and you will meet it in many books. It is optional, and it carries one condition worth remembering: if a class is declared public, the file must be named after that class. A class declared without it can live in a file of any name.
Here is a small but complete class definition for the bus route described earlier.
class Fare
{
int distance;
double rate;
double amount()
{
return distance * rate;
}
void show()
{
System.out.println("Distance = " + distance + " km");
System.out.println("Fare = Rs." + amount());
}
}Read it as a description, not as an instruction to be carried out. It says: a Fare is something that has a distance and a rate, that can work out an amount from them, and that can display itself. Nowhere does it say what any particular distance is.
Notice also that show() calls amount() without any object name in front of it. A method of a class may call another method of the same class directly, because both belong to whatever object is currently executing them. Some books call this a nested member method; it is simply an ordinary call.
10.2 Objects as Instances of a Class
A class, as section 10.1 established, is only a description. Nothing in it holds a value, and a program made only of class definitions does nothing at all.
The working parts of a program are the things built from those descriptions. Each one is an object: a real region of memory, created while the program runs, carrying its own values for the data members its class named.
The word instance is used constantly and means exactly “one particular case of”. The act of creating an object is called instantiation. Fare is a class; the fare for route 24 is an instance of it.
10.2.1 Modelling Real Situations as Classes and Objects
Before any Java is written, a problem has to be read as a set of things. This is a skill worth practising deliberately, because a class chosen badly makes every method that follows awkward.
A workable method is to read the problem statement and mark the nouns that the program must remember something about. Each such noun is a candidate class. The facts recorded about it become data members, and the actions the problem asks for become member methods.
Take a school library issue register. The problem says: for each book issued, record the accession number and the number of days it has been kept; a book kept for more than seven days attracts a fine of two rupees for each extra day; print the details of each issue.
Reading it that way gives one clear noun, an issue. The facts recorded are the accession number and the days kept, plus the fine that will be worked out from them. The actions asked for are calculating the fine and printing the details.
So the class is Issue, its data members are accNo, days and fine, and its member methods calculate and display. Each book actually issued becomes one object of that class, and two hundred issues are two hundred objects — not two hundred sets of loose variables.
Notice what has been left out. The library’s name, the shelf layout and the librarian are all nouns in the room, but the problem asks the program to remember nothing about them, so none of them becomes a class. A class earns its place by holding data the program uses.
| Feature | Class | Object |
|---|---|---|
| What it is | A description of data and behaviour, written by the programmer | A particular thing created from that description while the program runs |
| When it exists | Written and compiled before the program runs | Created at run time, by new |
| Memory for data | None reserved by the definition itself | Own copy of every instance variable |
| How many | One definition | As many as the program creates |
| Analogy | The design of a bus route ticket | One printed ticket, with a route and a fare on it |
10.2.2 Creating an Object with the new Operator
An object is created by the new operator, which is followed by the class name and a pair of parentheses. The usual statement takes this form.
Issue b1 = new Issue();That one line does three separate jobs, and separating them in your mind prevents a great deal of later confusion.
First, Issue b1 declares a variable of type Issue. Second, new Issue() sets aside memory at run time for one object, large enough for that class’s instance variables. Third, the object’s data members are initialised and the address of the new object is stored in b1.
The variable b1 is called a reference variable, and this is the point students most often pass over too quickly. A reference variable does not contain the object. It contains a reference to the object — in effect, the address of the memory where the object sits. Figure 10.2-1 shows the arrangement.
Diagram
Fig. 10.2-1 – left: a small box labelled b1 with an arrow leaving it; right: a larger box labelled “Issue object” divided into three labelled cells accNo, days, fine; the arrow from b1 points at the larger box; caption: “the reference variable holds the address, not the data”
The declaration and the creation may also be written as two statements, and doing so once makes the split obvious.
Issue b1;
b1 = new Issue();After the first line alone, b1 exists but refers to no object; there is nothing yet for it to point at. Only the second line brings an object into being.
The parentheses after the class name are not decoration. They are a call to a constructor, a special member that runs automatically when an object is created. A class that declares no constructor of its own is given one by the compiler, which sets every instance variable to a standard initial value — zero for numeric types, false for boolean, null for objects. Section 10.8 takes constructors up properly; until then, the empty parentheses are enough.
10.2.3 Memory Allocation for Objects
When two objects of the same class exist, each has its own copy of every instance variable. They share the class’s description, and they share its member methods, but they share none of their data.
This is what makes objects useful. The two hundred issues in the register do not interfere with one another, and no index has to be kept in step by hand, because each object physically holds its own accession number and its own day count.
The space one object occupies depends on the instance variables its class declares — two int members and one double member need more room than a single int. Member methods add nothing per object: the code of a method exists once for the whole class, however many objects call it.
Diagram
Fig. 10.2-2 – two reference variables b1 and b2 on the left, each with an arrow to its own object box; the b1 box holds accNo 1042, days 5, fine 0.0; the b2 box holds accNo 1177, days 12, fine 10.0; below both boxes a single shaded box labelled “member methods: assign(), computeFine(), show() — one copy for the class”
10.2.4 Calling Member Methods through an Object
Once an object exists, its members are reached through the reference variable, using the dot operator: the reference, a full stop, and the member’s name.
b1.computeFine();Read that as an instruction addressed to a particular object: this Issue, work out your fine. The same call written with b2 addresses a different object, and works on that object’s data members.
A data member can be reached the same way, as b1.days, whenever the class permits it. Section 10.4 explains how a class can forbid exactly this, and why forbidding it is usually the better design.
The program below assembles everything so far into a class that can actually be run.
10.3 Variables Declared inside a Class
Not every variable that appears inside a class definition means the same thing. Three kinds exist, and they differ in two respects: where they are declared, and how many copies of them exist while the program runs.
Getting these three apart is not a naming exercise. It decides whether a value survives after a method finishes, whether two objects see the same value, and whether Java will give the variable an initial value for you.
10.3.1 Instance Variables
An instance variable is declared inside the class but outside every method and constructor. It is the ordinary data member you have used so far — accNo and days in section 10.2 were both instance variables.
Every object gets its own copy of every instance variable, created when the object is created and destroyed with it. This is the source of the word instance: the variable belongs to one instance, not to the class.
Instance variables receive default initial values if you do not set them. A numeric member starts at zero, a boolean member at false, and a member whose type is a class starts at null, meaning it refers to no object yet.
class Meter
{
int reading; // starts at 0
double units; // starts at 0.0
boolean billed; // starts at false
String owner; // starts at null
}Relying on these defaults is legal but poor practice, because a reader of your program cannot tell whether zero was intended or merely happened. Section 10.8 shows the proper tool for setting initial values deliberately.
10.3.2 Class Variables
A class variable is also declared inside the class and outside every method, but with the keyword static written before its type. That one word changes how many copies exist.
class Meter
{
int reading;
static int connections;
}Here every Meter object has its own reading, but there is only one connections in the entire program, no matter how many objects are created — one hundred objects, one connections. It belongs to the class itself rather than to any object, which is why it is called a class variable, and why it is also described as a static data member.
Because it belongs to the class, a class variable exists from the moment the program starts, even if no object is ever created, and it may be referred to through the class name: Meter.connections. It is the natural home for a running total or a count of objects made, and section 10.5 develops both uses along with the methods that go with them.
A class variable may also be made constant by adding final, which fixes its value so that no later assignment is allowed. The names of such constants are conventionally written in capitals.
static final double SERVICE_CHARGE = 25.0;10.3.3 Local Variables
A local variable is declared inside a method, a constructor or a block, and belongs to that block alone. The formal arguments of a method are local variables too, created afresh on every call.
A local variable is created when execution enters its block and destroyed when execution leaves it. Nothing of it survives to the next call, which is exactly why a counter kept in a local variable resets to nothing every time.
The rule about initial values is the opposite of the one for instance variables, and this catches a great many students. A local variable receives no default value at all, and Java refuses to compile any attempt to read it before something has been assigned to it.
A local variable may share its name with an instance variable of the same class. That is legal, and inside the method the local name wins, hiding the member. Section 10.6 shows the keyword that lets you refer to the hidden member when you need it.
10.3.4 Scope and Lifetime Compared
Two words describe what separates these three kinds of variable. The scope of a variable is the region of the program in which its name may be used, and its lifetime is the period during which it actually exists in memory. Figure 10.3-1 shows where each kind lives.
Diagram
Fig. 10.3-1 – three labelled memory regions side by side. Left region “class area”, containing one box labelled “static int connections — one copy, exists from program start”. Middle region “objects”, containing two separate object boxes each holding its own “reading” cell, both labelled “one copy per object, exists while the object exists”. Right region “method in progress”, containing a stack frame box holding “sum” and “i”, labelled “created on entry to the method, destroyed on exit”. Arrows from the two object boxes to the single static box show that all objects share it
| Feature | Instance variable | Class variable | Local variable |
|---|---|---|---|
| Declared | Inside the class, outside all methods | Inside the class, outside all methods, with static |
Inside a method, constructor or block |
| Number of copies | One per object | One for the whole class | One per call of the method |
| Scope | The whole class | The whole class, and outside it through the class name | Only the block in which it is declared |
| Lifetime | As long as its object exists | From the start of the program to the end | Only while its block is executing |
| Default initial value | Yes — 0, false or null |
Yes — 0, false or null |
None; must be assigned before use |
| Typical use | A fact about one object, such as a roll number | A total or count shared by all objects | A temporary working value, such as a loop counter |
The program below uses two instance variables and two local variables together, so that the difference can be seen in one place.
Test of i < 3 |
i | marks[i] | sum after the addition |
|---|---|---|---|
| true | 0 | 72 | 72 |
| true | 1 | 65 | 137 |
| true | 2 | 80 | 217 |
| false | 3 | — | 217, loop ends |
Result: sum finishes at 217, which is then copied into total and printed. The trace also shows the local variables vanishing at the closing brace of record() — only roll and total, which live in the object, are still available when show() runs.
10.4 Access Specifiers and Data Hiding
Section 10.1 described encapsulation as keeping data and the methods that act on it in one unit. So far, though, nothing has stopped code outside the class from reaching straight past those methods and changing a data member directly.
Java lets you close that door. An access specifier is a keyword written before a member’s declaration that decides which code may use the member. Because they control what is visible from where, they are also called visibility modes.
Three specifiers are studied here: private, public and protected. A member declared with none of them is also possible, and is discussed at the end of this section.
10.4.1 private
A member declared private can be used only inside the class in which it is declared. No other class may read it, assign to it, or call it — the compiler simply refuses.
class Marks
{
private int mark;
}This looks at first like a way of making a class harder to use, and students reasonably ask why anyone would lock away the very data the program needs. The answer is that the data is not locked away; it is put behind a door that the class itself controls.
If mark is private, no outside code can set it to 130. The only way in is a method the class provides, and that method can check the value before storing it. The class becomes responsible for keeping its own data sensible, instead of trusting every part of the program to be careful.
This is data hiding put into practice, and it is why an instance variable is declared private unless there is a definite reason not to.
10.4.2 public
A member declared public may be used from anywhere — from inside the class, from any other class, throughout the program.
Member methods that form the class’s intended service to the rest of the program are declared public. In the class Marks, the method that stores a mark after checking it and the method that supplies the stored mark are both public, because outside code is meant to call them.
The keyword may also be written before class itself, as noted in section 10.1. A public class can be used from anywhere, and its file must carry its name.
10.4.3 protected
A member declared protected behaves like a private member as far as ordinary outside code is concerned. It differs in one respect: a class derived from this one may use it.
Deriving one class from another is inheritance, which is taken up in a later chapter. Until you meet it, read protected as “private, except to my own descendants”, and note that this is exactly the situation it exists for — a member that a specialised version of the class will need, but that no unrelated class should touch.
10.4.4 Choosing a Visibility for a Member
A member written with no specifier at all is not public, although several school textbooks state that it is. It has what is called default or package visibility: it can be used by any class in the same package, and by no class outside it.
The confusion is easy to explain. Programs written in a school laboratory usually keep every class in one folder, so they all sit in the same package, and a member with no specifier does then appear to be reachable from everywhere. Put the classes in different packages and the appearance vanishes. Write the specifier you mean, and the question never arises.
Figure 10.4-1 shows the arrangement a well-built class aims for.
Diagram
Fig. 10.4-1 – a large rounded boundary labelled “class Marks”; inside it a shaded inner box labelled “private int mark”; two openings drawn in the boundary labelled “public void setMark(int)” and “public int getMark()”, each with an arrow crossing the boundary; outside the boundary a box labelled “any other class” with an arrow reaching the two openings, and a third arrow aimed straight at the shaded inner box drawn crossed out
| Can it be used from… | private | default (no specifier) | protected | public |
|---|---|---|---|---|
| The same class | Yes | Yes | Yes | Yes |
| Another class in the same package | No | Yes | Yes | Yes |
| A derived class | No | Only if in the same package | Yes | Yes |
| Any unrelated class anywhere | No | No | No | Yes |
| Usual use | Data members | Rarely chosen deliberately | Members a derived class will need | Member methods offered to other classes |
The working rule that follows from the table is short: make data members private, make the methods that others must call public, and reach for protected only when inheritance is involved.
The program below applies that rule. It is written as two classes in one file, saved as MarksTest.java and run as MarksTest, because a class can never demonstrate its own privacy — code inside a class may always use its own private members.
10.5 Static Members of a Class
Most of what a class describes belongs to each object separately: this book’s accession number, that student’s total. Some facts, though, belong to the class as a whole.
The number of bills a counter has recorded is not a property of any one bill. The total sale for the day is not a property of any one sale. Values like these are needed by every object and owned by none, and Java marks them with the keyword static.
10.5.1 Static Data Members
A static data member, introduced in section 10.3.2 as a class variable, is declared inside the class with static before its type. Exactly one copy of it exists for the whole class.
class Sale
{
private double amount; // one per object
private static double total; // one for the class
}Because there is only one copy, an assignment made through any object is seen by all of them. This is precisely what makes a static member the right tool for an accumulator or a counter: every object adds into the same box, as Fig. 10.5-1 shows.
Diagram
Fig. 10.5-1 – two object boxes side by side labelled s1 and s2, each holding its own cells item, qty, rate and amount; below them a single wider box labelled “class Sale — static area” holding two cells, count and total; an arrow from each object box down to the static box, both arrows labelled “adds into”; a note beside the static box reading “one copy, whatever the number of objects”
A static member exists from the time the class is loaded, before any object is created, and continues to exist until the program ends. It takes the same default initial values as an instance variable — zero for numeric types, false for boolean, null for object types.
Since it belongs to the class rather than an object, the natural way to refer to it from outside is through the class name.
Sale.totalWriting s1.total is also accepted by the compiler, but it is misleading, because it suggests the value belongs to s1. Prefer the class name; it says what is true.
10.5.2 Static Member Methods
A static member method is declared with static before its return type. Like a static data member, it belongs to the class and not to any object, and it is called through the class name.
Sale.showTotal();You have in fact been writing a static method since your first program. main() is declared static for a plain reason: when the program starts, no object of your class exists yet, so there is nothing to call main() through. It must be callable through the class alone.
A static method is the right choice when the work it does concerns the class rather than any single object — reporting a shared total, counting the objects created, or performing a calculation that uses only its own arguments.
10.5.3 What a Static Method May and May Not Use
A static method may use static data members and call other static methods freely. It may not use instance variables, and it may not call instance methods, directly.
The reason is worth stating rather than memorising. A static method is called through the class, so no object is involved in the call. When such a method mentions amount, there is no object whose amount could be meant, and the compiler says so.
The restriction runs one way only. An ordinary member method may use static members whenever it wants, because an object always has a class behind it. That is exactly what the recording method in the program below does.
| Feature | Instance member | Static member |
|---|---|---|
| Belongs to | One object | The class as a whole |
| Number of copies | One per object | Exactly one, whatever the number of objects |
| Exists | While its object exists | From class loading to the end of the program |
| Normally called or referred to as | objectName.member |
ClassName.member |
| May use instance members directly | Yes | No |
| May use static members directly | Yes | Yes |
| Typical example | A student’s marks; a method that prints them | A count of students; a method that prints the count |
| Call | amount of the calling object | count after the call | total after the call |
|---|---|---|---|
s1.record("Notebook", 4, 45.0) |
s1.amount = 180.0 | 1 | 180.0 |
s2.record("Pen", 10, 8.5) |
s2.amount = 85.0 | 2 | 265.0 |
Result: each object keeps its own amount, but both calls add into one count and one total, which finish at 2 and 265.0. Had count and total not been static, each object would have counted only itself and the printed total would have been 85.0.
10.6 Referring to the Current Object: the this Keyword
When s1.show() and s2.show() run the same lines yet print different values, something must be telling the method which object it is working on. That something has a name in Java, and you can write it down.
Inside every member method, the keyword this refers to the current object — the object through which the method was called. During s1.show(), this is s1; during s2.show(), the very same method sees this as s2.
The keyword has been present in every program of this chapter without being written. When show() names item, Java reads it as this.item, and supplies the object for you. Most of the time that is exactly what you want, and writing this adds nothing.
Two situations make it necessary rather than optional. The first is a clash of names, and it is much the more common.
10.6.1 When a Local Name Hides an Instance Variable
Section 10.3.3 noted that a local variable — including a formal argument — may carry the same name as an instance variable, and that inside the method the local name wins.
This happens constantly in real classes, because the natural name for the argument of a method that stores a number of hours is hours, and the natural name for the member that keeps it is also hours. Java does not object. It simply takes every plain hours in the method to mean the argument.
The result is one of the quietest bugs a beginner can write.
Writing this.number on the left and number on the right is not a trick. The two names refer to different variables, and this is what distinguishes them: with the keyword, the member; without it, the argument that hides the member.
Diagram
Fig. 10.6-1 – centre: a box labelled “issue(int number, int hours)” containing two cells for the arguments, number = 17 and hours = 3; to its right two object boxes labelled t1 and t2, each with cells number, hours, charge; a bold arrow labelled “this” runs from inside the method box to the t1 box only, with the caption “during t1.issue(17, 3) the current object is t1”; a small note beside the argument cells reading “plain number means these”
The program below is the corrected version in full.
10.6.2 Other Uses of this
Because this is an ordinary reference to the current object, it can be used anywhere such a reference is wanted, and three further uses are worth knowing.
It can be passed to another method as an argument, so that the method receives the object it was called from. A method written as register(this) hands over the current object for another class to record or work on.
It can be returned from a method whose return type is the class itself, with return this;, when the calling code should be given back the object it started with.
Inside a constructor, this(...) with arguments calls another constructor of the same class, and must be the first statement in that constructor. Constructors are the subject of section 10.8; the use is mentioned here so that the list is complete.
One restriction applies, and section 10.5.3 has already prepared it. The keyword this cannot be used inside a static method, because such a method is called through the class and no current object exists for this to refer to.
10.7 Objects as Arguments and Return Values
A class, once written, is a type. Anywhere Java allows a type — the declaration of a variable, the parameter list of a method, the return type of a method — a class name may be written in place of int or double.
That single fact is what this section is about. A method can be handed a whole object to work on, and a method can hand a whole object back.
10.7.1 Passing an Object to a Method
A parameter whose type is a class receives an object. The method then reaches that object’s members through the parameter name and a dot, exactly as main() does.
void add(Weight a, Weight b)Two things surprise students here, and both are worth settling before the program.
The first is that a method of Weight may read a.kg even though kg is private. This is allowed, and it is not a loophole. Privacy in Java is decided per class, not per object: code inside Weight may use the private members of any Weight, because that code is exactly what was trusted with them. A method in a different class still could not.
The second concerns what actually travels into the method. When you pass an int, the method receives a copy of the number, and changing it inside the method leaves the caller’s variable untouched. When you pass an object, what is copied is the reference — the address — and the copy points at the very same object. There is no second object anywhere.
The consequence is direct: a method that changes a member of the object it was given changes the caller’s object, because there is only one object involved. A method that assigns a whole new object to its parameter changes nothing outside itself, because it has only redirected its own copy of the address.
| Feature | Primitive argument | Object argument |
|---|---|---|
| What the method receives | A copy of the value | A copy of the reference |
| How many values or objects exist | Two — the caller’s and the copy | One object, with two references to it |
| Changing a member inside the method | Not applicable | The caller sees the change |
| Assigning a new value or object to the parameter | Caller unaffected | Caller unaffected |
| Typical use | A single number, character or flag | A whole record the method must read or update |
Diagram
Fig. 10.7-1 – top: three reference boxes labelled w1, w2, w3 in main(), each with an arrow to its own object box holding cells kg and gm (2/750, 1/400, and 0/0); below: a method frame labelled “w3.add(a, b)” containing two parameter boxes a and b, with arrows from a to the same object as w1 and from b to the same object as w2, and a third arrow labelled “this” to the w3 object; caption: “the parameters hold copies of the addresses, not copies of the objects”
The program below adds two weights, each recorded in kilograms and grams, and stores the result in a third object.
10.7.2 Returning an Object from a Method
A method’s return type may also be a class name. Such a method must return a reference to an object of that class, and the caller normally stores it in a reference variable.
The add() method above works by being called on the object that is to hold the answer, which forces the caller to create that object first. An alternative design lets the method make the answer itself and hand it back. Adding the method below to the class Weight provides it.
Weight plus(Weight b)
{
Weight t = new Weight();
t.kg = kg + b.kg;
t.gm = gm + b.gm;
if (t.gm >= 1000)
{
t.gm = t.gm - 1000;
t.kg = t.kg + 1;
}
return t;
}The header declares Weight as the return type, a new object is created inside the method and filled in, and return t; sends back its reference. With the call written as
Weight w4 = w1.plus(w2);
w4.show();the printed line is 4 kg 150 g, the same answer by a different route.
Notice that the object t does not vanish when the method ends, even though t itself is a local variable. The variable disappears; the object survives, because a reference to it has been handed to the caller and stored in w4. Figure 10.7-2 shows the moment the reference is passed back.
Diagram
Fig. 10.7-2 – left: a method frame labelled “w1.plus(w2)” containing a local reference box t with an arrow to a newly drawn object box holding kg 4 and gm 150; right: the caller’s reference box w4; a broad arrow labelled “return t” from t to w4, and after it a dashed outline where the method frame used to be, with both t’s box and the frame greyed out while the object box and w4’s arrow to it remain solid
Which of the two designs is better depends on the problem. A method that returns an object reads more naturally in an expression and leaves the caller free of the job of creating the result. A method that fills in the current object avoids creating anything, which matters when many results are produced in a loop. Both appear in ISC class specifications, and the specification always makes clear which one is wanted: a method described with the return type Weight must return an object, and one described as void must not.
10.8 Constructors
Every program in this chapter so far has created an object and then, in a second step, put values into it — through assign(), set(), issue() or record(). The two steps are separate, and that is the weakness.
A constructor removes the gap. It is a member of the class that runs automatically at the moment an object is created, so an object is never handed to the program in an unfinished state.
10.8.1 Why Initialisation Cannot Be Left to the User
Consider what the class Weight in section 10.7 depends on. Its add() method assumes that every weight it is given has fewer than 1000 grams; its output assumes that both members hold real measurements.
Nothing enforces either assumption. A caller who writes new Weight() and forgets the call to set() gets an object holding two zeros, and the program cheerfully adds nothing to nothing and prints the result.
The trouble is not that the caller is careless. It is that the class has published a rule — fill me in before using me — and has provided no way to insist on it. Any rule that depends on every future caller remembering it will eventually be broken.
A constructor turns the rule into a mechanism. Because it is called by new itself, there is no way to create the object and skip it.
10.8.2 Features of a Constructor
Five properties define a constructor, and each of them follows from what it is for.
Its name is exactly the name of the class, including the capitalisation. This is how the compiler recognises it as a constructor rather than an ordinary method.
It declares no return type — not
int, notString, and not evenvoid. It is not called by your code and has no caller to return a value to.It is invoked automatically when an object is created with
new, and at no other time. You never writet1.Trip();.It may take arguments, and a class may have several constructors with different parameter lists. Section 10.8.7 develops this.
It may carry an access specifier.
publicis usual, since other classes must be able to create objects; aprivateconstructor is legal Java and has the effect of preventing creation from outside the class.
Note carefully what is not in that list. A constructor is not obliged to be public, although several school textbooks state that it always is, and nothing prevents it from containing calculations — a constructor that computes a fare from a distance it has just stored is perfectly ordinary. What it must not do is return a value.
10.8.3 The Default Constructor
A class need not declare a constructor at all. Every class in this chapter before now has managed without one, and new Issue() worked perfectly well.
That is because a class which declares no constructor is given one by the compiler. It takes no arguments, its body is empty, and its effect is to leave every instance variable at the default value described in section 10.3.1 — zero, false or null according to type. This compiler-supplied constructor is called the default constructor.
class Sample
{
int n; // 0 after new Sample()
double d; // 0.0
boolean b; // false
String s; // null
}One consequence of this arrangement surprises almost everyone the first time. The default constructor is supplied only when the class declares no constructor whatsoever. Write a constructor that takes two arguments, and the free no-argument one disappears; new Sample() will then fail to compile.
The remedy is simply to write the no-argument constructor yourself when you want both, which brings us to the next kind.
10.8.4 Non-parameterised Constructor
A non-parameterised constructor is one you write with an empty parameter list. It looks like the default constructor and is called in the same way, by new ClassName(), but its body is yours.
Trip()
{
route = 0;
km = 0.0;
}Writing zeros explicitly may look pointless, since the defaults would have supplied them. It is not. It states the intention, so a reader knows the initial state was chosen rather than inherited by accident, and it puts a place in the class where a more sensible starting value can later be written.
The distinction between this and the default constructor is a favourite of examiners and is easy to hold on to: the default constructor is supplied by the compiler and is invisible in your source, while a non-parameterised constructor is written by you and visible.
10.8.5 Parameterised Constructor
A parameterised constructor declares arguments, and the values for them are supplied inside the parentheses of the new statement.
Trip(int route, double km)
{
this.route = route;
this.km = km;
}The call new Trip(24, 13.5) creates the object and initialises it in one indivisible act. There is no moment at which a Trip exists with no route, and no way for a caller to forget the second step, because there is no second step.
Note the use of this here, exactly as section 10.6 explained. The arguments have been given the members’ own names, which reads well in the header, so each assignment must say which of the two it means.
10.8.6 Copy Constructor
Sometimes a new object should begin life holding the same values as an existing one. A copy constructor does this: it takes an object of the same class as its argument and copies that object’s members into the object being created.
Trip(Trip t)
{
route = t.route;
km = t.km;
}The call is new Trip(t2). As section 10.7.1 established, reading t.route from inside the class is allowed even though the member is private, because privacy is a matter of class rather than of object.
This is the point at which to be careful about a genuinely different operation that is often confused with it. The statement below copies no object at all.
Trip t4 = t2;It copies a reference. After it, t2 and t4 are two names for one object, and a change made through either name is seen through the other. A copy constructor makes a second object; assignment makes a second name. Figure 10.8-1 puts the two side by side, and the program that follows proves the difference by running it.
Diagram
Fig. 10.8-1 – two panels. Left panel titled “Trip t3 = new Trip(t2);”: reference boxes t2 and t3, each with an arrow to its own separate object box, the two boxes holding identical values route 24, km 13.5, with a dashed arrow between them labelled “values copied at creation”. Right panel titled “Trip t4 = t2;”: reference boxes t2 and t4 with both arrows meeting at a single object box holding route 24, km 13.5, labelled “one object, two names”
| Statement | Objects in existence, as (route, km) | What the references name |
|---|---|---|
Trip t1 = new Trip(); |
A(0, 0.0) | t1 → A |
Trip t2 = new Trip(24, 13.5); |
A(0, 0.0), B(24, 13.5) | t1 → A, t2 → B |
Trip t3 = new Trip(t2); |
A(0, 0.0), B(24, 13.5), C(24, 13.5) | t3 → C, a new object |
Trip t4 = t2; |
A, B, C unchanged | t4 → B, no new object made |
t4.change(31, 20.0); |
A(0, 0.0), B(31, 20.0), C(24, 13.5) | references unchanged |
Result: only three objects were ever created, and the single call to change() altered object B, which both t2 and t4 refer to. The trace shows why the copy constructor cannot be replaced by an assignment: assignment adds a name, not an object.
10.8.7 Constructor Overloading
The class Trip declares three constructors, all named Trip. Writing several constructors that differ in their parameter lists is called constructor overloading, and it is entirely ordinary.
The compiler decides which one to use from the arguments in the new statement — their number first, then their types. new Trip() matches the empty list, new Trip(24, 13.5) matches the int, double list, and new Trip(t2) matches the list expecting a Trip.
For this to work, no two constructors may have the same parameter list. Two constructors both taking a single int cannot be told apart, and the class will not compile, however different their bodies are.
Overloading is what makes a class convenient to use. The caller who has values supplies them, the caller who has none does not, and the caller holding an existing trip copies it — three natural ways to say “make me a Trip”, all served by the same class.
10.8.8 Constructor and Member Method Compared
The two are easily confused, because a constructor is written inside the class among the methods and looks much like them. Table 10.13 sets out the differences that matter.
| Feature | Constructor | Member method |
|---|---|---|
| Name | Exactly the class name | Any valid identifier, and by convention not the class name |
| Return type | None, not even void |
Compulsory — a type, or void |
| When it runs | Automatically, when an object is created with new |
When your code calls it explicitly |
| How often per object | Once, at creation | As often as it is called |
| Purpose | To bring the object into a valid initial state | To do the object’s work afterwards |
| May be overloaded | Yes | Yes |
10.9 Designing a Class from a Given Specification
In every program so far, the class was invented as the problem was read. In practice a class is more often handed to you already described — by a colleague, by a design document, or by the problem statement itself.
Such a description is called a class specification. It names the class, lists the data members with their types and meanings, and lists each method with what it must accept and what it must do. It stops short of saying how any of it is to be achieved; that part is yours.
Working from a specification is a skill of its own, and it is mostly a skill of reading carefully.
10.9.1 Reading a Specification and Planning the Class
A specification can be turned into a class skeleton almost mechanically, provided four questions are asked of it in order.
The first is which entries are data and which are behaviour. Data entries become instance variables, declared with the types the specification gives; behaviour entries become constructors and methods.
The second is which of the methods is a constructor. The give-away is the name: an entry named exactly like the class is a constructor, and it will be described as assigning or initialising the data members.
The third question is asked of every remaining method separately: what does it return, and what does it accept? A description that begins “to display” or “to store” returns nothing and takes void; one that begins “returns the…” needs a return type; one described with the class’s own name as its type must return an object, as section 10.7.2 showed.
The fourth is visibility. Unless the specification says otherwise, data members are private and methods are public, for the reasons set out in section 10.4.
Two habits are worth forming while you do this. Use the exact names the specification gives, because those names are the agreement between the person who wrote it and you — a method quietly renamed is a method the rest of the program cannot call. And write the skeleton in full, with empty bodies, before writing a single statement inside them; a class that compiles empty will not surprise you later with a missing brace.
10.9.2 A Complete Worked Design
Here is a specification of the kind you will meet, for a class that prepares a household water bill.
| Member | Type or return type | Description |
|---|---|---|
| name | String | Name of the consumer |
| units | int | Units of water consumed in the month |
| amount | double | Amount payable |
| WaterBill(String n, int u) | — | Constructor: assigns the name and the units, and sets the amount to zero |
| compute() | void | Calculates the amount payable from the units, using the slab below |
| display() | void | Displays the name, the units consumed and the amount payable |
The slab is stated separately, as such rules usually are.
| Units consumed | Charge |
|---|---|
| Up to 20 | Rs. 150 fixed, whatever the consumption |
| 21 to 50 | Rs. 150 plus Rs. 4 for each unit above 20 |
| Above 50 | Rs. 150 plus Rs. 4 for each of units 21 to 50, plus Rs. 6 for each unit above 50 |
Read the slab twice before writing anything, because the whole difficulty of the class lives in it. The higher rate applies only to the units inside its own band, not to the entire consumption — a consumer of 70 units is not charged six rupees for all seventy. Figure 10.9-1 shows the bands.
Diagram
Fig. 10.9-1 – a horizontal number line of units from 0 to about 80, divided into three shaded bands with boundary marks at 20 and 50; the first band labelled “0–20: fixed Rs. 150”, the second “21–50: Rs. 4 per unit in this band”, the third “above 50: Rs. 6 per unit in this band”; below the line, a worked bar for 70 units split into three lengths labelled 150, 30 × 4 = 120 and 20 × 6 = 120, with a total of 390 marked at the right
With the bands understood, the calculation can be stated in words before any Java is written.
The class follows directly.
Every class should be tried on the values where its behaviour changes, not only on comfortable ones. For this slab those values sit at the two boundaries.
| Units | Band | Amount expected |
|---|---|---|
| 20 | Top of the fixed band | 150.0 |
| 21 | First unit of the middle band | 154.0 |
| 50 | Top of the middle band | 270.0 |
| 51 | First unit of the highest band | 276.0 |
If your program agrees with all four, the two comparisons are the right way round and neither band has been left a unit short. Testing only 35 and 70, as main() does, would never have revealed a < written where <= was meant.
10.10 Summary
Classes and objects
- A class is a description, written by the programmer, of the data a thing holds and the operations it can perform. It defines a new type — a user defined data type — and by itself holds no values and occupies no memory for data.
- The values a class names become its data members; the operations become its member methods. Keeping the two together in one unit is encapsulation, and arranging matters so that outside code must go through the methods is data hiding.
- An object is an instance of a class: a real region of memory, created while the program runs, holding its own copy of every instance variable the class declares. Creating one is called instantiation.
- Reading a problem as a set of classes means finding the nouns the program must remember something about. A noun the program stores nothing about does not become a class.
- The
newoperator sets aside memory for one object, runs a constructor, and yields a reference to the object. A reference variable does not contain the object; it contains the address of the object. - Every object has its own copy of the instance variables, and the space it occupies depends on those variables. Member methods exist once for the whole class, however many objects call them.
- Members are reached through a reference and the dot operator. A member method always works on the object through which it was called.
The three kinds of variable
- An instance variable is declared in the class outside every method; there is one copy per object, and it lives as long as its object.
- A class variable carries the keyword
static; exactly one copy exists for the whole class, from the start of the program to the end, shared by every object and reachable through the class name. - A local variable is declared inside a method, constructor or block, including every formal argument; it is created on entry to the block and destroyed on exit.
- Instance and class variables receive default initial values — zero for numeric types,
falseforboolean,nullfor object types. Local variables receive none, and the compiler refuses to read one before it has been assigned. - Scope is the region in which a name may be used; lifetime is the period during which the variable exists. The three kinds differ in both.
Access specifiers
- An access specifier decides which code may use a member. A
privatemember can be used only inside its own class; apublicmember from anywhere; aprotectedmember behaves as private except to classes derived from it. - A member written with no specifier is not public. It has default, or package, visibility: usable by classes in the same package only.
- The working rule is that data members are private and the methods offered to other classes are public. Privacy costs nothing in reading, since a public method can supply a value, and gains control over every change.
- Privacy is decided per class, not per object: a method of a class may use the private members of any object of that same class.
Static members
- A static data member suits any fact that belongs to the class rather than to one object — a counter of how many objects or transactions there have been, or an accumulator such as a running total.
- A static member method belongs to the class and is called through the class name, needing no object.
mainis static for exactly this reason: it must run before any object exists. - A static method may use static members directly, but not instance variables or instance methods, because no object is involved in the call. The restriction does not run the other way — an ordinary method may freely use static members.
The current object
- Inside a member method,
thisrefers to the current object, the one through which the method was called. It is present implicitly in every unqualified use of a member’s name. - A local variable or formal argument may share a name with an instance variable, and inside the method the local name hides the member. Writing
thisbefore the name reaches the hidden member, which is what makes an assignment from an argument to a member of the same name work. - The keyword can also be passed to a method, returned from one, and used at the start of a constructor to call another constructor of the same class. It cannot appear in a static method.
Objects as arguments and return values
- A class name may be used wherever a type is expected, including the parameter list and the return type of a method.
- Passing an object passes a copy of the reference, not a copy of the object. One object exists, with two references to it, so a method that changes a member of the object it was given changes the caller’s object.
- A method that assigns an entirely new object to its parameter changes nothing outside itself, because it has redirected only its own copy of the address.
- A method whose return type is a class returns a reference. An object created inside such a method survives the method’s end, because the caller now holds a reference to it.
Constructors
- A constructor is a member with the same name as the class and no return type, invoked automatically when an object is created, whose purpose is to initialise the instance variables. It closes the gap in which a half-built object could be used.
- It may take arguments, may carry any access specifier, and may be overloaded. Declaring
voidbefore it does not make it a constructor but an ordinary method that shares the class’s name. - The default constructor is supplied by the compiler, takes no arguments and leaves every instance variable at its default value. It is supplied only when the class declares no constructor of its own.
- A non-parameterised constructor is one written by the programmer with an empty parameter list; a parameterised constructor accepts values in the
newstatement and initialises the object with them in a single act. - A copy constructor takes an object of the same class and copies its members into the object being created. This is not the same as assigning one reference to another, which makes a second name for one object rather than a second object.
- Constructor overloading means declaring several constructors differing in the number or types of their arguments; the compiler chooses among them by the arguments in the
newstatement. No two may have the same parameter list.
Designing a class from a specification
- A class specification names the class, its data members with their types and meanings, and each method with what it accepts and what it must do. It states what, not how.
- Turning it into a skeleton is a matter of four questions: which entries are data and which are behaviour, which method is the constructor, what each remaining method returns and accepts, and what visibility each member should carry.
- The names in the specification are part of the agreement and are used exactly as given. The method is stated in words before any statement is written, and the class is tested at the values where its behaviour changes, not only at comfortable ones.
10.11 Key Terms
- Access specifier — a keyword written before a member’s declaration that decides which code may use that member;
private,publicandprotectedare the three studied here. - Class — a description, written by the programmer, of the data a thing holds and the operations it can perform; it defines a type and holds no values itself.
- Class specification — a written description of a class, naming it and listing its data members with their types and its methods with what each accepts and does, without saying how any of it is to be done.
- Class variable — a variable declared inside a class with the keyword
static, of which exactly one copy exists for the whole class, shared by every object. - Constructor — a member of a class having the same name as the class and no return type, invoked automatically when an object is created, whose purpose is to initialise the instance variables.
- Constructor overloading — declaring several constructors in one class that differ in the number or the types of their arguments, among which the compiler chooses by the arguments in the
newstatement. - Copy constructor — a constructor that accepts an object of the same class and copies its members into the object being created, producing a second object rather than a second name.
- Current object — the object through which the member method now running was called; it is what the keyword
thisrefers to. - Data hiding — arranging a class so that code outside it cannot reach the data directly but must go through the class’s own methods.
- Data members — the variables declared inside a class, holding what an object of that class knows.
- Default constructor — the argument-less constructor supplied by the compiler when a class declares no constructor of its own, which leaves every instance variable at its default initial value.
- Default initial value — the value an instance variable or class variable receives when none is assigned: zero for numeric types,
falseforboolean, andnullfor object types. - Encapsulation — keeping data and the methods that act on that data together inside one unit, the class.
- Instance — one particular case of a class; the word from which instance variable and instantiation are formed.
- Instance variable — a data member declared inside the class and outside all methods, of which every object holds its own separate copy.
- Instantiation — the act of creating an object from a class.
- ISC — Indian School Certificate.
- Lifetime — the period during which a variable actually exists in memory.
- Local variable — a variable declared inside a method, a constructor or a block, including a formal argument; it exists only while that block is executing and has no default initial value.
- Member methods — the methods declared inside a class, describing what an object of that class can do.
- Non-parameterised constructor — a constructor written by the programmer with an empty parameter list, called as
new ClassName(). - Object — an instance of a class: a region of memory created at run time, holding its own copy of the class’s instance variables and able to perform its member methods.
- Parameterised constructor — a constructor that declares arguments, whose values are supplied inside the parentheses of the
newstatement and used to initialise the object. - Reference variable — a variable whose type is a class and which holds the address of an object, not the object itself.
- Scope — the region of a program in which a variable’s name may be used.
- Static data member — another name for a class variable: a member belonging to the class rather than to any object.
- Static member method — a method declared with
static, belonging to the class rather than to any object, called through the class name and able to use static members only. - User defined data type — a type created by the programmer rather than supplied by the language; in Java, a class.
- Visibility mode — another name for an access specifier, describing what it controls.
10.12 Points to Ponder
A private data member can still be handed out by a public method that returns it. In what sense, then, is anything actually hidden — and what exactly would a program lose if every class simply made its data public and trusted every programmer who used it to be careful?
A running total kept in a static member is shared by every object of the class, including objects created by parts of the program that know nothing about each other. When does that convenience turn into a liability, and how would you keep separate totals for two counters described by the same class?
Java lets a formal argument carry the same name as an instance variable, hiding it, and then supplies
thisto undo the hiding. Would the language be better if the clash were simply forbidden, so thathours = hours;could never be written? What would such a rule cost the programmer who has to name arguments?Assigning one reference to another gives a second name for one object; a copy constructor gives a second object. Some languages make the second behaviour the meaning of
=. Which choice would you defend for a class whose objects hold a great deal of data, and what would go wrong under the other one?The class in section 10.9 kept calculating and displaying in separate methods, and the specification insisted on it. Describe a concrete situation in which combining them into a single method would cost you something real — and one in which it genuinely would not matter.
A constructor makes it impossible to use an object before it has been initialised. Does it make it impossible to use an object that has been initialised badly? If not, what else must a class do, and where in the class should that work live?
10.13 Objective Questions
- A data member declared without any access specifier can be used by:
- any class anywhere in the program
- only the class in which it is declared
- any class in the same package
- only classes derived from it [1 mark]
- Which of the following is true of a constructor?
- Its return type must be
void - It has no return type at all
- Its return type must be the class name
- It may return any type the programmer chooses [1 mark]
- After the statement
Fee f = new Fee();the variablefholds:
- the object itself
- a copy of every instance variable of the object
- the address of the object
- the name of the class [1 mark]
- A static member method may use directly:
- an instance variable of its class
- a static data member of its class
- the keyword
this - an instance method of its class [1 mark]
- Memory for the instance variables of an object is set aside:
- when the class is compiled
- when a reference variable of that class is declared
- when the
newoperator is executed - when a member method is first called [1 mark]
- Assertion (A): A local variable must be assigned a value before it can be read. Reason (R): Local variables are not given any default initial value. Based on the two statements, choose the correct option:
- Both A and R are true, and R is the correct explanation of A
- Both A and R are true, but R is not the correct explanation of A
- A is true but R is false
- A is false but R is true [1 mark]
- Assertion (A): Assigning one object reference to another produces two independent objects. Reason (R): The
newoperator sets aside memory for an object at run time. Based on the two statements, choose the correct option:
- Both A and R are true, and R is the correct explanation of A
- Both A and R are true, but R is not the correct explanation of A
- A is true but R is false
- A is false but R is true [1 mark]
- Match each item in column A with the statement in column B that describes it.
| Column A | Column B |
|---|---|
| a. Class variable | i. Exists only while the method in which it is declared is running |
| b. Local variable | ii. Accepts an object of the same class and copies its members |
| c. Copy constructor | iii. Has exactly one copy for the whole class |
d. this |
iv. Refers to the object through which the method was called |
[1 mark]
Fill in the blank: A variable declared inside a class with the keyword ______ has a single copy shared by every object of that class. [1 mark]
Fill in the blank: The constructor supplied by the compiler when a class declares no constructor of its own is called the ______ constructor. [1 mark]
State whether true or false: A class reserves memory for its data members as soon as it is compiled. [1 mark]
10.14 Check Your Concepts
Define an object, and state one way in which an object differs from the class it belongs to. [2 marks]
What is meant by instantiation? Write the Java statement that instantiates a class named
Feeand stores the reference in a variablef. [2 marks]State any two features of a constructor that distinguish it from an ordinary member method. [2 marks]
Differentiate between an instance variable and a class variable, mentioning the number of copies of each and the period for which each exists. [3 marks]
Differentiate between a default constructor and a non-parameterised constructor. [3 marks]
Give reasons why a static member method cannot use an instance variable of its class directly, while an ordinary member method may freely use a static data member. [3 marks]
Explain, with a short example of your own, how the keyword
thisresolves the clash that arises when a formal argument of a method carries the same name as an instance variable. [4 marks]A class
Bookdeclares only the constructorBook(String t, double p). State with reasons what the compiler does with the statementBook b = new Book();, and explain what must be added to the class so that both forms of creation work. [4 marks]Explain the difference between passing a primitive value to a method and passing an object to a method. Illustrate with statements of your own what the calling code sees after the method has changed (i) the primitive argument and (ii) a data member of the object argument. [6 marks]
Compare a copy constructor with the assignment of one object reference to another. Write the statements needed for each, state how many objects exist in each case, and explain what happens to the second name when the first object is changed. [6 marks]
10.15 Output & Debugging
- Study the class below and answer the questions that follow.
class Ticket
{
private int id;
private static int made = 0;
Ticket()
{
made = made + 1;
id = made;
}
void show()
{
System.out.println("Ticket " + id + " of " + made);
}
public static void main(String args[])
{
Ticket a = new Ticket();
Ticket b = new Ticket();
Ticket c = new Ticket();
a.show();
c.show();
}
}- Write the exact output of the program.
- Explain why the number printed after the word “of” is the same in both lines, although the number after “Ticket” is not. [3 marks]
- The class below does not compile.
class Area
{
int side;
void set(int s)
{
side = s;
}
int square()
{
return side * side;
}
public static void main(String args[])
{
set(4);
System.out.println(square());
}
}- Name the error and state the reason for it.
- Rewrite
main()so that the class compiles and prints 16, changing nothing else. [3 marks]
- Study the class below and answer the questions that follow.
class Box
{
int n;
public static void main(String args[])
{
Box p = new Box();
Box q = new Box();
p.n = 5;
q = p;
q.n = 9;
System.out.println(p.n + " " + q.n);
}
}- Write the output of the program.
- State how many objects were created and how many of them are still referred to by a variable when the last statement runs. [3 marks]
- Study the class below and answer the questions that follow.
class Note
{
private int n;
Note()
{
n = 1;
}
Note(int n)
{
this.n = n;
}
void show()
{
System.out.println("n = " + n);
}
public static void main(String args[])
{
Note x = new Note();
Note y = new Note(7);
x.show();
y.show();
}
}- Write the output of the program, and name the constructor that runs for each object.
- State what happens to the program if the first constructor is deleted and
main()is left unchanged. [4 marks]
10.16 Programming Practice
- Design a class
Cuboidwith the following members.
| Member | Type or return type | Description |
|---|---|---|
| length, breadth, height | double | The three dimensions |
| Cuboid() | — | Constructor setting each dimension to 1.0 |
| Cuboid(double l, double b, double h) | — | Constructor assigning the three dimensions |
| volume() | double | Returns the volume of the cuboid |
| bigger(Cuboid c) | boolean | Returns true if the current object has the greater volume, and false otherwise |
| display() | void | Displays the three dimensions and the volume |
Submit the complete class with a main() method that creates one object with each constructor, displays both, and prints a message saying which is larger. Include a variable description table. [6 marks]
- A school science exhibition sells tickets at its gate. Design a class
Visitorwith the following members.
| Member | Type or return type | Description |
|---|---|---|
| name | String | Name of the visitor |
| tickets | int | Number of tickets bought by this visitor |
| count | static int | Number of visitors recorded so far |
| sold | static int | Total number of tickets sold so far |
| Visitor(String n, int t) | — | Constructor assigning the name and tickets, and updating both static members |
| display() | void | Displays this visitor’s name and tickets |
| report() | static void | Displays the number of visitors and the total tickets sold |
Submit the complete class with a main() method that records three visitors of your choice, displays each of them, and then calls report() without using any object. State clearly which members are static and why. [6 marks]
- Design a class
Feesthat calculates a coaching fee from the number of months paid for, using the rates below.
| Months paid for | Rate |
|---|---|
| 1 to 3 | Rs. 500 for each month |
| 4 to 8 | Rs. 450 for each month |
| More than 8 | Rs. 400 for each month |
The class must have private data members for the student’s name, the number of months and the amount; a parameterised constructor that assigns the name and the months and sets the amount to zero; a copy constructor; a method compute() that calculates the amount; and a method display() that shows the name, the months and the amount.
Submit the algorithm for compute() in pseudocode, then the complete class with a main() method that creates one object, computes and displays it, then creates a second object as a copy of the first and displays that too. Test your class with 6 months, and then with the unseen input of 12 months. [6 marks]
- A class
Lengthstores a distance as private memberskm(int) andm(int), where 1000 metres make one kilometre, and already has a constructor, an input method and a display method written for you.
Write only the method Length sum(Length d), which adds the distance held by the object passed to it to the distance held by the current object, and returns a new Length object holding the total with the metres correctly carried into kilometres. Neither object passed in nor the current object may be altered. State how the method would be called from main(). [4 marks]