Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Big Object Oriented Programming with Java, Exercises of Java Programming

Getting Started with Java,Learning Language Fundamentals,Discovering Classes and Objects and Mastering Advanced Language Features.

Typology: Exercises

2021/2022

Uploaded on 02/11/2022

ekachakra
ekachakra 🇺🇸

4.6

(33)

269 documents

1 / 109

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
643
Appendix A
Solutions to Exercises
Each of Chapters 1 through 14 closes with an “Exercises” section that tests your understanding of
the chapter’s material. Solutions to these exercises are presented in this appendix.
Chapter 1: Getting Started with Java
1. Java is a language and a platform. The language is partly patterned after the
C and C++ languages to shorten the learning curve for C/C++ developers.
The platform consists of a virtual machine and associated execution
environment.
2. A virtual machine is a software-based processor that presents its own
instruction set.
3. The purpose of the Java compiler is to translate source code into instructions
(and associated data) that are executed by the virtual machine.
4. The answer is true: a classfile’s instructions are commonly referred to as
bytecode.
5. When the virtual machine’s interpreter learns that a sequence of bytecode
instructions is being executed repeatedly, it informs the virtual machine’s Just
In Time (JIT) compiler to compile these instructions into native code.
6. The Java platform promotes portability by providing an abstraction over
the underlying platform. As a result, the same bytecode runs unchanged on
Windows-based, Linux-based, Mac OS X–based, and other platforms.
7. The Java platform promotes security by providing a secure environment in
which code executes. It accomplishes this task in part by using a bytecode
verifier to make sure that the classfile’s bytecode is valid.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e
pf2f
pf30
pf31
pf32
pf33
pf34
pf35
pf36
pf37
pf38
pf39
pf3a
pf3b
pf3c
pf3d
pf3e
pf3f
pf40
pf41
pf42
pf43
pf44
pf45
pf46
pf47
pf48
pf49
pf4a
pf4b
pf4c
pf4d
pf4e
pf4f
pf50
pf51
pf52
pf53
pf54
pf55
pf56
pf57
pf58
pf59
pf5a
pf5b
pf5c
pf5d
pf5e
pf5f
pf60
pf61
pf62
pf63
pf64

Partial preview of the text

Download Big Object Oriented Programming with Java and more Exercises Java Programming in PDF only on Docsity!

643

Appendix A

Solutions to Exercises

Each of Chapters 1 through 14 closes with an “Exercises” section that tests your understanding of the chapter’s material. Solutions to these exercises are presented in this appendix.

Chapter 1: Getting Started with Java

  1. Java is a language and a platform. The language is partly patterned after the C and C++ languages to shorten the learning curve for C/C++ developers. The platform consists of a virtual machine and associated execution environment.
  2. A virtual machine is a software-based processor that presents its own instruction set.
  3. The purpose of the Java compiler is to translate source code into instructions (and associated data) that are executed by the virtual machine.
  4. The answer is true: a classfile’s instructions are commonly referred to as bytecode.
  5. When the virtual machine’s interpreter learns that a sequence of bytecode instructions is being executed repeatedly, it informs the virtual machine’s Just In Time (JIT) compiler to compile these instructions into native code.
  6. The Java platform promotes portability by providing an abstraction over the underlying platform. As a result, the same bytecode runs unchanged on Windows-based, Linux-based, Mac OS X–based, and other platforms.
  7. The Java platform promotes security by providing a secure environment in which code executes. It accomplishes this task in part by using a bytecode verifier to make sure that the classfile’s bytecode is valid.
  1. The answer is false: Java SE is the platform for developing applications and applets.
  2. The JRE implements the Java SE platform and makes it possible to run Java programs.
  3. The difference between the public and private JREs is that the public JRE exists apart from the JDK, whereas the private JRE is a component of the JDK that makes it possible to run Java programs independently of whether or not the public JRE is installed.
  4. The JDK provides development tools (including a compiler) for developing Java programs. It also provides a private JRE for running these programs.
  5. The JDK’s javac tool is used to compile Java source code.
  6. The JDK’s java tool is used to run Java applications.
  7. Standard I/O is a mechanism consisting of Standard Input, Standard Output, and Standard Error that makes it possible to read text from different sources (keyboard or file), write nonerror text to different destinations (screen or file), and write error text to different destinations (screen or file).
  8. You specify the main() method’s header as public static void main(String[] args).
  9. An IDE is a development framework consisting of a project manager for managing a project’s files, a text editor for entering and editing source code, a debugger for locating bugs, and other features. The IDE that Google supports for developing Android apps is Eclipse.

