0% found this document useful (0 votes)
2 views26 pages

JavaObj 11 Chap2

JavaObj_11_Chap2

Uploaded by

balaji.pvb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views26 pages

JavaObj 11 Chap2

JavaObj_11_Chap2

Uploaded by

balaji.pvb
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Object-Oriented Java

Chapter 2

Encapsulation in Java

Rev. 1.1 [Link] 2-1


Copyright © 1999 William W. Provost
Object-Oriented Java

Encapsulation in Java

Objectives

After completing this unit you will be able to:


• Implement a class design in Java using classes, fields
and methods.
• Write methods to use the implicit this reference as
well as to make references outside the class or object
scope.
• Define constructors to properly initialize class
instances.
• Define field and method visibility according to class
design and Java package design.
• Overload methods to provide semantic convenience to
the client code.
• Implement one-to-many relationships using Java
collection classes.

Rev. 1.1 [Link] 2-2


Copyright © 1999 William W. Provost
Object-Oriented Java

Getting Our Bearings

• In the previous module we studied Java largely as a


procedural programming language.
• The previous chapter provided a grounding in object-
oriented methodology and terminology.
• Now we undertake a study of Java as an object-
oriented language, beginning to get the full value
from class and object relationships and inheritance.
− We will study the implementation of a class or class design in
the Java language.
− We will look at some Java-specific techniques for
implementing a robust system.

Rev. 1.1 [Link] 2-3


Copyright © 1999 William W. Provost
Object-Oriented Java

Java Classes

• Java models classes using the class construct.


− Classes hold fields and methods as members, and the total of
these members defines a type.
− Classes can be instantiated one or many times in the run of
an application; the instances are objects.

• Each field is represented by the appropriate


allocation of memory for each instance of the class.
− So different objects of one type can have different state.
− When a field is defined as static, there will be only one
representation of the field as a value in memory; the state is
then related to the class itself. Reference a static field with
the dot separator, using the name of the class, not the object.

• Each method is represented only once as runnable


code in memory.
− When a method is called, it is called on a particular object,
using the dot separator.
− This object reference is then implicit in the method’s
behavior; it is in fact provided to the method via a compiler-
initialized reference called this.
− When the method code refers to it’s own class’ members, the
this reference is used implicitly.
− A method defined as static simply has no this reference, and
thus cannot operate on non-static fields or call non-static
methods.
Rev. 1.1 [Link] 2-4
Copyright © 1999 William W. Provost
Object-Oriented Java

A Java Date Class

• Consider a simple example: a Date class as shown:

public class Date


{
public short getYear ()
{
return year;
}
...
public boolean equals (Date other)
{
return year == [Link] &&
month == [Link] &&
day == [Link];
}
...
private short year;
private short month;
private short day;
private static short[] daysInAMonth;
}
• Note that the getYear method can refer directly to the
year field; the particular value is known thanks to the
implicit expansion of year to [Link].
• To compare to another date instance, however, the
code must combine implicit self-reference and
reference to members of the passed date object.
• The static member daysInAMonth occurs only once.

Rev. 1.1 [Link] 2-5


Copyright © 1999 William W. Provost
Object-Oriented Java

Visibility

• The visibility of a member determines what other


pieces of the system can see and use it.
• Object-oriented analysis and design in general
recognize three levels of visibility, and in Java each is
defined by a corresponding keyword:
− public members are just that; anyone can use them.
− private members can only be seen from inside the class.
− protected members can only be see from inside the class and
from any subclasses.

• Java adds another level, known as default or package


visibility.
− It is called package visibility because it dictates that the
member can be seen only by classes that share the enclosing
class’ package.
− The potential use of this level can have a great deal of impact
on choices regarding the best package design.
− It is called default visibility because there is no keyword
used to define it; it applies by default.

• Define visibility per member using the public, private,


and protected modifiers, or nonefor package visibility.
• Note that visibility applies to classes, not to objects:
two objects of the same type can see each other’s
private or protected members.
Rev. 1.1 [Link] 2-6
Copyright © 1999 William W. Provost
Object-Oriented Java

Constructors

• Java recognizes a specialized method definition


known as a constructor.
• Constructors are defined much as are methods, with
some basic distinctions.
− Constructors always bear the name of the class itself.
− Constructors do not return a value.
− They may take arguments and throw exceptions.
public class Point
{
public Point (int x, int y) { ... }
}

