01 April 2002
This lecture covers the reading in Day 4: Working with Objects |
|
Except for a limited number of "primitives" (numbers and characters), the object-oriented model, rather than the procedural model, dictates how you program in Java. Even strings are objects.
First some review using analogies from the real world.
This blueprint is a template for constructing the new California Governor's mansion that allows the government to function even if PG&E fails due to bankruptcy, terrorism, or migration to Texas. In any case, California politicians have to supply the hot air or wind power.
For how many instances of wind-powered mansions can this blueprint provide the model?
For how many instances (objects) can a class (template) provide the model?
What limits the number of instances that can be created for a class?
The only limit is memory, except in the case of a singleton object; which means the application can only create one instance of that class. In that case I declare a private default constructor and have a static variable containing a single instance of the object. For example:
class SingleFoo { private static SingleFoo sfoo = new SingleFoo(); private SingleFoo() } public getSingleFoo() { return sfoo; } }
The United States Navy refers to a
model for a ship as its "class".
The Navy refers to each instance of the "class" as a "ship".
How many class properties (or fields) are common to each instance of the Seawolf
class of nuclear submarines?
How many instances (objects) have been constructed?
What is the value of the cost property? Do you
believe that constructing an object can be expensive?
http://www.chinfo.navy.mil/navpalib/factfile/ships/ship-ssn.html
General Characteristics, Seawolf class:
Builders: General Dynamics Electric Boat Division.
Power Plant: One nuclear reactor, one shaft
Length: 353 feet (107.6 meters)
Draft: 35 feet (10.67 meters)
Beam: 40 feet (12.2 meters)
Displacement: 8,060 tons (8,189.35 metric tons) surfaced; 9,150 tons
(9,296.84 metric tons) submerged
Speed: 25+ knots (28+ miles per hour, 46.3+ kph)
Cost: about $2.1 billion each
Ships:
USS
Seawolf (SSN 21), Groton, Ct.
USS
Connecticut (SSN 22), Groton, Ct.
Jimmy Carter (SSN 23), (under construction)
Crew: 13 Officers; 121 Enlisted
Armament: Tomahawk
missiles, MK-48
torpedoes, eight torpedo tubes.
Now that we are clear about how a class is a template for the construction of objects, and that an object is an instance of a specific class, we can look at HOW to create an object.
David explain that a string is a special object because the syntax to create a string object is more simple than that of other objects:
String cityName = "Berkeley";
The API for the Java platform also makes it convenient to work with strings.
We do not have to build a string from an array of characters.
Just so you know, however, the string:
String jediMaster = "Yoda";
is equivalent to something more tedious to code:
char myArrayOfChars[] = {'Y', 'o', 'd', 'a'}; String jediMaster = new String(myArrayOfChars);
In line 5, I declare and define an array of characters.
In line 6, I declare and define a string by passing the name of the character
array as an argument for the creation and initialization of a new string. When I
create the string jediMasters, it copies the input characters into its
own internal character array. (I have access to the array of characters in line
5, but I do not have access to the internals of the string in line 6.)
In line 7, I instruct the method that prints a line to output a string.
Except for the string object, we use the new operator to create an instance.
The new operator is what you use to create a new object. As long as there is one or more references to the object, the Java virtual machine will not make the object eligible for eventual "garbage collection".
I can use the new operator even with a string:
String firstName = new String();
String lastName = new String("Einstein"); // create a string object with an argument
The new operator creates a new object by calling the constructor that initializes the object. In this case, the initialization of lastName assigns the value "Einstein".
The output is:
123
456
789
1011
1213
The initialization for the quote1 instance of
the String object takes one argument.
The initialization for the quote2 instance of the
String object takes two arguments.
This is an example of an "overloaded constructor", about which we will
talk more later.
The output is:
Token 1: VIZY
Token 2: 3
Token 3: -1/16
Token 1: NPLI
Token 2: 9 27/3
Token 3: 3/32
When you create the StringTokenizer() method, the Java runtime checks for the signature (the number and type of arguments), and calls the constructor that matches the signature.
Use the dot operator (.) to access the instance variables and the instance methods of an object:
In the TokenDemo.java example, at line 8 we create an
instance of the StringTokenizer object and
we name this object st. In line 10, we
call a method that this instance inherits from the StringTokenizer object
in the java.util package. st.nextToken() |
System.out.println("Hello World"); The System class is unusual because it cannot
be instantiated and has only static methods and variables. . |
Let's set the values for some variables.
RockGroup fabfour = new RockGroup("Beatles");
fabfour.leadGuitar = "George";
fabfour.bass = "Paul";
System.out.println("Lead Guitar: " + fabfour.leadGuitar);
In this case the variables leadGuitar and bass were declared within the class definition.
Normally you will only access instance variables within the class itself, or within a subclass, or a "friend" class in the same package. That's part of encapsulation.
Similarly, you can reset the value of any variable. For example:
boolean Player.isWinner = true; // set to true boolean Player.isWinner = false; // reset to false
The keywords static and final have different meanings.
class MostPowerfulPoliticalFamilyMember { // static applies to all instances // final means the value cannot change, and therefore is a constant static final String lastName = "Bush"; // only one copy of lastname for all instances String firstName; String homeState; }
A method is a chunk of Java code with a name. A program can call (or invoke) a method so that the Java virtual machine executes the method. Methods take parameters as arguments (input), and return a result called a return value (output).
Let's look at how a program called factorial.java uses methods.
Line 11 passes to the factorial() method in a parameter, an integer called x. The factorial() method returns a double. This is different from line 5, where the main() method that is declared void and therefore does not return a value. The method body for factorial() begins on line 11 and ends on line 20. The main() method calls the factorial method on line 7. When the main() method calls the factorial() method, the main() method passes an argument called input, which is the number that the user types in as a command-line argument. The main() method parses the user's command line argument on line 6.
We are already familiar with this method call that uses the dot operator:
System.out.println("Hello World!");
The println() method returns a string.
The dot operator enables you to call a method of the object you specify.
A typical syntax is objectReference.methodName(argumentList);
Method calls always need parentheses.
For readability, it is good that the programmer defines input on line 6, and
result on line 7.
However, I can comment out the declarations of lines 6 and 7 to pass something
more complex to the println() method on line 8.
I pass to println() the return value of the factorial() method.
The factorial method, we see on line 11, takes an integer argument.
On line 8, I pass to the factorial method the return value of the parseInt()
method as an argument.
Let's look at some code the works with methods that get values by using the dot operator.
This following example is a bit more involved.
Line 9 calls the talkToManager() method of the OrderManager class. This
method prints a string.
Line 9 works because the new operator on line 8 creates myCustomer as an
instance of the CustomerManager class.
The CustomerManager class defines only one method, cancelAllOrders(), which, in
line 17 creates an instance of the OrderManager class, om.
Line 18 returns this instance, which is necessary for the string to output,
because line 24 defines a string to output, but is void!
Line 22 is the key to it all, because it is the constructor for the OrderManager
class.
When line 17 uses the new operator to call the constructor, the constructor
initializes the om instance of the OrderManager class by calling the
talkToManager() method, which in turn calls the println() method.
Therefore, in line 18, when the cancelAllOrders() method returns the om
instance, the om instance has the string to print!
Note: When the Java runtime resolves method calls, it goes from the lowest (most local) level first, then working its way up the hierarchy until it finds a method body. This is critical to object-oriented behavior, which allows for both inheritance and local overriding of inherited behavior.
The new operator creates a new object and returns a reference to it. You assign that reference to a variable. For example, you might assign a Point reference to a variable called origin_one.
http://java.sun.com/docs/books/tutorial/java/data/objectcreation.html
The following strings, myName and yourName, refer to separate objects:
Therefore, we can change the value of one variable without changing the value
of the other variable.
The output is:
myName is Someone who sells glasses yourName is eye doctor
However, the Point
class and the Rectangle
class
allow free access to their member variables by declaring them public
.
Casting is the translation of a primitive type into another primitive type or the translation of one object into another object. In a cast, the Java runtime knows enough about the types and how they are related to do this conversion automatically.
byte, short, int, long, float, double | cast to/from | byte, short, int, long, float, double |
Explicit cast to smaller type: (typename)value
The output is:
The product as double is 3.75 The product as integer is = 3
Booleans cannot be cast.
When you cast a floating point type to an integer type, or a double to a float, there may be loss of precision. For example, (int)3.2 will truncate the .2 and just return 3. Also, when casting from a larger integer type to a smaller one, if the number is very large, it might be truncated and return a smaller number. You need to check for this yourself.
You can cast an object to another class if the two classes are related by inheritance.
For example, all objects inherit from the superclass Object.
Therefore, all objects have a GetClass() method.
I do not need to make an explicit cast for my string object to use this method.
The output is:
The class of myClass@111f71 is myClass The class of [Ljava.lang.String;@273d3c is [Ljava.lang.String;
You don't need an explicit cast when upcasting but you do need one when downcasting. For example,
String s = "Heeeeeeeeere's Johnny"; Object o = s; // implicit upcast, no casting syntax needed String sz = (String)o; // explicit downcast, need casting syntax
You can use the instanceof operator to test an object's class before doing a downcast:
String s = "Heeeeeeeeere's Johnny"; Object o = s; String sz; if (o instanceof String) { sz = (String)o; }
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/other.html
Here, the instanceof operator determines whether its first operand is an instance
of its second operand.
Converting is the translation of one type into another, when you cannot do a
simple cast.
Unlike a cast, the runtime does not know enough about the types to do this
automatically.
Some code must be written to handle the conversion
Suppose that you have been storing zip codes as strings, but now you need to treat those zip codes as integers.
String myZipCode = "94568"; // myZipCode ing is a String object int myZip = Integer.parseInt(myZipCode); // myZip is a primitive
To convert an integer primitive into an object of its corresponding Integer class:
The output is:
The class to which 94568 is an instance is java.lang.Integer
The most common type of conversion is to and from a String.
The java.lang.Object package defines a toString()
method with a simple default implementation.
Many classes override this implementation to provide a translation that
preserves the object's content.
For example, an XML document might use the toString()
method.
java.lang.Object defines an equals()
method, but the default implementation is simply a == test.
Many objects override this to do something more useful, for example, with
Strings.
The following example uses both the equals()
method and the == test.
Line 5 creates a second variable that points to the object, but line 11 reassigns that second variable to a second object.
______________
course
homepage course
calendar