Chapter 2: Learning Language Fundamentals

  1. Unicode is a computing industry standard for consistently encoding, representing, and handling text that’s expressed in most of the world’s writing systems.
  2. A comment is a language feature for embedding documentation in source code.
  3. The three kinds of comments that Java supports are single-line, multiline, and Javadoc.
  4. An identifier is a language feature that consists of letters (A–Z, a–z, or equivalent uppercase/lowercase letters in other human alphabets), digits (0–9 or equivalent digits in other human alphabets), connecting punctuation characters (e.g., the underscore), and currency symbols (e.g., the dollar sign $). This name must begin with a letter, a currency symbol, or a connecting punctuation character; and its length cannot exceed the line in which it appears.
  1. The while statement evaluates its Boolean expression at the top of the loop, whereas the do-while statement evaluates its Boolean expression at the bottom of the loop. As a result, while executes zero or more times, whereas do-while executes one or more times.
  2. The difference between the break and continue statements is that break transfers execution to the first statement following a switch statement or a loop, whereas continue skips the remainder of the current loop iteration, reevaluates the loop’s Boolean expression, and performs another iteration (when true) or terminates the loop (when false).
  3. Listing A-1 presents an OutputGradeLetter application (the class is named OutputGradeLetter) whose main() method executes the grade letter code sequence presented while discussing the if-else statement.

Listing A-1. Classifying a Grade public class OutputGradeLetter { public static void main(String[] args) { char gradeLetter = 'u'; // unknown int testMark = 100;

if (testMark >= 90) { gradeLetter = 'A'; System.out.println("You aced the test."); } else if (testMark >= 80) { gradeLetter = 'B'; System.out.println("You did very well on this test."); } else if (testMark >= 70) { gradeLetter = 'C'; System.out.println("Not bad, but you need to study more for future tests."); } else if (testMark >= 60) { gradeLetter = 'D'; System.out.println("Your test result suggests that you need a tutor."); }

else { gradeLetter = 'F'; System.out.println("Your test result is pathetic; you need summer school."); } } }

  1. Listing A-2 presents a Triangle application whose main() method uses a pair of nested for statements along with System.out.print() to output a 10-row triangle of asterisks, where each row contains an odd number of asterisks (1, 3, 5, 7, and so on).

Listing A-2. Printing a Triangle of Asterisks public class Triangle { public static void main(String[] args) { for (int row = 1; row < 20; row += 2) { for (int col = 0; col < 19 - row / 2; col++) System.out.print(" "); for (int col = 0; col < row; col++) System.out.print("*"); System.out.print('\n'); } } }

Chapter 3: Discovering Classes and Objects

  1. A class is a template for manufacturing objects.
  2. You declare a class by providing a header followed by a body. The header minimally consists of reserved word class followed by an identifier. The body consists of a sequence of declarations placed between a pair of brace characters.
  3. An object is a named aggregate of code and data.
  4. You instantiate an object by using the new operator followed by a constructor.
  5. A constructor is a block of code for constructing an object by initializing it in some manner.
  6. The answer is true: Java creates a default noargument constructor when a class declares no constructors.
  1. You prevent a field from being shadowed by changing the name of a same-named local variable or parameter or by qualifying the local variable’s name or parameter’s name with this or the class name followed by the member access operator.
  2. A method is a named block of code declared within a class body.
  3. The difference between an instance method and a class method is that an instance method describes some behavior of the real-world entity that an object is modeling and can access a specific object’s state, and a class method identifies some behavior that is common to all objects and cannot access a specific object’s state.
  4. Recursion is the act of a method invoking itself.
  5. You overload a method by introducing a method with the same name as an existing method but with a different parameter list into the same class.
  6. A class initializer is a static-prefixed block that is introduced into a class body. An instance initializer is a block that is introduced into a class body as opposed to being introduced as the body of a method or a constructor.
  7. A garbage collector is code that runs in the background and occasionally checks for unreferenced objects.
  8. The answer is false: String[] letters = new String[2] { "A", "B" }; is incorrect syntax. Remove the 2 from between the square brackets to make it correct.
  9. A ragged array is a two-dimensional array in which each row can have a different number of columns.
  10. Calculating the greatest common divisor of two positive integers, which is the greatest positive integer that divides evenly into both positive integers, provides another example of tail recursion. Listing A-3 presents the source code.

