Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Object Oriented Programming

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 30

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 is Garbage Collected


You do not need to explicitly allocate or deallocate memory in Java. Memory is allocated as needed, both on the stack and the heap, and reclaimed by the garbage collector when it is no longer needed. There's no malloc(), free(), or destructor methods. There are constructors and these do allocate memory on the heap, but this is transparent to the programmer. The exact algorithm used for garbage collection varies from one virtual machine to the next. The most common approach in modern VMs is generational garbage collection for short-lived objects, followed by mark and sweep for longer lived objects. I have never encountered a Java VM that used reference counting.

Primitive Data Types in Java


Java's primitive data types are very similar to those of C. They include boolean, byte, short, int, long, float, double, and char. The boolean type has been added. However the implementation of the data types has been substantially cleaned up in several ways. 1. Where C and C++ leave a number of issues to be machine and compiler dependent (for instance the size of an int) Java specifies everything. 2. Java prevents casting between arbitrary variables. Only casts between numeric variables and between sub and superclasses of the same object are allowed. 3. All numeric variables in Java are signed. sizeof isn't necessary in Java because all sizes are precisely defined. For instance, an int is always 4 bytes. This may not seem to be adequate when dealing with objects that aren't base data types. However even if you did know the size of a particular object, you couldn't do anything with it anyway. You cannot convert an arbitrary object into bytes and back again.

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

usly_long_that_it_won't_fit_on_the_page_I_cant_imagine_why_you_would _need_such_a_long_variable_name_but_if_you_do_you_can_have_it The following are not legal variable names:


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 .

Java Flow Control


if else else if while for do while switch case break continue

goto is a reserved word. It is not implemented.

The if statement in Java


All but the most trivial computer programs need to make decisions. They test a condition and operate differently based on the outcome of the test. This is quite common in real life. For instance you stick your hand out the window to test if it's raining. If it is raining then you take an umbrella with you. If it isn't raining then you don't. All programming languages have some form of an if statement that tests conditions. In the previous code you should have tested whether there actually were command line arguments before you tried to use them. Arrays have lengths and you can access that length by referencing the variable arrayname.length You test the length of the args array as follows. // This is the Hello program in Java class Hello { public static void main (String args[]) { if (args.length > 0) { System.out.println("Hello " + args[0]); } } } System.out.println(args[0]) was wrapped in a conditional test, if (args.length > 0) { }. The code inside the braces, System.out.println(args[0]), now gets executed if and only if the length of the args array is greater than zero. The arguments to a conditional statement like if must be a boolean value, that is something that evaluates to true or false. Integers are not permissible. In Java numerical greater than and lesser than tests are done with the > and < operators respectively. You can test whether a number is less than or equal to or greater than or equal to another number with the <= and >= operators.

Objects

The switch statement in Java


Switch statements are shorthands for a certain kind of if statement. It is not uncommon to see a stack of if statements all relate to the same quantity like this: if (x == 0) doSomething0(); else if (x == 1) doSomething1(); else if (x == 2) doSomething2(); else if (x == 3) doSomething3(); else if (x == 4) doSomething4(); else doSomethingElse(); Java has a shorthand for these types of multiple if statements, the switch-case statement. Here's how you'd write the above using a switch-case: switch (x) { case 0: doSomething0(); break; case 1: doSomething1(); break; case 2: doSomething2(); break; case 3: doSomething3(); break; case 4: doSomething4(); break; default: doSomethingElse(); } In this fragment x must be a variable or expression that can be cast to an int without loss of precision. This means the variable must be or the expression must return an int, byte, short or char. x is compared with the value of each the case statements in succession until one matches. This fragment compares x to literals, but these too could be variables or expressions as long as the variable or result of

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.

Subclasses and Polymorphism


Car and Motorcycle are subclasses of MotorVehicle. If you instantiate a Car or a Motorcycle with new, you can use that object anywhere you can use a MotorVehicle, because cars are motor vehicles. Similarly you can use a Motorcycle anywhere you can use a MotorVehicle. This use of a subclass object in place of a superclass object is the beginning of polymorphism. I'll say more about polymorphism later. The converse is not true. Although all cars are motor vehicles, not all motor vehicles are cars. Some are motorcycles. Therefore if a method expects a Car object you shouldn't give it a MotorVehicle object instead. Note that I said you shouldn't give a method that expects a Car a MotorVehicle. I didn't say you couldn't. Objects can be cast into their subclasses. This is useful when using data structures like Vectors that only handle generic objects. It's up to

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

