You are on page 1of 17

Object-Oriented Programming Laboratory (Java Lab)

ITS 103 ICT SIIT


Boontawee Suntisrivaraporn (sun@siit.tu.ac.th)

Lab ]4 - Visibility Modifiers and Encapsulation


Lab objectives
To understand and use UML class diagrams
To be able to use Java modifiers
To understand the concepts of package and encapsulation

Visibility modifiers and data encapsulation


Depending on the purposes of data fields (i.e. member variables) and methods, Java provides a way to modify their
visibility. Together with the default visibility, there are four levels of visibility of class data fields and methods:
private data fields and methods can only be accessed/modified from within the declaring class;
protected modifier specifies that the member can only be accessed within its own package and, in addition,
by a subclass of its class in another package. We will talk more about superclass and subclass in a further lab
sesssion. Hence, omit the content in this lab.
public data fields and methods can be accessed/modified by any class anywhere; and
by default, data fields and methods are accessible from classes in the same package of the declaring class.
Table 1 shows the access to members permitted by each modifier.

Modifier
public
protected
no modifier
private

Table 1: Access Levels


Class Package Subclass
3
3
3
3
3
3
3
3
5
3
5
5

Anywhere
3
5
5
5

In UML, private data fields and methods are prefixed with , while public and protected data fields and
methods are prefixed with + and # respectively. The following demonstrates an example UML with visibility
modifiers:
Circle
radius: double
-PI: float = 3.14f
+Circle(radius: double)
getArea(): double
-computeDiameter(): double
+getCircumference(): double
+getDiameter(): double

Using Java packages


A Java package is a directory-like name space that is used to group related classes, and possibly also other packages
and interfaces, together. In other words, packages are an encapsulation mechanism to make a large program more
modular and reusable. To create a new package select File New Package. Optioanally, you may right click
on a project in the Package Explorer view and select New Package.

Using the import statements


After a package declaration, a number of import statements may follow with allows to specify other classes to be
reused/referenced. There are two syntactic forms for import declarations:
import <package-path>.*; //Makes visible all classes within package-path
import <package-path>.<class-name>; //Makes visible the specified class in package-path
Create a new project named Lab04-Example01. In this project, create a new package named p1, and then add
the following classes into the package. For each class, you need to create a new Java file. Compile and run the
program.

Example 1: Basic Usage of Modifier and Package


//Circle.java
package p1;
public class Circle {
double radius;
private static float PI = 3.14f;
public Circle(double radius) {
this.radius = radius;
}
double getArea() {
return PI*radius*radius;
}
private double computeDiameter() {
return 2*radius;
}
public double getCircumference() {
return 2*PI*radius;
}
public double getDiameter() {
return computeDiameter();
}
}
//CircleTester.java
package p1;
public class CircleTester{
public static void main(String[] args) {
Circle tc = new Circle(3.0);
System.out.println("Radius of the circle is " + tc.radius);
System.out.println("Area of the circle is " + tc.getArea());
}
}

