Oop Exercises Java Programming Tutorial For Beginers
Oop Exercises Java Programming Tutorial For Beginers
Java Programming
1.1 Exercise: The Circle Class
1.2 Exercise: The Author and Boo
1.3 Exercise: The MyPoint Class
Tutorial 1.4 Exercise: The MyCircle Class
1.5 Exercise: The MyTriangle Cla
https://www3.ntu.edu.sg/home/ehchua/programming/java/J3f_OOPExercises.html
1/3
Two public methods: getRadius() and getArea().
The source codes for Circle is as follows:
// 1st constructor, which sets both radius and color to default public Circle() {
radius = 1.0; color = "red";
}
// 2nd constructor with given radius, but color default public Circle(double r) {
radius = r; color = "red";
}
// A public method for computing the area of circle public double getArea() {
return radius*radius*Math.PI;
}
Compile "Circle.java". Can you run the Circle class? Why? This Circle class does not have a main()
method. Hence, it cannot be run directly. This Circle class is a “building block” and is meant to be used in
another program.
Let us write a test program called TestCircle which uses the Circle class, as follows:
TRY:
1. Constructor: Modify the class Circle to include a third constructor for constructing a Circle instance
with the given radius and color.
// Construtor to construct a new instance of Circle with the given radius and color
public Circle (double r, String c) {......}
Modify the test program TestCircle to construct an instance of Circle using this constructor.
2. Getter: Add a getter for variable color for retrieving the color of a Circle instance.
5. Keyword "this": Instead of using variable names such as r ﴾for radius﴿ and c ﴾for color﴿ in the
methods' arguments, it is better to use variable names radius ﴾for radius﴿ and color ﴾for color﴿ and use
the special keyword "this" to resolve the conflict between instance variables and methods' arguments. For
example,
// Instance variable
private double radius;
// Setter of radius
public void setRadius(double radius) {
this.radius = radius; // "this.radius" refers to the instance variable
// "radius" refers to the method's argument
}
Modify ALL the constructors and setters in the Circle class to use the keyword "this".
6. Method toString(): Every well‐designed Java class should contain a public method called
toString() that returns a short description of the instance ﴾in a return type of String﴿. The toString()
method can be called explicitly ﴾via instanceName.toString()﴿ just like any other method; or implicitly
through println(). If an instance is passed to the println(anInstance) method, the toString()
method of that instance will be invoked implicitly. For example, include the following toString() methods
to the Circle class:
public String toString() {
return "Circle: radius=" + radius + " color=" + color;
}
Try calling toString() method explicitly, just like any other method:
﴾There is no default constructor for Author, as there are no defaults for name, email and gender.﴿
public getters/setters: getName(), getEmail(), setEmail(), and getGender();
﴾There are no setters for name and gender, as these attributes cannot be changed.﴿
A toString() method that returns "author‐name (gender) at email", e.g., "Tan Ah Teck ﴾m﴿ at
ahTeck@somewhere.com".
Write the Author class. Also write a test program called TestAuthor to test the constructor and public
methods. Try changing the email of an author, e.g.,
getQtyInStock(), setQtyInStock().
toString() that returns "'book‐name' by author‐name (gender) at email".
﴾Take note that the Author's toString() method returns "author‐name (gender) at email".﴿
Write the class Book ﴾which uses the Author class written earlier﴿. Also write a test program called TestBook to
test the constructor and public methods in the class Book. Take Note that you have to construct an instance of
Author before you can construct an instance of Book. E.g.,
Take note that both Book and Author classes have a variable called name. However, it can be differentiated via
the referencing instance. For a Book instance says aBook, aBook.name refers to the name of the book; whereas
for an Author's instance say auAuthor, anAuthor.name refers to the name of the author. There is no need ﴾and
not recommended﴿ to call the variables bookName and authorName.
TRY:
1. Printing the name and email of the author from a Book instance. ﴾Hint: aBook.getAuthor().getName(),
aBook.getAuthor().getEmail()﴿.
2. Introduce new methods called getAuthorName(), getAuthorEmail(), getAuthorGender() in the Book
class to return the name, email and gender of the author of the book. For example,
le distance(MyPoint another) { // this version takes a MyPoint instance as argument int xDiff = this.x – another.x;
gram
= new MyPoint(3, 0); MyPoint p2 = new MyPoint(0, 4);
2. Write a program that allocates 10 points in an array of MyPoint, and initializes to (1, 1), (2, 2), ... (10,
10).
Hints: You need to allocate the array, as well as each of the ten MyPoint instances.
Notes: Point is such a common entity that JDK certainly provided for in all flavors.
Write the MyCircle class. Also write a test program ﴾called TestMyCircle﴿ to test all the methods defined in the
class.
Write the MyTriangle class. Also write a test program ﴾called TestMyTriangle﴿ to test all the methods defined in
the class.
1.6 Exercise: The MyComplex class
A class called MyComplex, which models
complex numbers x+yi, is designed as
shown in the class diagram. It contains:
Two instance variable named
real﴾double﴿ and imag﴾double﴿
which stores the real and imaginary
parts of the complex number
respectively.
A constructor that creates a
MyComplex instance with the given
real and imaginary values.
Getters and setters for instance
variables real and imag.
A method setValue() to set the
value of the complex number.
A toString() that returns "(x +
yi)" where x and y are the real and
imaginary parts respectively.
Methods isReal() and
isImaginary() that returns true
if this complex number is real or
imaginary, respectively. Hint:
A method equals(double real, double imag) that returns true if this complex number is equal to the
given complex number of ﴾real, imag﴿.
An overloaded equals(MyComplex another) that returns true if this complex number is equal to the given
MyComplex instance another.
A method magnitude﴿﴾that returns the magnitude of this complex number.
Methods argumentInRadians() and argumentInDegrees() that returns the argument of this complex
number in radians ﴾in double﴿ and degrees ﴾in int﴿ respectively.
Note: The Math library has two arc‐tangent methods, Math.atan(double) and Math.atan2(double,
double). We commonly use the Math.atan2(y, x) instead of Math.atan(y/x) to avoid division by zero.
Read the documentation of Math class in package java.lang.
A method conjugate() that returns a new MyComplex instance containing the complex conjugate of this
instance.
conjugate(x+yi) = x ‐ yi
Hint:
return new MyComplex(real, ‐imag); // construct a new instance and return the constructed instance
Methods add(MyComplex another) and subtract(MyComplex another) that adds and subtract this
instance with the given MyComplex instance another, and returns a new MyComplex instance containing the
result.
Hint:
Take note that there are a few flaws in the design of this class, which was introduced solely for teaching purpose:
Comparing doubles in equal() using "==" may produce unexpected outcome. For example, (2.2+4.4)==6.6
returns false. It is common to define a small threshold called EPSILON ﴾set to about 10^‐8﴿ for comparing
floating point numbers.
The method add(), subtract(), and conjugate() produce new instances, whereas multiplyWith() and
divideBy() modify this instance. There is inconsistency in the design ﴾introduced for teaching
purpose﴿. Unusual to have both argumentInRadians() and argumentInDegrees().
// Test program
// Can invoke with a variable number of arguments
MyPolynomial p1 = new MyPolynomial(1.1, 2.2, 3.3);
MyPolynomial p1 = new MyPolynomial(1.1, 2.2, 3.3, 4.4,
5.5);
// Can also invoke with an array
Double coeffs = {1.2, 3.4, 5.6, 7.8}
MyPolynomial p2 = new MyPolynomial(coeffs);
Another constructor that takes coefficients from a file ﴾of the given filename﴿, having this format:
Degree‐n(int)
c0(double)
c1(double)
......
......
cn‐1(double)
cn(double) (end‐
of‐file)
Hints:
public MyPolynomial(String filename) { Scanner in = null;
https://www3.ntu.edu.sg/home/ehchua/programming/java/J3f_OOPExercises.html
10/3
try {
in = new Scanner(new File(filename));// open file
} catch (FileNotFoundException e) { e.printStackTrace();
}
int degree = in.nextInt();// read the degree coeffs = new double[degree+1];// allocate the array for (int i
coeffs[i] = in.nextDouble();
}
+c1x+c0".
A method evaluate(double x) that evaluate the polynomial for the given x, by substituting the given x into
the polynomial expression.
Methods add() and multiply() that adds and multiplies this polynomial with the given MyPolynomial
instance another, and returns a new MyPolynomial instance that contains the result.
Write the MyPolynomial class. Also write a test program ﴾called TestMyPolynomial﴿ to test all the methods
defined in the class.
Question: Do you need to keep the degree of the polynomial as an instance variable in the MyPolynomial class in
Java? How about C/C++? Why?
Hints:
import java.math.BigInteger
public class TestBigInteger {
public static void main(String[] args)
{ BigInteger i1 = new BigInteger(...);
BigInteger i2 = new BigInteger(...);
System.out.println(i1.add(i2));
.......
}
}
1.9 Exercise: The MyTime Class
A class called MyTime, which models a
time instance, is designed as shown in
the class diagram.
Write the code for the MyTime class. Also write a test program ﴾called TestMyTime﴿ to test all the methods
defined in the MyTime class.
A class called MyDate, which models a date instance, is defined as shown in the class diagram.
It also contains the following private static variables ﴾drawn with underlined in the class diagram﴿:
strMonths ﴾String[]﴿, strDays ﴾String[]﴿, and dayInMonths ﴾int[]﴿: static variables, initialized as
shown, which are used in the methods.
The MyDate class has the following
public static methods ﴾drawn
with underlined in the class
diagram﴿:
isLeapYear(int year):
returns true if the given year
is a leap year. A year is a leap
year if it is divisible by 4 but not
by 100, or it is divisible by 400.
isValidDate(int year, int
month, int day): returns
true if the given year, month,
and day constitute a valid date.
Assume that year is between 1
and 9999, month is between 1
﴾Jan﴿ to 12 ﴾Dec﴿ and day shall
be between 1 and 28|29|30|
31 depending on the month
and whether it is a leap year on
Feb.
getDayOfWeek(int year,
int month, int day): returns
the day of the week, where 0
for Sun, 1 for Mon, ..., 6 for
Sat, for the given date. Assume
that the date is valid. Read the
earlier exercise on how to
determine the day of the week ﴾
or Wiki "Determination of the
day of the week"﴿.
Notes:
The constructors take an array of Author ﴾i.e., Author[]﴿, instead of an Author instance.
The toString() method shall return "book‐name by n authors", where n is the number of
authors. A new method printAuthors() to print the names of all the authors.
class. Hints:
// Declare and allocate an array of Authors Author[] authors = new Author[2];
authors[0] = new Author("Tan Ah Teck", ", 'm'); authors[1] = new Author("Paul Tan", "", 'm');
1.12 Exercise: Book and Author Classes Once More ‐ A Fixed‐length Array
of Objects as an Instance Variable
In the above
exercise, the
number of authors
cannot be changed
once a Book
instance is
constructed.
Suppose that we
wish to allow the
user to add more
authors ﴾which is
really unusual but
presented here for
academic purpose﴿.
We shall remove
the authors from
the constructors,
and add a new
method called
addAuthor() to
add the given Author instance to this Book.
We also need to pre‐allocate an Author array, with a fixed length ﴾says 5 ‐ a book is written by 1 to 5 authors﴿,
and use another instance variable numAuthors ﴾int﴿ to keep track of the actual number of authors.
......
......
// Test program
Book javaDummy = new Book("Java for Dummy", 19.99, 99);
System.out.println(javaDummy); // toString()
System.out.print("The authors are: ");
javaDummy.printAuthors();
2. Try writing a method called removeAuthorByName(authorName), that remove the author from this Book
instance if authorName is present. The method shall return true if it succeeds.
Advanced Note: Instead of using a fixed‐length array in this case, it is better to be a dynamically allocated array
﴾e.g., ArrayList﴿, which does not have a fixed length.
Δx = d × cos(θ)
Δy = ‐d × sin(θ)
x +=
Δx y
+= Δy
reflectHorizontal() which reflects the ball horizontally ﴾i.e., hitting a vertical wall﴿
Δx = ‐Δx
Δy no changes
Δx no changes
Δy = ‐Δy
toString() which prints the message "Ball at (x, y) of velocity (Δx, Δy)".
Write the Ball class. Also write a test program to test all the methods defined in the
class.
2. Exercises on Inheritance
Write a test program ﴾says TestCylinder﴿ to test the Cylinder class created, as follow:
Method Overriding and "Super": The subclass Cylinder inherits getArea() method from its superclass
Circle. Try overriding the getArea() method in the subclass Cylinder to compute the surface area
﴾=2π×radius×height + 2×base‐area﴿ of the cylinder instead of base area. That is, if getArea() is called by a
Circle instance, it returns the area. If getArea() is called by a Cylinder instance, it returns the surface area of
the cylinder.
If you override the getArea() in the subclass Cylinder, the getVolume() no longer works. This is because the
getVolume() uses the overridden getArea() method found in the same class. ﴾Java runtime will search the
superclass only if it cannot locate the method in this class﴿. Fix the getVolume().
Hints: After overridding the getArea() in subclass Cylinder, you can choose to invoke the getArea() of the
superclass Circle by calling super.getArea().
TRY:
Provide a toString() method to the Cylinder class, which overrides the toString() inherited from the
superclass Circle, e.g.,
@Override
public String toString() { // in Cylinder class
return "Cylinder: subclass of " + super.toString()// use Circle's toString()
+ " height=" + height;
}
Note: @Override is known as annotation ﴾introduced in JDK 1.5﴿, which asks compiler to check whether there is
such a method in the superclass to be overridden. This helps greatly if you misspell the name of the toString().
If @Override is not used and toString() is misspelled as ToString(), it will be treated as a new method in the
subclass, instead of overriding the superclass. If @Override is used, the compiler will signal an error. @Override
annotation is optional, but certainly nice to have.
2.2 Exercise: Superclass Shape and its subclasses Circle, Rectangle and
Square
Write a superclass called Shape ﴾as shown in the class diagram﴿, which
contains: Two instance variables color ﴾String﴿ and filled ﴾boolean﴿.
Two constructors: a no‐arg ﴾no‐argument﴿ constructor that initializes the color to "green" and filled to
true, and a constructor that initializes the color and filled to the given values.
Getter and setter for all the instance variables. By convention, the getter for a boolean variable xxx is called
isXXX() ﴾instead of getXxx() for all the other types﴿.
A toString() method that returns "A Shape with color of xxx and filled/Not filled".
Write two subclasses of Shape called Circle and Rectangle, as shown in the class
Write a class called Square, as a subclass of Rectangle. Convince yourself that Square can be modeled as a
subclass of Rectangle. Square has no instance variable, but inherits the instance variables width and length from
its superclass Rectangle.
Provide the appropriate constructors ﴾as shown in the class diagram﴿. Hint:
Override the toString() method to return "A Square with side=xxx, which is a subclass of yyy",
where yyy is the output of the toString() method from the superclass.
Do you need to override the getArea() and getPerimeter()? Try them out.
Override the setLength() and setWidth() to change both the width and length, so as to maintain the
square geometry.
// Constructor
public Point (int x, int y) {......}
// Public methods
public String toString() {
return "Point: (" + x + "," + y + ")";
}
// Constructors
public Line (Point begin, Point end) {// caller to construct the Points this.begin = begin;
......
}
public Line (int beginX, int beginY, int endX, int endY) {
begin = new Point(beginX, beginY);// construct the Points here
......
}
// Public methods
public String toString() {}
The class diagram for composition is as follows ﴾where a diamond‐hollow‐head arrow pointing to its constituents﴿:
Instead of composition, we can design a Line class using inheritance. Instead of "a line composes of two
points", we can say that "a line is a point extended by another point", as shown in the following class diagram:
Let's re‐design the Line class ﴾called LineSub﴿ as a subclass of class Point. LineSub inherits the starting point
from its superclass Point, and adds an ending point. Complete the class definition. Write a testing class called
TestLineSub to test LineSub.
public class LineSub extends Point {
// A line needs two points: begin and end.
// The begin point is inherited from its superclass Point.
// Private variables
Point end; // Ending point
// Constructors
public LineSub (int beginX, int beginY, int endX, int endY) { super(beginX, beginY);// construct the begin Poin
}
public LineSub (Point begin, Point end) {// caller to construct the Points super(begin.getX(), begin.getY());/
}
// Public methods
// Inherits methods getX() and getY() from superclass Point public String toString() { ... }
public Point getBegin() { ... } public Point getEnd() { ... } public void setBegin(...) { ... }
public void setEnd(...) { ... }
public int getBeginX() { ... } public int getBeginY() { ... } public int getEndX() { ... }
public int getEndY() { ... }
Summary: There are two approaches that you can design a line, composition or inheritance. "A line composes
two points" or "A line is a point extended with another point"”. Compare the Line and LineSub designs: Line
uses composition and LineSub uses inheritance. Which design is better?
Write a test class to test these statements involving polymorphism and explain the outputs. Some statements may
trigger compilation errors. Explain the errors, if any.
@Override
public void greeting(Dog another)
{ System.out.println("Woooooowwwww!");
}
}
Explain the outputs ﴾or error﴿ for the following test program.
public class TestAnimal {
public static void main(String[] args) {
// Using the subclasses Cat cat1 = new Cat(); cat1.greeting();
Dog dog1 = new Dog(); dog1.greeting();
BigDog bigDog1 = new BigDog(); bigDog1.greeting();
// Downcast
Dog dog2 = (Dog)animal2;
BigDog bigDog2 = (BigDog)animal3; Dog dog3 = (Dog)animal3;
Cat cat2 = (Cat)animal2; dog2.greeting(dog3); dog3.greeting(dog2); dog2.greeting(bigDog2); bigDog2.greeting(dog
}
}
Let's write two concrete classes ‐ MovablePoint and MovableCircle ‐ that implement the Movable interface.
For the MovablePoint class, declare the instance variable x, y, xSpeed and ySpeed with package access as
shown with '~' in the class diagram ﴾i.e., classes in the same package can access these variables directly﴿. For the
MovableCircle class, use a MovablePoint to represent its center ﴾which contains four variable x, y, xSpeed
and ySpeed﴿. In other words, the MovableCircle composes a MovablePoint, and its radius.
// Constructor
public MovablePoint(int x, int y, int xSpeed, int ySpeed) {
this.x = x;
......
}
......
// Constructor
public MovableCircle(int x, int y, int xSpeed, int ySpeed, int radius) {
// Call the MovablePoint's constructor to allocate the center instance.
center = new MovablePoint(x, y, xSpeed, ySpeed);
......
}
......
1. Write the interface called GeometricObject, which declares two abstract methods: getParameter()
and getArea(), as specified in the class diagram.
Hints:
2. Write the implementation class Circle, with a protected variable radius, which implements the interface
GeometricObject.
Hints:
// Constructor
......
......
}
3. Write a test program called TestCircle to test the methods defined in Circle.
4. The class ResizableCircle is defined as a subclass of the class Circle, which also implements an
interface called Resizable, as shown in class diagram. The interface Resizable declares an abstract
method resize(), which modifies the dimension ﴾such as radius﴿ by the given percentage. Write the
interface Resizable and the class ResizableCircle.
Hints:
// Constructor
public ResizableCircle(double radius) {
super(...);
}
5. Write a test program called TestResizableCircle to test the methods defined in ResizableCircle.
The class DiscountRate contains only static variables and methods ﴾underlined in the class diagram﴿.
import java.util.*;
public class PolyLine {
private List<Point> points = new ArrayList<Point>();
// Allocate an ArrayList of Points and upcast to List
// return (x1,y1)(x2,y2)(x3,y3)....
public String toString() {
StringBuilder sb = new StringBuilder();
for (Point aPoint : points) {
sb.append(aPoint.toString());
}
return sb.toString();
}
}
Try:
1. Modify the push() method to throw an IllegalStateException if the stack is full.
2. Modify the push() to return true if the operation is sucessful, or false otherwise.
3. Modify the push() to increase the capacity by reallocating another array, if the stack is full.
[TODO]
Study the existing open source codes, including JDK.
Specialized algorithms, such as shortest path.
Exercise ﴾Maps﴿:
[TODO]
Representation of map data.
Specialized algorithms, such as shortest path.
[TODO]
Study the existing open source codes, including JDK's 2D Graphics and JOGL's 3D Graphics.
Efficient and specialized codes for 3D Graphics ﴾4D matrices﴿. Handle various primitive types such as int, float and double efficiently.
Feedback, comments, corrections, and errata can be sent to Chua HockChuan (ehchua@ntu.edu.sg) | HOME