• Constructors are called implicitly on object creation,


after memory has been allocated for the object’s
fields, to allow the object to initialize that memory.
− If no constructor is explicitly defined for a class, the compiler
will supply a public default constructor: one that takes no
arguments.
− If any constructors are defined, this default constructor will
not be built by the compiler. It is a good idea to define a
default constructor if you think you will use one.
− When the object is created with new, any arguments supplied
at that time are passed to the constructor.
Point myPoint = new Point (4, 5);

Rev. 1.1 [Link] 2-7


Copyright © 1999 William W. Provost
Object-Oriented Java

Explicit Use of this

• The this reference, often used implicitly, can be useful


as explicit code in a number of situations.
• A method may need to be defined to pass the current
object reference to another method as an argument.
− For instance a method in one class may need to add the
object to a collection implemented by another class.
− Here the this reference can be used just like any other object
reference:
public makeAppt (Calendar cal, String desc)
{
[Link] (this, desc);
}

• Also, in constructors especially, and sometimes in


other methods, this can be used to override scoping
rules.
− It is legal for a class member and a method’s local variable to
have the same name.
− The compiler sees the unqualified name as referring to the
local or method scope by default.
− You can refer to the class member that would be hidden by
this local name using this:
public Point (int x, int y)
{
this.x = x;
this.y = y;
}

Rev. 1.1 [Link] 2-8


Copyright © 1999 William W. Provost
Object-Oriented Java

Finalizers

• Those familiar with C++ in particular will wonder


where is the construct in Java for the opposite
number of a constructor (a destructor in C++).
• Java does not define or recognize destructors.
• Remember that Java is a garbage-collected
environment.
− You create an object on the heap using new, and a
constructor is called as part of that process.
− The object is reference-counted implicitly by the JVM, and
when no longer referenced is freed for garbage collection.
− This happens on another thread and has no guaranteed
timing.
− Also, there is little need for a destructor, since most
destructor code has to do with explicitly deleting other
referenced objects, and in Java this is unnecessary.

• Java does define a special method called a finalizer


which is at least roughly analogous to a destructor.
protected void finalize ()
− Most classes do not need or have finalizers, and because they
are called in unpredictable patterns they are of limited use.
− However there are times at which they are important, such as
when an object holds a reference to something outside the
JVM, a CORBA reference for instance and needs to clean up.

Rev. 1.1 [Link] 2-9


Copyright © 1999 William W. Provost
Object-Oriented Java

Static Initializers

• Since there are no globals in Java, a class that defines


static fields must have a well-defined entry point for
initializing those fields.
• Simple fields can be initialized right in the
declaration, but collections are another matter.
public static String filename = “[Link]”;

• The constructor would be workable, but


inappropriate, because it is called every time an
object is created.
• Java recognizes a construct called a static initializer
block, code in which will be invoked once and once
only, when the class itself is loaded into the JVM.
• Perform initializations of static fields here.
public class Car
{
public static String[] optionNames;

static
{
optionNames = new String[5];
optionNames[0] = “Alloy wheels”;
optionNames[1] = “Power locks”;
optionNames[2] = “Onboard GPS”;
optionNames[3] = “10-disc CD changer”;
optionNames[4] = “Reciprocal defenestrator”;
}
}

Rev. 1.1 [Link] 2-10


Copyright © 1999 William W. Provost
Object-Oriented Java

Overloaded Methods

• You can provide multiple signatures for the same


method or constructor in Java.
− This is called overloading a method.
− The caller can call the method with arguments to match any
of the overloaded parameter lists.
public class Thread // in [Link] package
{
public Thread ();
public Thread (Runnable behavior);
}
... Thread thread1 = new Thread ();
Thread thread2 = new Thread (MyTask);

• Overloading constructors is especially useful, since


you don’t have a choice of method name.
• It is common to use overloads as a way of providing
default values for some arguments.
− Remember, Java does not support default arguments as part
of the method signature.
− One method with fewer parameters can call another overload
of the method, providing the default arguments.
public class Dialer
{
public void dial (int number, int retries) {...}
public void dial (int number)
{
dial (number, 3);
}
}

Rev. 1.1 [Link] 2-11


Copyright © 1999 William W. Provost
Object-Oriented Java

