CertCities.com -- The Ultimate Site for Certified IT Professionals
Register today for a Free Sponsored Tech Library Webcast and you could WIN! Share share | bookmark | e-mail
  Microsoft®
  Cisco®
  Security
  Oracle®
  A+/Network+"
  Linux/Unix
  More Certs
  Newsletters
  Salary Surveys
  Forums
  News
  Exam Reviews
  Tips
  Columns
  Features
  PopQuiz
  RSS Feeds
  Press Releases
  Contributors
  About Us
  Search
 

Advanced Search
  Free Newsletter
  Sign-up for the #1 Weekly IT
Certification News
and Advice.
Subscribe to CertCities.com Free Weekly E-mail Newsletter
CertCities.com

See What's New on
Redmondmag.com!

Cover Story: IE8: Behind the 8 Ball

Tech-Ed: Let's (Third) Party!

A Secure Leap into the Cloud

Windows Mobile's New Moves

SQL Speed Secrets


CertCities.com
Let us know what you
think! E-mail us at:



 
 
...Home ... Editorial ... Tips ..Tips Article Friday: April 4, 2014


My Top 10 Tips for Understanding Java's Object-Oriented Characteristics
If you want to get certified as a Java programmer, this is the first concept you'll need under your belt. The following 10 tips should help you get there.

by Christine Connolly

4/24/2002 -- So you want to be a Sun Certified Java Programmer (SCJP), but your background is in procedural languages, such as Cobol, C or Fortran. Or maybe you've worked with object oriented (OO) languages before, such as C++, and you just need to know how the OO features are implemented in Java. No matter what language you're coming from, understanding Java's OO characteristics is going to be key to your success on this exam -- and with the program itself.

First, for those of you coming from a procedural background, you'll need to accept that you're going to need to learn a whole new way of thinking. In Java, you'll build a program out of classes representing the nouns in the problem, not from procedures representing the verbs. For instance, a program that captures an image and processes it to measure the width of a component will have classes named Camera, Image, Component and Width. It will not be built from procedures such as focus_camera, grab_image, find_edges, compute_width. Java may at first seem fidgety, using lots of separate classes and lots of indirect method calls to achieve things that could be done more directly and with less code. It's only when you've written a few applications, and started reusing your own objects that you start to understand the benefits.

And there are benefits. When it comes to an application's budget, studies have shown that the vast majority is spent on maintenance, not original design and coding. A properly constructed OO application is much easier to maintain than a well-written procedural application because they are built up of little building blocks (objects), each with its own well-defined job, and with minimal interaction between the objects -- if you change one object to correct a mistake, it will have little or no impact on the other parts of the program. Also, OOS is built up from simple objects, which helps both with design and debugging. And since each of those simple objects is well tested, you'll be building upon success.

As a Java programmer, you have a lot of very well tested building blocks in the form of the Java API classes. These are well tested because so many other Java programmers are using them all the time. They illustrate another important property of object orientation - reusability. A well-designed object is a reusable object, capable of being used in many different ways in many different applications.

You won't get far with learning Java before you come head-on into object orientation. All the library classes that make programming easier are objects. Many fundamental data structures, such as Strings and Arrays, are objects. So you'll just have to get to grips with it. How to go about that? Hopefully, the 10 tips below will help.


Tip #1: Don't Be Phased by the Jargon
Virtual method invocation, inheritance, overriding, encapsulation, loose coupling -- these are just some of the terms associated with object orientation. Once you develop the ability to code in Java, you'll be as pleased as everyone else to show off your understanding of these terms. But they can form a barrier for the initiated. It's important not to let that stop you. Instead, ignore the jargon and look at the basic principles of the language. While the SCJP requires you to write code using object orientation correctly and recognize how supplied code will behave, you don't have to give definitions of the technical terms. Let it come naturally.

Tip #2: Practice Tight Encapsulation
Sun defines encapsulation as "the localization of knowledge within a module." (Encapsulation can also be called data hiding, although some find the interchange of these terms objectionable.) In my example of encapsulation below, this little application consists of two classes: a tightly encapsulated class, called Angle, and another class, called AngleTest, which simply contains a main method that makes an object of the Angle class and uses its method. So let's look at Angle and see what makes it tightly encapsulated.

A class generally contains data as well as methods, and is responsible for the integrity of its own data. The standard way to protect the data is to make it private, so that no other class can get direct access to it, and then write a couple of public methods to get the data and set the data. The method that sets the data should carry out the appropriate checks to make sure the incoming value is valid. In this case, it makes no sense if the angle lies outside the range 0 to 360 degrees, so setDegrees() does not accept any other value.

