Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Zaawansowane programowanie obiektowe Lecture 2 Szymon Grabowski [email protected] http://szgrabowski.kis.p.lodz.pl/zpo/ Thx to Wojciech Bieniecki for sharing stuff and friendly advices Łódź, 2009 Obfuscated code in Java? Why not... class PrintQuirks { static public void main(String[] args) { System.out.println( 'A' ); System.out.println( 'A' + 'B' ); } } Output: A 131 Joshua Bloch and Neal Gafter wrote a book Java Puzzlers: Traps, Pitfalls, and Corner Cases. Chapter for download: http://www.ftponline.com/books/chapters/ 032133678X.pdf 2 String vs StringBuffer (1/3) Objects of class String are immutable in Java. String s = "test"; s[0] = 'b'; // compile-error: // array required, but java.lang.String found There is charAt(int i) method in String, but only to read. So, how can we e.g. append a character to a String?! Short answer: we cannot. We need to create another String: String s1 = "ice-cream"; s1 = s1 + "s"; // SLOW esp. if s1 is long // creates a temp object 3 String vs StringBuffer (2/3) [http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html] Class StringBuffer – smth like String but its objects can be modified. At any point in time it contains some particular sequence of chars, but its length and content can be changed through certain method calls. StringBuffer sb = new StringBuffer(new String("start")); sb.append("le"); // "startle" or: sb.insert(4, "le"); // start starlet 4 String vs StringBuffer (3/3) [http://java.sun.com/javase/6/docs/api/java/lang/StringBuffer.html] [http://mindprod.com/jgloss/immutable.html] Every string buffer has a capacity. Initially (JDK 6) – 16 characters for an empty string buffer, and 16 + |str| if using public StringBuffer(String str) constructor. If the internal buffer overflows, it is automatically made larger. Why String immutable? • thread-safe. Two threads can both work on an immutable object at the same time without any possibility of conflict; • immutable objects are much better suited to be Hashtable keys. If you change the value of an object that is used as a hash table key without removing it and re-adding it, you lose the mapping. 5 Packages Packages are class libraries. To include (“import”) a package in your code, write smth like import java.util.*; Or you want to import a single class for a package? Example: import java.util.ArrayList; java.lang package is automatically imported. Using an imported class: either (in the same example) java.util.ArrayList or just ArrayList. More convenient than in C/C++: you can import a package more than once (no compiler complaint...), you can write the import... line in any place in your code. 6 Packages, cont’d Collisions possible: Say that you’ve created a class Vector in a package called school.my_cool_data_structures. But you’ve also imported java.util. Now, the line Vector v = new Vector(); makes a collision. Solution: use full path. java.util.Vector v = new java.util.Vector(); or school.my_cool_data_structures.Vector v = new school.my_cool_data_structures.Vector() 7 How to create an own package Very simply. Just write the code of your class (in a file with the same name as the class name) and start it with line e.g. package myutils.text; Your class will be added to the package myutils.text. Of course, there can be many classes in a package. Remember: earlier in the file than the package... line may be only comments. 8 Access modifiers (for classes, methods, fields) [ http://www.particle.kth.se/~lindsey/JavaCourse/Book/ Part1/Java/Chapter05/access.html ] Java provides 4 access modifiers: 1.public – access by any other class anywhere. 2.protected – accessible by the package classes and any subclasses that are in other packages. 3. default (also known as “package private”) – accessible to classes in the same package but not by classes in other packages, even if these are subclasses. 4.private – accessible only within the class. Even methods in subclasses in the same package do not have access. A Java file can have only one public class! 9 Access modifiers, visualized [ members.tripod.com/~psdin/comlang/basicJava.PDF ] no! If there is no direct access to a field (property), provide accessor / mutator (aka get / set) methods. 10 Why private (or protected)? To avoid accidental “spoiling” of some data. To provide a proper class interface (ensapsulation rule: hide unimportant details). C++ programmers, beware: put public / protected / private in front of EACH method or field you want to specify that way. (In C++, in contrast, an access specifier is valid for all the definitions following it until another access specifier occurs.) 11 Default package class X { // file X.java int x; void doSomething() { ... } } class Y { // file Y.java in the same directory void someMethod() { X x = new X(); x.doSomething(); // does it work? Can Y see components of X ? } } X’s components are NOT public. So the question is: are Y and X in the same package? We didn’t write package ... Yes! Because they are in the same directory and have no explicit package name. 12 Field initialization Fields are initialized to ZERO (0, false for the boolean type, null for references (i.e., object types)). BEWARE: local variables are not initialized (have random values)! Like in C/C++, by the way. But trying to read an unitialized variable yields a compile error. You can also explicitly initialize a field, e.g. class Pair { static String text = "Pairs"; static int x = -1; int a = x+1; ..... 13 Field initialization, cont’d We can also init object fields, e.g. class X { Flower f = new Flower(); ... } Or like that: class X { int i = f(); int j = g(i); ..... } But not ..... int j = g(i); int i = f(); // order matters! 14 Inheritance An inherited class “extends” its parent. For example, the class Vehicle may have the following descendants: Car, Bike or Tank. New fields possible like Terminology: int number_of_doors in Car. superclass, New methods possible like base class, void loadMissile() in Tank. parent class public class Car extends Vehicle { int number_of_doors; ..... subclass, } derived class, extended class, child class 15 Hierarchy can be long, of course class Vehicle { ... } class Tank extends Vehicle { ... void loadMissile() { ... } // it wasn’t in the parent class } class Rudy102 extends Tank { ... void feedTheDog(byte germans) { ... } // it wasn’t in the parent class } 16 Inheritance, cont’d All non-private methods from the parent class are present in the child class. You can inherit from a single class (as opposed to C++). All Java classes are derived from the class Object. Constructors in the child class should call explicitly the constructor of the parent class. Keyword super. public class Vector3D extends Vector2D { .... public Vector3D(int x, int y, int z) { super(x,y); // calling the parent constructor this.z = z; // setting a remaining field } } 17 Creating an object of a derived class (what goes on) 1. The subclass constructor is launched. 2. If the first instruction in the constructor is super(args), then the superclass constructor is run, with arguments args. Remember: if super(args) is invoked in the subclass constructor, it must be its first instruction. 3. If no super(...), then the zero-argument constructor of the superclass is run. 4. The lines of the subclass constructor are executed. 18 Keyword final once more final class X { ... } means that X cannot be extended (for example, String class is final) final int someMethod(...); means that someMethod(...) cannot be overridden Terminology: don’t confuse (method) overloading and overriding! Overloading a function: same name but a different list of params. Overriding a function: same signature but in some descendant class. 19 final, cont’d final int[] a = { 1, 2, 3, 4 }; a[0]++; // OK ??? Yes. The reference is final (cannot be changed), not the pointed object. Therefore, of course, a = b; would be erroneous. Blank finals private final int i = 0; // Initialized final private final int j; // Blank final Value must be assigned to a blank final in every constructor. Why blank finals? Since they provide flexibility: a final field inside a class can now be different for each object. 20 Constant stuff No constant methods. I.e. everything may change the object. Method name convention: getMember: an accessor (getter) setMember: a mutator (setter) Constant instance fields: with final keyword. A constructor (of a given class or some ancestor class in the hierarchy) must set them to a value, and then it is fixed. Final arguments: e.g. void fun(final int j) { j++; } // j is read-only 21 Polymorphism, virtual methods A method that can be overridden = virtual method. (In Java, there’s no extra keyword.) Polymorphism: one name, many forms. Three distinct forms of polymorphism in Java [http://www.developer.com/tech/article.php/966001]: compile-time • method overloading; polymorphism • method overriding through inheritance; • method overriding through the Java interface. run-time polymorphism 22 Polymorphism, simple example (based on [Barteczko’04], pp. 304–305) class Car extends Vehicle { ... } ... Car c = new Car(...); Vehicle v = c; // ! v.start(); // start() from Vehicle overridden in Car Can the compiler (javac) know it should run start() from the class Car rather than Vehicle? Perhaps in this example, yes. But not in general. 23 Polymorphism, cont’d (based on [Barteczko’04], pp. 304–305) Consider this: public static void main(String args[]) { Car c = new Car(...); Motorcycle m = new Motorcycle(...); // Motorcycle also extends Vehicle Vehicle v; if (args[0].equals("Jawa")) v = m; else v = c; v.start(); // can the compiler know what is v ?!?! } (Run-time) polymorphism implies late binding. 24 (Almost) all methods in Java are virtual Methods that cannot be redefined: • static ones; • methods with final keyword (of course...); • private methods. Performance problems? (Yeah, probably.) Interview with Anders Hejlsberg, the lead C# architect ( http://www.artima.com/intv/nonvirtual.html ) Q: Why is non-virtual the default in C#? A: There are several reasons. One is performance. We can observe that as people write code in Java, they forget to mark their methods final. Therefore, those methods are virtual. Because they're virtual, they don't perform as well. There's just performance overhead associated with being a virtual method. (...) 25 What is derived from the Object class [ http://www.developer.com/tech/article.php/966001 ] The class Object defines default versions of the following methods: • clone() • equals(Object obj) • finalize() Every class inherits • getClass() them, • hashCode() and can override. • notify() • notifyAll() • toString() • wait() • wait(long timeout) • wait(long timeout, int nanos) 26 Abstract classes Abstract class – cannot have instances (objects). Methods can also be abstract (no definition). Abstract methods – only in abstract classes. But not all methods in an abstract class have to be abstract. public abstract class Shape { } What for? To have a common design for inherited classes. 27 Interfaces An interface is an abstract class which has only abstract methods. Using an interface: a class promises to implement all the methods declared in a given interface. interface Barkable { void bark(); void barkLoud(); void howl(); void whine(); } class Dog implements Barkable { void bark() { ... } ..... } 28 Interfaces, cont’d Interfaces declare public abstract methods (hence the words public, abstract are redundant). Interfaces may also store static constant fields. (Again, the words final static are not necessary.) Interface implementation: a class implementing all the interface methods (and now the word public is required). 29 Interfaces, example (based on [Barteczko’04]) interface Speakable { int QUIET = 0; int LOUD = 1; String getVoice(int voice); } interface Moveable { void startMoving(); void stopMoving(); } class Dog extends Animal implements Speakable, Moveable { Dog() {} Dog(String s) { super(s); } String getType() { return "Dog"; } public String getVoice(int voice) { if (voice == LOUD) return "WOOF... WOOF... WOOF..."; else return "woof... woof..."; } public void startMoving() { System.out.println("Dog " + name + " is running."); } public void stopMoving() { System.out.println("Dog " + name + " stood still."); } } 30 Interfaces in real world – e.g. CharSequence [http://java.sun.com/j2se/1.4.2/docs/api/java/lang/CharSequence.html] The public interface CharSequence is implemented by CharBuffer, String, StringBuffer. A CharSequence is a readable sequence of characters. This interface provides uniform, read-only access to many different kinds of character sequences. Its methods: char charAt(int index) int length() CharSequence subSequence(int start, int end) String toString() 31 Is it safe? [ http://www.manning-source.com/books/forman/forman_chp5.pdf ] 32 It isn’t safe 33 Now it’s safe [ http://www.manning-source.com/books/forman/forman_chp5.pdf ] TimeIntervalImpl2 makes defensive copies in both the constructor and the accessors, which means that no outside object holds a reference to the parts of the time interval. 34 Adapters Sometimes we really care for implementing only some (few) methods from an interface. But the language rules require implementing all of them. Some implemented methods can thus be “dummy” – but they must appear. Tedious, boring. Adapters free us from some typing. 35 Adapters, example interface R2D2 { String display(); String show(); int calculate(int a, int b); float generate(); double mean(); } abstract class R2D2Adapter implements R2D2 { public String display(){return "";} public String show(){return "";} public int calculate(int a, int b){return 0;} public float generate(){return 0.0f;} public double mean(){return 0.0d;} } 36 Adapters, example, cont’d public class Robot extends R2D2Adapter { public String display() { String s = "Adapting R2D2 to Robot"; System.out.println(s); return s; } public static void main(String args[]) { Robot r = new Robot(); r.display(); } } 37 Adapters, formally speaking (based on [http://web.mit.edu/1.124/LectureNotes/Swing.html]) An adapter is a class that implements an interface, with empty definitions for all of the functions. The idea is that if we subclass the adapter, we will only have to override the functions that we are interested in. 38 Legal assignments, casts [ members.tripod.com/~psdin/comlang/basicJava.PDF ] refOfSuper = refOfSub is valid // refOfSub = refOfSuper is not valid: compile error (even when the refOfSuper really refers to the sub object) refOfSub = (Sub) refOfSuper is valid may cause ClassCastException at run-time if - refOfSuper actually refers to a super object, - refOfSuper refers to object of another subclass of that super class 39 Reference assignment rules [ members.tripod.com/~psdin/comlang/basicJava.PDF ] (Enforced at compile-time.) SourceType srcRef; DestinationType destRef = srcRef; If SourceType is a class type, then - either DestinationType is a superclass of SourceType; - or DestinationType is an interface type which is implemented by the class SourceType. 40 Reference assignment rules, cont'd [ members.tripod.com/~psdin/comlang/basicJava.PDF ] If SourceType is an interface type, then - either DestinationType is Object; - or DestinationType is a superinterface of subinterface SourceType. If SourceType is an array type, then - either DestinationType is Object; - or DestinationType is an array type, where the element type of SourceType can be converted to the element type of DestinationType. 41 Assignments and casts – example [ members.tripod.com/~psdin/comlang/basicJava.PDF ] class A{ } class B extends A{ } class C{ } public class Class1 { public static void main(String[] args) { A a; B b; C c; a = new A(); b = new B(); // b = (B)a; // ok? WRONG. Will throw java.lang.ClassCastException. a = b; // ok? OK. a ref to subclass B object. // b = a; // ok? WRONG. Compile error; can't implicitly convert. // c = (C)a; // ok? WRONG. Compile error; can't convert A to C. b = (B)a; a = new A(); 42 // b = (B)a; // ok? WRONG. java.lang.ClassCastException. Shadowed variables [ members.tripod.com/~psdin/comlang/basicJava.PDF ] A variable in a subclass shadows an inherited variable if both have the same name. class A { int x; ... } class B extends A { int x; ... } How to distinguish them? Easily. In the child class: use x or this.x for x from this class, and super.x or ((ParentClass)this).x to for the shadowed x. Outside both classes: cast an object to the appropriate type. 43 Wrapper classes [ http://www.jchq.net/certkey/0803certkey.htm ] Wrappers are classes that wrap up primitive values (e.g., integers, doubles) in classes that offer utility methods to manipulate the values. What for? Say, you want to have a Vector (from java.util) of integers but the Vector class can only store objects, not primitive type entities. 44 Wrapper classes, example [ http://www.jchq.net/certkey/0803certkey.htm ] import java.util.*; public class VecNum { public static void main(String argv[]) { Vector v = new Vector(); v.add(new Integer(1)); v.add(new Integer(2)); for (int i=0; i < v.size(); i++) { Integer iw =(Integer) v.get(i); System.out.println(iw.intValue()); } } } 45 Wrapper classes, cont’d [ http://www.janeg.ca/scjp/pkglang/wrapper.html ] The wrapper classes are in java.lang (imported by default, no need to type import...) • one for each primitive type: Boolean, Byte, Character, Double, Float, Integer, Long, and Short, • Byte, Double, Float, Integer and Short extend the abstract Number class, • all are public final, i.e., cannot be extended, • get around limitations of primitive types. 46 Wrapper classes, cont’d [ http://www.janeg.ca/scjp/pkglang/wrapper.html ] Selected methods All except Character: valueOf(String s). Integer, Short, Byte, Long: parseType methods, eg. parseInt(), parseShort(), etc. that take a String and parse it into the appropriate type. Integer and Long: also have the static methods toBinaryString(), toOctalString() and toHexString() which take an integer value and convert it to the appropriate String representation. Character: public static int digit(char ch, int radix), public static int getNumber(char ch), public static char toLowerCase(char ch)... 47 Wrapper classes, examples Integer i = new Integer(20); byte b = i.byteValue(); ... double d = Double.parseDouble("3.14"); ... int i = Integer.parseInt("10011110",2); what can we deduce from this notation..? Simple question [http://java.sun.com/developer/technicalArticles/Interviews/bloch2006_qa.html] Finite or infinite loop? for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++) doSomething(i); 48 Beware... Integer[] arr = new Integer[100]; // OK? It’s not finished. Created an array of 100 references to Integer objects, not the objects themselves. Trying to access arr[i] will throw an exception. So, after the line above, write e.g. arr[0] = new Integer(30); arr[1] = new Integer(rand.nextInt(100)); .... 49 Exceptions Exception = some unexpected run-time erroneous situation. ...Or let us give the Sun official definition (from java.sun.com): An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. Examples: trying to open a non-existent file, division by zero. Exceptions are raised (thrown). Exceptions are handled. Exceptions in Java are objects from exception classes. Exception names are actually class names. Class hierarchy starts from Throwable. 50 Exception handling basics When an erroneous situation happens, it is impossible to continue the current program execution “context” (eg. if the resulting value x cannot be obtained because of div by 0 error, how could we continue calculations with x? If a file cannot be open, how can we later read from it or so?). Now the exception handling mechanism takes control. 51 Simple method, high level look [ http://www1.cs.columbia.edu/~lok/3101/lectures/04-softwareeng.pdf ] readSomeDevice { open the device figure out how much to read create our destination object actually do the reading close the device } 52 Traditional approach [ http://www1.cs.columbia.edu/~lok/3101/lectures/04-softwareeng.pdf ] errno readFile() { int errorCode = 0; open the file; if (theFileIsOpen) { // determine file length if (gotTheFileLength) { // allocate memory; if (gotEnoughMemory) { // read the file if (readFailed) { errorCode = -1; } } else { errorCode = -2; } } else { errorCode = -3; } close the file; if (fileNotClosed && errorCode == 0) { errorCode = -4; } else { errorCode = errorCode and -4; } } else { errorCode = -5; } return errorCode; } 53 Exception approach [ http://www1.cs.columbia.edu/~lok/3101/lectures/04-softwareeng.pdf ] readFile() { try { open the file; determine its size; allocate that much memory; read the file into memory; close the file; } catch (fileOpenFailed) { doSomething; } catch (sizeDeterminationFailed) { doSomething; .......... } catch (fileCloseFailed) { doSomething; } } 54 Exception class hierarchy fatal errors are here 55 java.lang.Error, java.lang.RuntimeException [ members.tripod.com/~psdin/comlang/basicJava.PDF ] java.lang.Error: • LinkageError, VirtualMachineError, AWTError, ...; • usually irrecoverable; • don't try to catch ’em. java.lang.RuntimeException: • ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException, ... • often due to programmatic errors, rather than special runtime conditions. 56 Checked vs. unchecked exceptions [ members.tripod.com/~psdin/comlang/basicJava.PDF ] Unchecked exceptions: RuntimeException, Error, and their subclasses. A method is NOT oblidged to deal with them. Checked exceptions: those which are not unchecked. You HAVE TO catch them: either directly in the method in which the exception occurs, or pass on the method that can throw a checked exception (directly or undirectly), to its caller. 57 Exception stuff keywords try { ... } – specifies a block of code that might throw an exception catch (ExceptionClass e) { ... } – exception handler; handles the type of exception indicated by its argument finally { ... } – this block always executes when the try block exits throw someThrowableObject – simply throws a given exception public void someMethod() throws SomeException { ... } – specifies what someMethod() can throw. A method can only throw those checked exceptions that are specified in its throws clause. 58 Exception handling, basic scheme int a, b, c; String s; try { /* in the try block we keep the code lines that can cause an exception */ a = b/c; // if e.g. c==0, then ArithmeticException will be raised // CAVEAT: not for floating-point number division! // 1.0 / 0.0 --> Infinity !!! s = Integer.toString(a); } catch(ArithmeticException ex) { // exceptions are handled in a catch block s = "*" ; } 59 A few notes After one try { ... } block, there can be many (disjoint) catch { ... } blocks. Each catch { ... } works like a mini-method: accepts only a single parameter of a specific exception type. try { // here can be fires, floods, plane hijacks and other disasters } // nothing in between catch(type1 id1) { // id1 exception handling, e.g. evacuate people } catch(type1 id2) { // id2 exception handling, e.g. extinguish fire } ... 60 How to catch smartly The order of catch blocks DOES matter. The execution goes (only) to the first catch block that fits the occurring exception. Many might fit! The conclusion is therefore: first specify more specific exceptions, then more general ones! E.g. try { ... } catch (FileNotFoundException e) { ... } // subclass catch (IOException e) { .... } // superclass /* after try { ... } block (and possibly handling an exception) we are here */ 61 finally. Look at this! Output 62 finally. Modified code output 63 Exception example ([Barteczko’00]) (1/4) import java.awt.*; import java.awt.event.*; class NotValidZipException extends Exception { // exception class public String msg = "Valid zipcode is of form dd-ddd"; NotValidZipException(String s) { // constructor msg = "Bad zipcode: "+s+". "+msg; } } 64 Example (2/4) class ZipField extends TextField { // component class ZipField() { super(); } ZipField(String s) { super(s); } ZipField(int n) { super(n); } public String getZip() throws NotValidZipException { final int N = 6, P = 2; String zip = getText(); boolean valid = true; char[] c = zip.toCharArray(); if (c.length != N || c[P] != '-') valid = false; for (int i = 0; i<N && valid; i++) { if (i == P) continue; if (!Character.isDigit(c[i])) valid = false; } if (!valid) throw new NotValidZipException(zip); return zip; } } 65 Example (3/4) class Exc3 extends Frame implements ActionListener { ZipField zf = new ZipField(10); public static void main(String[] args) { new Exc3(); } Exc3() { setLayout(new FlowLayout()); Button b = new Button("Enter"); b.addActionListener(this); add(zf); add(b); pack(); setVisible(true); } 66 Example (4/4) public void actionPerformed(ActionEvent e) { String txt = null; try { txt = zf.getZip(); } catch(NotValidZipException exc) { System.out.println(exc.msg); return; } System.out.println("You entered: " + txt); } } 67 A simpler example [ http://www.freshsources.com/Apr01.html ] Suppose, for example, that in main we call a function f which calls a function g which finally calls a function h. // In main() try { f(); } catch (MyException e) { System.out.println(e); } Now, all we have to do to raise an exception in h is to throw it, like this: // In h() throw new MyException("optional text here"); 68 Whence exceptions? (based on [ http://www.freshsources.com/Apr01.html ]) Throw exceptions only in truly exceptional situations. Not e.g. when not finding an element in an array (this is a normal situation and can be handled by returning –1 (pseudo)index). Consider a stack data structure. The contract of the pop method requires that the stack not be empty when it is called, so if you try to pop something from an empty stack, that's exceptional. There is no meaningful value to return in this case, and you shouldn’t have made the call in the first place. Similar logic applies to the top and push methods. 69 FixedStack class example [ http://www.freshsources.com/Apr01.html ] class FixedStack { private int capacity; private int size; private Object[] data; ... public Object pop() throws StackException { if (size <= 0) throw new StackException("underflow"); return data[--size]; } public void push(Object o) throws StackException { if (size == capacity) throw new StackException("overflow"); data[size++] = o; } ... } 70 FixedStack, cont’d [ http://www.freshsources.com/Apr01.html ] class StackException extends Exception { StackException() {} StackException(String msg) { super(msg); } } 71 Ops, FixedStack is gonna fall on me! ([http://www.freshsources.com/Apr01.html]) 72 What use of finally? ([ http://www.freshsources.com/Apr01.html ] again) Problems? f.close() occurs twice in the code – a bit unelegant 73 What use of finally? Cont’d ([ http://www.freshsources.com/Apr01.html ] again) Nicer! 74 One more example import java.util.*; class Numbers1 { public static void main(String args[]) { String num1 = "123"; String num2 = "-10"; String num3 = "3.5"; // now, not an integer String result = null; try { // a conversion may fail int a = Integer.parseInt(num1); // conversion int b = Integer.parseInt(num2); double c = Double.parseDouble(num3); result = String.valueOf(a+b+c); // conversion System.out.println("Result = " + result); } catch(NumberFormatException e) { System.out.println("Bad numeric format!"); } } } 75 Exception handling – only for error messages?? No. Sometimes we can fix a run-time error. E.g. ask the user to re-enter the data. ([Barteczko’04]) 76 Example, cont’d ([Barteczko’04]) 77 A little puzzle [ http://www.csc.uvic.ca/~csc330/ ] "Java"? No... Why not? 78 Puzzle, solution [ http://www.csc.uvic.ca/~csc330/Assignment1/Ass1-answers.pdf ] There are four constructors for the class StringBuffer. None of the constructors accepts a parameter of type char, which is what the program uses. However, in Java a value of type char can be coerced to a value of type int. So the instantiation is equivalent to new StringBuffer(74) because 'J' has the ASCII code 74. That particular invocation creates a new StringBuffer which is empty but which has an initial capacity of 74 characters. (But later, ‘a’ etc. will be appended, so the output is: ava (beware, word.length() == 3, but word.capacity() == 74). 79