Before we can really answer that, we have to answer another question:
What is the Object-Oriented Paradigm?
The Object-Oriented Paradigm, or OOP, is a method of coding which results in better, more reliable and more reusable code.
"The fundamental idea behind object-oriented languages is to combine into a single unit both data and the functions that operate on that data. Such a unit is called an object." [LaFore, 1995] By using objects, we can model the real world in a more natural fashion, and we also achieve some other useful side effects.
An example of OOP v/s Structured programming:
Let's say we have to write code that will model a store. We have to keep track of customers, how much money the customers have, and how much the customers have bought. We have to keep track of the sales clerks, where they are and when their shifts are. And we have to keep track of the merchadise, how much we have and where it is.
First we'll look at a Structural method. To keep track of the
customers and their money and purchases, we'll need an array of
structures. Same for the clerks, and same for the merchandise.
That pretty much takes care of the data.
Now, we'll need a function to spend a customer's money, one to add a customer's purchases, one to move the clerks, one to update the clerks' shifts, one to move merchandise, and one to sell the merchandise. Each of these functions will be globally available and will be called by a larger control structure. Also, all of the data will be visable to all of the functions.
Now, let's look at an OOP implementation. We'll define three
objects, Customer, Clerk, and Merchandise. The Customer object
will have a Money variable and a Purchases array. The Customer
object will also have a Spend method and a Buy method to update
the money and purchases, respectively.
The Clerk object will have a Location variable and Shift variable. It will have a Move method and a CheckShift method.
The Merchandise object will have a Price variable and a Location variable. It will have Move and Sell methods.
We will have to have three arrays, one for each object type. The methods will be visable to the control structure, but the data will be hidden, or encapsulated, within each object.
So, what's the difference? They both have pretty much the same
stuff; it's just arranged a little differently.
Well, the different arrangement is what makes OOP more powerful. The first obvious advantage is that the data is hidden. You cannot accidentally alter the data for a customer while fiddling with something else. You can only access one of the object's data by directly going through that object.
Another advantage is reusablilty of the code. Say, for instance,
we now have to simulate an assembly line. One of the things we'll
need to keep track of is where the workers are, and who's currently
working. We can just borrow the Clerk object from our current
model and plop it in our new project without any
modification! It already knows how to keep track of where it is,
and when it's shifts negin and end. That's all we need for an
Try doing that with the Structured code! You'd have to copy out the code for the structure, the code for each of the relevant functions, and modify the functions to fit the new array name, along with some other house keeping.
OOP allows you to bundle together related data and functions so that they can be easily moved around and reused.
Yet another advantage is in maintenance. Say we want to be more
specific now. We want to model a grocery store. And, we don't want
to keep track of just "merchandise." We want to keep
track of meat, fruits and vegatebles, and dry goods.
With the structured method, we'd have to trade the merchandise array for three separate item arrays. We would then have to write three new structures to handle the different data to be kept for each item. We would also have to modify all the functions which used the merchadise array to now work with the three new arrays, which could be a pain by itself!
With OOP we could take advantage of a property called inheritance.
Inheritance allows an object to inherit code from another object, saving the time of writing all new code.
We could create three new objects, Meat, Fruit_N_Veggies and Dry_Goods. Each of these new objects can be a child of our previous Merchandise class. So, each will automatically inherit all of the data and function contained in Merchandise.
Then, we could further specifiy each new object. For example, for Meat, we could add a SellDate variable and a Spoiled method so that we can measure losses from spoilage.
Now, here's the really cool part. Since they are all children of Merchadise, they can all still go in the Merchandise array. We don't have to make a new array for each of them.
Now, the last real advantage we'll talk about is called polymorphism.
The best way to explain this will be by example.
When we create a new Clerk, we want to be able to initialize his or her (Gender variable, anyone?) starting position and shifts. So, when we create a Clerk, we can do this:
Clerk new_clerk = new Clerk(); new_clerk.Location = "aisle 9"; new_clerk.Shift = "12pm-12am";
But, this is rather long-winded and clumbsy. We can define something called a constructor, which we'll discuss later, which will allow us to do the same thing like this:
Clerk new_clerk = new Clerk("aisle 9", "12pm-12am");
Now, isn't that better? But, the code for initializing the object
is in the constructor, so we haven't really changed anything.
Here is where the power of polymorphism comes in. What if we don't want to always assign both the shift and the location at the same time? What if we want to be able to just assign the location and leave the shift until later? We can do that without any problem. We can define another constructor so that we can do this:
Clerk new_clerk = new Clerk("aisle 9");
Now, look at the two initializations by constructor. they both
call Clerk() (which is the name of the constructor). How can they
both be named the same, but use different arguements?
The answer is polymorphism! In OOP you can declare a method or constructor more than once, each with a different set of arguements, but the same name. When you call the method, the compiler knows from the arguement list, called the signature, which version of the method you mean.
This may not be a major code-saving feature, but it reduces confusion by 100%. Instead of add_int(), add_float(), add_short(), etc., you can just have an add() which will know by the arguements which one you need.
Well, now that we understand OOP, we can answer our original question:
What is Java?
Java is a "simple, object-oriented, distributed, interpreted, robust, secure, architecture neutral, portable, high-performance, multithreaded, and dynamic language." [Flanagan, 1996]
What does all that mean?
Simple: Java was made to look and act much like C and C++, since so many people are already familiar with those languages. However, to simplify matters, several features common to C and C++ were not included. Among those are pointers, header files, and goto's.
Object-Oriented: We just finished explaining that. Java is not 100% object-oriented like SmallTalk, but it is much more so that C++.
Distributed: Java was designed with today's distributed networks in mind. It is capable of network communication and handling socket calls.
Interpreted: Java code is compiled into byte-code, which is somewhat similar to a binary executable. Instead of being run by your operating system, though, the byte-code is run by the Java Virtual Machine, a byte-code interpreter. The advantage is that the Java code doesn't have to be directly translated into the system-specific machine code. Instead, the Java Virtual Machine acts as an intermediary which will be the same on every system. So, the end result is code that acts the same on every computer.
Robust: Java is a strongly typed language, and so will catch most errors long before run-time. Also, since Java doesn't support pointers, code written in Java is much more reliable. Another feature adding to Java's robustness is its exception handling. When an error occurs, the code is able to deal with it on the fly, allowing for a high rate of recovery.
Secure: Java was designed with the internet in mind. As such, it
has to be secure to be usable at all. Java applets are not allowed
to do any file I/O. Also, the lack of pointers prevents a large
amount of potential problems.
The internet is a dangerous place. There is really no way to be competely secure without being useless. Java has tried to find a middle ground between being unprotected and being unusable.
Portable: Because Java runs on the Java Virtual Machine, and not the individual system itself, Java code is easily portable to any system capable of running the virtual machine.
Performance: Java is approxiamtely 20 times slower than C. However, it is more than fast enough for most of its more commons uses such as applets and multimedia. Java does allow you, though, to import native C code for the times when speed is essential.
Multithreaded: Java can run several simulateous process threads. This allows the user to easily code programs with can do more than one thing at once. Such multitasking capability is invaluable for use in building GUI's and other such applications.
Dynamic: Java was built to be able to adapt to the continually evolving environment. It can dynamically load in classes when they are needed, and it can even got out over the 'Net to find them.
O.K. Now we now all about what Java is and why you should learn it. In the next lesson, Basics we'll start to learn about what Java can do, and how it works.
[LaFore, 1995] Robert LaFore, "Object-Oriented Programming in C++," The Waite Group Press, 1995, p.6.
[Flanagan, 1996] David Flanagan, "Java in a Nutshell," O'Reilly & Associates, Inc., 1996, p.xii.