Encapsulation
Encapsulation is the technique of making the variables in a class private and providing access to those variables
via public methods. One of the ways we can enforce data encapsulation is through the use of accessors and
mutators. The role of accessors and mutators are to return and set the values of class variables. If a variable is
declared private, it cannot be accessed by class outside, thus hiding the variables within the class. For this reason,
encapsulation is also referred to as data hiding. The benefits of encapsulation may be listed as follows:
1. The variables of a class can be made read-only.
2. The callers of a class do not know how the class stores its data.
3. A class can have a full control over what is stored in its body but the access is limited to the callers from
outside.
Example 2: Basic Data Encapsulation
//Puppy.java
public class Puppy{
private String name;
private int age;
public Puppy(String name){
this(name, 1);
}
public Puppy(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//PuppyTester.java
public class PuppyTester {
public static void main(String []args){
Puppy tommy = new Puppy( "Tommy" );
tommy.setAge(2);
System.out.println("Puppy name: " + tommy.getName() );
System.out.println("Age:" + tommy.getAge());
}
}

The accessor methods are used to return the value of private variables. Customarily, we use a naming scheme
prefixing the word get to the start of accessor method names. In contrast, mutator methods are used to set values
of private variables. They follow a naming scheme prefixing the word set to the start of the method names.
TO DO
From E xample 2, explain to a TA which methods are either accessor or mutator.

Example 3: Data Encapsulation and Packaging


//Horse.java
package pet;
public class Horse {
private String gender;
private int age;
private String species;
public Horse(String gender, int age, String species){
this.gender = gender;
this.age = age;
this.species = species;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
}
//Joggy.java
package rider;
import pet.Horse;
public class Joggy {
private String name;

private Horse horse;


public Joggy(String name, Horse horse){
this.name = name;
this.horse = horse;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Horse getHorse() {
return horse;
}
public void setHorse(Horse horse) {
this.horse = horse;
}
}
//JoggyTester.java
package racing;
import pet.Horse;
import rider.Joggy;
public class JoggyTester {
public static void main(String[] args){
Horse americanMorgan = new Horse("Male", 10, "American Morgan");
Joggy joe = new Joggy("Joe Jackman", americanMorgan);
printJoggyInfo(joe);
}
public static void printJoggyInfo(Joggy joggy){
Horse horse = joggy.getHorse();
System.out.println("Joggy name: "+joggy.getName());
System.out.println("Horse species: "+horse.getSpecies());
System.out.println("Horse age: "+horse.getAge());
System.out.println("Horse gender: "+horse.getGender());
}
}

Exercises
Exercise 1
1. Create a new project named Lab04-Exercise01, and copy all classes from Lab04-Example01.
2. Create another package called p2.
3. Move the class CircleTester from the package p1 to the new package p2.
4. Add the import statement right after the package declaration so that you can refer to the class Circle in
package p1.
5. Compile the source files. At this point, you should get an error at the lines where the data field radius and
the method getArea are accessed. Note that both are defined in the class Circle within the package p1, and
note also their visibility level. Explain to TA what happens and why!
6. Modify the class Circle so that the modifier of the variable radius and the method getArea are set to be
public.
7. Compile and run the source files. Explain to TA how the errors are resolved.
Exercise 2
1. Create a new project named Lab04-Exercise02, and copy the code from Lab04-Exercise01.
2. Modify the class Circle by changing the modifier of the radius data field to be private.
3. Compile the source files. You should get an error in the class CircleTester at the line where radius is
accessed. Explain to TA what happens and why!
4. Comment out the line that is erroneous.
5. Add a method public double getRadius() into the class Circle. This method simply returns the radius
of the circle.
6. Add another method public void setRadius(double radius) into the class Circle. This method assigns
the value of the input argument radius to the class data field radius. Make sure that the radius will never
become negative. If the input from a user is negative, use the default value of 0.
7. Test the modified Circle class by using the dot operator to:
a. call the method setRadius(5.0),
b. call the method getRadius(),
c. call the method getArea(),
d. call the method getDiameter(), and
e. call the method getCircumference()
8. Print out to the console screen all the returned values from Exercise 2.7. The output should look like:
The
The
The
The

radius of the circle is 5.0


area of the circle is 78.5
diameter of the circle is 10.0
circumference of the circle is 31.4

9. Explain to TA whether or not we can use the dot operator to call the method computeDiameter from within
the class CircleTester2. Why?
Note that the methods from Exercise 2.5 and 2.6 are called accessor and mutator, respectively.

Exercise 3
1. Create a new project named Lab04-Exercise03, and create a new package named p1.
2. In the package p1, implement a class Person according to the following UML:
Person
-firstName: String
-lastName: String
-age: int
+Person(firstName: String, lastName: String, age: int)
+setFirstName(firstName: String): void
+getFirstName(): String
+setLastName(lastName: String): void
+getLastName(): String
+setAge(age: int): void
+getAge(): int
3. Implement the constructor with three parameters: firstName, lastName and age of which values are assigned
to the class data fields firstName, lastName and age, respectively.
4. Implement the accessor methods: getFirstName, getLastName and getAge that access the respective data
fields.
5. Implement the modifier methods: setFirstName, setLastName and setAge that assign to the respective data
field a new value from the methods parameter.
Exercise 4
1. Create a new project named Lab04-Exercise04, and copy the code from Lab04-Exercise03.
2. Augment to the project by creating a new package named p2.
3. In package p2, implement a class Account according to the following UML. Here you may modify the source
file Lab03-Exercise02 to satisfy the specification. Note that you need to add an import statement after the
package declaration in the class Account so that you can refer to the class Person in the package p1.
Account
-NUM OF ACCS: int = 0
-accID: int
-balance: double
-owner: Person
+Account(accID: int, owner: Person, balance: double)
+deposite(amount: double): void
+withdraw(amount: double): void
+GET NUM OF ACCS(): int
+printAccountDetail(): void
4. Implement a constructor with three parameters: accID, owner and balance of which values are assigned to the
respective class data fields. Additionally, the constructor increases the value of the static variable NUM OF ACCS
by 1.
5. Implement the method deposit to take an argument amount of type double and update balance by adding
amount to its value.
6. Implement the method withdraw to check whether the amount to be withdrawn is greater than balance of
the account. If so, print to the screen that the account has an insufficient fund. Otherwise, subtract it from
the balance.

7. Implement the static method GET NUM OF ACCS to simply return the value of the static variable NUM OF ACCS.
8. Implement the method printAccountDetail to print the accounts details including the account ID, owner,
owners name, owners age and the current balance. The output format should be:
Account number: XXX
Owner: XXX
Age: XXX
Current balance: XXX
where the XXX is a detail of the account.
9. Try to remove the static keyword from the data field declaration NUM OF ACCS and see what happens. Explain
to TA why?
Exercise 5
1. Create a new project named Lab04-Exercise05, and copy the code from Lab04-Exercise04.
2. Augment to the project by creating a new package named p3.
3. In the package p3, create a new class called AccountTester.
4. Add import statements after the package declaration in the class AccountTester so that the classes Person
and Account in packages p1 and p2, respectively, can be accessed.
5. Add a main method to AccountTester. Add statements to the main method to perform the following tasks:
i. Create an instance of Person whose first name is Keanu, last name is Reef, and age is 36. Then,
assign it to a variable cust1 of type Person.
ii. Create another instance of Person whose first name is Leonado, last name isDicaprio, and age is 28.
Then, assign it to a variable cust2 of type Person. Use the dot operator to:
a. call setFirstName with Tom as the input argument,
b. call setLastName with Cruise as the input argument, and
c. call setAge with 35 as the input argument.
iii. Create an instance of Account where the account ID is 1, the owner is cust1, and balance is 1000. Then,
assign it to a variable acc1 of type Account. Use the dot operator to:
a. call deposit with 1000 as the input argument,
b. call withdraw with 200 as the input argument, and
c. call printAccountDetail
iv. Create another instance of Account where the account ID is 2, the owner is cust2 and balance is 2000.
Then, assign it to a variable acc2 of type Account. Use the dot operator to call printAccountDetail.
The output from these new statements should be:
Account number: 1
Owner: Keanu Reef
Age: 36
Current balance: 1800.0
Account number: 2
Owner: Tom Cruise
Age: 35
Current balance: 2000.0
6. Try to call the method GET NUM OF ACCS from within the class context Account and from an object context,
e.g. acc1. Is there any error? If so, why? If not, what are the values from the two calls? Explain your
understanding to TA.

Exercise 6
1. Create a new project named Lab04-Exercise06, and copy classes from the project Lab04-Example03.
2. In the package pet, implement a class PetOwner according to the following UML.
PetOwner
-name: String
-address: String
+PetOwner(name: String, address: String)
+setName(name: String): void
+getName(): String
+setAddress(address: String): void
+getAddress(): String
The constructor takes two parameters: name and address of which values are assigned to the respective class
data fields. The setter methods assign the input value to their correspondants. The getter methods return
the respective values back to the caller.
3. In the package pet, edit the class Horse to meet the following UML.
Horse
-gender: String
-age: int
-species: String
-owner: PetOwner
+Horse(gender: String, age: int, species: String)
+Horse(gender: String, age: int, species: String, owner: PetOwner )
+getGender(): String
+setGender(gender: String): void
+getAge(): int
+setAge(age: int): void
+getSpecies(): String
+setSpecies(species: String): void
+getOwner(): PetOwner
+setOwner(owner: PetOwner): void
In the three-argument constructor, instead of a direct value assignment, use the this keyword to invoke the
four-argument constructor. Passing the fourth argument, you need to create a new object of type PetOwner
whose owners name and owners address are unknown.
Exercise 7
1. Create a new project named Lab04-Exercise07, and copy classes from the project Lab04-Exercise06.
2. In the class JoggyTester, edit the method printJoggyInfo to print additional information of the horses
owner including owners name and owners address. Note that you need to add an import statement after the
package declaration so that you can refer to the class PetOwner in the package pet.
3. In addition to the main method, do the following tasks:
i. Create an instance of PetOwner whose name is Bob Lee, and address is 151 Kensington Street, UK.
Then, assign it to a variable bob of type PetOwner.
ii. Create an instance of Horse whose horse gender, horse age, horse species, and its owner are Female,
11, Arabian, and bob repectively. Then, assign it to a variable arabian of type Horse.

iii. Create an instance of Joggy whose joggy name and horse are Sam Olens, and arabian repectively.
Then, assign it to a variable sam of type Joggy. Make a call to the method printJoggyInfo. Use the
object sam as an input argument. You should have outputs similar to the following.
Joggy
Horse
Horse
Horse
Owner
Owner

name: Joe Jackman


species: American Morgan
age: 10
gender: Male
name: unknown
addr: unknown

Joggy
Horse
Horse
Horse
Owner
Owner

name: Sam Olens


species: Arabian
age: 11
gender: Female
name: Bob Lee
addr: 151 Kensington Street, UK

10

Appendix this is only for TA use and must not be handed out to students
Solution to Exercise 1
package p1;
public class Circle{
public double radius;
static float PI = 3.14f;
public Circle(double radius){
this.radius = radius;
}
public double getArea(){
return PI*radius*radius;
}
private double computeDiameter(){
return 2*radius;
}
public double getCircumference(){
return 2*PI*radius;
}
public double getDiameter(){
return computeDiameter();
}
}
package p2;
import p1.Circle;
public class CircleTester{
public static void main(String[] args) {
Circle tc = new Circle(3.0);
System.out.println("The radius of the circle is " + tc.radius);
System.out.println("The area of the circle is " + tc.getArea());
System.out.println("The aiameter of the circle is " + tc.getDiameter());
System.out.println("The circumference of the circle is "
+ tc.getCircumference());
}
}
Solution to Exercise 2
// Circle.java
package p1;
public class Circle{
private double radius;
static float PI = 3.14f;
public Circle(double radius){
this.radius = radius;
}

11

public void setRadius(double radius){


if(radius < 0)
radius = 0;
this.radius = radius;
}
public double getRadius(){
return radius;
}
public double getArea(){
return PI*radius*radius;
}
private double computeDiameter(){
return 2*radius;
}
public double getCircumference(){
return 2*PI*radius;
}
public double getDiameter(){
return computeDiameter();
}
}
// TestCircle.java
package p2;
import p1.Circle;
public class CircleTester2{
public static void main(String[] args) {
Circle tc = new Circle(3.0);
//System.out.println("Radius of a circle is "+tc.radius);
tc.setRadius(5.0);
System.out.println("Radius of the circle is "+tc.getRadius());
System.out.println("Area of the circle is "+tc.getArea());
System.out.println("Diameter of the circle is "+tc.getDiameter());
System.out.println("Circumference of the circle is
"+tc.getCircumference());
}
}
Solution to Exercise 3-5
// Person.java
package p1;
public class Person {
private String firstName;
private String lastName;
private int age;
public Person(String firstName, String lastName, int age){
this.firstName = firstName;

12

this.lastName = lastName;
this.age = age;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
// Account.java
package p2;
import p1.Person;;
public class Account{
private static int NO_OF_ACCS = 0;
private int accID;
private double balance;
private Person owner;
public Account(int accID, Person owner, double balance){
this.accID = accID;
this.owner = owner;
this.balance = balance;
NO_OF_ACCS++;
}
public void deposit(double amount) {
balance = balance + amount;
}
public void withdraw(double amount) {
if (balance - amount < 0) {
System.out.println("Insufficient funds for account "+accID);
} else {
balance = balance - amount;
}

13

}
public static int GET_NUM_OF_ACCS() {
return NO_OF_ACCS;
}
public void printAccountDetail(){
System.out.println("Account number: "+accID);
System.out.println("Owner: "+owner.getFirstName()+" "
+owner.getLastName());
System.out.println("Age: "+owner.getAge());
System.out.println("Current balance: "+balance); System.out.println();
}
}
// AccountTester.java
package p3;
import p1.Person;
import p2.Account;
public class AccountTester {
public static void main(String args[]){
Person cust1 = new Person("Keanu","Reef",36);
Person cust2 = new Person("Leonado","Dicaprio",28);
cust2.setFirstName("Tom");
cust2.setLastName("Cruise");
cust2.setAge(35);
Account.GET_NUM_OF_ACCS();
Account acc1 = new Account(1, cust1, 1000);
acc1.deposit(1000);
acc1.withdraw(200);
acc1.printAccountDetail();
System.out.println("Number of accounts: "+Account.GET_NUM_OF_ACCS());
System.out.println("Number of accounts: "+acc2.GET_NUM_OF_ACCS());
Account acc2 = new Account(2, cust2, 2000);
acc2.printAccountDetail();
System.out.println("Number of accounts: "+Account.GET_NUM_OF_ACCS());
System.out.println("Number of accounts: "+acc2.GET_NUM_OF_ACCS());
}
}
Solution to Exercise 6-7
\\Horse.java
package pet;
public class Horse {
private String gender;
private int age;
private String species;
private PetOwner owner;

14

public Horse(String gender, int age, String species){


this(gender, age, species, new PetOwner("unknown","unknown"));
}
public Horse(String gender, int age, String species, PetOwner owner){
this.gender = gender;
this.age = age;
this.species = species;
this.owner = owner;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
public PetOwner getOwner() {
return owner;
}
public void setOwner(PetOwner owner) {
this.owner = owner;
}
}
//PetOwner.java
package pet;
public class PetOwner {
private String name;
private String address;
public PetOwner(String name, String address){
this.name = name;
this.address = address;
}

15

public String getName() {


return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
//Joggy.java
package rider;
import pet.Horse;
public class Joggy {
private String name;
private Horse horse;
public Joggy(String name, Horse horse){
this.name = name;
this.horse = horse;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Horse getHorse() {
return horse;
}
public void setHorse(Horse horse) {
this.horse = horse;
}
}
//JoggyTester.java
package racing;
import pet.Horse;
import pet.PetOwner;
import rider.Joggy;

16

public class JoggyTester {


public static void main(String[] args){
Horse americanMorgan = new Horse("Male", 10, "American Morgan");
Joggy joe = new Joggy("Joe Jackman", americanMorgan);
printJoggyInfo(joe);
PetOwner bob = new PetOwner("Bob Lee", "151 Kensington Street, UK");
Horse arabian = new Horse("Female", 11, "Arabian", bob);
Joggy sam = new Joggy("Sam Olens", arabian);
printJoggyInfo(sam);
}
public static void printJoggyInfo(Joggy joggy){
Horse horse = joggy.getHorse();
System.out.println("Joggy name: "+joggy.getName());
System.out.println("Horse species: "+horse.getSpecies());
System.out.println("Horse age: "+horse.getAge());
System.out.println("Horse gender: "+horse.getGender());
PetOwner owner = horse.getOwner();
System.out.println("Owner name: "+owner.getName());
System.out.println("Owner addr: "+owner.getAddress());
System.out.println();
}
}

17

You might also like