Blakes 21 Days Chapter 03 Document
Day 3, Working with Objects
- 067 Java is an object-oriented programming language. When you do work in Java, you primarily use objects to get the job done. You create objects, modify them, change their variables, call their methods, and combine them with other objects. You develop classes, create objects out of those classes, and use them with other classes and objects.
- Today, you work extensively with objects as you undertake these essential tasks:
- Creating objects
- Testing and modifying their class and instance variables
- Calling an object's methods
- Converting objects from one class to another
Creating New Objects
- Top
- 068 When you write a Java program, you define a set of classes.
- As you learned in Day 1, a class is a template used to create one or more objects.
- These objects, which also are called instances, are self-contained elements of a program with related features and data.
- For the most part, you use the class merely to create instances and then work with those instances.
- In this section, you learn how to create a new object from any given class.
- 068 When using strings during Day 2, you learned that a string literal, characters enclosed in double quotation marks, can be used to create a new instance of the class String with the value of that string.
- 068 The String class is unusual in that respect. Although it's a class, it can be assigned a value with a literal as if it was a primitive data type.
- This shortcut is available only for strings and classes that represent primitive data types, such as Integer and Double.
- To create instances for all other classes, the new operator is used.
- 068 NOTE: What about the literals for numbers and characters? Don't they create objects too? Actually, they don't. The primitive data types for numbers and characters create numbers and characters, but for efficiency they actually aren't objects. On Day 5, you learn how to use objects to represent primitive values.
Using new
- Top
- 068 To create a new object, you use the new operator with the name of the class that should be used as a template.
- The name of the class is followed by parentheses, as in these three examples:
- String name = new String("Hal Jordan");
- URL address = new URL("http://www.java21days.com");
- MarsRobot robbie = new MarsRobot();
- The parentheses are important and can't be omitted
- They are empty, however, in which case the most simple, basic object of that class is created.
- The parentheses also can contain arguments that determine the values of instance variables or other initial qualities of that object.
- 069 Here are two objects being created with arguments:
- Random seed = new Random(606843071);
- Point pt = new Point(0, 0);
- The number and type of arguments to include inside the parentheses are defined by the class itself using a special method called a constructor.
- If you try to create a new instance of a class with the wrong number or wrong type of arguments, or if you give it no arguments and it needs them, an error occurs when the program is compiled.
- Top
- 069 Today's first project is a demonstration of creating different types of objects with different numbers and types of arguments.
- The StringTokenizer class in the java.util package divides a string into a series of shorter strings called tokens.
- You divide a string into tokens by applying a character or characters as a delimiter.
- For example, the text "02/20/67" could be divided into three tokens = "02", "20", and "67" - using the slash character / as a delimiter.
- 069 Today's first project is a Java application that uses string tokens to analyze stock price data.
- In NetBeans, create a new empty Java file for the class TokenTester in the com.java21days package, and enter the code in Listing 3.1 as its source code.
- This program creates StringTokenizer objects by using new in two different ways and then displays each token the objects contain.
Listing 3.1
- Top
- page 069-070
package com.java21days;
import java.util.StringTokenizer;
class TokenTester {
public static void main(String[] arguments) {
StringTokenizer st1, st2;
String quote1 = "GOOG 530.80 -9.98";
st1 = new StringTokenizer(quote1);
System.out.println("Token 1: " + st1.nextToken() );
System.out.println("Token 2: " + st1.nextToken() );
System.out.println("Token 2: " + st1.nextToken() );
String quote2 = "RHT@75.00@0.22";
st2 = new StringTokenizer(quote2, "@");
System.out.println("\nToken 1: " + st2.nextToken() );
System.out.println("Token 2: " + st2.nextToken() );
System.out.println("Token 3: " + st2.nextToken() );
}
}
Listing 3.1 (screenshot from NetBeans) goes here
- Top
- Earlier I was having issues with NetBeans running a previous program result's in the Output pane. The "New Empty Java File" screen comes from that attempt.
Source & Output
- Top
- I originally has parentheses in the wrong place and a \n in lines 19 & 20 which shouldn't have been there.
- This is the code copied and pasted from the book's source folder.
- Top
- 070 Save this file by choosing File, Save or clicking the Save All button on the NetBeans toolbar.
- Run the application by choosing Run, Run File to see the output.
- 070 Two different StringTokenizer objects are created using different arguments to the constructor.
- 070 The first object is created using new StringTokenizer() with one argument, a String object named quote1 (line 11).
- This creates a StringTokenizer object that uses the default delimiters, which are blank spaces, tabs, newlines, carriage returns, or formfeed characters.
- If any of these characters is contained in the string, it is used to divide the string.
- Because the quote1 string contains spaces, these are used as delimiters dividing each token.
- Lines 12 to 14 display the values of all three tokens: "GOOG", "530.80", and "-9.98".
- The second StringTokenizer object in this example has two arguments when it is constructed in line 16 - a String object named quote2 and an at-sign character @.
- This second argument indicates that the @ character should be used as the delimiter between tokens.
- The StringTokenizer object created in line 17 contains three tokens: "RHT", "75.00", and "0.22".
How Objects are Constucted
- Top | Back to Casting Objects
- 070 Several things happen when you use the new operator.
- The new instance of the given class is created, memory is allocated for it
- and a special method defined in the given class is called.
- This method is called a constructor.
- 071 A constructor is a way to create a new instance of a class.
- A constructor initializes the new object and its variables,
- creates any other objects that the object needs
- and performs any additional operations the object requires to initialize itself.
- 071 A class can have several different constructors, each with a different number or type of argument.
- When you use new, you can specify different arguments in the argument list, and the correct constructor for those arguments are called.
- 071 In the TokenTester project, multiple constructor definitions enabled the StringTokenizer class to accomplish different things with different uses of the new operator.
- When you create your own classes, you can define as many constructors as you need to implement the behavior of the class.
- 071 No two constructors in a class can have the same number and type of arguments, because this is the only way constructors are differentiated from each other.
- 071 If a class defines no constructors, a constructor with no arguments is called by default when an object is created.
- The only thing this constructor does is call the same constructor in its superclass.
- 071 - CAUTION: The default constructor only exists in a class that has not defined any constructors.
- Once you define at least one constructor in a class, you can't count on there being a default constructor with no arguments.
A Note on Memory Management
- Top
- 071 If you are familiar with other object-oriented programming languages, you might wonder whether the new operator has an opposite that destroys an object when it is no longer needed.
- 071 Memory management in Java is dynamic and automatic.
- When you create a new object, Java automatically allocates the proper amount of memory for that object.
- You don't have to allocate any memory for that object.
- You don't have to allocate any memory for objects explicitly.
- The Java Virtual Machine (JVM) does that for you.
- 071 Because Java memory management is automatic, you don't need to deallocate the memory an object uses when you're finished using it.
- Under most circumstances, when you are finished with an object you have created, Java can determine that the object no longer has any live references to it.
- (In other words, the object isn't assigned to any variables still in use or stored in any arrays.)
- 072 As a program runs, the JVM periodically looks for unused objects and reclaims the memory that those objects are using.
- This process is called dynamic garbage collection and occurs without any programming on your part.
- You don't have to explicitly free the memory taken up by an object,
- you just have to make sure that you're not still holding onto an object you want to get rid of.
- This feature is one of the most touted advantages of the language over its predeccessor C++.
Using Class and Instance Variables
- Top
- 072 At this point, you can create your own object with class and instance variables, but how do you work with those variables?
- They're used in largely the same manner as the local variables you learned about in our last chapter.
- You can put them in expressions, assign values to them in statements, and so on.
- You just refer to them slightly differently.
Getting Values
- Top
- 072 To get to the value of an instance variable, you use dot notation, a form of addressing in which an instance or class variable name has two parts.
- A reference to an object or class on the left side of a dot operator .
- A variable on the right side of the dot operator .
- 072 Dot notation is how you refer to an object's instance variable and methods.
- For example, if you have an object named customer with a variable called orderTotal, here's how that variable could be referred to in a statement:
- float total = customer.orderTotal;
- This statement assigns the value of the customer object's orderTotal instance variable to a floating-point variable named total.
- Accessing variables in dot nottation isan expression (meaning that it returns a value).
- Both sides of the doot also are expressions.
- This means that you can chain instance variable access.
- 072 Extending the preceding example, suppose the customer object is an instance variable of the store class.
- Dot notation can be used twice, as in this statement:
- float total = store.customer.orderTotal;
- 073 Dot expressions are evaluated from left to right, so you start with store's instance variable customer, which itself has an instance variable orderTotal.
- The value of this variable is assigned to the total variable.
- 073 One thing to note when chaining objects together in this manner is that the statement will fail with an error if any object in the chain does not have a value yet.
Setting Values
- Top
- 073 Assigning a value to an instance variable with dot notation employs the = operator just like variables holding primitive types:
- customer.layaway = true;
- This example sets the value of a boolean instance variable named layaway to true.
- The PointSetter application in Listing 3.2 test and modifies the instance variables in a Point object.
- Point, a class in the java.awt package, represents points in a coordinate system with (x, y) values.
- 073 Create a new empty Java file in NetBeans with the class name PointSetter and the package name com.java21days
- then type the source code shown in Listing 3.2 and save the file.
Listing 3.2
- Top
- page 073
package com.java21days;
import java.awt.Point;
class PointSetter {
public static void main(String[] arguments) {
Point location = new Point(4, 13);
System.out.println("Starting location:");
System.out.println("X equals " + location.x);
System.out.println("Y equals " + location.y);
System.out.println("\nMoving to (7, 6)");
location.x = 7;
location.y = 6;
System.out.println("\nEnding location: ");
System.out.println("X equals " + location.x);
System.out.println("Y equals " + location.y);
}
}
Listing 3.2 (screenshot from NetBeans) goes here
- Top
- 074 When you run this application, the output should match Figure 3.2
- reserve
Figure 3.2 (screenshot from NetBeans Output pane) goes here
- Top
- 074 In this application, you create an instance of Point where x equals 4 and y equals 13 (line 8).
- These individual values are retrieved using dot notation.
- 074 The value of x is changed to 7 and y to 6 (lines 15-16).
- The values are displayed again to show how they have changed.
Class Variables
- Top | Back to Chap 5: Class Variables
- 074 Class variables, as you have learned, are variables defined and stored in the class itself.
- Their values apply to the class and all its instances.
- 074 With instance variables, each new instance of the class gets a new copy of the instance variables that the class defines.
- Each instance then can change the values of those instance variables without affecting any other instances.
- With class variables, only one copy of that variable exists when the class is loaded.
- Changing the value of that variable changes it for all instances of that class.
- 074 You define class variables by including the static keyword before the variable itself.
- For example, consider the following partial class definition:
- class FamilyMember {
static String surname = "Mendoza";
String name;
int age;
{
- 074 Each instance of the class FamilyMember has its own values for name and age, but the class variable surname has only one value for all family members: "Mendoza".
- If the value of surnameis changed, all instances of FamilyMember are affected.
- 075 NOTE: calling these static variables refers to one of the meanings of the word "static", fixed in one place. If a class has a static variable, every object of that class has the same value for that variable.
- Top
- 075 To access class variables, you use the same dot notation as with instance variables.
- To retrieve or change the value of the class variable, you can use either the instance or the name of the class on the left side of the dot . operator.
- Both lines of output in this example display the same value:
- FamilyMember dad = new FamilyMember();
- System.out.println("Family's surname is: " + dad.surname);
- System.out.println("Family's surname is: " + FamilyMember.surname);
- 075 Because you can use an object to change the value of a class variable, it's easy to become confused about class variables and where their values are coming from.
- Remember that the value of a class variable affects all objects of that particular class.
- If the surname instance variable of one FamilyMember object was set to "Paciorek", all objects of that class would have that new surname.
- 075 To reduce confusion when using class variables, it's a good idea to use the name of the class when you refer to a class variable - not an object of that class.
- This makes the use of a class variable more clear and helps strange results become easier to debug.
Calling Methods
- Top
- 075 Methods of an object are called to make it do something.
- Calling a method in an object also makes use of dot notation.
- The object whose method is being called is on the left side of the dot, and the name of the method and its arguments are on the right side:
- customer.addToCart (itemNumber, price, quantity);
- All method calls must have parentheses after them, even when the method takes no arguments,
- as in this example: customer.cancelOrder();
- 075 In Listing 3.3 the StringChecker application shows an example of calling some methods defined in the String class.
- Strings include methods for string tests and modification.
- 075 Create this program in NetBeans
- as an empty Java file
- with the class name StringerChecker
- and package name com.java21days
Listing 3.3
- Top
- page 076
package com.java21days;
class StringerChecker {
public static void main(String[] arguments) {
String str = "A Lannister always pays his debts";
System.out.println("The string is: " + str);
System.out.println("Length of this string: "
+ str.length() );
System.out.println("The character at position 6: "
+ str.charAt(6) );
System.out.println("The substring from 12 to 18: "
+ str.substring(12, 18) );
System.out.println("The index of the first 't': "
+ str.indexOf('t') );
System.out.println("The index of the begining of the "
+ "substring \"debts\": " + str.indexOf("debts") );
System.out.println("The string in uppercase: "
+ str.toUpperCase() );
}
}
- 076 Running the program produces the output shown in Figure 3.3
- reserve
Figure 3.3 Goes Here
- Top
- 076 In line 6, you create a new instance of String by using the string literal "A Lannister always pay his debts".
- The remainder of the program simply calls different string methods to do different operations on that string:
- Line 7 prints the value of the string
- Line 9 calls the length() method in the new String object to find out how many characters it contains
- 077
- continue
- Line 11 calls the charAt() method, which returns the character at the given position in the string.
- Note that string positions start at position 0 rather than 1
- so the character at position 6 is 'i'.
- Line 13 calls the substring() method, which takes two integers indicating a range and returns the substring with those starting and ending points.
- The substring() method also can be called with only one argument, which returns the substring from that position to the end of the string.
- Line 15 calls the indexOf() method, which returns the position of the first instance of the given character.
- Character literals are surrounded by single quotation marks
- so the argument is 't' (not "t").
- Line 17 shows a different use of the indexOf() method, which takes a string argument and returns the index of the beginning of that string.
- String literals always are surrounded by double quotation marks.
- Line 19 uses the toUpperCase() method to return a copy of the string in all uppercase.
- 077 NOTE: If you compare the output of the StringChecker application to the characters in the string,
- you might be wondering how 't' could be at position 6 when it is the seventh character in the string.
- All of the methods look like they're off by one (except for length()).
- The reason is that the methods are zero-based, which means they begin counting with 0 instead of 1.
- So 'A' is at position 0, a space at position 1, 'L' at position 2 and so on.
- This kind of numbering is something you encounter often in Java.
Formatting Strings
- Top
- 077 Numbers such as money often need to be displayed in a precise manner.
- There are only two places after the decimal for the number of cents,
- a dollar sign ($) preceding the value,
- and commas separating groupsof three numbers - as in $22,453.70 (the amount the U.S. National Debt goes up in one second).
- reserve
- 077 This kind of formatting when displaying strings can be accomplished with the System.out.format() method.
- 078 This method takes two arguments: the output format template and the string to display.
- Here's an example:
- int accountBalance = 5005;
- System.out.format("Balance: $%,d%n", accountBalance);
- This code produces the output Balance: $5,005
- The formatting string begins with a percent % sign followed by one or more flags
- The %,d code displays a decimal with commas dividing each group of three digits.
- The %n code displays a newline character
- 078 The next example displays the value of pi to 11 decimal places:
- double pi = Math.PI;
- System.out.format("%,11f%n", pi);
- the output is 3.14159265359
- 078 TIP Oracle's Java site includes a beginner's tutorial for print f-style output that describes some of the most useful formatting codes:
Nested Method Calls
- Top
- 078 A Method can return
- a reference to an object,
- a primitive data type,
- or no value at all
- 078 In the StringChecker application, all the methods called on String object str returned values that are displayed.
- The charAt() method returned a character at a specified position in the string.
- 078 The value returned by a method also can be stored in a variable:
- String label = "From";
- String upper = label.toUpperCase();
- 078 In this example, the String object upper contains the value returned by calling label.toUpperCase(), which which is the text "FROM".
- 078 If the method returns an object, you can call the methods of that object in the same statement.
- This makes it possible for you to nest methods as you would variables.
- Top
- 079 Earlier today, you saw an example of a method called with no arguments
- customer.cancelOrder();
- If the cancelOrder() method returns an object, you can call methods of that object in the same statement.
- customer.cancelOrder().fileComplaint();
- This statement calls the fileComplaint()method, which is defined in the object returned by the cancelOrder()method of the customer object.
- 079 You can combine nested method calls and instance variable reference as well.
- In the next example, the putOnLayaway() method is defined in the object stored by the orderTotal instance variable, which itself is part of the customer object
- customer.orderTotal.putOnLayaway(itemNumber, price, quantity);
- This manner of nesting variables and methods is demonstrated in a method you've used frequently in the first three days of this book:
- System.out.println()
- That method displays strings and other data to the computer's standard output device.
- Top
- 079 The System class, part of the java.lang package, describes behavior specific to the computer system on which Java is running.
- System.out is a class variable that contains an instance of the class PrintStream representing the system's standard output,
- which normily is the monitor but can be a printer or file.
- PrintStream objects have a println() method that sends a string to that output stream.
- The PrintStream class is in the java.io package.
Class Methods
- Top | Back to Chap 5: Creating Methods
- 079 Class Methods, also called static methods, apply to the class as a whole and not to its instances just like class variables.
- Class methods commonly are used for general utility methods that might not operate directly on an object of that class
- but do fit with that class conceptually.
- For example, the String class contains a class method called valueOf(), which can take one of many types of arguments (integers, Boolean, objects, and so on).
- The valueOf() method then returns a new instance of String containing the argument's string value.
- This method doesn't operate directly on an existing instance of String, but getting a string from another object or data type is behavior that makes sense to define in the String class.
- 079 Class methods also can be useful for gathering methods in one place.
- For example, the Math class, defined in the java.lang package, contains a large set of mathematical operations as class methods.
- No objects can be created from the Math class, but you still can use its methods with numeric or Boolean arguments.
- Top
- 080 For example, the class method Math.max() takes two arguments and returns the larger of the two.
- You don't need to create a new instance of Math; it can be called anywhere you need it, as in the following:
- int firstPrice = 225;
- int secondPrice = 217;
- int higherPrice = Math.max(firstPrice, secondPrice);
- 080 Dot notation is used to call a class method
- As with class variables, you can use either an instance of the class or the class itself on the left side of the dot.
- For the same reasons noted earlier abot class variables, using the name of the class makes your code easier to read
- 080 The last two lines in this example both produce strings equal to "550":
- String s, s2;
- s = "potrzebie";
- s2 = s.valueOf(550);
- s2 = String.valueOf(550);
References to Objects
- Top
- 080 As you work with objects, it's important to understand references
- a reference is an address that indicates where an object's variables and method are stored.
- 080 You aren't actually using objects when you assign an object to a variable or pass an object to a mthod as an argument.
- You aren't even using copies of the objects.
- Instead, you're using references to thos objects
- 080 To better illustrate what this means, the RefTester application in Listing 3.4 shows how references work.
- Create an empty Java file in NetBeans for the class RefTester in the package com.java21days, and enter Listing 3.4 as the application's source code.
Listing 3.4
- Top
- page 080-081
package com.java21days;
import java.awt.Point;
class RefTester {
public static void main(String[] arguments) {
Point pt1, pt2;
pt1 = new Point(100, 100);
pt2 = pt1;
pt1.x = 200;
pt1.y = 200;
System.out.println("Point1: " + pt1.x + ", " + pt1.y);
System.out.println("Point2: " + pt2.x + ", " + pt2.y);
}
}
Listing 3.4 (screenshot from NetBeans) goes here
- Top
- 081 Save and run the application. The output is shown in Figure 3.4
Figure 3.4 displays the Ouput pane
- Top
- 081 The following takes place in the first part of this program:
- Line 7 - Two Point variables are created
- Line 8 - A new Point object is assigned to pt1
- Line 9 - The variable pt1 is assigned to pt2
- 081 Lines 11 - 14 are the tricky part
- The x and y variables of pt1 both are set to 200 and all variables of pt1 and pt2 are displayed on screen.
- 081 You might expect pt1 and pt2 to have different values, but Figure 3.4 shows this not to be the case.
- The x and y variables of pt2 also have changed even though nothing in the program explicitly changes them.
- This happens because line 7 creates a reference from pt2 to pt1 instead of creating pt2 as a new object copied from pt1
- 081 The variable pt2 is a reference to the same object as pt1, as shown in Figure 3.5
- Either variable can be used to refer to the object or to change its variables
Figure 3.5 goes here
- Top
- 082 If you wanted pt1 and pt2 to refer to separate objects, you could use separate new Point() statements on lines 6 - 7 to create separate objects, as shown here:
- pt1 = new Point(100, 100);
- pt2 = new Point(100, 100);
- 082 References in Java become particularly important when arguments are passed to methods. You learn more about this later today
- 082 NOTE: Java has no explicit pointers or pointer arithmetic, unlike C and C++.
- By using references and Java arrays, you can duplicate most pointer capabilities without many drawbacks.
Casting Objects and Primitive Types
- Top
- 082 One thing you discover quickly about Java is how finicky it is about the information it will handle.
- Java methods and constructors require things to take a specific form and won't accept alternatives
- 082 When you send arguments to methods or use variables in expressions, you must use variables of the correct data types.
- If a method requires an int, the Java compiler responds with an error if you try to send a float value to the method.
- Likewise, if you set up one variable with the value of another, they must be of compatible types.
- The two variables must be the same type or the variable receiving the value must be big enough to hold the value.
- 082 NOTE: There is one area where Java's compiler is decidedly flexible: the String object.
- String handling in println() methods, assignment statements, and method arguments is simplified by the + concatenation operator.
- If any variable in a group of concatenated variables is a string, Java treats the whole thing as a Sting.
- This makes the following possible:
- float gpa = 2.25F;
- System.out.println("Honest, mom, my GPA is a " + (gpa + 1.5) );
- Using the concatenation operator, a single string can hold the text representation of multiple objects and primitive types in Java.
- Top
- 083 Sometimes you have a value in your Java class that isn't the right type for what you need.
- It might be the wrong class or the wrong data type, such as float when you need an int.
- 083 In these situations, you can use a process called casting to convert a value from one type to another.
- Although casting is reasonably simple, the process complicated by the fact that Java has both primitive types (such as int, float, and boolean) and object types (String, Point, and the like).
- This section discusses three forms of casts and conversions:
- Casting between primative types, such as int to float or float to double
- Casting from an object of a class to an object of another class, such as from Object to String
- Casting primitive types to objects and then extracting primitive values from those objects
- When discussing casting, it can be easier to think in terms of sources and destinations.
- The source is the variable being cast into another type.
- The destination is the result.
Casting Primitive Types
- Top
- 083 Casting between primitive types enables you to convert the value of one type to another.
- This most commonly occurs with the numeric types, but one primitive type never can be used in a cast.
- Boolean values must be either true or false and cannot be used in a casting operation.
- 083 In many casts between primitive types, the destination can hold larger values than the source, so the value is converted easily.
- An example would be casting a byte into an int.
- Because a byte holds values from -128 to 127 and an int holds from around -2,100,000 to 2,100,000, there's more than enough room to cast a byte into an int.
- 083 Often you can automatically use a byte or char as an int, an int as a long, an int as a float, or anything as a double.
- In most cases, because the larger type provides more precision than the smaller, no loss of information occurs as a result.
- The exception is casting integers to floating-point values.
- Casting a long to a float or a long to a double can cause some loss of precision.
- Top
- 084 NOTE: A character can be used as an int because each character has a corresponding numeric code that represents its position in the character set.
- If the variable key has the value 65, the cast (char) key produces the character value 'A'.
- The numeric code associated with a capital A is 65 in the ASCII character set, which Java adopted as part of its character support.
- 084 You must use an explicit cast to convert a value in a large type to a smaller type.
- Explicit cats take the following form:
- Here typename is the name of the primitive data type to which you're converting, such as short, int, or float
- value is an expression that results in the value of the source type.
- For example, in the following statement, the value of x is divided by the value of y and the result is cast into an int:
- Note that because the precedence of casting is higher than that of arithmetic, you have to use parentheses here.
- Otherwise, first the value of x would be cast into an int, and then it would be divided by y, which could produce a different result.
Casting Objects
- Top
- 084 Objects of classes also can be cast into objects of other classes when the source and the destination classes are related by inheritance and one class is a subclass of the other.
- Some objects might not need to be cast explicitly.
- In particular, because a subclass contains all the information as its superclass, you can use an object of a subclass anywhere a superclass is expected.
- For example, consider a method that takes two arguments, one of type Object and another of type Component in the java.awt package (which has classes for a graphical user interface).
- You can pass an instance of any class for the Object argument because all Java classes are subclasses of Object.
- For the Component argument, you can pass in its subclasses, such as Button, Container, and Label (all in java.awt).
- This is true antwhere in a program, not just inside method calls. If you had a variable defined as class Component, you could assign objects of that class or any of its subclasses to that vatiable without casting.
- 085 This also is true in the reverse, so you can use a superclass when a subclass is expected.
- There is a catch, however: Because subclasses contain more behavior than their superclasses, a loss of precision occurs in the casting.
- Those superclass objects might not have all the behavior needed to act in place of a subclass object.
- 085 Consider this example: If you have an operation that calls methods in objects of the class Integer
- Using an object of its superclass Number won't include many methods specified in Integer.
- Errors occur if you try to call methods that the destination object doesn't have.
- 085 To use superclass objects where subclass objects are expected, you must cast them explicitly.
- You won't lose any information in the cast, but you gain all the methods and variables that the subclass defines.
- 085 To cast an object to another class,
- you use the same operation as for primitive types,
- which takes the form:
- In this template, classname is the name of the destination class, and object is a reference to the source object.
- Casting creates a reference to the old object of the type classname, the old object continues to exist as it did before.
- 085 The following example casts an instance of the class VicePresident to an instance of the class Employee.
- VicePresident is a subclass of Employees with more information:
- Employee emp = new Employee();
- VicePresident veep = new VicePresident();
- emp = veep; // no cast needed for upward use
- veep = (VicePresident) emp; // must cast explicitly
- 085 When you begin working with graphical user interfaces during Week 2, "The Java Class Library,"
- you will see that casting one object is necessary whenever you use Java2D graphics operations.
- You must cast a Graphics object to a Graphics2D object before you can draw onscreen.
- The following example uses a Graphics object called screen to create a new Graphics2D object called screen2D:
- Graphics2D screen2D = (Graphics2D) screen;
- Graphics2D is a subclass of Graphics and both belong to the java.awt package.
- You'll explore this subject fully during Day 13, "Creating Java2D Graphics."
- In addition to casting objects to classes, you can cast objects to interfaces, but only if an object's class or one of its superclasses actually implements the interface.
Converting Primitive Types to Objects and Vice Versa
- Top
- 086 One thing you can't do is cast from an object to a primitive data type, or vice versa.
- Primitive types and objects are different things in Java, and you can't automatically cast between the two.
- 086 As an alternative, the java.lang package includes classes that correspond to each primitive data type: Float, Boolean, Byte, and so on.
- Most of these classes have the same names as the data types, except that the class names begin with a capital letter
- (Short instead of short, Double instead of double, and the like).
- Also, two classes have names that differ from the corresponding data type: Character is used for char variables and Integer for int variables
- Using the classes that correspond to each primitive type, you can create an object that holds the same value.
- The following statement creates an instance of the Integer class with the integer value 7801
- Integer dataCount = new Integer(7801);
- After you have created an object in this manner, you can use it as you would any object (although you cannot change its value).
- When you want to use that value again as a primitive value, there are methods for that as well.
- For example, if you wanted to get an int value from a dataCount object, the following statement shows how:
- int newCount = dataCount.intValue(); // returns 7801
- A common translation you need in programs is converting a String to a numeric type, such as an integer.
- When you need an int as the result, this can be done by using the parseInt() class method of the Integer class.
- The String to convert is the only argument sent to the method, as in the following example:
- String pennsylvania = "65000";
- int penn = Integer.parseInt(pennsylvania);
- The following classes can be used to work with objects instead of primitive data types: Boolean, Byte, Character, Double, Float, Integer, Long, Short, and Void.
- These classes are commonly called object wrappers because they provide an object representation that contains a primitive value
- Top
- 086 CAUTION: If you try to use the preceding example in a program, your program won't compile.
- The parseInt() method is designed to fail with a NumberFormatException error if the argument to the method is not a valid numeric value.
- To deal with errors of this kind, you must use special error-handling statements, which are introduced during Day 7, "Exceptions and Threads."
- 087 Working with primitive types and objects that represent the same value is made easier through autoboxing and unboxing, an automatic conversion process.
- Autoboxing automatically converts a primitive type to an object.
- Unboxing converts in the other direction.
- 087 If you write a statement that uses an object where a primitive type is expected, or vice versa, the value is converted so that the statement executes successfully.
- Here's an example of autoboxing and unboxing:
- Float f1 = 12.5F;
- Float f2 = 27.2F;
- System.out.println("Lower number: " + Math.min(f1, f2) );
- The Math.min() method takes two float values as arguments, but the preceding example sends the method two Float objects as arguments instead.
- The compiler does not report an error over this discrepancy.
- Instead, the Float objects automatically are unboxed into float values before being sent to the min() method.
- Top
- 087 CAUTION: Unboxing an object works only if the object has a value.
- If no constructor has been called to set up the object,
- compilation fails with an error.
Comparing Object Values and Classes
- Top
- 087 In addition to casting, you often will perform three other common tasks that involve objects:
- Comparing objects
- Finding out the class of any given object
- Testing whether an object is an instance of a given class
Comparing Objects
- Top
- 087 Yesterday, you learned about operators for comparing values - equal, not equal, less than, and so on.
- Most of these operators work only on primitive types, not on objects.
- If you try to use other values as operands, the Java compiler produces errors.
- 088 The exception to this rule are the == operator for equality and the != operator for inequality.
- When applied to objects, these operators don't do what you might first expect.
- Instead of checking whether one object has the same value as the other, they determine whether both sides of the operator refer to the same object.
- 088 To compare objects of a class and have meaningful results, you must implement special methods in your class and call those methods.
- A good example of this is the String class.
- It is possible to have two different String objects that represent text.
- If you were to employ the == operator to compare these objects, however, they would be considered unequal.
- Although their contents match, they are not the same object.
- 088 To see whether two String objects have matching values, an equals() method of the class is used.
- The method tests each character in the string and returns true if the two strings have the same value.
- Top
- 088 The EqualsTester application shown in Listing 3.5 illustrates this.
- Create the application with NetBeans in the com.java21days package
- and save the file, either by choosing File, Save or clicking the Save All toolbar button.
Listing 3.5
- Top
- page 088
package com.java21days;
class EqualsTester {
public static void main(String[] arguments) {
String str1, str2;
str1 - "Boy, that escalated quickly.";
str2 = str1;
System.out.println("String1: " + str1);
System.out.println("String2: " + str2);
System.out.println("Same object? " + (str1 == str2) );
str2 = new String(str1);
System.out.println("String1: " + str1);
System.out.println("String2: " + str2);
System.out.println("Same object? " + (str1 == str2) );
System.out.println("Same value? " + (str1.equals(str2) );
}
}
Listing 3.5 (screenshot from NetBeans) goes here
- Top
- 089 The program's output appears in Figure 3.6
Figure 3.6 (screenshot from NetBeans Output pane) goes here
- Top
- 089 The first part of this program declares two variables (str1 and str2), assigns the literal "Boy, that escalated quickly." to str1, and then assigns that value to str2 (lines 5-7).
- As you learned earlier, str1 and str2 now point to the same object, and the equality test at line 11 proves that.
- 089 In the second part of this program, you create a new String object with the same value as str1 and assign str2 to that new String object.
- 089 Now that you have two different string objects in str1 and str2, both with the same value.
- Testing them to see whether they're the same object by using == operator returns the expected answer: false (line 17).
- They are not the same object in memory.
- Testing them using the equals() method in line 18 also returns the expected answer of true, which shows they have the same value.
- Top
- 089 NOTE: Why can't you just use another literal when you change str2, instead of using new ?
- String literals are optimized in Java.
- If you create a string using a literal and then use another literal with the same characters, Java gives you back the first String object.
- Both strings are the same object, you have to go out of your way to create two separate objects.
- reserve
Determining the Class of an Object
- Top
- 089 Want to find the name of an object's class ?
- Here's how for an object assigned to the variable key:
- String name = key.getClass().getName();
- 090 The getClass() method is defined in the Object class, so it can be called in all Java objects.
- The method returns a Class object that represents the object's class.
- That object's getName() method returns a string holding the name of the class.
- 090 Another useful test is the instanceof operator, which has two operands: a reference to an object on the left, and a class name on the right.
- The expression produces a Boolean value true if the object is an instance of the named class or any of that class's subclasses, or false otherwise, as in these examples:
- boolean check1 = "Texas" instanceof String; // true
Object
obiwan = new Object();
- boolean check2 = obiwan instanceof String; // false
- The instanceof operator also can be used for interfaces.
- If an object implements an interface, the instanceof operator returns true when this is tested.
- Unlike other operators in Java, instanceof is not a form of punctuation like * for multiplication or + for addition.
- Instead, the instanceof keyword is the operator.
Summary
- Top
- 090 Now that you have spent three days exploring how object-oriented programming is implemented in Java, you're in a better position to decide how useful it can be in your programming.
- Object-oriented programming is beneficial because of its benefits: improved reliability, reusability, and maintenance.
- 090 This chapter taught you how to deal with objects:
- creating them,
- reading their values,
- changing them
- calling their methods.
- 090 How to cast objects from one class to another,
- cast to and from primitive data types and classes,
- and take advantage of automatic conversions through autoboxing and unboxing.
- reserve
Q & A
- Top
- Q I'm confused about the difference between objects and the primitive data types, such as int and boolean.
- A The primitive types (byte, short, int, long, float, double, boolean, and char) are not objects,
- although in many ways they can be handled like objects. They can be assigned to variables and passed in and out of methods.
- Q The length() and charAt() methods in the StringChecker application Listing 3.3) don't appear to make sense.
- If length() says that a string is 33 characters long, shouldn't the characters be numbered from 1 to 33 when charAt() is used to display characters in the string ?
- A The two methods look at strings differently.
- The length() method counts the characters in the string,
- with the first character counting as 1, the second as 2, and so on.
- The charAt() method considers the first character in the string to be located at position 0.
- This is the same numbering system used with arry elements in Java.
- Consider the string "Charlie Brown".
- It has 13 characters ranging from position 0 (the letter "C") to position 12 (the letter "n").
- Q If Java lacks pointers, how can I do something like linked lists, where there's a pointer from one node to another so that they can be traversed ?
- A It's incorrect to say that Java has no pointers, it just has no explicit pointers.
- Object references are effectively pointers.
- To create something like a linked list, you could create a class called Node, which would have an instance variable also of type Node.
- To link node objects, assign a node object to the instance variable of the object immediately before it in the list.
- Because object references are pointers, linked lists set up this way behave as you would expect them to.
- (You'll work with Java class library's version of linked lists on Day 8, "Data Structures.")
- reserve
Quiz - Questions
- What operator do you use to call an object's constructor and create a new object ?
- +
- new
- instanceof
- What kind of methods apply to all objects of a class rather than an individual object ?
- Universal methods
- Instance methods
- Class methods
- If you have a program with objects named obj1 and obj2, what happens when you use the statement obj2 = obj1 ?
- The instance variables in obj2 are given the same values as obj1.
- obj2 and obj1 are considered to be the same object.
- Neither A nor B.
Answers
- Top | Note A is 1, B is 2, and C is 3
- B. The new operator is followed by a call to the object's constructor.
- C. Class methods can be called without creating an object of that class.
- B. The = operator does not copy values from one object to another. Instead, it makes both variables refer to the same object.
Certification Practice
- Top
- 092 The following question is the kind of thing you could expect to be asked on a Java programming certification test. Answer it without looking at today's material or using the Java compiler to test the code.
- The answer is available on the book's website at www.java21days.com
- Given:
public class AyeAye {
int i = 40;
int j;
public AyeAye() {
setValue (i++);
}
void setValue(int inputValue) {
int i = 20;
j = i + 1;
System.out.println("j = " + j);
}
}
- What is the value of the j variable at the time it is displayed inside the setValue() method ?
- 42
- 40
- 21
- 20
Exercise
- Top
- To extend your knowledge of the subjects covered today, try the following exercises:
- Create a program that turns a birthday in MM/DD/YYYY format (such as 04/29/2016) into three individual strings.
- Create a class with instance variables for height, weight, and depth, making each an integer.
- Create a Java application that uses your new class,
- sets each of these values in an object,
- and displays the values.
Reserve