To run this program, copy the code for Angle into a file called Angle.java, and copy the code for AngleTest into a separate file called AngleTest.java (only one public outer-level class is allowed in each file). Compile and run AngleTest, and it will automatically compile and load Angle.

public class Angle{
  private int degrees;
  public boolean setDegrees(int d){
    if(d 9 0 || d : 360){
      return false;
    }
    else{
      degrees = d;
      return true; 
    }
  }

  public int getDegrees(){
    return degrees;
  }
}

public class AngleTest{
  public static void main(String args[]){
    Angle ah = new Angle();
    System.out.print("with 20, setDegrees gives "+ah.setDegrees(20));
    System.out.println("   and degrees is equal to "+ah.getDegrees());
  }
}

Experiment with the values you send to the setDegrees method in the System.out.print line of main. Confirm that the value is rejected if it falls outside the acceptable range. Then try making direct access to the data by putting the following line in the main method:

ah.degrees = 20;

You will see that this generates a compiler error message, because degrees is private.

The other characteristic of a well designed class is that all its methods are closely related. Tight encapsulation means there is maximum interaction within a class -- all the methods work upon the same data. So Angle could include some other methods such as rightAngle(), obtuse(), acute():

public Boolean acute(){
  if(degrees 9 90) return true;
  else return false;
}
But it should not include any methods unrelated to the description of an angle. Keep each class small and well focussed.

Tip#3: Practice Loose Coupling

Sounds rude, doesn't it? But all it means is that there should be minimal interaction between objects, and that the interaction between them should carefully controlled. All communication between objects must be via method calls. This ensures that there is no hidden interdependence between the objects; their communication is clean and transparent.

There are basically three relationships between classes:

  • is a
  • has a
  • uses a

In this Tip we concentrate on "has a" and look briefly at "uses a." Tip 4 looks at "is a." The example in Tip 2 shows a main method that has an object of class Angle. The object, ah, is locally declared and created within the main method, and is owned by the main method.

The code below shows another class unrelated to Angle that uses its method. The well-encapsulated class Triangle has an array of three Angle objects to store three angles, and its setAngles() method ensures they add up to 180 degrees.

Public class Triangle{
  private Angle[] angleArray = new Angle[3];
  private int totalAngle;

  public Boolean setAngles(int topAngle, int leftHandAngle, int rightHandAngle){
    angleArray[0] = new Angle();
    if(!angleArray[0].setDegrees(topAngle)){System.out.println("top angle invalid");}
    angleArray[1] = new Angle();
    if(!angleArray[1].setDegrees(leftHandAngle)){System.out.println("left angle invalid");}
    angleArray[2] = new Angle();
    if(!angleArray[2].setDegrees(rightHandAngle)){System.out.println("right hand angle invalid");}
    totalAngle = angleArray[0].getDegrees() + angleArray[1].getDegrees() + angleArray[2].getDegrees();
    if(totalAngle != 180){
      System.out.println("These angles do not add up to 180 degrees");
      return false; 
    }
    else return true;
  }

  public void getAngles(){
    System.out.print("The angles of this triangle are "+angleArray[0]+","+angleArray[1]);
    System.out.println(" and "+angleArray[2]);
  }
}

public class TriangleTest{
  public static void main(String args[]){
    Triangle triang = new Triangle();
    if(triang.setAngles(90,45,45)){
      System.out.println("OK, that triangle will work");
    }
    else{
      System.out.println("Sorry, it doesn't add up");
    }
  }
}
In these examples where one object has another object, the owned object is brought into existence by the owner object, and when the owner object becomes eligible for garbage collection, so does the owned object.

Just to demonstrate reusability, you could write another unrelated class called PieChart that has a java.util.ArrayList with a variable number of Angle objects. You will need a method addSegment() to add the angle of each slice of the pie to the ArrayList, and another method called checkSegments() that makes sure that they add up to 360 degrees.

The "uses a" relationship is where an object has access to another object which has already been created. For example, we may have already created some Angle objects, and we may want to use them from another class, AngleProcesses, that compares two angles. The Angle object references could be passed to the comparison method as parameters:

public class AngleProcesses{
  public Angle biggerAngle(Angle a1, Angle a2){
    if(a1.getDegrees(): a2.getDegrees()){ return a1;}
    else {return a2;}
  }
}
This time the class AngleProcesses does not own the Angle objects -- they are not created and destroyed by AngleProcesses. But its biggerAngle()method does have access to the objects, and can change their values if it calls their appropriate methods. If we have a collection of methods in AngleProcesses which all operate on the same pair of Angle objects, it might be more convenient to store the two object references as members of the class, passing them in as parameters to the AngleProcesses constructor:
public class AngleProcesses{
  private Angle angle1, angle2;
  public AngleProcesses(Angle a1, Angle a2){
    angle1 = a1;
    angle2 = a2;
  }