Rules for Overloading

• Overloads must be differentiated by their parameter


lists.
− Different overloads can have different return types.
− But return type alone cannot be used to disambiguate method
signatures when the compiler is trying to build a call.

• Consider the following code, meant to allow the caller


to get the SSID attribute as a number or as a string:
public class MyClass
{
public int SSID ();
public String SSID ();
}

• The compiler would not be able to decide for sure


which method signature should be invoked based on
the call as shown, so it disallows the overload.
• Some good news: the compiler can decide on a
method using widening (implicit) type conversions,
which it will favor over narrowing conversions:
public class MyClass
{
public void sendIt (short number);
public void sendIt (long number);
}
...
[Link] (5L); // long
[Link] ((short) 5); // short
[Link] (5); // long!

Rev. 1.1 [Link] 2-12


Copyright © 1999 William W. Provost
Object-Oriented Java

What Can’t You Overload?

• Java is not nearly as ambitious in supporting


overloading as for instance the C++ language.
• You cannot overload operators in Java.
− All Java operators have predefined usages for various
argument types.
− Some are essentially overloaded in the compiler’s support for
them: for instance the + operator can be a unary sign
operator, a binary mathematical operator, or a binary string-
concatenation operator.
− You cannot change the behaviors of operators, and these
behaviors are all understood at compile time.

• Similar capability can be implemented for a class by


virtue of the fact that all Java classes ultimately
inherit the [Link] class.
− Instead of overloading operators, the technique in Java is
usually to override a member of this class.

− For instance, instead of overloading the == operator to define


equivalence for a class, override the equals method.

• Also, you cannot overload new in Java.


− Memory allocation must be strictly controlled by the JVM.
− Therefore new has a simple set of behaviors based on
different usages like arguments, array allocations, etc.

Rev. 1.1 [Link] 2-13


Copyright © 1999 William W. Provost
Object-Oriented Java

Implementing Relationships

• All relationships in a class design will be expressed in


Java through some use of object references.
• If one class simply uses another’s semantics, but does
not have any closer relationship – a dependency –
typically the first class’ methods will take object
references of the second class:
public void myMethod (SomeOtherClass collaborator)
{
// do my stuff
[Link] (this);
}

• Aggregation of one class by another is usually


implemented by adding an field to the aggregating
class of the aggregated type:
public void myMethod ()
{
// do my stuff
[Link] (this);
}

private SomeOtherClass collaborator;

• Other associations may be realized in a number of


ways, for instance via a third class that allows one
class’ code to lookup instances of another.

Rev. 1.1 [Link] 2-14


Copyright © 1999 William W. Provost
Object-Oriented Java

Collections

• To implement a one-to-many relationship, for


instance an aggregation, you will most likely use
either an array or a collection of some sort.
• Java provides, via the Core API in the [Link]
package, a library of collection classes and interfaces.
• There are various implementations and behaviors
available through different classes in the package:
− Vector provides an indexed collection with inexpensive
random access but more expensive insertion and reallocation.
− LinkedList implements a simple linked list with only
next/previous traversal but inexpensive insertions and
deletions.
− Hashtable offers a hashed key-value table, expensive to
allocate but very efficient for searching.

• The various collection classes implement one or more


standard collection interfaces, giving consistent
semantics regardless of underlying implementation.
− This simplifies coding and allows performance tuning
throughout development by substituting different collection
types as usage patterns are recognized.
− It also provides algorithms with consistent interfaces for
behaviors like iterating, search, sorting, shuffling, etc.

• All collections hold instances of the Object class.

Rev. 1.1 [Link] 2-15


Copyright © 1999 William W. Provost
Object-Oriented Java

Iterators

• There are standard interfaces and classes for


iteration behaviors.
• Get a collection’s iterator by calling it’s iterator
method.
• There are a few flavors of iterator, some providing
behaviors that only certain collection
implementations could support.
• Here is an example of use of a LinkedList and
ListIterator to gather some strings and then
concatenate them to one:
LinkedList listStrings = new LinkedList ();
[Link] (“Hello”);
[Link] (“there”);
[Link] (“handsome”);

ListIterator eachString = [Link] ();


String complete = “”;
while ([Link] ())
{
complete += (String) [Link] ();
complete += “ “;
}

• Note that any object can be converted to type Object,