Listing A-3. Recursively Calculating the Greatest Common Divisor public static int gcd(int a, int b) { // The greatest common divisor is the largest positive integer that // divides evenly into two positive integers a and b. For example, // GCD(12, 18) is 6.

if (b == 0) // Base problem return a; else return gcd(b, a % b); }

  1. Listing A-4 presents the source code to a Book class with name, author, and International Standard Book Number (ISBN) fields and a suitable constructor and getter methods that return field values. Furthermore, a main() method is present that creates an array of Book objects and iterates over this array outputting each book’s name, author, and ISBN.

Listing A-4. Building a Library of Books public class Book { private String name; private String author; private String isbn;

public Book(String name, String author, String isbn) { this.name = name; this.author = author; this.isbn = isbn; }

public String getName() { return name; }

public String getAuthor() { return author; }

public String getISBN() { return isbn; }

public static void main(String[] args) { Book[] books = new Book[] { new Book("Jane Eyre", "Charlotte Brontë", "0895772000"), new Book("A Kick in the Seat of the Pants", "Roger von Oech", "0060155280"), new Book("The Prince and the Pilgrim", "Mary Stewart", "0340649925") };

  1. You cannot make an overriding subclass method less accessible than the superclass method it is overriding because subtype polymorphism would not work properly if subclass methods could be made less accessible. Suppose you upcast a subclass instance to superclass type by assigning the instance’s reference to a variable of superclass type. Now suppose you specify a superclass method call on the variable. If this method is overridden by the subclass, the subclass version of the method is called. However, if access to the subclass’s overriding method’s access could be made private, calling this method would break encapsulation—private methods cannot be called directly from outside of their class.
  2. You tell the compiler that a method overrides another method by prefixing the overriding method’s header with the @Override annotation.
  3. Java doesn’t support multiple implementation inheritance because this form of inheritance can lead to ambiguities.
  4. The name of Java’s ultimate superclass is Object. This class is located in the java.lang package.
  5. The purpose of the clone() method is to duplicate an object without calling a constructor.
  6. Object’s clone() method throws CloneNotSupportedException when the class whose instance is to be shallowly cloned doesn’t implement the Cloneable interface.
  7. The difference between shallow copying and deep copying is that shallow copying copies each primitive or reference field’s value to its counterpart in the clone, whereas deep copying creates, for each reference field, a new object and assigns its reference to the field. This deep copying process continues recursively for these newly created objects.
  8. The == operator cannot be used to determine if two objects are logically equivalent because this operator only compares object references and not the contents of these objects.
  9. Object’s equals() method compares the current object’s this reference to the reference passed as an argument to this method. (When I refer to Object’s equals() method, I am referring to the equals() method in the Object class.)
  10. Expression "abc" == "a" + "bc" returns true. It does so because the String class contains special support that allows literal strings and string-valued constant expressions to be compared via ==.
  11. You can optimize a time-consuming equals() method by first using == to determine if this method’s reference argument identifies the current object (which is represented in source code via reserved word this).
  1. The purpose of the finalize() method is to provide a safety net for calling an object’s cleanup method in case that method is not called.
  2. You should not rely on finalize() for closing open files because file descriptors are a limited resource and an application might not be able to open additional files until finalize() is called, and this method might be called infrequently (or perhaps not at all).
  3. A hash code is a small value that results from applying a mathematical function to a potentially large amount of data.
  4. The answer is true: you should override the hashCode() method whenever you override the equals() method.
  5. Object’s toString() method returns a string representation of the current object that consists of the object’s class name, followed by the @ symbol, followed by a hexadecimal representation of the object’s hash code. (When I refer to Object’s toString() method, I am referring to the toString() method in the Object class.)
  6. You should override toString() to provide a concise but meaningful description of the object to facilitate debugging via System.out.println() method calls. It is more informative for toString() to reveal object state than to reveal a class name, followed by the @ symbol, followed by a hexadecimal representation of the object’s hash code.
  7. Composition is a way to reuse code by composing classes out of other classes based on a “has-a” relationship between them.
  8. The answer is false: composition is used to describe “has-a” relationships and implementation inheritance is used to describe “is-a” relationships.
  9. The fundamental problem of implementation inheritance is that it breaks encapsulation. You fix this problem by ensuring that you have control over the superclass as well as its subclasses by ensuring that the superclass is designed and documented for extension or by using a wrapper class in lieu of a subclass when you would otherwise extend the superclass.
  10. Subtype polymorphism is a kind of polymorphism where a subtype instance appears in a supertype context, and executing a supertype operation on the subtype instance results in the subtype’s version of that operation executing.
  11. Subtype polymorphism is accomplished by upcasting the subtype instance to its supertype; by assigning the instance’s reference to a variable of that type; and, via this variable, calling a superclass method that has been overridden in the subclass.
  1. Listings A-5 through A-11 declare the Animal, Bird, Fish, AmericanRobin, DomesticCanary, RainbowTrout, and SockeyeSalmon classes that were called for in Chapter 4.

Listing A-5. The Animal Class Abstracting Over Birds and Fish (and Other Organisms) public abstract class Animal { private String kind; private String appearance;

public Animal(String kind, String appearance) { this.kind = kind; this.appearance = appearance; }

public abstract void eat();

public abstract void move();

@Override public final String toString() { return kind + " -- " + appearance; } }

Listing A-6. The Bird Class Abstracting Over American Robins, Domestic Canaries, and Other Kinds of Birds public abstract class Bird extends Animal { public Bird(String kind, String appearance) { super(kind, appearance); }

@Override public final void eat() { System.out.println("eats seeds and insects"); }

@Override public final void move() { System.out.println("flies through the air"); } }

Listing A-7. The Fish Class Abstracting Over Rainbow Trout, Sockeye Salmon, and Other Kinds of Fish

public abstract class Fish extends Animal { public Fish(String kind, String appearance) { super(kind, appearance); }

@Override public final void eat() { System.out.println("eats krill, algae, and insects"); }

@Override public final void move() { System.out.println("swims through the water"); } }

Listing A-8. The AmericanRobin Class Denoting a Bird with a Red Breast

public final class AmericanRobin extends Bird { public AmericanRobin() { super("americanrobin", "red breast"); } }

Listing A-9. The DomesticCanary Class Denoting a Bird of Various Colors

public final class DomesticCanary extends Bird { public DomesticCanary() { super("domestic canary", "yellow, orange, black, brown, white, red"); } }

Listing A-10. The RainbowTrout Class Denoting a Rainbow-Colored Fish

public final class RainbowTrout extends Fish { public RainbowTrout() { super("rainbowtrout", "bands of brilliant speckled multicolored " + "stripes running nearly the whole length of its body"); } }

Listing A-14. The Refactored Animal Class for Help in Census Taking

public abstract class Animal implements Countable { private String kind; private String appearance;

public Animal(String kind, String appearance) { this.kind = kind; this.appearance = appearance; }

public abstract void eat();

public abstract void move();

@Override public final String toString() { return kind + " -- " + appearance; }

@Override public final String getID() { return kind; } }

Listing A-15. The Modified Animals Class for Carrying Out the Census

public class Animals { public static void main(String[] args) { Animal[] animals = { new AmericanRobin(), new RainbowTrout(), new DomesticCanary(), new SockeyeSalmon(), new RainbowTrout(), new AmericanRobin() }; for (int i = 0; i < animals.length; i++) { System.out.println(animals[i]); animals[i].eat(); animals[i].move(); System.out.println(); }

Census census = new Census(); Countable[] countables = (Countable[]) animals; for (int i = 0; i < countables.length; i++) census.update(countables[i].getID());

for (int i = 0; i < Census.SIZE; i++) System.out.println(census.get(i)); } }

Chapter 5: Mastering Advanced Language Features Part 1

  1. A nested class is a class that is declared as a member of another class or scope.
  2. The four kinds of nested classes are static member classes, nonstatic member classes, anonymous classes, and local classes.
  3. Nonstatic member classes, anonymous classes, and local classes are also known as inner classes.
  4. The answer is false: a static member class doesn’t have an enclosing instance.
  5. You instantiate a nonstatic member class from beyond its enclosing class by first instantiating the enclosing class and then prefixing the new operator with the enclosing class instance as you instantiate the enclosed class. Example: new EnclosingClass().new EnclosedClass().
  6. It’s necessary to declare local variables and parameters final when they are being accessed by an instance of an anonymous class or a local class.
  7. The answer is true: an interface can be declared within a class or within another interface.
  8. A package is a unique namespace that can contain a combination of top-level classes, other top-level types, and subpackages.
  9. You ensure that package names are unique by specifying your reversed Internet domain name as the top-level package name.
  10. A package statement is a statement that identifies the package in which a source file’s types are located.
  11. The answer is false: you cannot specify multiple package statements in a source file.
  12. An import statement is a statement that imports types from a package by telling the compiler where to look for unqualified type names during compilation.
  13. You indicate that you want to import multiple types via a single import statement by specifying the wildcard character (*).
  14. During a runtime search, the virtual machine reports a “no class definition found” error when it cannot find a classfile.
  1. A runtime exception is an exception that represents a coding mistake.
  2. You would introduce your own exception class when no existing exception class in the standard class library meets your needs.
  3. The answer is false: you use a throws clause to identify exceptions that are thrown from a method by appending this clause to a method’s header.
  4. The purpose of a try statement is to provide a scope (via its brace-delimited body) in which to present code that can throw exceptions. The purpose of a catch block is to receive a thrown exception and provide code (via its brace-delimited body) that handles that exception by providing a workaround.
  5. The purpose of a finally block is to provide cleanup code that is executed whether an exception is thrown or not.
  6. Listing A-16 presents the G2D class that was called for in Chapter 5.

Listing A-16. The G2D Class with Its Matrix Nonstatic Member Class public class G2D { private Matrix xform;

public G2D() { xform = new Matrix(); xform.a = 1.0; xform.e = 1.0; xform.i = 1.0; }

private class Matrix { double a, b, c; double d, e, f; double g, h, i; } }

  1. To extend the logging package (presented in Chapter 5’s discussion of packages) to support a null device in which messages are thrown away, first introduce Listing A-17’s NullDevice package-private class.

Listing A-17. Implementing the Proverbial “Bit Bucket” Class package logging;

class NullDevice implements Logger { private String dstName;

NullDevice(String dstName) { }

public boolean connect() { return true; }

public boolean disconnect() { return true; }

public boolean log(String msg) { return true; } }

Continue by introducing, into the LoggerFactory class, a NULLDEVICE constant and code that instantiates NullDevice with a null argument—a destination name is not required—when newLogger()’s dstType parameter contains this constant’s value. Check out Listing A-18.

Listing A-18. A Refactored LoggerFactory Class

package logging;

public abstract class LoggerFactory { public final static int CONSOLE = 0; public final static int FILE = 1; public final static int NULLDEVICE = 2;

public static Logger newLogger(int dstType, String...dstName) { switch (dstType) { case CONSOLE : return new Console(dstName.length == 0? null : dstName[0]); case FILE : return new File(dstName.length == 0? null : dstName[0]); case NULLDEVICE: return new NullDevice(null); default : return null; } } }