Class or static Members


A method or a field in a Java program can be declared static. This means the member belongs to the class rather than to an individual object. If a variable is static, then when any object in the class changes the value of the variable, that value changes for all objects in the class. For example, suppose the Car class contained a speedLimit field that was set to 112 kph (70 mph). This would be the same for all cars. If it changed (by act of Congress) for one car, it would have to change for all cars. This is a typical static field. Methods are often static is if they neither access nor modify any of the instance (non-static) fields of a class and they do not invoke any non-static methods in the class. This is common in calculation methods like a square root method that merely operate on their arguments and return a value. One way of thinking of it is that a method should be static if it neither uses nor needs to use this.

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

public class Applet extends Panel java.lang.Object | +----java.awt.Component | +----java.awt.Container | +----java.awt.Panel |

+----java.applet.Applet

The APPLET Element


Applets are embedded in web pages using the <APPLET> and </APPLET> tags. The APPLET element is similar to the IMG element. Like IMG APPLET references a source file that is not part of the HTML page on which it is embedded. IMG elements do this with the SRC attribute. APPLET elements do this with the CODE attribute. The CODE attribute tells the browser where to look for the compiled .class file. It is relative to the location of the source document. Thus if you're browsing http://www.ibiblio.org/javafaq/index.html and that page references an applet with CODE="Animation", then the file Animation.class should be at the URL http://www.ibiblio.org/javafaq/Animation.class. If the applet resides somewhere other than the same directory as the page it lives on, you don't just give a URL to its location. Rather you point at the CODEBASE. The CODEBASE attribute contains a URL that points at the directory where the .class file is. The CODE attribute is the name of the .class file itself. For instance if on the HTML page of the previous section you had written <applet code="HelloWorldApplet" codebase="classes" width="200" height="200"> </applet> then the browser would have tried to find HelloWorldApplet.class in the classes directory in the same directory as the HTML page that included the applet. On the other hand if you had written <applet code="HelloWorldApplet" codebase="http://www.foo.bar.com/classes" width="200" height="200"> </applet> then the browser would try to retrieve the applet from http://www.foo.bar.com/classes/HelloWorldApplet.class regardless of where the HTML page was. In short the applet viewer will try to retrieve the applet from the URL given by the formula (CODEBASE + "/" + code). Once this URL is formed all the usual rules about relative and absolute URLs apply. If the applet is in a non-default package, then the full package qualified name must be used. For example,

<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.

Passing Parameters to Applets


Parameters are passed to applets in NAME=VALUE pairs in <PARAM> tags between the opening and closing APPLET tags. Inside the applet, you read the values passed through the PARAM tags with the getParameter() method of the java.applet.Applet class. The program below demonstrates this with a generic string drawing applet. The applet parameter "Message" is the string to be drawn. import java.applet.*; import java.awt.*; public class DrawStringApplet extends Applet { private String defaultMessage = "Hello!"; public void paint(Graphics g) { String inputFromPage = this.getParameter("Message"); if (inputFromPage == null) inputFromPage = defaultMessage; g.drawString(inputFromPage, 50, 25); } } You also need an HTML file that references your applet. The following simple HTML file will do: <HTML>

<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

The Event Queue


Instead GUI models require an event approach. Each user action, be it a mouse click, a key press, or something else is placed in an event queue as it occurs. Normally this takes place at the operating system level. The program removes events from the queue and processes them, one at a time. Generally an infinite while loop reads from the queue, and a big switch statement dispatches each different event to the appropriate code to handle it. Depending on the architecture of the system, there may be only one system event queue or each application may have its own event queue. The operating system is responsible for making sure the right events get to the right programs. In the applications we're concerned with, that is Java programs, each virtual machine has one main AWT event queue. There's almost certainly a native event queue as well, but from here on out I'll only talk about the Java event queue. Your Java program will only see events that are sent to it by the native queue.