so the additions don’t need typecasts, but the
retrieval of each element through next returns an
Object that must be downcast to the correct type.

Rev. 1.1 [Link] 2-16


Copyright © 1999 William W. Provost
Object-Oriented Java

The Car Dealership

• We will begin an implementation of the car


dealership design from the previous chapter in our
two labs, and continue to refine it throughout the rest
of the course.
• The class design from Lab 1A calls for support for a
few behaviors; we will state them more clearly now
prior to starting the labs.
− The client must be able to get a look at all the cars on the lot,
through a method [Link].
− The client must be able to get details about a car based on its
Vehicle Identification Number, or VIN, through a method
[Link].
− The client must be able to buy a car by providing the Car as
an object reference along with an reference to a Customer,
which will be queried for details as the sale proceeds, through
the method [Link].

Rev. 1.1 [Link] 2-17


Copyright © 1999 William W. Provost
Object-Oriented Java

Lab 2A

Building the Car Dealership

In this lab you will implement the car dealership design from Lab
1A.

Suggested time: 45 minutes

Rev. 1.1 [Link] 2-18


Copyright © 1999 William W. Provost
Object-Oriented Java

Lab 2B

Selling Optional Features

In this lab you will complete the implementation of the car


dealership design from lab 1A. The starter code is the completion
of lab 2A plus some additional initialization code.

Suggested Time: 15 minutes

Rev. 1.1 [Link] 2-19


Copyright © 1999 William W. Provost
Object-Oriented Java

Summary

• Java provides complete support for implementation


of object-oriented designs.
• In fact, Java relies heavily on classes for its basic
functionality as an environment, partially through
enforcement of the rule that all classes ultimately
inherit [Link].
• We will study this more carefully in the next chapter,
in which we focus on inheritance and polymorphism
as supported by the Java language.
• Java is pointedly object-oriented, and all code in a
Java application must live in some class.
• In lieu of globals (and for other reasons), Java
recognizes the definition of static fields and methods,
which may or may not be made publically visible.
• The Core API provides a library of collection classes
to simplify the implementation and management of
one-to-many relationships between classes.

Rev. 1.1 [Link] 2-20


Copyright © 1999 William W. Provost
Object-Oriented Java

Lab 2A

Building the Car Dealership

Introduction

In this lab you will implement the car dealership design from lab 1A. If you did not do
that lab, read over it now for background on the requirements for the implementation.
The final class diagram from that lab is reproduced here:

Starter code is provided for each of the three classes shown here, plus a simple console
Application class. Each starter file defines a public class in the correct package. You
will begin by reviewing some of the additional starter code.

Suggested Time: 45 minutes

Directories: Labs\JavaMod3Lab2A (do your work here)


Examples\Cars\Step0 (backup copy of starter files)
Examples\Cars\Step1 (answer)

Files: [Link]
[Link]
[Link]
[Link]

Packages: [Link]

Rev. 1.1 [Link] 2-21


Copyright © 1999 William W. Provost
Object-Oriented Java

Instructions
1. Open the Application source file and review the starter code. There is a method
prime to create a salesman and to initialize his collection of cars. The main method
parses the command line for a command argument and implements the three use
cases based on that and other arguments. Note that this class won’t compile until you
fill in the other three.

2. Now review the Car class, the main data type for the system. All the fields of the
class are private. For each field, there is a public accessor method. Which of the
fields should have mutators as well?

3. Implement a mutator void setSold (boolean). The other fields can all be read-only
for our purposes. (This certainly begs the question of where all the data will come
from, but that’s another matter, and one which we’ll treat in a later module at that.)

4. How will a new car be created? If you build a new one and try to set all its fields you
will not have visibility. This is of course a job for a constructor. Implement a public
constructor that accepts parameters (in this order) make, model, year, VIN, color,
mileage, and price. Initialize the class completely; you will assume that the car is not
sold when it is created. Compile the Car class.

5. Now let’s turn our attention to the Customer class. Create private fields for name
and money. (We will implement options later in this lab.) Take the same approach
as with Car: read-only fields, a constructor that can fully initialize an instance.

6. Add the method canAfford to the Customer class. Just compare the argument price
to the money field and return true or false. Compile the class.

7. Salesman will tie this all together. First build a collection of Cars as a field on the
class. What sort of collection would be best? Consider the likely usage pattern based
on the designs (including the conclusion of lab 1B.)

