In the textbook reading for this week, Chapter 2, the book introduces Java Applets. These are a slightly different form of a Java program that you can create. Applets are meant to be inserted into webpages and they can be used to great effect. To start with, my examples and the class assignments will be in the form of Java Applications. This is the more standard form and (maybe) is easier to start with. We'll make some Java Applets after the midterm when we try making some graphical programs.
Shooter
to define a type of object that can do what I want. Objects that are made from this class will be referred to as objects of the type Shooter
, or Shooter
objects. Shooter
objects can also be referred to as instances of the Shooter
class. Since I'll need to know how many shots the player has attempted and made, I'll give my class two variables: shotsAttempted
, and shotsMade
. We'll ignore variable types and how they're created and initialized for now. In addition to those 2 numbers just mentioned, I'll need to somehow have my object update its stats whenever the player makes or misses a shot. To do this I'll have two methods: madeShot()
and missedShot()
. Finally, I'll have a method called getShotPercentage()
to tell me the player's current shooting percentage. With these things included, my outline for the class looks like this:
class name: Shooter variables: int shotsAttempted - records how many shots attempted int shotsMade - records how many shots made methods: Shooter() - constructor method madeShot() - add another made shot missedShot() - add another missed shot getShotPercentage() - return the current shooting percentage as a 'double' valueThe method that I have not mentioned yet is the special constructor method
Shooter()
. The name of the constructor method is always the same as its class's name. A constructor of a class is a method that is used to create an instance of that class. So, the Shooter()
constructor creates an instance of the Shooter
class (which would be a Shooter
object). Using this class as a "blueprint" I can create as many Shooter
objects as I like. To create two variables holding references to Shooter
objects called player1
and player2
, I would use these lines:
Shooter player1 = new Shooter();
Shooter player2 = new Shooter();
new
operator works by calling the constructor method for the class. New objects are always created using this reserved word new
so you should plan on using it often. Note that the objects referenced by player1
and player2
are two different objects, even though the same "blueprint" class was used to create them. Also, remember the differences between references and objects here. For example, the value held by player1
is a reference to a Shooter
object. The player1
variable does not hold an actual Shooter
object. Because of this, the code "new Shooter()
" does not actually give a Shooter
object. It creates a new Shooter
object but instead gives a reference to that object which is then placed into the variable to the left of the '=' operator.
player1
's madeShot()
method, I would use the line of code:
player1.madeShot();
+,-,*,/,%
. This dot operator takes the name of the variable we want on its left side. On the right side of the dot operator we place the name of that variable's method that we want to use. Note that there are also left and right parantheses after the method name. Between these parantheses you place whatever data (variables, literals, etc.) the method requires be passed to it. Pieces of data that are passed to a method are called parameters. This method doesn't require any parameters, but we'll see a couple that do later in this lecture.
player1
variable and we're wanting to use the madeShot
method from that variable. One way to think of this is that the madeShot
method is "acting on" the player1
object. Another way to think about this is that the method madeShot
is a service provided by the player1
object. In either case, we are invoking the madeShot
method on the player1
object. The dot operator can also be used to access variables or fields within an object. We do this by placing the field's name to the right of the dot operator (instead of a method name).
Shooter
objects even though we didn't have the specific code defining the Shooter
class. The outline that I gave was an abstraction - something to hide unnecessary details to reduce complexity. In this case, the details of how to really write classes and how they work is more than we needed to cover right now. Instead, we can trust that the methods will do what they promise and not worry about how they actually accomplish their tasks.
player1
and player2
objects had the same class "blueprint", they are distinct objects - just like two basketball players they might represent. The players each the same features - eyes, ears, hands, feet, shoe contracts - but they are completely different people. They each have feet, but the size of one player's feet doesn't affect the size of another player's feet. Similarly, since we created two different Shooter
objects, the values held by each may be different. To illustrate this point, and note some of the effects of storing references rather than straight values, let's look at a class already written for us: DecimalFormat
.
DecimalFormat
class is one commonly available, simple class. Here we'll only take a small look at the abilities and methods of this class. We'll be looking at 3 methods from the class:
DecimalFormat (String pattern)
DecimalFormat
object that uses the specified pattern.
void applyPattern (String pattern)
String format (double number)
DecimalFormat
object.
DecimalFormat
object is to format decimal numeric values to a certain number of decimal places. Note that each of the methods now specifies a parameter that must be given when that method is called. The DecimalFormat
and applyPattern
methods require a single parameter: a reference to a String
object. The format
method requires a parameter of type double
. The format
method also states that it returns a reference to a String
object. Lastly, the use of the reserved word void by the applyPattern
method is to state that it does not return any values. This is the same reserved word as has been used by each main
method in every program you've written. We'll see much more about parameters when we start writing our own classes later in this course.
DecimalFormat
objects and a single double
constant to hold a decimal number to be formatted. This last one is a constant rather than a variable because of the reserved word final beginning the declaration for the variable VALUE
. This is a modifier indicating that once the value for this constant is set, it's value will not ever be changed again. The conventions for how the names of constants are commonly written state that all letters in the name should be capitalized and that multiple words should be separated by the underscore (_) character. Otherwise, you can basically treat constants as variables that you can never modify.
ReferenceTest.java
program starts out by intializing the double
constant and two of the DecimalFormat
objects.
DecimalFormat formatter1 = new DecimalFormat("0.##");
DecimalFormat formatter2 = new DecimalFormat("0.###");
final double VALUE = 0.1234567;
double
variable holds an actual value while the two DecimalFormat
variables only hold references to actual DecimalFormat
objects. The DecimalFormat
objects are denoted by the rounded-edge boxes and are labeled with "#1" or "#2" to denote them as seperate objects. Their current formatting patterns are also listed.
DecimalFormat
objects are formatting. Next, the third and final DecimalFormat
variable formatter3
is declared. Since it is not initialized, it is automatically initialized to the special value null. 'null'
can be thought of as a placeholder value so that the computer can deal with uninitialized variables (often by crashing your program). The next diagram reflects the null
value of formatter3
by placing a slash symbol in it's box. Since the variable VALUE
holds the same numeric value throughout the program, it is left out of the remaining diagrams.
DecimalFormat formatter3;
DecimalFormatter
object to formatter3
. This is done with the following line of code and results in the following diagram:
formatter3 = formatter2;
formatter3
variable now has a reference to a DecimalFormat
object, but it's the same object that formatter2
references. Logically, this is the conclusion that we should have come to since these variables hold references to objects and not the actual objects themselves. Using the bucket analogy, the assignment operator (=) takes the value out of the bucket on the right side and places it into the bucket on the left side. In this case, it takes the value held in formatter2
's memory space (a reference to DecimalFormat
object #2) and places that value into formatter3
's memory space. In this way formatter3
is set to reference the same object as formatter2
. The program next does another printout to verify this.
formatter3.applyPattern("0.######");
formatter2
and formatter3
referencing the same object, any changes directly to that object affect both variables. This changes when formatter2
is next assigned a new reference to a new object.
formatter2 = new DecimalFormat("0.#");
formatter3
variable because we didn't modify the object it was referencing. By using the new
operator formatter2
was given a completely new object to reference. This once again seperates it from the formatter3
variable. The program tests this after doing yet another printout to show the current state of things.
formatter3.applyPattern("0.####");
formatter3
object once again modified the object that it was referencing. Since it is the only variable now referencing that object, all other variables were unaffected.
null
.