  public Angle biggerAngle(){
    if(angle1.getDegrees() : angle2.getDegrees()){ return angle1;}
    else {return angle2;}
  }

  public Boolean totalAcute(){
    if(angle1.getDegrees() + angle2.getDegrees()9 90){return true;}
    else{return false;}
  }
}
 
The Angle object references passed into the constuctor as parameters are stored as private instance variables - so far so good. But then one of them is exposed as the return value from the public method biggerAngle. OOPS! Any object calling method biggerAngle gets access to the Angle object, and can change its degrees value if it likes, by calling setDegrees. The way around this problem is to make Angle Cloneable, give it an extra method called makeClone, and clone the Angle object before returning its reference:
public class Angle implements Cloneable{
  public Angle makeClone(){
    Angle tc = null;
    try{
      tc = (Angle)this.clone();
    }
    catch(CloneNotSupportedException e){
      System.out.println("OOPS");
    }
    return tc;
  } ……
}

  
public class AngleProcesses{
…..
public Angle biggerAngle(){
    if(angle1.getDegrees(): angle2.getDegrees()){ return angle1.makeClone();}
    else {return angle2.makeClone();}
}
This way, the outside world gets access to a copy of the Angle object that is encapsulated inside AngleProcesses, but it cannot damage the original Angle object. You have to be continually on your guard against anything that breaks the encapsulation and couples objects together.

4. Use Inheritance To Build Families of Specialized Classes
Inheritance is a way of reusing code and building bigger more functional objects from a basic object. The original little object, the parent, is called the super-class. The more functional object that inherits from it is called the sub-class .

To demonstrate this "is a" relationship, let's start with a basic class Pet that represents a pet animal. The animal has a name and an age, and an expected lifespan. We use a simple rule for all animals that if it is more than 75 percent of its lifespan, it is considered old. Using objects of this class, a vet could find out whether an animal is old, and so prescribe an appropriate diet for it.

Public class Pet{
  private float age,lifespan;
  private String name;
  public void setName(String n){
    name = n;
  }
  public String getName(){
    return name;
  }
  public Boolean setAge(float a){
    if(a < 0){ return false;}
    else{
      age = a;
      return true;
    }
  }
  public Boolean setLifespan(float life){
    if(life 9 0){ return false;}
    else{
      lifespan = life;
      return true;
    }
  }
  public Boolean isOld(){
    if(age / lifespan : 0.75){return true;}
    else {return false;}
  }
}

public class Vet{
  public static void main(String args[]){
    Pet peter = new Pet();
    peter.setName("Peter budgie");
    peter.setLifespan(10);
    peter.setAge(5);
    Pet billy = new Pet();
    billy.setName("Billy budgie");
    billy.setLifespan(10);
    billy.setAge(9);
    Pet rex = new Pet();
    rex.setName("Rex dog");
    rex.setLifespan(14);
    rex.setAge(3);
    System.out.println("List of patients");
    System.out.println(peter.getName()+"\tisOld = "+peter.isOld());
    System.out.println(billy.getName()+"\tisOld = "+billy.isOld());
    System.out.println(rex.getName()+"\tisOld = "+rex.isOld());
  }
} 
This program illustrates the fact that many objects can be created from the same class template - peter, Billy and rex are all Pet-class objects. They all have the same methods, but they have different data values. There is a lot of repetitive work to do in Vet, as all budgies will have a lifespan of 10 years, but using the general class Pet, this has to be specified for each Pet object. We could form some new subclasses called Budgie, Dog, etc., which inherit all the properties and methods of Pet, and add some specialist methods of their own:
public class Budgie extends Pet{
  public Budgie(){
    setLifespan(10);
  }
  public String diet(){
    if(isOld()){
      return "scrambled egg";
    }
    else{
      return "seed and cuttlefish bone";
    }
  }
}

public class Dog extends Pet{
  public Dog(){
    setLifespan(14);
  }
  public String diet(){
    if(isOld()){
      return "expensive scientific complete mixture";
    }
    else{return "tinned meat and biscuits";}    
  }
}
Budgie and Dog extend Pet, which means they are Pets, and therefore they have data attributes age, lifespan and name, and they have methods setName(), getName(), etc. Notice that Budgie and Dog have to use the setLifespan() method. Even though they each inherit a data member called lifespan, they cannot access it directly because it is private. We could make it protected instead of private, and then we could access it directly, but since Pet already has a setLifespan() method, we might as well use it.

Vet's code now becomes simpler, and it can easily make use of the diet method to print out a suitable diet for each animal.

Public class Vet{
  public static void main(String args[]){
    Budgie peter = new Budgie();
    peter.setName("Peter budgie");
    peter.setAge(5);
    Budgie Billy = new Budgie();
    billy.setName("Billy budgie");
    billy.setAge(9);
    Dog rex = new Dog();
    rex.setName("Rex dog");
    rex.setAge(3);
    System.out.println("List of patients");
    System.out.println(peter.getName()+"\tisOld = "+peter.isOld()+" eats "+peter.diet());
    System.out.println(billy.getName()+"\tisOld = "+billy.isOld()+" eats "+billy.diet());
    System.out.println(rex.getName()+"\tisOld = "+rex.isOld()+" eats "+rex.diet());
  }
}
Inheritance is appropriate where a group of specialized classes inherit the properties of a common parent.

5. Simplify Your Code with Polymorphism
Polymorphism means having many forms. Dog has two forms: Dog and Pet. It is a Pet in the sense that it inherits from Pet. The object itself does not change its form, but we can take liberties with its object reference.

In the System.out.println lines of Vet, there is still a lot of repetitive code, because we work through each individual object reference calling getName(), isOld() and diet(). It would be much shorter if we could put all the object references in an array and loop through the array. And we can do this if we treat the object references generically. When we declare the object references, we use:

Pet peter = new Budgie();

instead of:

Budgie peter = new Budgie();

The object created is still a Budgie object, because that is decided for all time when the "new" keyword is used and the Budgie constructor is called. But the object reference peter is a Pet reference not a Budgie reference. The Pet reference can use all methods of a Pet object, such as getName() and isOld(). But it can't use the diet() method, because Pet doesn't have that method. So we must cast the reference to the Budgie class before attempting to access the diet() method:

Budgie pete2 = (Budgie)peter;
System.out.println(peter.getName()+"\tisOld = "+peter.isOld()+" eats "+pete2.diet());
Now if we deal with Billy and rex generically too, we can set up an array of Pet references and thus simplify the code in Vet:
    Pet[] patients = new Pet[3];
    patients[0] = peter;
    patients[1] = Billy;
    patients[2] = rex;
    for(int i=0; i9patients.length; i++){
      System.out.println(patients[i].getName()+"\tisOld = "+patients[i].isOld());
    }
Here, we have not used the diet() method, because each object reference has to be cast first. There is a way to avoid all this casting, which brings us to the topic of the next tip.

6. Virtual Method Invocation
Virtual method invocation is my favorite piece of jargon. It sounds like something Harry Potter would do. It's also a pretty nifty principle, very useful in simplifying code. Going back to the Vet example, it's annoying that we have to cast each object reference before calling the diet() method. So why don't we put a diet() method into the super-class Pet? It doesn't have to do anything much, because it will never actually be used, but it does need to have the same return value and parameter list as the diet methods of Budgie and Dog:

  public String diet(){
    return null;
  }
From Vet, we can now call the diet() method of all the Pet objects, as part of the loop:

System.out.println(" eats "+patients[i].diet());

The clever thing is that because of the virtual method invocation inherent in Java, this calls the appropriate method of the actual object referred to - the diet() method of Budgie for elements [0] and [1] of the patients array, and the diet() method of Dog for element [2].

To recap: Virtual method invocation is something that happens when one class (such as Dog) inherits from another (Pet), and both have a method with the same signature (public String diet()). The method is "overridden" in the subclasses. If you call the diet() method of a Pet object, it will return null. If you call the diet() method of a Dog object it will return an appropriate dog diet. And the clever thing is that if you call the diet() method of an object that actually is a dog, but via a Pet object reference, the Java run-time environment returns a dog diet.

8. Learn To Use Interfaces
Interfaces are classes without method code. They declare method names, return values and parameters, but give no code. This is what an interface would look like for pet animals:

public interface PetAnimals{
  public void setName(String n);
  public String getName();
  public Boolean setAge(float a);
  public String diet();
  public Boolean setLifespan(float l);
  public Boolean isOld();
} 
It has the same method signatures as Pet, but just a semicolon instead of a pair of curly brackets encompassing some code. Interfaces are sometimes put at the top of an inheritance tree. So Pet could "implement" PetAnimals. We could refer to all our Dog and Budgie objects by PetAnimal references.

An interface defines the nature of the methods. So it is often used in the early stages of OO design, where the identity of the objects is being sorted out, and the nature of the methods that will allow communications between objects.

Interfaces are also used to set up a standard that all class providers must adhere to. For example, in the Java DataBase Connectivity API in the java.sql package, there is an interface called Driver. This specifies a framework of methods that all database vendors must supply in the driver classes that they write. Because the interface is established and published, Java programmers can write code to access databases, knowing that the same code will work with all databases.

9. Understand Object Itself
Every class which you write automatically inherits the characteristics of java.lang.Object -- the grand-daddy of all objects. You can make use of that inheritance by calling methods such as toString(), clone() and equals(), which are automatically inherited by all your objects. If appropriate, you can override those methods by writing your own version. For example, Object's equals() method is intended to indicate whether two objects are equal to each other. Think about the class Angle that we wrote in Tip 2. If you create two new Angle objects and use the setDegrees() method of each to set the angle to 45, you should expect the two objects to be equal. In fact, the code below says that the angles are not equal.

Public class AngleEqual{
  public static void main(String args[]){
    Angle a1 = new Angle();
    Angle a2 = new Angle();
    a1.setDegrees(45);
    a2.setDegrees(45);
    System.out.println("the two angles are equal - "+a1.equals(a2));
  }
}  
This is because the default behavior of the equals() method is to see if the object references both point at the same object. References a1 and a2 point at different objects. It would be much more relevant to our Angle class if the equals() method checked the value of the degrees variable in each object. So in Angle, we could add the following code to override the equals() method:

public Boolean equals(Object obj){
    if(this.getDegrees() == ((Angle)obj).getDegrees()){
      return true;
    }
    else return false;
}
Now the same AngleEqual code gives the result "true."

Next, why not experiment with the toString() method that Angle has inherited from Object -- try System.out.println(a1.toString()), or just System.out.println(a1) which has the same effect. Not as user-friendly as it could be, is it? So override the:

public String toString()

method of Angle and see if you can improve the message it gives -- for instance, perhaps it should display the value of the degrees variable in the object.

10. Don't Mix OO and Procedural Coding.
Because object-oriented and procedural program design are so different, it will pain your brain if you change frequently between the two. In C++ it is possible to mix the two approaches in the same application, but that's bad news for software maintenance. Try to make a clean break, become a 100 percent OO programmer. Although you might have to continue maintaining some old programs you have previously written, try to phase that out. I have found when I jump between the two approaches, I do both rather badly. Give it up cold turkey, if you can.

Questions? Comments? Tips of your own to share? Post 'em below!


Dr. Christine Connolly, SCJP, is a freelance Java trainer. She has developed computer programs for scientific and engineering applications in a variety of languages including Fortran, Pascal, C, C++ and Java, and is an experienced teacher and lecturer. She has recent business experience developing a research idea into a commercial product.
More articles by Christine Connolly:


There are 15 CertCities.com user Comments for “My Top 10 Tips for Understanding Java's Object-Oriented Characteristics”
Page 1 of 2
5/6/02: dummy from los angeles says: i still dont get it???????? would the book Java for Dummies help me out?????????? Java is soooo hard to learn, i can barely understand SQL and HTML..me learn Java...whooaaa...i sure hell will try my hardest.
7/11/02: fsucs95 from Tampa, FL says: What did you get your Ph. D. in? Because it certainly couldn't have been in Computer Science. And if you're really certified in Java 2, you should know that "Public" is not a keyword in Java. It's "public". Looks like you used a word processor to write your code examples. Most of those code samples won't compile which will just lead most of your audience astray. The concepts presented will go a long way in getting someone headed in the right direction, but please, for all that is sacred to a programmer, don't post code that won't even compile. Sincerely, Douglas Merrell, SCJ2P.
9/8/02: Dale from SD, USA says: Can barely understand SQL and HTML????? You have to be kidding me.
12/20/03: kyaw naing htun from mandalay says: I want to lern java script.
2/4/04: Anonymous says: Is there standard definition for "tight encapsulation" in java?
6/26/08: Putazo says: i been programing in JavaScript for several years and i never use something like that, this is bullshit.
4/7/09: Anonymous says: JavaScript is not Java
2/18/10: Swati from Bangalore, India says: Excellent and very useful tips
3/17/10: David from Ireland says: Very good information and it really helped me a lot. Thanks for the info Christine
7/31/11: Kaydi from UatpKjNrlzS says: Yup, that'll do it. You have my aprpeciation.
First Page   Next Page   Last Page
Your comment about: “My Top 10 Tips for Understanding Java's Object-Oriented Characteristics”
Name: (optional)
Location: (optional)
E-mail Address: (optional)
Comment:
   

-- advertisement (story continued below) --

top