Object Oriented Programming
Object Oriented Programming
Object Oriented Programming
In classic, procedural programming you try to make the real world problem you're attempting to solve fit a few, predetermined data types: integers, floats, Strings, and arrays perhaps. In object oriented programming you create a model for a real world system. Classes are programmer-defined types that model the parts of the system. A class is a programmer defined type that serves as a blueprint for instances of the class. You can still have ints, floats, Strings, and arrays; but you can also have cars, motorcycles, people, buildings, clouds, dogs, angles, students, courses, bank accounts, and any other type that's important to your problem. Classes specify the data and behavior possessed both by themselves and by the objects built from them. A class has two parts: the fields and the methods. Fields describe what the class is. Methods describe what the class does. Using the blueprint provided by a class, you can create any number of objects, each of which is called an instance of the class. Different objects of the same class have the same fields and methods, but the values of the fields will in general differ. For example, all people have eye color; but the color of each person's eyes can be different from others. On the other hand, objects have the same methods as all other objects in the class except in so far as the methods depend on the value of the fields and arguments to the method. This dichotomy is reflected in the runtime form of objects. Every object has a separate block of memory to store its fields, but the bytes in the methods are shared between all objects in a class. Another common analogy is that a class is to an object as a cookie cutter is to a cookie. One cookie cutter can make many cookies. There may be only one class, but there can be many objects in that class. Each object is an instance of one class.
Introduction to java
Java is an object-oriented programming language with a built-in application programming interface (API) that can handle graphics and user interfaces and that can be used to create applications or applets. Because of its rich set of API's, similar to Macintosh and Windows, and its platform independence, Java can also be thought of as a platform in itself. Java also has standard libraries for doing mathematics. Much of the syntax of Java is the same as C and C++. One major difference is that Java does not have pointers. However, the biggest difference is that you must write object oriented code in Java. Procedural pieces of code can only be embedded in objects. In the following we assume that the reader has some familiarity with a programming language. In particular, some familiarity with the syntax of C/C++ is useful. In Java we distinguish between applications, which are programs that perform the same functions as those written in other programming languages, and applets, which are programs that can be embedded in a Web page and accessed over the Internet. Our initial focus will be on writing applications. When a program is compiled, a byte code is produced that can be read and executed by any platform that can run Java. Object oriented programming is the catch phrase of computer programming in the 1990's. Although object oriented programming has been around in one form or another since the Simula language was invented in the 1960's, it's really begun to take hold in modern GUI environments like Windows, Motif and the Mac. In objectoriented programs data is represented by objects. Objects have two sections, fields (instance variables) and methods. Fields tell you what an object is. Methods tell you what an object does. These fields and methods are closely tied to the object's real world characteristics and behavior. When a program is run messages are passed back and forth between objects. When an object receives a message it responds accordingly as defined by its methods. In practice object-oriented programs have been just as slow, expensive and buggy as traditional non-object-oriented programs. In large part this is because the most popular object-oriented language is C++. C++ is a complex, difficult language that shares all the obfuscation of C while sharing none of C's efficiencies. It is possible in practice to write clean, easy-to-read Java code.
Features of Java
Platform Independent
Java was designed to not only be cross-platform in source form like C, but also in compiled binary form. Since this is frankly impossible across processor architectures Java is compiled to an intermediate form called byte-code. A Java program never really executes natively on the host machine. Rather a special native program called the Java interpreter reads the byte code and executes the corresponding native machine instructions. Thus to port Java programs to a new platform all that is needed is to port the interpreter and some of the library routines. Even the compiler is written in Java. The byte codes are precisely defined, and remain the same on all platforms. The second important part of making Java cross-platform is the elimination of undefined or architecture dependent constructs. Integers are always four bytes long, and floating point variables follow the IEEE 754 standard for computer arithmetic exactly. You don't have to worry that the meaning of an integer is going to change if you move from a Pentium to a PowerPC. In Java everything is guaranteed.
High Performance
Java byte codes can be compiled on the fly to code that rivals C++ in speed using a "just-in-time compiler." Several companies are also working on native-machinearchitecture compilers for Java. These will produce executable code that does not require a separate interpreter, and that is indistinguishable in speed from C++. While you'll never get that last ounce of speed out of a Java program that you might be able to wring from C or Fortran, the results will be suitable for all but the most demanding applications. It is certainly possible to write large programs in Java. The HotJava browser, the Eclipse integrated development environment, the LimeWire file sharing application, the jEdit text editor, the JBoss application server, the Tomcat servlet container, the Xerces XML parser, the Xalan XSLT processor, and the javac compiler are large programs that are written entirely in Java.
Multi threaded
Java is inherently multi-threaded. A single Java program can have many different threads executing independently and continuously. Three Java applets on the same page can run together with each getting equal time from the CPU with very little extra effort on the part of the programmer. This makes Java very responsive to user input. It also helps to contribute to Java's robustness and provides a mechanism whereby the Java environment can ensure that a malicious applet doesn't steal all of the host's CPU cycles. Unfortunately multithreading is so tightly integrated with Java, that it makes Java rather difficult to port to architectures like Windows 3.1 or the PowerMac that don't natively support preemptive multi-threading. There is a cost associated with multi-threading. Multi-threading is to Java what pointer arithmetic is to C, that is, a source of devilishly hard to find bugs. Nonetheless, in simple programs it's possible to leave multi-threading alone and normally be OK.
Dynamically Linked
Java does not have an explicit link phase. Java source code is divided into .java files, roughly one per each class in your program. The compiler compiles these into .class files containing byte code. Each .java file generally produces exactly one .class file. The compiler searches the current directory and directories specified in the CLASSPATH environment variable to find other classes explicitly referenced by name in each source code file. If the file you're compiling depends on other, noncompiled files the compiler will try to find them and compile them as well. The compiler is quite smart, and can handle circular dependencies as well as methods that are used before they're declared. It also can determine whether a source code file has changed since the last time it was compiled. More importantly, classes that were unknown to a program when it was compiled can still be loaded into it at runtime. For example, a web browser can load applets of differing classes that it's never seen before without recompilation. Furthermore, Java .class files tend to be quite small, a few kilobytes at most. It is not necessary to link in large runtime libraries to produce a (non-native) executable. Instead the necessary classes are loaded from the user's CLASSPATH.
Java is Simple
Java was designed to make it much easier to write bug free code. According to Sun's Bill Joy, shipping C code has, on average, one bug per 55 lines of code. The most important part of helping programmers write bug-free code is keeping the language simple. Java has the bare bones functionality needed to implement its rich feature set. It does not add lots of syntactic sugar or unnecessary features. Despite its simplicity Java has considerably more functionality than C, primarily because of the large class library. Because Java is simple, it is easy to read and write. Obfuscated Java isn't nearly as common as obfuscated C. There aren't a lot of special cases or tricks that will confuse beginners. About half of the bugs in C and C++ programs are related to memory allocation and deallocation. Therefore the second important addition Java makes to providing bug-free code is automatic memory allocation and deallocation. The C library memory allocation functions malloc() and free() are gone as are C++'s destructors. Java is an excellent teaching language, and an excellent choice with which to learn programming. The language is small so it's easy to become fluent. The language is interpreted so the compile-run-link cycle is much shorter. The runtime environment provides automatic memory allocation and garbage collection so there's less for the programmer to think about. Java is object-oriented unlike Basic so the beginning programmer doesn't have to unlearn bad programming habits when moving into real world projects. Finally, it's very difficult (if not quite impossible) to write a Java program that will crash your system, something that you can't say about any other language.
Java Operators
An operator is a symbol that operates on one or more arguments to produce a result. The Hello World program is so simple it doesn't use any operators, but almost all other programs you write will. Operator + += -= * *= / /= % %= ++ -> >= < <= ! != && || == = ~ ?: | |= ^ ^= & &= >> >>= Purpose addition of numbers, concatenation of Strings add and assign numbers, concatenate and assign Strings subtraction subtract and assign multiplication multiply and assign division divide and assign take remainder take remainder and assign increment by one decrement by one greater than greater than or equal to less than less than or equal to boolean NOT not equal to boolean AND boolean OR boolean equals Assignment bitwise NOT Conditional bitwise OR bitwise OR and assign bitwise XOR bitwise XOR and assign bitwise AND bitwise AND and assign shift bits right with sign extension shift bits right with sign extension and assign
shift bits left shift bits left and assign unsigned bit shift right unsigned bit shift right and assign
Identifiers in Java
Identifiers are the names of variables, methods, classes, packages and interfaces. Unlike literals they are not the things themselves, just ways of referring to them. In the HelloWorld program, HelloWorld, String, args, main and println are identifiers.
Identifiers must be composed of letters, numbers, the underscore _ and the dollar sign $. Identifiers may only begin with a letter, the underscore or a dollar sign. Each variable has a name by which it is identified in the program. It's a good idea to give your variables mnemonic names that are closely related to the values they hold. Variable names can include any alphabetic character or digit and the underscore _. The main restriction on the names you can give your variables is that they cannot contain any white space. You cannot begin a variable name with a number. It is important to note that as in C but not as in Fortran or Basic, all variable names are case-sensitive. MyVariable is not the same as myVariable. There is no limit to the length of a Java variable name. The following are legal variable names:
MyVariable myvariable MYVARIABLE x i _myvariable $myvariable _9pins andros OReilly This_is_an_insanely_long_variable_name_that_just_keeps_going_and_goin g_and_going_and_well_you_get_the_idea_The_line_breaks_arent_really_p art_of_the_variable_name_Its_just_that_this_variable_name_is_so_ridiculo
My Variable // Contains a space 9pins // Begins with a digit a+c // The plus sign is not an alphanumeric character testing1-2-3 // The hyphen is not an alphanumeric character O'Reilly // Apostrophe is not an alphanumeric character OReilly_&_Associates // ampersand is not an alphanumeric character .
Objects
the expression is an int, byte, short or char. If no cases are matched, the default action is triggered. Once a match is found, all subsequent statements are executed until the end of the switch block is reached or you break out of the block. This can trigger decidedly unexpected behavior. Therefore it is common to include the break statement at the end of each case block. It's good programming practice to put a break after each one unless you explicitly want all subsequent statements to be executed. It's important to remember that the switch statement doesn't end when one case is matched and its action performed. The program then executes all statements that follow in that switch block until specifically told to break.
Overloading
Overloading is when the same method or operator can be used on many different types of data. For instance the + sign is used to add ints as well as concatenate strings. The plus sign behaves differently depending on the type of its arguments. Therefore the plus sign is inherently overloaded. Methods can be overloaded as well. System.out.println() can print a double, a float, an int, a long, or a String. You don't do anything different depending on the type of number you want the value of. Overloading takes care of it. Programmer-defined classes can overload methods as well. To do this simply write two methods with the same name but different argument lists. For instance last week you saw several different versions of the Car constructor, one that took three arguments and one that took two arguments, and one that took no arguments. You can use all of these in a single class, though here I only use two because there really aren't any good default values for licensePlate and maxSpeed. On the other hand, 0 is a perfectly reasonable default value for speed. public class Car { private String licensePlate; // e.g. "New York A456 324" private double speed; // kilometers per hour private double maxSpeed; // kilometers per hour
// constructors public Car(String licensePlate, double maxSpeed) { this.licensePlate = licensePlate; this.speed = 0.0; if (maxSpeed >= 0.0) { this.maxSpeed = maxSpeed; } else { maxSpeed = 0.0; } } public Car(String licensePlate, double speed, double maxSpeed) { this.licensePlate = licensePlate; if (maxSpeed >= 0.0) { this.maxSpeed = maxSpeed; } else { maxSpeed = 0.0; } if (speed < 0.0) { speed = 0.0; } if (speed <= maxSpeed) { this.speed = speed; } else { this.speed = maxSpeed; } } // other methods... } Normally a single identifier refers to exactly one method or constructor. When as above, one identifier refers to more than one method or constructor, the method is said to be overloaded. You could argue that this should be called identifier overloading rather than method overloading since it's the identifier that refers to
more than one method, not the method that refers to more than one identifier. However in common usage this is called method overloading. Which method an identifier refers to depends on the signature. The signature is the number, type, and order of the arguments passed to a method. The signature of the first constructor in the above program is Car(String, double). The signature of the second method is Car(String, double, double). Thus the first version of the Car() constructor is called when there is one String argument followed by one double argument and the second version is used when there is one String argument followed by two double arguments. If there are no arguments to the constructor, or two or three arguments that aren't the right type in the right order, then the compiler generates an error because it doesn't have a method whose signature matches the requested method call. For example Error: Method Car(double) not found in class Car. Car.java line 17
Operator Overloading
Some object oriented languages, notably C++, allow you to not only overload methods but also operators like + or -. This is very useful when dealing with user defined mathematical classes like complex numbers where + and - have welldefined meanings. However most non-mathematical classes do not have obvious meanings for operators like + and -. Experience has shown that operator overloading is a large contributor to making multi-person programming projects infeasible. Therefore Java does not support operator overloading.
Inheritance
Code reusability is claimed to be a key advantage of object-oriented languages over non-object-oriented languages. Inheritance is the mechanism by which this is achieved. An object can inherit the variables and methods of another object. It can keep those it wants, and replace those it doesn't want.
Overriding Methods
Suppose that one day you've just finished your Car class. It's been plugged into your traffic simulation which is chugging along merrily simulating traffic. Then your pointy haired boss rolls in the door, and tells you that he needs the Car class to not accelerate past the 70 miles per hour (pointy haired bosses rarely understand the metric system) even if the car's a Ferrari with a maximum speed in excess of 200 miles per hour. What are you going to do? Your first reaction may be to change the class that you already wrote so that it limits the speed of all the cars. However you're using that class elsewhere and things will break if you change it. You could create a completely new class in a different file, either by starting from scratch or by copying and pasting. This would work, but it would mean that if you found a bug in the Car class now you'd have to fix it in two files. And if you wanted to add new methods to the Car class, you'd have to add them in two files. Still this is the best you could do if you were writing in C or some other traditional language.
the programmer to keep track of what kind of object is stored in a Vector, and to use it accordingly. The proper choice of classes and subclasses is a skill learned primarily through experience. There are often different ways to define classes. toString() as example of polymorphism
What is an Applet?
According to Sun "An applet is a small program that is intended not to be run on its own, but rather to be embedded inside another application....The Applet class provides a standard interface between applets and their environment." Four definitions of applet:
A small application A secure program that runs inside a web browser A subclass of java.applet.Applet An instance of a subclass of java.applet.Applet
+----java.applet.Applet
<applet code="com.macfaq.greeting.HelloWorldApplet" codebase="http://www.example.com/classes" width="200" height="200"> </applet> In this case the browser will look for http://www.example.com/classes/com/macfaq/greeting/HelloWorldApplet.class so the directory structure on the server should also mirror the package hierarchy. The HEIGHT and WIDTH attributes work exactly as they do with IMG, specifying how big a rectangle the browser should set aside for the applet. These numbers are specified in pixels and are required.
<HEAD> <TITLE> Draw String </TITLE> </HEAD> <BODY> This is the applet:<P> <APPLET code="DrawStringApplet" width="300" height="50"> <PARAM name="Message" value="Howdy, there!"> This page will be very boring if your browser doesn't understand Java. </APPLET> </BODY> </HTML> Of course you are free to change "Howdy, there!" to a "message" of your choice. You only need to change the HTML, not the Java source code. PARAMs let you customize applets without changing or recompiling the code.
This applet is very similar to the HelloWorldApplet. However rather than hardcoding the message to be printed it's read into the variable inputFromPage from a PARAM element in the HTML. You pass getParameter() a string that names the parameter you want. This string should match the name of a PARAM element in the HTML page. getParameter() returns the value of the parameter. All values are passed as strings. If you want to get another type like an integer, then you'll need to pass it as a string and convert it to the type you really want. The PARAM element is also straightforward. It occurs between <APPLET> and </APPLET>. It has two attributes of its own, NAME and VALUE. NAME identifies which PARAM this is. VALUE is the string value of the PARAM. Both should be enclosed in double quote marks if they contain white space. An applet is not limited to one PARAM. You can pass as many named PARAMs to an applet as you like. An applet does not necessarily need to use all the PARAMs that are in the HTML. Additional PARAMs can be safely ignored
Components
Components are graphical user interface (GUI) widgets like checkboxes, menus, windows, buttons, text fields, applets, and more. In Java all components are subclasses of java.awt.Component. Subclasses of Component include
Canvas TextField TextArea Label List Button Choice Checkbox Frame JButton JLabel JComboBox JMenu
To use menus in your application you need to add instances of all three classes, one MenuBar with one or more Menus, each with several MenuItems.
The java.awt.MenuComponent class is the ultimate superclass of all these classes. MenuComponent extends java.lang.Object. Thus menus, menu bars, and menu items are not components and cannot be added to containers in the usual fashion. java.lang.Object | +---java.awt.MenuComponent | +---java.awt.MenuBar | +---java.awt.MenuItem | +---java.awt.Menu | +---java.awt.PopupMenu Both MenuBar and MenuItem extend MenuComponent. Menu extends MenuItem. (This sounds a little strange, but if you think about it a menu is an item in a menu bar.) Furthermore, MenuBar implements the java.awt.MenuContainer interface.
The java.io package contains classes that perform input and output. In Java, I/O classes are differentiated according to the type of data being read or written. Byte oriented and numeric data is written with output streams and read with input streams. Character data, that is text, is written with writers and read with readers. Whether you use streams or readers and writers depends on the type of data you're dealing with. All text data, especially non-ASCII text, should be passed through a reader or writer. The two main stream classes are java.io.InputStream and java.io.OutputStream. The two main reader and writer classes are java.io.Reader and java.io.Writer These are abstract base classes for many different subclasses with more specialized abilities.
BufferedInputStream BufferedOutputStream ByteArrayInputStream ByteArrayOutputStream DataInputStream DataOutputStream FileInputStream FileOutputStream FilterInputStream FilterOutputStream LineNumberInputStream ObjectInputStream ObjectOutputStream PipedInputStream PipedOutputStream PrintStream PushbackInputStream SequenceInputStream
Both threads and processes are methods of parallelizing an application. However, processes are independent execution units that contain their own state information, use their own address spaces, and only interact with each other via interprocess communication mechanisms (generally managed by the operating system). Applications are typically divided into processes during the design phase, and a master process explicitly spawns sub-processes when it makes sense to logically separate significant application functionality. Processes, in other words, are an architectural construct. By contrast, a thread is a coding construct that doesn't affect the architecture of an application. A single process might contains multiple threads; all threads within a process share the same state and same memory space, and can communicate with each other directly, because they share the same variables. Threads typically are spawned for a short-term benefit that is usually visualized as a serial task, but which doesn't have to be performed in a linear manner (such as performing a complex mathematical computation using parallelism, or initializing a large matrix), and then are absorbed when no longer required. The scope of a thread is within a specific code modulewhich is why we can bolt-on threading without affecting the broader application.
You never call run() explicitly. It is called automatically by the runtime as necessary once you've called start(). There are also methods to suspend and resume threads, to put threads to sleep and wake them up, to yield control to other threads, and many more. I'll discuss these later. The Runnable interface allows you to add threading to a class which, for one reason or another, cannot conveniently extend Thread. It declares a single method, run(): public abstract void run() By passing an object which implements Runnable to a Thread() constructor, you can substitute the Runnable's run() method for the Thread's own run() method. (More properly the Thread object's run() method simply calls the Runnable's run() method.)
Thread Priorities
Not all threads are created equal. Sometimes you want to give one thread more time than another. Threads that interact with the user should get very high priorities. Threads that calculate in the background should get low priorities. Thread priorities are defined as integers between 1 and 10. Ten is the highest priority. One is the lowest. The normal priority is five. Higher priority threads get more CPU time. For your convenience java.lang.Thread defines three mnemonic constants, Thread.MAX_PRIORITY, Thread.MIN_PRIORITY and Thread.NORM_PRIORITY which you can use in place of the numeric values. You set a thread's priority with the setPriority(int priority) method. The following program sets Chris's priority higher than Mary's whose priority is higher than Frank's. It is therefore likely that even though Chris starts last and Frank starts first, Chris will finish before Mary who will finish before Frank. public class MixedPriorityTest { public static void main(String[] args) { NamedBytePrinter frank = new NamedBytePrinter("Frank"); NamedBytePrinter mary = new NamedBytePrinter("Mary"); NamedBytePrinter chris = new NamedBytePrinter("Chris"); frank.setPriority(Thread.MIN_PRIORITY);
Methods
Methods say what an object does. class TwoDPoint { double x; double y; void print() { System.out.println(this.x + "," + this.y); } } Notice that you use the Java keyword this to reference a field from inside the same class. TwoDPoint origin = new TwoDPoint(); origin.x = 0.0; origin.y = 0.0; origin.print(); noun-verb instead of verb-noun; that is subject-verb instead of verb-direct object. subject-verb-direct object(s) is also possible.
Applet Security
The possibility of surfing the Net, wandering across a random page, playing an applet and catching a virus is a fear that has scared many uninformed people away from Java. This fear has also driven a lot of the development of Java in the direction it's gone. Earlier I discussed various security features of Java including automatic garbage collection, the elimination of pointer arithmetic and the Java interpreter. These serve the dual purpose of making the language simple for programmers and secure for users. You can surf the web without worrying that a Java applet will format your hard disk or introduce a virus into your system. In fact both Java applets and applications are much safer in practice than code written in traditional languages. This is because even code from trusted sources is likely to have bugs. However Java programs are much less susceptible to common bugs involving memory access than are programs written in traditional languages like C. Furthermore the Java runtime environment provides a fairly robust means of trapping bugs before they bring down your system. Most users have many more problems with bugs than they do with deliberately malicious code. Although users of Java applications aren't protected from out and out malicious code, they are largely protected from programmer errors.
Applets implement additional security restrictions that protect users from malicious code too. This is accomplished through the java.lang.SecurityManager class. This class is subclassed to provide different security environments in different virtual machines. Regrettably implementing this additional level of protection does somewhat restrict the actions an applet can perform. Let's explore exactly what an applet can and cannot do.
Graphics Objects
In Java all drawing takes place via a Graphics object. This is an instance of the class java.awt.Graphics.
Initially the Graphics object you use will be the one passed as an argument to an applet's paint() method. Later you'll see other Graphics objects too. Everything you learn today about drawing in an applet transfers directly to drawing in other objects like Panels, Frames, Buttons, Canvases and more. Each Graphics object has its own coordinate system, and all the methods of Graphics including those for drawing Strings, lines, rectangles, circles, polygons and more. Drawing in Java starts with particular Graphics object. You get access to the Graphics object through the paint(Graphics g) method of your applet. Each draw method call will look like g.drawString("Hello World", 0, 50) where g is the particular Graphics object with which you're drawing. For convenience's sake in this lecture the variable g will always refer to a preexisting object of the Graphics class. As with any other method you are free to use some other name for the particular Graphics context, myGraphics or appletGraphics perhaps.