8. The best choice would probably be a TreeSet; since we’d like to search for a car by
its VIN, and since the collection is initialized all at once at startup, this would make
for the most efficient use. For this lab, however, we’re going to keep it simple and
use a LinkedList. Add a field of type List called cars, and initialize it in its
declaration to be a new LinkedList. Note that you need to import the class from
package [Link]; the import statement is already in the source file. Give the field
package visibility, so that the Application class can populate the collection. (This is
frankly a concession of proper practice to available time. We will revisit the
initialization of this collection in later labs.) Try a compile, and compile the
Application class at this point as well. Test by use case 1 with the following
command line:
java [Link] list

Rev. 1.1 [Link] 2-22


Copyright © 1999 William W. Provost
Object-Oriented Java

9. Well, it’s a step, but the printout isn’t very helpful to the potential car buyer, is it?
Look at the code for [Link] and see that it is printing each car directly to
the output stream. This means that the implicit string conversion is being used. Does
Car have a toString implementation? We’d better give it one. Write code to return a
string of the following format:
<year> <make> <model> (<VIN>)

10. Rebuild and retest. You should see a more pleasing printout at this point. While at it,
implement [Link], if you haven’t already; just return the customer
name.

11. Now implement the findCar method to take a VIN and return a reference to the car,
or null if not in the collection. (Look to the listCars implementation for an example
of iterating over a list.) You will need to downcast each list element to type Car
before getting the VIN and comparing to the argument. You can test this as follows;
look at the list from the last step for a valid VIN:
java [Link] find <VIN>

12. Now for the big one: implement sellCar to accept a Car and a Customer parameter;
get the price of the car and pass it to the customer’s canAfford method, failing if this
returns false; then complete the sale by marking the car as sold and returning true.
Code this, rebuild and test as shown below. (Note that the Application code parses
the money argument as an integer, not a floating-point number.) Try different
amounts of money and see that your code handles each situation correctly.
java [Link] buy <VIN> <Customer name> <money>

Rev. 1.1 [Link] 2-23


Copyright © 1999 William W. Provost
Object-Oriented Java

Lab 2B

Selling Optional Features

Introduction

In this lab you will complete the implementation of the car dealership design from lab
1A. The starter code is the completion of lab 2A plus some additional initialization code.

Suggested Time: 15 minutes

Directories: Labs\JavaMod3Lab2B (do your work here)


Examples\Cars\Step2 (backup copy of starter files)
Examples\Cars\Step3 (answer)

Files: [Link]
[Link]
[Link]
[Link]

Packages: [Link]

Instructions
1. Add support for options to the Car class. Remember that our design calls for a public
static string array optionNames to support the option names available for all cars, and
a non-static double array optionPrices to support the available options and pricing
per car instance. Give this latter array package visibility (yes, another corner cut).
Compile the class. (Note that there is a static initializer block in the class’ starter
code that initializes the optionNames array, and a new addOption method that is
used by the data initialization code in Application.)

2. Open the Customer source and review the additions to code since the last lab. There
is a wantsOption method that refers to a hardcoded array of desirable options. This
is just to keep things simple; of course in a real development we would provide a
more thorough interface to this feature.

3. Open the Application source and add code to the find command handler to report the
available options and prices along with other details. Do this by looping over the
[Link] array, and for each, test that the price in [Link] is not
negative (our way of expressing that it is not available), and if not print the name and
the corresponding price. Build and test with the find command.

Rev. 1.1 [Link] 2-24


Copyright © 1999 William W. Provost
Object-Oriented Java

4. Now add code to [Link] to check with the customer about available
options prior to making the sale. Specifically, for each option in the
[Link] array, check that it is available (non-negative price); if so, ask the
customer if she wants the named option; if so, add the price to the total price of the
car. (You may want to add a diagnostic to this loop, to report to the console the result
of each option check.) Then check that total price against [Link] as
before. Compile the whole project and test by trying to buy a car with just enough
money for the car itself, such that if the car has options that are in the (currently
hardcoded) list in [Link], the price will go over the customer’s
limit.

Rev. 1.1 [Link] 2-25


Copyright © 1999 William W. Provost
Object-Oriented Java

Rev. 1.1 [Link] 2-26


Copyright © 1999 William W. Provost

You might also like