Containers and LayoutManagers


A FlowLayout arranges widgets from left to right until there's no more space left. Then it begins a row lower and moves from left to right again. Each component in a FlowLayout gets as much space as it needs and no more. A FlowLayout is useful for laying out buttons but not for much else. This is the default LayoutManager for applets and panels (special containers to aid with layouts about which you'll learn more very shortly). A BorderLayout organizes an applet into North, South, East, West and Center sections. North, South, East and West are the rectangular edges of the applet. They're continually resized to fit the sizes of the widgets included in them. Center is whatever's left over in the middle. A CardLayout breaks the applet into a deck of cards, each of which has its own LayoutManager. Only one card appears on the screen at a time. The user flips between cards, each of which shows a different set of components. The common analogy is with HyperCard on the Mac and Toolbook on Windows. In Java this might be used for a series of data input screens, where more input is needed than can comfortably be fit on one screen. A GridLayout divides an applet into a specified number of rows and columns which form a grid of cells, each equally sized and spaced. As components are added to the layout, they are placed in the cells, starting at the upper left hand corner and moving to the right and down the page. Each component is sized to fit into its cell. This layout manager tends to squeeze and stretch components unnecessarily. However the GridLayout is great for arranging Panels. GridBagLayout is the most precise of the five AWT LayoutManagers. It's similar to the GridLayout, but components do not need to be the same size. Each component can occupy one or more cells of the layout. Furthermore components are not necessarily placed in the cells beginning at the upper left-hand corner and moving to the right and down. In simple applets with just a few components you often need only one layout manager. In more complicated applets, however, you'll often split your applet into panels, lay out the panels according to a layout manager, and give each panel its own layout manager that arranges the components inside it.

The Menu Classes


The AWT contains four main classes to handle menus:

java.awt.Menu java.awt.MenuBar java.awt.MenuItem java.awt.PopupMenu

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.

Input and Output in Java

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.

The Stream Classes


Most stream classes are part of the java.io package. (There are also a few more in the sun.io and sun.net packages, but those are deliberately hidden from you. There are also a couple in java.util.zip.) The two main classes are java.io.InputStream and java.io.OutputStream. These are abstract base classes for many different subclasses with more specialized abilities, including:

BufferedInputStream BufferedOutputStream ByteArrayInputStream ByteArrayOutputStream DataInputStream DataOutputStream FileInputStream FileOutputStream FilterInputStream FilterOutputStream LineNumberInputStream ObjectInputStream ObjectOutputStream PipedInputStream PipedOutputStream PrintStream PushbackInputStream SequenceInputStream

Threads vs. Processes

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.

The Thread Classes


Java has two ways a program can implement threading. One is to create a subclass of java.lang.Thread. However sometimes you'll want to thread an object that's already a subclass of another class. Then you use the java.lang.Runnable interface. The Thread class has three primary methods that are used to control a thread: public void start() public void run() public final void stop() The start() method prepares a thread to be run; the run() method actually performs the work of the thread; and the stop() method halts the thread. The thread dies when the run() method terminates or when the thread's stop() method is invoked.

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);

mary.setPriority(Thread.NORM_PRIORITY); chris.setPriority(Thread.MAX_PRIORITY); frank.start(); mary.start(); chris.start(); } }

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.

The OBJECT Element


HTML 4.0 deprecates the APPLET element. Instead you are supposed to use the OBJECT element. For the purposes of embedding applets, the OBJECT element is used almost exactly like APPLET except that the class attribute becomes the classid attribute. For example, <object classid="MyApplet" codebase="http://www.foo.bar.com/classes" width="200" height="200" align="right" hspace="5" vspace="10"> </object> OBJECT elements are also used to embed ActiveX controls and other kinds of active content, and the tag has a few additional attributes to allow it to do that. However, for the purposes of Java you don't need to know about these. You can support both by placing an APPLET element inside an OBJECT element like this: <object classid="MyApplet" width="200" height="200"> <applet code="MyApplet" width="200" height="200"> </applet> </object> Browsers that understand <OBJECT> will ignore its content while browsers that don't will display its content. PARAM elements are the same for OBJECT as for APPLET.

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.

You might also like