text: Read..
  The. it'sget classlist[3].name. The average for student number i can be computed by calling classlist[i].getAverage(). You can do anything with classlist[i] that you could do with any other variable of type Student., every time a new PairOfDice is created,. And a constructor can have a list of formal parameters. In fact, the ability to include parameters is one of the main reasons for using constructors. The parameters can provide data to be used in the construction of the object. For example, a constructor for the PairOfDiceclass. In this version of PairOfDice,:
  The end result of this is that you have a reference to a newly constructed object.. // The name can't be null. if ( theName == null ) throw new IllegalArgumentException("name can't be null"); thename properly. In the new version of the class, there is no way to create a Student object except by calling the constructor, and that constructor automatically sets the name. Furthermore, the constructor makes it impossible to have a student object whose name is null. get.
  Note that it would be legal, and good style, to declare the variable name to be "final" in this class. An instance variable can be final provided it is either assigned a value in its declaration or is assigned a value in every constructor in the class. It is illegal to assign a value to a final instance variable, except inside a constructor.
  Let's take this example a little farther to illustrate one more aspect of classes: What happens when you mix static and non-static in the same class? In that case, it's legal for an instance method in the class to use static member variables or call static member subroutines. An object knows what class it belongs to, and it can refer to static members of that class. But there it only one copy of the static member, in the class itself. Effectively, all the objects share one copy of the static member.
  As an example, consider a version of the Student class to which I've added an ID for each student and a static member called nextUniqueID. Although there is an ID variable in each student object, there is only one nextUniqueID variable.
  public class Student { private String name; // Student's name. public double test1, test2, test3; // Grades on three tests. private int ID; // Unique ID number for this student.() { // Getter method for reading the value of the private // instance variable, name. return name; } public int getID() { // Getter method for reading the value of ID. return ID; } public double getAverage() { // Compute average test grade. return (test1 + test2 + test3) / 3; } } // end of class Student
  Since nextUniqueID is a static variable,.
  (Unfortunately, if you think about it a bit more, it turns out that the guarantee isn't quite absolute. The guarantee is valid in programs that use a single thread. But, as a preview of the difficulties of parallel programming, I'll note that in multi-threaded programs, where several things can be going on at the same time, things can get a bit strange. In a multi-threaded program, it is possible that two threads are creating Student objects at exactly the same time, and it becomes possible for both objects to get the same ID number. We'll come back to this in Subsection 12.1.3, where you will learn how to fix the problem.) in consecutive statements!):.
  THERE ARE SEVERAL WAYS in which object-oriented concepts can be applied to the process of designing and writing programs. The broadest of these is object-oriented analysis and design which applies an object-oriented methodology to the earliest stages of program development, during which the overall design of a program is created.. Let's take a moment to look at a few built-in classes that you might find useful.
  A string can be built up from smaller pieces using the + operator, but this is not alwaysBuilder makes it possible to be efficient about building up a long string from a number of smaller pieces. To do this, you must make an object belonging to the StringBuilder class. For example:
  StringBuilder builder = new StringBuilder();
  (This statement both declares the variable builder and initializes it to refer to a newly created StringBuilder object. Combining declaration with initialization was covered in Subsection 4.7.1 and works for objects just as it does for primitive types.)
  Like a String, a StringBuilder contains a sequence of characters. However, it is possible to add new characters onto the end of a StringBuilder without continually making copies of the data that it already contains. If x is a value of any type and builder is the variable defined above, then the command builder.append(x) will add x, converted into a string representation, onto the end of the data that was already in the builder. This can be done more efficiently than copying the data every time something is appended. A long string can be built up in a StringBuilder using a sequence of append() commands. When the string is complete, the function builder.toString() will return a copy of the string in the builder as an ordinary value of type String. The StringBuilder class is in the standard package java.lang, so you can use its simple name without importing it.
  A number of useful classes are collected in the package java.util. For example, this package contains classes for working with collections of objects. We will study such collection classes extensively in Chapter 10. Another class in this package, java.util.Date, is used to represent times. When a Date object is constructed without parameters, the result represents the current date and time, so an easy way to display this information is:
  System.out.println( new Date() );
  Of course, since it is in the package java.util, in order to use the Date class in your program,.
  Many of Java's standard classes are used in GUI programming. You will encounter a number of them in the Chapter 6. Here, I will mention only the class Color, from the package java.awt, so that I can use it in the next example. A Color object represents a color that can be used for drawing. In Section 3.9, you encountered color constants such as Color.RED. These constants are final, static member variables in the Color class, and their values are objects of type Color. It is also possible to create new color objects. Class Color has several constructors. One of them, which is called as new Color(r,g,b), takes three integer parameters to specify the red, green, and blue components of the color. The parameters must be in the range 0 to 255. Another constructor, new Color(r,g,b,t), adds a fourth integer parameter, which must also be in the range 0 to 255. The fourth parameter determines how transparent or opaque the color is. When you draw with a transparent color, the background shows through the color to some extent. A larger value of the parameter t gives a color that is less transparent and more opaque. (If you know hexadecimal color codes, there is a constructor for you. It takes one parameter of type int that encodes all the color components. For example, new Color(0x8B5413) creates a brown color.)
  A Color object has only a few instance methods that you are likely to use. Mainly, there are functions like getRed() to get the individual color components of the color. There are no "setter" methods to change the color components. In fact, a Color is an immutable object, meaning that all of its instance variables are final and cannot be changed after the object is created. Strings are another example of immutable objects, and we will make some of our own later in this section.
  The main point of all this,:
  /** * Return a String representation of a pair of dice, where die1 * and die2 are instance variables containing the numbers that are * showing on the two dice. */ public String toString() {.
  As an example, we will write an animation program, based on the same animation framework that was used in Subsection 3.9.3. The animation shows a number of semi-transparent disk that grow in size as the animation plays. The disks have random colors and locations. When a disk gets too big, or sometimes just at random, the disk disappears and is replaced with a new disk at a random location. Here is a screenshot from the program:
  A disk in this program can be represented as an object. A disk has properties -- color, location, and size -- that can be instance variables in the object. As for instance methods, we need to think about what we might want to do with a disk. An obvious candidate is that we need to be able to draw it, so we can include an instance method draw(g), where g is a graphics context that will be used to do the drawing. The class can also include one or more constructors. A constructor initializes the object. It's not always clear what data should be provided as parameters to the constructors. In this case, as an example, the constructor's parameters specify the location and size for the circle, but the constructor makes up a color using random values for the red, green, and blue components. Here's the complete class:
  import java.awt.Color; // import some standard GUI classes import java.awt.Graphics; /** * A simple class that holds the size, color, and location of a colored disk, * with a method for drawing the filled circle in a graphics context. The * circle is drawn as a filled oval, with a black outline. */ public class CircleInfo { public int radius; // The radius of the circle. public int x,y; // The location of the center of the circle. public Color color; // The color of the circle. /** * Create a CircleInfo with a given location and radius and with a * randomly selected, semi-transparent color. * @param centerX The x coordinate of the center. * @param centerY The y coordinate of the center. * @param rad The radius of the circle. */ public CircleInfo( int centerX, int centerY, int rad ) { x = centerX; y = centerY; radius = rad; int red = (int)(255*Math.random()); int green = (int)(255*Math.random()); int blue = (int)(255*Math.random()); color = new Color(red,green,blue, 100); } /** * Draw the disk in graphics context g, with a black outline. */ public void draw( Graphics g ) { g.setColor( color ); g.fillOval( x - radius, y - radius, 2*radius, 2*radius ); g.setColor( Color.BLACK ); g.drawOval( x - radius, y - radius, 2*radius, 2*radius ); } }
  It would probably be better style to write getters and setters for the instance variables, but to keep things simple, I made them public.
  The main program for my animation is a class GrowingCircleAnimation. The program uses 100 disks, each one represented by an object of type CircleInfo. To make that manageable, the program uses an array of objects. The array variable is a member variable in the class:
  private CircleInfo[] circleData; // holds the data for all 100 circles
  Note that it is not static. GUI programming generally uses objects rather than static variables and methods. Basically, this is because we can imagine having several GrowingCircleAnimations going on at the same time, each with its own array of disks. Each animation would be represented by an object, and each object will need to have its own circleData instance variable. If circleData were static, there would only be one array and all the animations would show exactly the same thing.
  The array must be created and filled with data. The array is created using new CircleInfo[100], and then 100 objects of type CircleInfo are created to fill the array. The new objects are created with random locations and sizes. In the program, this is done before drawing the first frame of the animation. Here is the code, where width and height are the size of the drawing area:
  circleData = new CircleInfo[100]; // create the array for (int i = 0; i < circleData.length; i++) { // create the objects circleData[i] = new CircleInfo( (int)(width*Math.random()), (int)(height*Math.random()), (int)(100*Math.random()) ); }
  In each frame, the radius of the disk is increased and the disk is drawn using the code
  circleData[i].radius++; circleData[i].draw(g);
  These statements look complicated, so let's unpack them. Now, circleData[i] is an element of the array circleData. That means that it is a variable of type CircleInfo. This variable refers to an object of type CircleInfo, which contains a public instance variable named radius. This means that circleData[i].radius is the full name for that variable. Since it is a variable of type int, we can use the ++ operator to increment its value. So the effect of circleData[i].radius++ is to increase the radius of the circle by one. The second line of code is similar, but in that statement, circleData[i].draw is an instance method in the CircleInfo object. The statement circleData[i].draw(g) calls that instance method with parameter g.
  The source code example GrowingCircleAnimation.java contains the full source code for the program, if you are interested. Since the program uses class CircleInfo, you will also need a copy of CircleInfo.java in order to compile and run the program.
  Every programmer builds up a stock of techniques and expertise expressed as snippets of code that can be reused in new programs using the tried-and-true method of cut-and-paste: The old code is physically copied into the new program and then edited to customize it as necessary. The problem is that the editing is error-prone and time-consuming, and the whole enterprise is dependent on the programmer's ability to pull out that particular piece of code from last year's project that looks like it might be made to fit. (On the level of a corporation that wants to save money by not reinventing the wheel for each new project, just keeping track of all the old wheels becomes a major task.)
  Well-designed classes are software components that can be reused without editing.. If a class needs to be customized, a subclass can be created, and additions or modifications can be made in the subclass without making any changes to the original class. This can be done even if the programmer doesn't have access to the source code of the class and doesn't know any details of its internal, hidden implementation..
  A large programming project goes through a number of stages, starting with specification of the problem to be solved, followed by analysis of the problem and design of a program to solve it. Then comes coding, in which the program's design is expressed in some actual programming language. This is followed by testing and debugging of the program. After that comes a long period of maintenance, which means fixing any new problems that are found in the program and modifying it to adapt it to changing requirements. Together, these stages form what is called the software life cycle. (In the real world, the ideal of consecutive stages is seldom if ever meet their specifications and that are easy to modify if necessary. There is a wide range of "methodologies" that can be applied to help in the systematic design of programs. (Most of these methodologies seem to involve drawing little boxes to represent program components, with labeled arrows to represent relationships among the boxes.)
  We have been discussing object orientation in programming languages, which is relevant to the coding stage of program development. But there are also object-oriented methodologies for analysis and design. The question in this stage of the software life cycle is, How can one discover or invent the overall structure of a program? As an example of a rather simple object-oriented approach to analysis and design, consider this advice: Write down a description of the problem. Underline all the nouns in that description. The nouns should be considered as candidates for becoming classes.
  In this section, we look at some specific examples of object-oriented design in a domain that is simple enough that we have a chance of coming up with something reasonably reusable. Consider card games that are played with a standard deck of playing cards (a so-called "poker" deck, since it is used in the game of poker).
  In a typical card game, each player gets a hand of cards. The deck is shuffled and cards are dealt one at a time from the deck and added to the players' hands. In some games, cards can be removed from a hand, and new cards can be added. The game is won or lost depending on the value (ace, 2, ..., king) and suit (spades, diamonds, clubs, hearts) of the cards that a player receives. If we look for nouns in this description, there are several candidates for objects: game, player, hand, card, deck, value, and suit. Of these, the value and the suit of a card are simple values, and they might just be represented as instance variables in aCard object. In a complete program, the other five nouns might be represented by classes. But let's work on the ones that are most obviously reusable: card, hand, and deck.
  If we look for verbs in the description of a card game, we see that we can shuffle a deck and deal a card from a deck. This gives use us two candidates for instance methods in a Deck class: shuffle() and dealCard(). Cards can be added to and removed from hands. This gives two candidates for instance methods in a Hand class: addCard() and removeCard(). Cards are relatively passive things, but we at least need to be able to determine their suits and values. We will discover more instance methods as we go along.
  First, we'll design the deck class in detail. When a deck of cards is first created, it contains 52 cards in some standard order. The Deck class will need a constructor to create a new deck. The constructor needs no parameters because any new deck is the same as any other. There will be an instance method called shuffle() that will rearrange the 52 cards into a random order. The dealCard() instance method will get the next card from the deck. This will be a function with a return type of Card, since the caller needs to know what card is being dealt. It has no parameters -- when you deal the next card from the deck, you don't provide any information to the deck; you just get the next card, whatever it is. What will happen if there are no more cards in the deck when its dealCard() method is called? It should probably be considered an error to try to deal a card from an empty deck, so the deck can throw an exception in that case. But this raises another question: How will the rest of the program know whether the deck is empty? Of course, the program could keep track of how many cards it has used. But the deck itself should know how many cards it has left, so the program should just be able to ask the deck object. We can make this possible by specifying another instance method, cardsLeft(), that returns the number of cards remaining in the deck. This leads to a full specification of all the subroutines in the Deck class:
  Constructor and instance methods in class Deck: /** * Constructor. Create an unshuffled deck of cards. */ public Deck() /** * Put all the used cards back into the deck, * and shuffle it into a random order. */ public void shuffle() /** * As cards are dealt from the deck, the number of * cards left decreases. This function returns the * number of cards that are still left in the deck. */ public int cardsLeft() /** * Deals one card from the deck and returns it. * @throws IllegalStateException if no more cards are left. */ public Card dealCard()
  This is everything you need to know in order to use the Deck class. Of course, it doesn't tell us how to write the class. This has been an exercise in design, not in coding. You can look at the source code, Deck.java, if you want. It should not be a surprise that the class includes an array of Cards as an instance variable, but there are a few things you might not understand at this point. Of course, you can use the class in your programs as a black box, without understanding the implementation.
  We can do a similar analysis for the Hand class. When a hand object is first created, it has no cards in it. An addCard() instance method will add a card to the hand. This method needs a parameter of type Card to specify which card is being added. For the removeCard() method, a parameter is needed to specify which card to remove. But should we specify the card itself ("Remove the ace of spades"), or should we specify the card by its position in the hand ("Remove the third card in the hand")? Actually, we don't have to decide, since we can allow for both options. We'll have two removeCard() instance methods, one with a parameter of type Card specifying the card to be removed and one with a parameter of type int specifying the position of the card in the hand. (Remember that you can have two methods in a class with the same name, provided they have different numbers or types of parameters.) Since a hand can contain a variable number of cards, it's convenient to be able to ask a hand object how many cards it contains. So, we need an instance method getCardCount() that returns the number of cards in the hand. When I play cards, I like to arrange the cards in my hand so that cards of the same value are next to each other. Since this is a generally useful thing to be able to do, we can provide instance methods for sorting the cards in the hand. Here is a full specification for a reusable Hand class:
  Constructor and instance methods in class Hand: /** * Constructor. Create a Hand object that is initially empty. */ public Hand() /** * Discard all cards from the hand, making the hand empty. */ public void clear() /** * Add the card c to the hand. c should be non-null. * @throws NullPointerException if c is null. */ public void addCard(Card c) /** * If the specified card is in the hand, it is removed. */ public void removeCard(Card c) /** * Remove the card in the specified position from the * hand. Cards are numbered counting from zero. * @throws IllegalArgumentException if the specified * position does not exist in the hand. */ public void removeCard(int position) /** * Return the number of cards in the hand. */ public int getCardCount() /** * Get the card from the hand in given position, where * positions are numbered starting from 0. * @throws IllegalArgumentException if the specified * position does not exist in the hand. */ public Card getCard(int position) /** * Sorts the cards in the hand so that cards of the same * suit are grouped together, and within a suit the cards * are sorted by value. */ public void sortBySuit() /** * Sorts the cards in the hand so that cards are sorted into * order of increasing value. Cards with the same value * are sorted by suit. Note that aces are considered * to have the lowest value. */ public void sortByValue()
  Again, there are a few things in the implementation of the class that you won't understand at this point, but that doesn't stop you from using the class in your projects. The source code can be found in the file Hand.java
  We will look at the design and implementation of a Card class in full detail. The class will have a constructor that specifies the value and suit of the card that is being created. There are four suits, which can be represented by the integers 0, 1, 2, and 3. It would be tough to remember which number represents which suit, so I've defined named constants in the Card class to represent the four possibilities. For example, Card.SPADES is a constant that represents the suit, "spades". (These constants are declared to be public final static ints. It might be better to use an enumerated type, but I will stick here to integer-valued constants.) The possible values of a card are the numbers 1, 2, ..., 13, with 1 standing for an ace, 11 for a jack, 12 for a queen, and 13 for a king. Again, I've defined some named constants to represent the values of aces and face cards. (When you read the Card class, you'll see that I've also added support for Jokers.)
  A Card object can be constructed knowing the value and the suit of the card. For example, we can call the constructor with statements such as:
  card1 = new Card( Card.ACE, Card.SPADES ); // Construct ace of spades. card2 = new Card( 10, Card.DIAMONDS ); // Construct 10 of diamonds. card3 = new Card( v, s ); // This is OK, as long as v and s // are integer expressions.
  A Card object needs instance variables to represent its value and suit. I've made these private so that they cannot be changed from outside the class, and I've provided getter methods getSuit() and getValue()so that it will be possible to discover the suit and value from outside the class. The instance variables are initialized in the constructor, and are never changed after that. In fact, I've declared the instance variables suit and value to be final, since they are never changed after they are initialized. An instance variable can be declared final provided it is either given an initial value in its declaration or is initialized in every constructor in the class. Since all its instance variables are final, a Card is an immutable object.
  Finally, I've added a few convenience methods to the class to make it easier to print out cards in a human-readable form. For example, I want to be able to print out the suit of a card as the word "Diamonds", rather than as the meaningless code number 2, which is used in the class to represent diamonds. Since this is something that I'll probably have to do in many programs, it makes sense to include support for it in the class. So, I've provided instance methods getSuitAsString() and getValueAsString() to return string representations of the suit and value of a card. Finally, I've defined the instance method toString() to return a string with both the value and suit, such as "Queen of Hearts". Recall that this method will be used automatically whenever a Card needs to be converted into a String, such as when the card is concatenated onto a string with the + operator. Thus, the statement
  System.out.println( "Your card is the " + card );
  is equivalent to
  System.out.println( "Your card is the " + card.toString() );
  If the card is the queen of hearts, either of these will print out "Your card is the Queen of Hearts".
  Here is the complete Card class. It is general enough to be highly reusable, so the work that went into designing, writing, and testing it pays off handsomely in the long run.
  /** * An object of type Card represents a playing card from a * standard Poker deck, including Jokers. The card has a suit, which * can be spades, hearts, diamonds, clubs, or joker. A spade, heart, * diamond, or club has one of the 13 values: ace, 2, 3, 4, 5, 6, 7, * 8, 9, 10, jack, queen, or king. Note that "ace" is considered to be * the smallest value. A joker can also have an associated value; * this value can be anything and can be used to keep track of several * different jokers. */ public class Card { public final static int SPADES = 0; // Codes for the 4 suits, plus Joker. public final static int HEARTS = 1; public final static int DIAMONDS = 2; public final static int CLUBS = 3; public final static int JOKER = 4; public final static int ACE = 1; // Codes for the non-numeric cards. public final static int JACK = 11; // Cards 2 through 10 have their public final static int QUEEN = 12; // numerical values for their codes. public final static int KING = 13; /** * This card's suit, one of the constants SPADES, HEARTS, DIAMONDS, * CLUBS, or JOKER. The suit cannot be changed after the card is * constructed. */ private final int suit; /** * The card's value. For a normal card, this is one of the values * 1 through 13, with 1 representing ACE. For a JOKER, the value * can be anything. The value cannot be changed after the card * is constructed. */ private final int value; /** * Creates a Joker, with 1 as the associated value. (Note that * "new Card()" is equivalent to "new Card(1,Card.JOKER)".) */ public Card() { suit = JOKER; value = 1; } /** * Creates a card with a specified suit and value. * @param theValue the value of the new card. For a regular card (non-joker), * the value must be in the range 1 through 13, with 1 representing an Ace. * You can use the constants Card.ACE, Card.JACK, Card.QUEEN, and Card.KING. * For a Joker, the value can be anything. * @param theSuit the suit of the new card. This must be one of the values * Card.SPADES, Card.HEARTS, Card.DIAMONDS, Card.CLUBS, or Card.JOKER. * @throws IllegalArgumentException if the parameter values are not in the * permissible ranges */ public Card(int theValue, int theSuit) { if (theSuit != SPADES && theSuit != HEARTS && theSuit != DIAMONDS && theSuit != CLUBS && theSuit != JOKER) throw new IllegalArgumentException("Illegal playing card suit"); if (theSuit != JOKER && (theValue < 1 || theValue > 13)) throw new IllegalArgumentException("Illegal playing card value"); value = theValue; suit = theSuit; } /** * Returns the suit of this card. * @returns the suit, which is one of the constants Card.SPADES, * Card.HEARTS, Card.DIAMONDS, Card.CLUBS, or Card.JOKER */ public int getSuit() { return suit; } /** * Returns the value of this card. * @return the value, which is one of the numbers 1 through 13, inclusive for * a regular card, and which can be any value for a Joker. */ public int getValue() { return value; } /** * Returns a String representation of the card's suit. * @return one of the strings "Spades", "Hearts", "Diamonds", "Clubs" * or "Joker". */ public String getSuitAsString() { switch ( suit ) { case SPADES: return "Spades"; case HEARTS: return "Hearts"; case DIAMONDS: return "Diamonds"; case CLUBS: return "Clubs"; default: return "Joker"; } } /** * Returns a String representation of the card's value. * @return for a regular card, one of the strings "Ace", "2", * "3", ..., "10", "Jack", "Queen", or "King". For a Joker, the * string is always numerical. */ public String getValueAsString() { if (suit == JOKER) return "" + value; else {"; default: return "King"; } } } /** * Returns a string representation of this card, including both * its suit and its value (except that for a Joker with value 1, * the return value is just "Joker"). Sample return values * are: "Queen of Hearts", "10 of Diamonds", "Ace of Spades", * "Joker", "Joker #2" */ public String toString() { if (suit == JOKER) { if (value == 1) return "Joker"; else return "Joker #" + value; } else return getValueAsString() + " of " + getSuitAsString(); } } // end class Card
  I will finish this section by presenting a complete program that uses the Card and Deck classes. The program lets the user play a very simple card game called HighLow. A deck of cards is shuffled, and one card is dealt from the deck and shown to the user. The user predicts whether the next card from the deck will be higher or lower than the current card. If the user predicts correctly, then the next card from the deck becomes the current card, and the user makes another prediction. This continues until the user makes an incorrect prediction. The number of correct predictions is the user's score.
  My program has a static method that plays one game of HighLow. This method has a return value that represents the user's score in the game. The main() routine lets the user play several games of HighLow. At the end, it reports the user's average score.
  I won't go through the development of the algorithms used in this program, but I encourage you to read it carefully and make sure that you understand how it works. Note in particular that the subroutine that plays one game of HighLow returns the user's score in the game as its return value. This gets the score back to the main program, where it is needed. Here is the program:
  /** * This program lets the user play HighLow, a simple card game * that is described in the output statements at the beginning of * the main() routine. After the user plays several games, * the user's average score is reported. */ public class HighLow { public static void main(String[] args) { System.out.println("This program lets you play the simple card game,"); System.out.println("HighLow. A card is dealt from a deck of cards."); System.out.println("You have to predict whether the next card will be"); System.out.println("higher or lower. Your score in the game is the"); System.out.println("number of correct predictions you make before"); System.out.println("you guess wrong."); System.out.println(); int gamesPlayed = 0; // Number of games user has played. int sumOfScores = 0; // The sum of all the scores from // all the games played. double averageScore; // Average score, computed by dividing // sumOfScores by gamesPlayed. boolean playAgain; // Record user's response when user is // asked whether he wants to play // another game. do { int scoreThisGame; // Score for one game. scoreThisGame = play(); // Play the game and get the score. sumOfScores += scoreThisGame; gamesPlayed++; System.out.print("Play again? "); playAgain = TextIO.getlnBoolean(); } while (playAgain); averageScore = ((double)sumOfScores) / gamesPlayed; System.out.println(); System.out.println("You played " + gamesPlayed + " games."); System.out.printf("Your average score was %1.3f.\n", averageScore); } // end main() /** * Lets the user play one game of HighLow, and returns the * user's score in that game. The score is the number of * correct guesses that the user makes. */ private static int play() { Deck deck = new Deck(); // Get a new deck of cards, and // store a reference to it in // the variable, deck. Card currentCard; // The current card, which the user sees. Card nextCard; // The next card in the deck. The user tries // to predict whether this is higher or lower // than the current card. int correctGuesses ; // The number of correct predictions the // user has made. At the end of the game, // this will be the user's score. char guess; // The user's guess. 'H' if the user predicts that // the next card will be higher, 'L' if the user // predicts that it will be lower. deck.shuffle(); // Shuffle the deck into a random order before // starting the game. correctGuesses = 0; currentCard = deck.dealCard(); System.out.println("The first card is the " + currentCard); while (true) { // Loop ends when user's prediction is wrong. /* Get the user's prediction, 'H' or 'L' (or 'h' or 'l'). */ System.out.print("Will the next card be higher (H) or lower (L)? "); do { guess = TextIO.getlnChar(); guess = Character.toUpperCase(guess); if (guess != 'H' && guess != 'L') System.out.print("Please respond with H or L: "); } while (guess != 'H' && guess != 'L'); /* Get the next card and show it to the user. */ nextCard = deck.dealCard(); System.out.println("The next card is " + nextCard); /* Check the user's prediction. */ if (nextCard.getValue() == currentCard.getValue()) { System.out.println("The value is the same as the previous card."); System.out.println("You lose on ties. Sorry!"); break; // End the game. } else if (nextCard.getValue() > currentCard.getValue()) { if (guess == 'H') { System.out.println("Your prediction was correct."); correctGuesses++; } else { System.out.println("Your prediction was incorrect."); break; // End the game. } } else { // nextCard is lower if (guess == 'L') { System.out.println("Your prediction was correct."); correctGuesses++; } else { System.out.println("Your prediction was incorrect."); break; // End the game. } } /* To set up for the next iteration of the loop, the nextCard becomes the currentCard, since the currentCard has to be the card that the user sees, and the nextCard will be set to the next card in the deck after the user makes his prediction. */ currentCard = nextCard; System.out.println(); System.out.println("The card is " + currentCard); } // end of while loop System.out.println(); System.out.println("The game is over."); System.out.println("You made " + correctGuesses + " correct predictions."); System.out.println(); return correctGuesses; } // end play() } // end class HighLow
  A CLASS REPRESENTS A SET OF OBJECTS which share the same structure and behaviors. The class determines the structure of objects by specifying variables that are contained in each instance of the class, and it determines behavior by providing the instance methods that express the behavior of the objects. This is a powerful idea. However, something like this can be done in most programming languages. The central new idea in object-oriented programming -- the idea that really distinguishes it from traditional programming -- is to allow classes to express the similarities among objects that share some, but not all, of their structure and behavior. Such similarities can be expressed using inheritance and polymorphism.
  The topics covered in later subsections of this section are relatively advanced aspects of object-oriented programming. Any programmer should know what is meant by subclass, inheritance, and polymorphism. However, it will probably be a while before you actually do anything with inheritance except for extending classes that already exist. In the first part of this section, we look at how that is
  public class subclass-name extends existing-class-name { . . // Changes and additions. . }
  As an example, suppose you want to write a program that plays the card game, Blackjack. You can use the Card, Hand, and Deck classes developed in Section 5 { /** * Computes and returns the value of this hand in the game * of Blackjack. */ public int getBlackjackValue() { int val; // The value computed for the hand. boolean ace; // This will be set to true if the // hand contains an ace. int cards; // Number of cards in the hand. val = 0; ace = false; cards = getCardCount(); // (method defined in class Hand.) namedgetBlackjackValue(). For example, if bjh is a variable of type BlackjackHand, then the following are all legal: bjh.getCardCount(), bjh.removeCard(0), and bjh.getBlackjackValue(). The first two methods are defined in Hand, but are inherited by BlackjackHand.
  Variables and methods from the Hand class are inherited by BlackjackHand, and they can be used in the definition of BlackjackHand just as if they were actually defined in that class -- except for any that are declared to be private, which prevents access even by subclasses. The statement "cards = getCardCount();" in the above definition of getBlackjackValue() calls the instance method getCardCount(), which was defined in Hand.
  Extending existing classes is an easy way to build on previous work. We'll see that many standard classes have been written specifically to be used as the basis for making subclasses.
  Access modifiers such as public and private are used to control access to members of a class. There is one more access modifier, protected, that comes into the picture when subclasses are taken into consideration. When protected is applied as an access modifier to a method or member variable in a class, that member can be used in subclasses -- direct or indirect -- of the class in which it is defined, but it cannot be used in non-subclasses. (There is an exception: A protected member can also be accessed by any class in the same package as the class that contains the protected member. Recall that using no access modifier makes a member accessible to classes in the same package, and nowhere else. Using the protected modifier is strictly more liberal than using no modifier at all: It allows access from classes in the same package and from subclasses that are not in the same package.)
  When you declare a method or member variable to be protected, you are saying that it is part of the implementation of the class, rather than part of the public interface of the class. However, you are allowing subclasses to use and modify that part of the implementation.
  For example, consider a PairOfDice class that has instance variables die1 and die2 to represent the numbers appearing on the two dice. We could make those variables private to make it impossible to change their values from outside the class, while still allowing read access through getter methods. However, if we think it possible that PairOfDice will be used to create subclasses, we might want to make it possible for subclasses to change the numbers on the dice. For example, a GraphicalDice subclass that draws the dice might want to change the numbers at other times besides when the dice are rolled. In that case, we could make die1 and die2 protected, which would allow the subclass to change their values without making them public to the rest of the world. (An even better idea would be to define protected setter methods for the variables. A setter method could, for example, ensure that the value that is being assigned to the variable is in the legal range 1 through 6.)
  The term inheritance refers to the fact that one class can inherit part or all of its structure and behavior from another class. The class that does the inheriting is said to be a subclass of the class from which it inherits. If class B is a subclass of class A, we also say that class A is a superclass of class B. (Sometimes the terms derived class and base class are used instead of subclass and superclass; this is the common terminology in C++.) A subclass can add to the structure and behavior that it inherits. It can also replace or modify inherited behavior (though not inherited structure). The relationship between subclass and superclass is sometimes shown by a diagram in which the subclass is shown below, and connected to, its superclass, as shown on the left below:
  In Java, to create a class named "B" as a subclass of a class named "A", you would write
  class B extends A { . . // additions to, and modifications of, . // stuff inherited from class A . }
  Several classes can be declared as subclasses of the same superclass. The subclasses, which might be referred to as "sibling classes," share some structures and behaviors -- namely, the ones they inherit from their common superclass. The superclass expresses these shared structures and behaviors. In the diagram shown on the right above, classes B, C, and D are sibling classes. Inheritance can also extend over several "generations" of classes. This is shown in the diagram, where class E is a subclass of class D which is itself a subclass of class A. In this case, class E is considered to be a subclass of class A, even though it is not a direct subclass. This whole set of classes forms a small class hierarchy.
  Let's look at an example. Suppose that a program has to deal with motor vehicles, including cars, trucks, and motorcycles. (This might be a program used by a Department of Motor Vehicles to keep track of registrations.) The program could use a class named Vehicle to represent all types of vehicles. Since cars, trucks, and motorcycles are types of vehicles, they would be represented by subclasses of the Vehicle class, as shown in this class hierarchy diagram:
  The Vehicle class would include instance variables such as registrationNumber and owner and instance methods such as transferOwnership(). These are variables and methods common to all vehicles. The three subclasses of Vehicle -- Car, Truck, and Motorcycle -- could then be used to hold variables and methods specific to particular types of vehicles. The Car class might add an instance variable numberOfDoors, the Truck class might have numberOfAxles, and the Motorcycle class could have a boolean variable hasSidecar. (Well, it could in theory at least, even if it might give a chuckle to the people at the Department of Motor Vehicles.) The declarations of these classes in a Java program would look, in outline, like this (although they are likely to be defined in separate files and declared as public classes):
  class Vehicle { int registrationNumber; Person owner; // (Assuming that a Person class has been defined!) void transferOwnership(Person newOwner) { . . . } . . . } class Car extends Vehicle { int numberOfDoors; . . . } class Truck extends Vehicle { int numberOfAxles; . . . } class Motorcycle extends Vehicle { boolean hasSidecar; . . . }
  Suppose that myCar is a variable of type Car that has been declared and initialized with the statement
  Car myCar = new Car();
  Given this declaration, a program could refer to myCar.numberOfDoors, since numberOfDoors is an instance variable in the class Car. But since class Car extends class Vehicle, a car also has all the structure and behavior of a vehicle. This means that myCar.registrationNumber, myCar.owner, and myCar.transferOwnership() also exist.
  Now, in the real world, cars, trucks, and motorcycles are in fact vehicles. The same is true in a program. That is, an object of type Car or Truck or Motorcycle is automatically an object of type Vehicle too. This brings us to the following Important Fact:
  A variable that can hold a reference
  to an object of class A can also hold a reference
  to an object belonging to any subclass of A.
  The practical effect of this in our example is that an object of type Car can be assigned to a variable of type Vehicle. That is, it would be legal to say
  Vehicle myVehicle = myCar;
  or even
  Vehicle myVehicle = new Car();
  After either of these statements, the variable myVehicle holds a reference to a Vehicle object that happens to be an instance of the subclass, Car. The object "remembers" that it is in fact a Car, and not just a Vehicle. Information about the actual class of an object is stored as part of that object. It is even possible to test whether a given object belongs to a given class, using the instanceof operator. The test:
  if (myVehicle instanceof Car) ...
  determines whether the object referred to by myVehicle is in fact a car.
  On the other hand, the assignment statement
  myCar = myVehicle;
  would be illegal because myVehicle could potentially refer to other types of vehicles that are not cars. This is similar to a problem we saw previously in Subsection 2.5.6: The computer will not allow you to assign an int value to a variable of type short, because not every int is a short. Similarly, it will not allow you to assign a value of type Vehicle to a variable of type Car because not every vehicle is a car. As in the case of ints and shorts, the solution here is to use type-casting. If, for some reason, you happen to know that myVehicle does in fact refer to a Car, you can use the type cast (Car)myVehicle to tell the computer to treat myVehicle as if it were actually of type Car. So, you could say
  myCar = (Car)myVehicle;
  and you could even refer to ((Car)myVehicle).numberOfDoors. (The parentheses are necessary because of precedence. The "." has higher precedence than the type-cast, so (Car)myVehicle.numberOfDoors would be read as (Car)(myVehicle.numberOfDoors), an attempt to type-cast the int myVehicle.numberOfDoors into a Vehicle, which is impossible.)
  As an example of how this could be used in a program, suppose that you want to print out relevant data about the Vehicle referred to by myVehicle. If it's a Car, you will want to print out the car's numberOfDoors, but you can't say myVehicle.numberOfDoors, since there is no numberOfDoors in the Vehicle class. But you could say:
  System.out.println("Vehicle Data:"); System.out.println("Registration number: " + myVehicle.registrationNumber); if (myVehicle instanceof Car) { System.out.println("Type of vehicle: Car"); Car c; c = (Car)myVehicle; // Type-cast to get access to numberOfDoors! System.out.println("Number of doors: " + c.numberOfDoors); } else if (myVehicle instanceof Truck) { System.out.println("Type of vehicle: Truck"); Truck t; t = (Truck)myVehicle; // Type-cast to get access to numberOfAxles! System.out.println("Number of axles: " + t.numberOfAxles); } else if (myVehicle instanceof Motorcycle) { System.out.println("Type of vehicle: Motorcycle"); Motorcycle m; m = (Motorcycle)myVehicle; // Type-cast to get access to hasSidecar! System.out.println("Has a sidecar: " + m.hasSidecar); }
  Note that for object types, when the computer executes a program, it checks whether type-casts are valid. So, for example, if myVehicle refers to an object of type Truck, then the type cast (Car)myVehicle would be an error. When this happens, an exception of type ClassCastException is thrown. This check is done at run time, not compile time, because the actual type of the object referred to by myVehicle is not known when the program is compiled.
  As another example, consider a program that deals with shapes drawn on the screen. Let's say that the shapes include rectangles, ovals, and roundrects of various colors. (A "roundrect" is just a rectangle with rounded corners.)
  Three classes, Rectangle, Oval, and RoundRect, could be used to represent the three types of shapes. These three classes would have a common superclass, Shape, to represent features that all three shapes have in common. The Shape class could include instance variables to represent the color, position, and size of a shape, and it could include instance methods for changing the values of those properties. Changing the color, for example, might involve changing the value of an instance variable, and then redrawing the shape in its new color:
  class Shape { Color color; // (must be imported from package java.awt) void setColor(Color newColor) { // Method to change the color of the shape. color = newColor; // change value of instance variable redraw(); // redraw shape, which will appear in new color } void redraw() { // method for drawing the shape ? ? ? // what commands should go here? } . . . // more instance variables and methods } // end of class Shape
  Now, you might see a problem here with the method redraw(). The problem is that each different type of shape is drawn differently. The method setColor() can be called for any type of shape. How does the computer know which shape to draw when it executes the redraw()? Informally, we can answer the question like this: The computer executes redraw() by asking the shape to redraw itself. Every shape object knows what it has to do to redraw itself.
  In practice, this means that each of the specific shape classes has its own redraw() method:
  class Rectangle extends Shape { void redraw() { . . . // commands for drawing a rectangle } . . . // possibly, more methods and variables } class Oval extends Shape { void redraw() { . . . // commands for drawing an oval } . . . // possibly, more methods and variables } class RoundRect extends Shape { void redraw() { . . . // commands for drawing a rounded rectangle } . . . // possibly, more methods and variables }
  Suppose that someShape is a variable of type Shape. Then it could refer to an object of any of the types Rectangle, Oval, or RoundRect. As a program executes, and the value of someShape changes, it could even refer to objects of different types at different times! Whenever the statement
  someShape.redraw();
  is executed, the redraw method that is actually called is the one appropriate for the type of object to which someShape actually refers. There may be no way of telling, from looking at the text of the program, what shape this statement will draw, since it depends on the value that someShape happens to have when the program is executed. Even more is true. Suppose the statement is in a loop and gets executed many times. If the value of someShape changes as the loop is executed, it is possible that the very same statement "someShape.redraw();" will call different methods and draw different shapes as it is executed over and over. We say that the redraw() method is polymorphic. A method is polymorphic if the action performed by the method depends on the actual type of the object to which the method is applied. Polymorphism is one of the major distinguishing features of object-oriented programming. This can be seen most vividly, perhaps, if we have an array of shapes. Suppose that shapelist is an a variable of type Shape[], and that the array has already been created and filled with data. Some of the elements in the array might be Rectangles, some might be Ovals, and some might be RoundRects. We can draw all the shapes in the array by saying
  for (int i = 0; i < shapelist.length; i++ ) { Shape shape = shapelist[i]; shape.redraw(); }
  As the computer goes through this loop, the statement shape.redraw() will sometimes draw a rectangle, sometimes an oval, and sometimes a roundrect, depending on the type of object to which array element number i refers.
  Perhaps this becomes more understandable if we change our terminology a bit: In object-oriented programming, calling a method is often referred to as sending a message to an object. The object responds to the message by executing the appropriate method. The statement "someShape.redraw();" is a message to the object referred to by someShape. Since that object knows what type of object it is, it knows how it should respond to the message. From this point of view, the computer always executes "someShape.redraw();" in the same way: by sending a message. The response to the message depends, naturally, on who receives it. From this point of view, objects are active entities that send and receive messages, and polymorphism is a natural, even necessary, part of this view. Polymorphism just means that different objects can respond to the same message in different ways.
  One of the most beautiful things about polymorphism is that it lets code that you write do things that you didn't even conceive of, at the time you wrote it. Suppose that I decide to add beveled rectangles to the types of shapes my program can deal with. A beveled rectangle has a triangle cut off each corner:
  To implement beveled rectangles, I can write a new subclass, BeveledRect, of class Shape and give it its own redraw() method. Automatically, code that I wrote previously -- such as the statementsomeShape.redraw() -- can now suddenly start drawing beveled rectangles, even though the beveled rectangle class didn't exist when I wrote the statement!
  In the statement "someShape.redraw();", the redraw message is sent to the object someShape. Look back at the method in the Shape class for changing the color of a shape:
  void setColor(Color newColor) { color = newColor; // change value of instance variable redraw(); // redraw shape, which will appear in new color }
  A redraw message is sent here, but which object is it sent to? Well, the setColor method is itself a message that was sent to some object. The answer is that the redraw message is sent to that same object, the one that received the setColor message. If that object is a rectangle, then it contains a redraw() method for drawing rectangles, and that is the one that is executed. If the object is an oval, then it is the redraw() method from the Oval class. This is what you should expect, but it means that the "redraw();" statement in the setColor() method does not necessarily call the redraw() method in the Shape class! The redraw() method that is executed could be in any subclass of Shape. This is just another case of polymorphism.
  Whenever a Rectangle, Oval, or RoundRect object has to draw itself, it is the redraw() method in the appropriate class that is executed. This leaves open the question, What does the redraw() method in the Shape class do? How should it be defined?
  The answer may be surprising: We should leave it blank! The fact is that the class Shape represents the abstract idea of a shape, and there is no way to draw such a thing. Only particular, concrete shapes like rectangles and ovals can be drawn. So, why should there even be a redraw() method in the Shape class? Well, it has to be there, or it would be illegal to call it in the setColor() method of the Shape class, and it would be illegal to write "someShape.redraw();". The compiler would complain that someShape is a variable of type Shape and there's no redraw() method in the Shape class.
  Nevertheless the version of redraw() in the Shape class itself will never actually be called. In fact, if you think about it, there can never be any reason to construct an actual object of type Shape! You can havevariables of type Shape, but the objects they refer to will always belong to one of the subclasses of Shape. We say that Shape is an abstract class. An abstract class is one that is not used to construct objects, but only as a basis for making subclasses. An abstract class exists only to express the common properties of all its subclasses. A class that is not abstract is said to be concrete. You can create objects belonging to a concrete class, but not to an abstract class. A variable whose type is given by an abstract class can only refer to objects that belong to concrete subclasses of the abstract class.
  Similarly, we say that the redraw() method in class Shape is an abstract method, since it is never meant to be called. In fact, there is nothing for it to do -- any actual redrawing is done by redraw() methods in the subclasses of Shape. The redraw() method in Shape has to be there. But it is there only to tell the computer that all Shapes understand the redraw message. As an abstract method, it exists merely to specify the common interface of all the actual, concrete versions of redraw() in the subclasses. There is no reason for the abstract redraw() in class Shape to contain any code at all.
  Shape and its redraw() method are semantically abstract. You can also tell the computer, syntactically, that they are abstract by adding the modifier "abstract" to their definitions. For an abstract method, the block of code that gives the implementation of an ordinary method is replaced by a semicolon. An implementation must then be provided for the abstract method in any concrete subclass of the abstract class. Here's what the Shape class would look like as an abstract class:
  public abstract class Shape { Color color; // color of shape. void setColor(Color newColor) { // method to change the color of the shape color = newColor; // change value of instance variable redraw(); // redraw shape, which will appear in new color } abstract void redraw(); // abstract method -- must be defined in // concrete subclasses . . . // more instance variables and methods } // end of class Shape
  Once you have declared the class to be abstract, it becomes illegal to try to create actual objects of type Shape, and the computer will report a syntax error if you try to do so.
  Note, by the way, that the Vehicle class discussed above would probably also be an abstract class. There is no way to own a vehicle as such -- the actual vehicle has to be a car or a truck or a motorcycle, or some other "concrete" type of vehicle.
  Recall from Subsection 5.3.2 that a class that is not explicitly declared to be a subclass of some other class is automatically made a subclass of the standard class Object. That is, a class declaration with no "extends" part such as
  public class myClass { . . .
  is exactly equivalent to
  public class myClass extends Object { . . .
  This means that class Object is at the top of a huge class hierarchy that includes every other class. (Semantically, Object is an abstract class, in fact the most abstract class of all. Curiously, however, it is not declared to be abstract syntactically, which means that you can create objects of type Object. However, there is not much that you can do with them.)
  Since every class is a subclass of Object, a variable of type Object can refer to any object whatsoever, of any type. Similarly, an array of type Object[] can hold objects of any type.
  The sample source code file ShapeDraw.java uses an abstract Shape class and an array of type Shape[] to hold a list of shapes. You might want to look at this file, even though you won't be able to understand all of it at this time. Even the definitions of the shape classes are somewhat different from those that I have described in this section. (For example, the draw() method has a parameter of type Graphics. This parameter is required because drawing in Java requires a graphics context.) I'll return to similar examples in later chapters when you know more about GUI programming. However, it would still be worthwhile to look at the definition of the Shape class and its subclasses in the source code. You might also check how an array is used to hold the list of shapes. Here is a screenshot from the program:
  If you run the ShapeDraw program, you can click one of the buttons along the bottom to add a shape to the picture. The new shape will appear in the upper left corner of the drawing area. The color of the shape is given by the "pop-up menu" in the lower right. Once a shape is on the screen, you can drag it around with the mouse. A shape will maintain the same front-to-back order with respect to other shapes on the screen, even while you are dragging it. However, you can move a shape out in front of all the other shapes if you hold down the shift key as you click on it.
  In the program, the only time when the actual class of a shape is used is when that shape is added to the screen. Once the shape has been created, it is manipulated entirely as an abstract shape. The routine that implements dragging, for example, works with variables of type Shape and makes no reference to any of its subclasses. As the shape is being dragged, the dragging routine just calls the shape's draw method each time the shape has to be drawn, so it doesn't have to know how to draw the shape or even what type of shape it is. The object is responsible for drawing itself. If I wanted to add a new type of shape to the program, I would define a new subclass of Shape, add another button, and program the button to add the correct type of shape to the screen. No other changes in the programming would be necessary.
  ALTHOUGH THE BASIC IDEAS of object-oriented programming are reasonably simple and clear, they are subtle, and they take time to get used to. And unfortunately, beyond the basic ideas there are a lot of details. The rest of this chapter covers more of those annoying details. Remember that you don't need to master everything in this chapter the first time through. In this section, we'll look at two variables, this and super, that are automatically defined in any instance method.
  What does it mean when you use a simple identifier such as amount or process() to refer to a variable or method? The answer depends on scope rules that tell where and how each declared variable and method can be accessed in a program. Inside the definition of a method, a simple variable name might refer to a local variable or parameter, if there is one "in scope," that is, one whose declaration is in effect at the point in the source code where the reference occurs. If not, it must refer to a member variable of the class in which the reference occurs. Similarly, a simple method name must refer to a method in the same class.
  A static member of a class has a simple name that can only be used inside the class definition; for use outside the class, it has a full name of the form class-name.simple-name. For example, "Math.PI" is a static member variable with simple name "PI" in the class "Math". It's always legal to use the full name of a static member, even within the class where it's defined. Sometimes it's even necessary, as when the simple name of a static member variable is hidden by a local variable or parameter of the same name.
  Instance variables and instance methods also have simple names. The simple name of such an instance member can be used in instance methods in the class where the instance member is defined (but not in static methods). Instance members also have full names -- but remember that an instance variable or instance method is actually contained in an object rather than in a class, and each object has its own version. A full name of an instance member starts with a reference to the object that contains the instance member. For example, if std is a variable that refers to an object of type Student, then std.test1 could be a full name for an instance variable named test1 that is contained in that object.
  But when we are working inside a class and use a simple name to refer to an instance variable like test1, where is the object that contains the variable? The solution to this riddle is simple: Suppose that a reference to "test1" occurs in the definition of some instance method. The actual method that gets executed is part of some particular object of type Student. When that method gets executed, the occurrence of the name "test1" refers to the test1 variable in that same object. (This is why simple names of instance members cannot be used in static methods -- when a static method is executed, it is not part of an object, and hence there are no instance members in sight!)
  This leaves open the question of full names for instance members inside the same class where they are defined. We need a way to refer to "the object that contains this method." Java defines a special variable named this for just this purpose. The variable this can be used in the source code of an instance method to refer to the object that contains the method. This intent of the name, "this," is to refer to "this object," the one right here that this very method is in. If var is an instance variable in the same object as the method, then "this.var".
  (Some object oriented languages use the name "self" instead of "this." Here, an object is seen as an entity that receives messages and responds by performing some action. From the point of view of that entity, an instance variable such as self.name refers to the entity's own name, something that is part of the entity itself. Calling an instance method such as self.redraw() is like saying "message to self: redraw!") that is also called "name." However, the instance variable can still be referred to by its full name, which is this.name. In the assignment statement "this.name = name",. You can store it in an array. In fact, you can do anything with this that you could do with any other variable, except change its value. (Consider it to be a final variable.).var always refers to an instance variable named var a subclass contains an instance method that has the same signature as a method in its superclass, the method from the superclass is hidden in the same way. We say that the method in the subclass overridest even know how it is implemented. It might look like an impossible problem, if the constructor in the superclass uses. (And if no such constructor exists in the superclass, the compiler will consider it to be a syntax error.)
  You can use the special variable this in exactly the same way to call another constructor in the same class. That is, the very first line of a constructor can look like a subroutine call with "this" as the name of the subroutine. The result is that the body of another constructor in the same class is executed. This can be very useful since it can save you from repeating the same code in several different constructors. As an example, consider MosaicPanel.java, which was used indirectly in Section 4.6. A MosaicPanel represents a grid of colored rectangles. It has a constructor with many parameters:
  public MosaicPanel(int rows, int columns, int preferredBlockWidth, int preferredBlockHeight, Color borderColor, int borderWidth)
  This constructor provides a lot of options and does a lot of initialization. I wanted to provide easier-to-use constructors with fewer options, but all the initialization still has to be done. The class also contains these constructors:
  public MosaicPanel() { this(42,42,16,16); } public MosaicPanel(int rows, int columns) { this(rows,columns,16,16); } public MosaicPanel(int rows, int columns, int preferredBlockWidth, int preferredBlockHeight) { this(rows, columns, preferredBlockWidth, preferredBlockHeight, null, 0); }
  Each of these constructors exists just to call another constructor, while providing constant values for some of the parameters. For example, this(42,42,16,16) calls the last constructor listed here, while that constructor in turn calls the main, six-parameter constructor. That main constructor is eventually called in all cases, so that all the essential initialization gets done in every case. concrete class that implements the Drawable interface must defineinterface.
  As with abstract classes, even though you can't construct an object from an interface, you can declare a variable whose type is given by the interface. For example, if Drawable is the interface given above, and ifLineDraw Drawable interface:
  Drawable[] listOfFigures; listOfFigures = new Drawable[10]; listOfFigures[0] = new Line(); listOfFigures[1] = new FilledCircle(); listOfFigures[2] = new Line(); . . .
  Every element of the array will then have a draw() method, so that we can say things like listOfFigures[i].draw(g).modifier can be omitted. Here is an example.:(); } }
  A concrete class that implements this interface must provide an implementation for readChar(). It will inherit a definition for readLine() from the interface, but can provide a new definition if necessary. Note that the default readLine() calls the abstract method readChar(), whose definition will only be provided in the implementing class. The reference to readChar() in the definition is polymorphic. The default implementation of readLine() is one that would make sense in almost any class that implements ); } } }
  Default methods provide Java with a capability similar to something called a "mixin" in other programming languages, namely the ability to mix functionality from another source into a class. Since a class can implement several interfaces, it is possible to mix in functionality from several different sources.. (In fact, a class can even be nested inside a subroutine, which must, of course, itself be inside a is used outside the containing class, its name must indicate its membership in the containing class. That is, the full name of the static nested class consists of the name of the class in which it is nested, followed by a period, followed by the name of the nestedWire
  The full name of the nested class is WireFrameModel.Line. That name can be used, for example, to declare variables., even if they are marked private. This can be another motivation for declaring a nested class, since it lets you give one class access to the private members of another class without making those members generally available to other classes. Note also that a nested class can itself be private, meaning that it can only be used inside the class in which it is nested. with the class in which its definition (although it does not literally contain a copy of the compiled code.
  In most cases, an inner class is used only within the class where it is defined. When that is true, using the inner class is really not much different from using any other class. You can create variables and declare objects using the simple name of the inner class in the usual way.
  From outside the containing class, however, an inner class has to be referred to using a name of the form variableName.NestedClassName, where variableName is a variable that refers to the object that contains the inner class. In order to create an object that belongs to an inner class, you must first have an object that belongs to the containing class. (When working inside the class, the object "this" is used implicitly.)
  Looking at an example will help, and will hopefully convince you that inner classes are really very natural. Consider a class that represents poker games. This class might include a nested class to represent the players of the game. The structure of the PokerGame class could be:
  public class PokerGame { // Represents a game of poker. an independent class or a static nested class, on the other hand, it would represent the general idea of a poker player, independent of a particular poker game.); } };
  Then redSquare refers to an object that implements Drawable and that draws a red square when its draw() method is called. By the way, the semicolon at the end of the statement is not part of the class definition; it's the semicolon that is required at the end of every declaration statement.
  Anonymous classes are often used for actual parameters. For example, consider the following simple method, which draws a Drawable in two different graphics contexts:
  void drawTwice( Graphics g1, Graphics g2, Drawable figure ) { figure.draw(g1); figure.draw(g2); }
  When calling this method, the third parameter can be created using an anonymous inner class. For example:
  drawTwice( firstG, secondG, new Drawable() { void draw(Graphics g) { g.drawOval(10,10,100,100); } } );.
  The syntax for anonymous classes is cumbersome. In many cases, an anonymous class implements an interface that defines just one method. Java 8 introduces a new syntax that can be used in place of the anonymous class in that circumstance: the lambda expression. Here is what the previous subroutine call looks like using a lambda expression:
  drawTwice( firstG, secondG, g -> g.drawOval(10,10,100,100) )
  The lambda expression is g -> g.drawOval(10,10,100,100). Its meaning is, "the method that has a parameter g and executes the code g.drawOval(10,10,100,100)." The computer knows that g is of type Graphics because it is expecting a Drawable as the actual parameter, and the only method in the Drawable interface has a parameter of type Graphics. Lambda expressions can only be used in places where this kind of type inference can be made. The general syntax of a lambda expression is
  formal-parameter-list -> method-body
  where the method body can be a single expression, a single subroutine call, or a block of statements enclosed between { and }. When the body is a single expression or function call, the value of the expression is automatically used as the return value of the method that is being defined. The parameter list in the lambda expression does not have to specify the types of the parameters, although it can. Parentheses around the parameter list are optional if there is exactly one parameter and no type is specified for the parameter; this is the form seen in the example above. For a method with no parameters, the parameter list is just an empty set of parentheses. Here are a few more examples of lambda expressions:
  () -> System.out.println("Hello World") g -> { g.setColor(Color.RED); g.drawRect(10,10,100,100); } (a, b) -> a + b (int n) -> { while (n > 0) { System.out.println(n); n = n/2; } } // lambda expressions ends here
  As you can see, the syntax can still get pretty complicated. There is quite a lot more to say about lambda expressions, but my intention here is only to briefly introduce one of the most interesting new features in Java 8.
  Source:
  This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License.