صفحه 1:
solaris ۷
Java Puzzles
Filipp Shubin
صفحه 2:
متسس
Overall Presentation Goal
OT
Learn some of the quirks of
programming in general and the
Java language in particular;
Have fun!
ة ————
صفحه 3:
oS!
Learning Objectives
° As aresult of this presentation, you
will be able to:
- Avoid some common programming
pitfalls
- Have some fun while you are learning
صفحه 4:
ee 5”
1. “All | Get is Static”
01 class Dog {
02 public static void bark() {
03 System. out.print ("woof ");
04 }
05 }
06 class Basenji extends Dog {
07 public static void bark() { }
os }
09 public class Bark {
10 public static void main(String args[]) {
11 Dog woofer = new Dog();
12 Dog nipper = new Basenji();
13 woofer.bark() ;
14 nipper.bark() ;
15 }
16 }
صفحه 5:
ne oS”
What Does It Print?
(a) woof
(b) woof woof
(c) It varies
صفحه 6:
ee oS:
What Does It Print?
(a) woof
(b) woof woof
(c) It varies
No dynamic dispatch on static methods
صفحه 7:
ee oS:
Another Look
01 class Dog {
02 public static void bark() {
03 System. out.print ("woof ");
04 }
05 }
06 class Basenji extends Dog {
07 public static void bark() { }
os }
09 public class Bark {
10 public static void main(String args[]) {
11 Dog woofer = new Dog();
12 Dog nipper = new Basenji();
13 woofer.bark() ;
14 nipper.bark() ;
15 }
16 }
صفحه 8:
ee oS:
How Do You Fix It?
e Remove static from the bark
method
صفحه 9:
oS!
The Moral
e Static methods can't be overridden
- They can only be hidden
° Don’t hide static methods
۰ Never invoke static methods on
instances
- Not Instance. staticMethod ()
- But Class. staticMethod ()
صفحه 10:
متسس
2. “What's in a Name?”
01 public class Name {
02 private String first, last;
03 public Name(String first, String last) {
04 this.first = first;
05 this.last = last;
06 }
07 public boolean equals (Object o) {
08 if (!(o instanceof Name)) return false;
09 Name n = (Name) o;
10 return n.first.equals(first) &&
n.last.equals (last) ; با
12 }
13 public static void main(String[] args) {
14 Set s = new HashSet();
15 s.add(new Name("Donald", "Duck")) ;
16 System. out.println(
17 s.contains (new Name("Donald", "Duck")));
18 }
19 }
صفحه 11:
ne oS”
What Does It Print?
(a) True
(b) False
(c) It varies
صفحه 12:
متسس
What Does It Print?
(a) True
(b) False
(c) It varies
Ponalc is in the set, but the set can’t find
im.
The Name class violates the hashCode contract.
صفحه 13:
ee oS:
Another Look
01 public class Name {
02 private String first, last;
03 public Name(String first, String last) {
04 this.first = first;
05 this.last = last;
06 }
07 public boolean equals (Object 0) {
08 if (!(o instanceof Name)) return false;
09 Name n = (Name) o;
10 return n.first.equals(first) &&
n.last.equals (last) ; با
} 12
13 public static void main(String[] args) {
14 Set s = new HashSet();
15 s.add(new Name("Donald", "Duck")) ;
16 System. out.println(
17 s.contains (new Name("Donald", "Duck")));
18 }
19 }
صفحه 14:
متسس
How Do You Fix It?
Add a hashCode method:
public int hashCode() {
return 31 * first.hashCode() + last.hashCode() ;
}
صفحه 15:
ee oS:
The Moral
- If you override equals, override
hashCode
* Obey general contracts when
overriding
* See Effective Java, Chapter 3
صفحه 16:
متسس
3
01 class Indecisive {
02 public static void main(String[] args) {
03 System. out.println(waffle());
04 1
05
06 static boolean waffle() {
07 try {
08 return true;
09 } finally {
10 return false;
11 }
12 }
13 }
صفحه 17:
ne oS”
What Does It Print?
(a) true
(b) false
(c) None of the above
صفحه 18:
ne oS”
What Does It Print?
(a) true
(b) false
(c) None of the above
The finally is processed after the try.
صفحه 19:
ee oS:
Another Look
01 class Indecisive {
02 public static void main(String[] args) {
03 System. out.println(waffle());
04 1
05
06 static boolean waffle() {
07 try {
08 return true;
09 } finally {
10 return false;
11 }
12 }
13 }
صفحه 20:
ee oS:
The Moral
* Avoid abrupt completion of
finally blocks
- Wrap unpredictable actions with nested
trys
- Don't return or throw exceptions
صفحه 21:
oS!
4. “The Saga of the Sordid Sort”
01 public class SordidSort {
02 public static void main(String args[]) {
03 Integer big = new Integer( 2000000000) ;
04 Integer small = new Integer (-2000000000) ;
05 Integer zero = new دعوه18۲ )0( ۶
06 Integer[] a = new Integer[] {big, small, zero};
07 Arrays.sort(a, new Comparator() {
08 public int compare (Object ol, Object 02) {
09 return ((Integer)o02).intValue() -
10 ( (Integer) 01) .intValue () ;
11 }
12 Me
8 System.out.printin (Arrays.asList (a));
14 }
15 }
صفحه 22:
متسس
What Does It Print?
(a) [-2000000000, 0, 2000000000]
(b) [2000000000, 0, -2000000000]
(c) [-2000000000, 2000000000, 0]
(d) It varies
صفحه 23:
متسس
What Does It Print?
(a) [-2000000000, 0, 2000000000]
(b) [2000000000, 0, -2000000000]
(c) [-2000000000, 2000000000, 0]
(d) It varies (behavior is undefined)
The comparator is broken!
* It relies on int subtraction
+ Int too small to hold difference of 2 arbitrary ints
صفحه 24:
ee oS:
Another Look
01 public class Sordidsort {
02 public static void main(String args[]) {
03 Integer big = new Integer( 2000000000) ;
04 Integer small = new Integer (-2000000000) ;
05 Integer zero = new Integer(0);
06 Integer[] a = new Integer[] {big,small,zero};
07 Arrays.sort(a, new Comparator() {
08 public int compare(Object 01, Object 02) {
09 return ((Integer)o2).intValue() -
10 ((Integer) 01) .intValue () ;
11 }
12 2۳
13 System. out.println (Arrays.asList (a) );
14 }
15 }
صفحه 25:
متسس
How Do You Fix It?
° Replace comparator with one that
works
01 public int compare(Object o1, Object 02) {
02 int i1 = ((Integer) 01) .intValue() ;
03 int i2 = ((Integer) 02) .intValue() ;
04 return
05 412 > 11 ۶ -1 : (i2 - 11 2 0 :
صفحه 26:
متسس
The Moral
e ints aren't integers!
¢ Think about overflow
¢ This particular comparison technique
- OK only if max - min <= Integer.MAX_VALUE
- For example: all values positive
¢ Don’t write overly clever code
صفحه 27:
متسس
5. “You're Such a Character”
01 public class Trivial {
02 public static void main(String args[]) {
03 System.out.print("H" + "a");
04 System.out.print('H' + 'a');
05 1
06 }
صفحه 28:
re oS.
What Does It Print?
(a) HaHa
(b) Ha
(c) None of the above
صفحه 29:
ee oS:
What Does It Print?
(a) HaHa
(b) Ha
(c) None of the above: It 0۲۱۱۲6 9
'H' + 'a' evaluated as int, then converted
to String. Ouch.
صفحه 30:
ee oS:
The Moral
* Use string concatenation (+) with
care
- At least one operand must be a String
- If it isn't, cast or convert
* Be glad operator overloading isn't
supported
صفحه 31:
متسس
6. “The Case of the Constructor”
O01 public class Confusing {
02 public Confusing(Object o) {
03 System. out.println("Object") ;
04 }
05 public Confusing(double[] dArray) {
06 System.out.println("double array") ;
07 }
08 public static void main(String args[]) {
09 new Confusing(nul1) ;
10 }
11 [
صفحه 32:
re oS.
What Does It Print?
(a) Object
(b) double array
(c) None of the above
صفحه 33:
ee oS:
What Does It Print?
(a) Object
(b) double array
(c) None of the above
When multiple overloadings
apply, the most specific wins
صفحه 34:
ee oS:
Another Look
O01 public class Confusing {
02 public Confusing(Object o) {
03 System. out.println("Object") ;
04 1
05 public Confusing(double[] dArray) {
06 System.out.println("double array") ;
07 }
08 public static void main(String args[]) {
09 new Confusing(nul1) ;
10 }
11 }
صفحه 35:
ee oS:
How Do You Fix It?
° There may be no problem
¢ If there is, use a cast:
New Confusing ( (Object) null) ;
صفحه 36:
ee oS:
The Moral
° Avoid overloading
° If you overload, avoid ambiguity
° If you do have ambiguous
overloadings, make their behavior
identical
e If you are using a "broken" class,
make intentions clear with a cast
صفحه 37:
es oS)
7. “A Big Delight in Every Byte”
01 public class ByteMe {
02 public static void main(String[] args) {
03 for (byte b = Byte.MIN VALUE;
04 b < Byte.MAX VALUE; bt+) {
05 if (b == 0x90)
06 System.out.print("Byte me! ");
07 }
08 }
09 (
صفحه 38:
ne oS”
What Does It Print?
(a) (nothing)
(b) Byte me!
(c) Byte me! Byte me!
صفحه 39:
متسس
What Does It Print?
(a) (nothing)
(b) Byte me!
(c) Byte me! Byte me!
Program compares a byte with an
int
- byte is promoted with surprising results
صفحه 40:
متسس
Another Look
01 public class ByteMe {
02 public static void main(String[] args) {
03 for (byte b = Byte.MIN VALUE;
04 b < Byte.MAX VALUE; bt+) {
05 if (b == 0x90) // (b == 144)
06 System.out.print("Byte me! ");
07 }
08 }
09 (۴
10
11 // But (byte)0x90 == -112
صفحه 41:
ee oS:
How Do You Fix It?
٠ Cast int to byte
if (b == (byte) 0x90)
System.out.printin ("Byte me!");
° Or convert byte to int, suppressing
sign extension with mask
if ((b & Oxff) == 0x90)
System.out.println("Byte me!");
صفحه 42:
ee oS:
The Moral
e Bytes aren't ints
e Be careful when mixing primitive
types
٠ Compare like-typed expressions
- Cast or convert one operand as
necessary
صفحه 43:
oS!
8. “Time for a Change”
° If you pay $2.00 for a gasket that
costs $1.10, how much change do
you get?
01 public class Change {
02 public static void main(String args[])
03 {
04 System.out.printlin(2.00 - 1.10);
05 }
06 }
صفحه 44:
re oS.
What Does It Print?
(a) 0.9
(b) 0.90
(c) It varies
(d) None of the above
صفحه 45:
ee oS:
What Does It Print?
(a) 0.9
(b) 0.90
(c) It varies
(d) None of the above:
0.89999999999999
Decimal Values can't be represented
exactly by float or double
صفحه 46:
متسس
How Do You Fix It?
01 import java.math.BigDecimal ;
02 public class Change2 {
03 public static void main(String args[]) {
04 System. out.println(
05 new BigDecimal ("2.00") .subtract (
06 new BigDecimal ("1.10")));
07 }
os }
09
10 public class Change {
11 public static void main(String args[]) {
12 System.out.println(200 - 110);
13 }
14 }
صفحه 47:
ee oS:
The Moral
- Avoid float and double where
exact answers are required
e Use BigDecimal, int, Or long
instead
صفحه 48:
ee oS:
9. “A Private Matter”
01 class Base {
02 public String name = "Base";
03 [
04
05 class Derived extends Base {
06 private String name = "Derived";
07 [
08
09 public class PrivateMatter {
10 public static void main(String[] args) {
11 System. out.println(new Derived() .name) ;
12 }
13 }
صفحه 49:
ee oS:
What Does It Print?
(a) Derived
(b) Base
(c) Compiler error in class Derived:
Can't assign weaker access to name
(d) None of the above
صفحه 50:
ee oS:
What Does it Print?
(a) Derived
(b) Base
(c) Compiler error in class Derived:
Can't assign weaker access to name
(d) None of the above: Compiler error in
class
PrivateMatter: Can't access name
Private method can't overrides public,
but private field can hide public
صفحه 51:
ee oS:
Another Look
01 class Base {
02 public String name = "Base";
03 [
04
05 class Derived extends Base {
06 private String name = "Derived";
07 1
08
09 public class PrivateMatter {
10 public static void main(String[] args) {
11 System. out.println(new Derived() .name) ;
12 }
13 }
صفحه 52:
متسس
How Do You Fix It?
01 class Base {
02 public String getName() { return "Base"; }
03 [
04
05 class Derived extends Base {
06 public String getName() { return "Derived"; }
07 1
08
09 public class PrivateMatter {
10 public static void main(String[] args) {
11 System.out.println(new Derived() .getName() ) ;
12 }
13 }
صفحه 53:
53530070040000
The Moral
۰ Avoid hiding
- Violates subsumption
¢ Avoid public fields
- Use accessor methods instead
صفحه 54:
es oS)
10. “Loopy Behavior”
01 public class Loopy {
02 public static void main(String[] args) {
03 final int start = Integer.MAX VALUE -
04 100;
05 final int end = Integer .MAX VALUE;
06 int count = 0;
(07 for (int i = start; i <= end; i++)
08 count++;
09 System.out.println (count) ;
10 ۱
11 (
صفحه 55:
re oS.
What Does It Print?
(a) 100
(b) 101
(c) (nothing)
صفحه 56:
متسس
What Does It Print?
(a) 100
(b) 101
(c) (nothing)
The loop test is broken - infinite loop!
صفحه 57:
ee oS:
Another Look
01 public class Loopy {
02 public static void main(String[] args) {
03 final int start = Integer.MAX VALUE -
04 100;
05 final int end = Integer .MAX VALUE;
06 int count = 0;
(07 for (int i = start; i <= end; i++)
08 count++;
09 System.out.println (count) ;
10 ۱
11 (
صفحه 58:
ee oS:
How Do You Fix It?
¢ Change loop variable from int
to long
for (long i = start; i <= end; i++)
count++;
صفحه 59:
re oS.
The Moral
e ints aren't integers!
¢ Think about overflow
‘use larger type ir
necessary
صفحه 60:
متسس
11. “Random Behavior’
01 public class RandomSet {
02 public static void main(String[] args) {
03 Set و = new HashSet ();
04 for (int i = 0; i < 100; i++)
05 s.add(randomInteger () );
06 System.out.printlin(s.size());
07 }
08
09 private static Integer randomInteger() {
10 return new Integer(new Random() .nextInt());
11 }
12 }
صفحه 61:
متسس
What Does It Print?
(a) Anumber close to 1
(bo) A number close to 50
(c) Anumber close to 100
(d) None of the above
صفحه 62:
ee oS:
What Does It Print?
(a) A number close to 1
(b) A number close to 50
(c) A number close to 100
(d) None of the above
A new random number generator is
created each iteration and the seed
changes rarely if at all.
صفحه 63:
ee oS:
Another Look
01 public class RandomSet {
02 public static void main(String[] args) {
03 Set و = new HashSet ();
04 for (int i=0; i<100; i++)
05 s.add(randomInteger ());
06 System.out.printlin(s.size());
07 }
08
09 private static Integer randomInteger() {
10 return new Integer(new Random().nextInt());
11 }
12 }
صفحه 64:
متسس
How Do You Fix It?
01 public class RandomSet {
02 public static void main(String[] args) {
03 Set و = new HashSet ();
04 for (int i=0; i<100; i++)
05 s.add(randomInteger () );
06 System.out.printlin(s.size());
07 }
08
09 private static Random rnd = new Random() ;
10
11 private static Integer randomInteger() {
12 return new Integer (rnd.nextInt());
13 }
14 }
صفحه 65:
oS!
The Moral
e Use one Random instance for each
sequence
¢ In most programs, One is all you
need
In multithreaded programs, you may
want multiple instances for
increased concurrency
— Seed explicitly or risk identical sequences
— Generally ok to use one instance to seed
others
صفحه 66:
oS!
12.“Making a Hash of It”
01 public class Name {
02 private String first, last;
03 public Name(String first, String last) {
04 if (first == null || last == null)
05 throw new NullPointerException () ;
06 this.first = first; this.last = last;
07 }
08 public boolean equals(Name o) {
09 return first.equals(o.first) && last.equals(o.last);
10 }
11 public int hashCode() {
12 return 31 * first.hashCode() + last. hashCode();
13 }
14 public static void main(String[] args) {
15 Set s = new HashSet();
16 s.add(new Name("Mickey", "Mouse")) ;
17 System. out.print1n (
18 s.contains (new Name("Mickey", "Mouse")));
19 1
صفحه 67:
ne oS”
What Does It Print?
(a) true
(b) false
(c) It varies
صفحه 68:
متسس
What Does It Print?
(a) true
(b) false
(c) It varies
Name overrides hashCode but not
equals.
The two Name instances are unequal.
صفحه 69:
ee oS:
Another Look
01 public class Name {
02 private String first, last;
03 public Name(String first, String last) {
04 if (first == null || last == null)
05 throw new NullPointerException () ;
06 this.first = first; this.last = last;
07 }
08 public boolean equals(Name 0) { // Accidental overloading
09 return first.equals(o.first) && last.equals(o.last);
10 }
1 public int hashCode() { // Overriding
12 return 31 * first.hashCode() + last.hashCode();
13 }
14 public static void main(String[] args) {
15 Set s = new HashSet();
16 s.add(new Name("Mickey", "Mouse")) ;
17 System. out.print1n (
18 s.contains (new Name ("Mickey", "Mouse")));
19 1
صفحه 70:
متسس
How Do You Fix It?
e Replace the overloaded equals method
with an overriding equals method
01 public boolean equals(Object o) {
02 if (!(o instanceof Name) )
03 return false;
04 Name n = (Name)o;
05 return n.first.equals (first) && n.last.equals (last) ;
صفحه 71:
ee oS:
The Moral
If you want to override a method:
— Make sure signatures match
—The compiler doesn’t check for you
—Do copy-and-paste declarations!
صفحه 72:
oS!
13. “Ping Pong”
01 class PingPong {
02 public static synchronized void main(String[] a)
{
03 Thread t = new Thread() {
04 public void run() {
05 pong() ;
06 1
07 1
08
09 t.run();
10 System. out.print ("Ping") ;
11 }
12
13 static synchronized void pong() {
14 System. out.print ("Pong") ;
15 }
16 }
صفحه 73:
ne oS”
What Does It Print?
(a) PingPong
(b) PongPing
(c) It varies
صفحه 74:
متسس
What Does It Print?
(a) PingPong
(b) PongPing
(c) It varies
Not a multithreaded program!
صفحه 75:
ee oS:
Another Look
01 class PingPong {
02 public static synchronized void main(String[] a) {
03 Thread t = new Thread() {
04 public void run() {
05 pong();
06 }
07 1
08
09 t.run(); // Common typo!
10 System.out.print ("Ping") ;
11 1
12
13 static synchronized void pong() {
14 System.out.print ("Pong") ;
15 1
16 }
صفحه 76:
متسس
How Do You Fix It?
01 class PingPong {
02 public static synchronized void main(String[] a) {
03 Thread t = new Thread() {
04 public void run() {
05 pong() ;
06 }
07 he
08
09 t.start();
10 System.out.print ("Ping") ;
11 1
12
13 static synchronized void pong() {
14 System.out.print ("Pong") ;
15 1
16 }
صفحه 77:
ee oS:
The Moral
e Invoke Thread.start, not
Thread.run
—Common error
—Can be very difficult to diagnose
¢ (Thread shouldn’t implement
Runnable)
صفحه 78:
a >
14. “Shifty”
01 public class Shifty {
02 public static void main(String[] args) {
03 int distance = 0;
04 while ((-1 << distance) != 0)
05 distance++;
06 System. out.printin (distance) ;
07 }
os }
صفحه 79:
ne oS”
What Does It Print?
(a) 31
(b) 32
(c) 33
(d) None of the above
صفحه 80:
متسس
What Does It Print?
(a) 31
(b) 32
(c) 33
(d) None of the above: infinite loop!
Shift distances are calculated mod 32.
صفحه 81:
متسس
Another Look
01 public class Shifty {
02 public static void main(String[] args) {
03 int distance = 0;
04 while ((-1 << distance) != 0)
05 distance++;
06 System. out.printin (distance) ;
07 }
os }
09
10 // (-1 << 32) << -1
صفحه 82:
a 6
How Do You Fix It?
01 public class Shifty {
02 public static void main(String[] args) {
03 int distance = 0;
04 for (int val = -1; val != 0; val <<= 1)
05 distance++;
06 System. out.printin (distance) ;
07 }
os }
صفحه 83:
ee oS:
The Moral
¢ Shift distances are computed mod
32 (or 64)
¢ It’s impossible to shift out an entire
int
(or long) using any shift operator or
distance
e Use care when shift distance is
not a literal
صفحه 84:
ee oS:
15. “Line Printer’
01 public class LinePrinter {
02 public static void main(String[] args) {
03 // Note: \u000A is Unicode representation for
newline
04 char c = 0x000A;
05 System.out.println(c) ;
06 }
07 [
صفحه 85:
re oS.
What Does It Print?
(a) Two blank lines
(b) 10
(c) Won't compile
(d) It varies
صفحه 86:
ee oS:
What Does It Print?
(a) Two blank lines
(b) 10
(c) Won't compile: Syntax error!
(d) It varies
The Unicode escape in the comment
breaks
it in two. The second half is garbage.
صفحه 87:
ee oS:
Another Look
01 // Unicode escapes are processed before comments!
02 public class LinePrinter {
03 public static void main(String[] args) {
04 / Note: \uO000A is unicode representation for
newline
05 char c = 0x000A;
06 System.out.println(c) ;
07 }
08 [
01 // This is what the parser sees
02 public class LinePrinter {
03 public static void main(String[] args) {
04 // Note:
05 is Unicode representation for newline
06 char c = 0x000A;
07 System.out.println(c) ;
08 }
صفحه 88:
متسس
How Do You Fix It?
01 public class LinePrinter {
02 public static void main(String[] args) {
03 // Escape sequences (like \n) are fine in comments
04 char c = '\n';
05 System. out.println(c) ;
06 }
07 [
صفحه 89:
oS!
The Moral
e Unicode escapes are dangerous
—Equivalent to the character they
represent!
e Use escape sequences instead, if
possible
e If you must use Unicode escapes, use
with care
—\u000A (newline) can break string
literals,
char literals, and single-line comments
—\u0022 (") can terminate string literals
صفحه 90:
ee 5”
16. “All Strung Out”
01 public class Puzzling {
02 public static void main(String[] args) {
03 String s = new String("blah") ;
04 System. out.println(s) ;
05 }
06 [
07 class String {
08 java.lang.String s;
09
10 public String(java.lang.String s) {
11 this.s = s;
12 }
13 public java.lang.String toString() {
14 return s;
15 }
16 }
صفحه 91:
re oS.
What Does It Print?
(a) Won't compile
(b) blah
(c) Throws an exception at runtime
(d) Other
صفحه 92:
ee oS:
What Does It Print?
(a) Won't compile
(b) blah
(c) Throws an exception at runtime
(d) Other
NoSuchMethodError is thrown
because the Puzzling class is missing
a main method.
صفحه 93:
ee oS:
Another Look
01 public class Puzzling {
02 public static void main(String[] args) {
03 String s = new String("blah") ;
04 System. out.println(s) ;
05 }
06 [
07 class String {
08 java.lang.String s;
09
10 public String(java.lang.String s) {
11 this.s = s;
12 }
13 public java.lang.String toString() {
14 return s;
15 }
16 }
صفحه 94:
متسس
How Do You Fix It?
01 public class Puzzling {
02 public static void main(String[] args) {
03 MyString s = new MyString("blah") ;
04 System. out.println(s) ;
05 }
06 [
07 class MyString {
08 String s;
09
10 public MyString(String s) {
11 this.s = s;
12 }
13 public String toString() {
14 return s;
15 }
16 }
صفحه 95:
ee oS:
The Moral
٠ Avoid name reuse in all its guises
—hiding, shadowing, overloading
* Don’t even think about reusing
platform
class names!
صفحه 96:
متسس
17. “Reflection Infection”
01 import java.lang.reflect.*;
02
03 public class Reflector {
04 public static void main(String[] args) throws Exception {
05 Set و = new HashSet();
06 s.add("£oo");
07 Iterator i = s.iterator();
08 Method m =
09 i.getClass ().getMethod("hasNext", new Class[0]);
10 System.out.printin(m.invoke(i, new Object[0]));
11 }
12 }
صفحه 97:
ne oS”
What Does It Print?
a) Won't compile
b) true
c) Throws exception
d) None of the above
aT Tm
صفحه 98:
متسس
What Does It Print?
(a) Won't compile
(b) true
(c) Throws exception -
IllegalAccessError
(d) None of the above
Attempts to invoke a method ona
private class
صفحه 99:
ee oS:
Another Look
01 import java.lang.reflect.*;
02
03 public class Reflector {
04 public static void main(String[] args) throws Exception {
05 Set و = new HashSet();
06 s.add("£oo");
07 Iterator i = s.iterator();
08 Method m =
09 i.getClass().getMethod("hasNext", new Class[0]);
10 System.out.printin(m.invoke (i, new Object[0]));
11 }
12 }
صفحه 100:
متسس
How Do You Fix It?
01 import java.lang.reflect.*;
02
03 public class Reflector {
04 public static void main(String[] args) throws Exception {
05 Set و = new HashSet();
06 s.add("£oo");
07 Iterator i = s.iterator();
08 Method m =
09 Iterator.class.getMethod ("hasNext",
10 new Class[0]);
11 System.out.printin(m.invoke(i, new Object[0]));
12 }
3 اک 1
صفحه 101:
ee oS:
The Moral
۰ Reflection has its own access rules
¢ Avoid reflection when possible
° If you must use reflection
—Instantiate using reflection
— Cast to an interface type
—Access via interface
¢ Avoid extralinguistic mechanisms
صفحه 102:
0011 الس م
18. “String Cheese”
01 public class StringCheese {
02 public static void main(String args[]) {
03 byte b[] = new byte[256];
04 for(int i = 0; i < 256; i++)
05 b[i] = (byte)i;
06 String str = new String(b);
07 for(int i = 0; i < str.length(); i++)
08 System.out.print((int)str.charAt(i) +." ");
09 1
10 [
صفحه 103:
ne oS”
What Does It Print?
(a) The numbers from 0 to 255
(b) The numbers from 0 to 127 then
-128 to -1
(c) It varies
(d) None of the above
صفحه 104:
متسس
What Does It Print?
(a) The numbers from 0 to 255
(b) The numbers from 0 to 127 then
-128 to -1
(c) It varies*
(d) None of the above
The sequence depends on the default
charset,which depends on OS and
locale.
صفحه 105:
oS!
Another Look
01 public class StringCheese {
02 public static void main(String args[]) {
03 byte b[] = new byte[256];
04 for(int i = 0; i < 256; i++)
05 b[i] = (byte)i;
06 String str = new String(b);
07 for(int i = 0; i < str.length(); i++)
08 System.out.print ((int)str.charAt(i) + "");
09 1
10 }
String (byte[] bytes) -
“Constructs a new String by decoding
the specified array of bytes using
the platform’s default
charset.” [from API Spec. ]
صفحه 106:
re: 3.
How Do You Fix It?
If you want it to print numbers from
0-255
in order:
01 public class StringCheese {
02 public static void main(String args[]) {
03 byte b[] = new byte[256];
04 for(int i = 0; i < 256; i++)
05 b[i] = (byte)i;
06 String str = new String(b, "ISO-8859-1");
07 for(int i = 0; i < str.length(); i++)
08 System.out.print((int)str.charAt(i) + " ");
09 }
10 }
Iso-8859-1 indicates the Latin1 charset.
صفحه 107:
ee oS:
The Moral
٠ Converting bytes to chars uses a
charset
* If you don’t specify one, you get
default
— Depends on OS and locale
¢ If you need predictability, specify a
charset
صفحه 108:
متسس
19. “Elvis Lives!”
01 public class Elvis {
02 public static final Elvis INSTANCE = new Elvis();
03 private final int beltSize;
04
05 private static final int CURRENT YEAR =
06 Calendar. getiInstance() .get (Calendar. YEAR) ;
07
08 private Elvis() { beltSize = CURRENT_YEAR - 1930; }
09 public int beltSize() { return beltSize; }
10
11 public static void main(String[] args) {
12 System. out.println("Elvis wears size " +
13 INSTANCE.beltSize() + " belt.");
14 }
15 }
صفحه 109:
ee oS:
What Does It Print?
(a) Elvis wears size 0 belt.
(b) Elvis wears size 73 belt.
(c) Elvis wears size -1930 belt.
(d) None of the above.
صفحه 110:
ee oS:
What Does It Print?
(a) Elvis wears size 0 belt.
(b) Elvis wears size 73 belt.
(c) Elvis wears size -1930 belt.
(d) None of the above.
The value of CURRENT_YEAR is used before it
Is
initialized, due to circularity in class
initialization.
صفحه 111:
ee oS:
Another Look
01 // Static initialization proceeds top to bottom.
02 public class Elvis {
03 // Recursive initialization returns immediately!
04 public static final Elvis INSTANCE = new Elvis();
05 private final int beltSize;
06
07 private static final int CURRENT_YEAR =
08 Calendar. getInstance() .get (Calendar. YEAR) ;
09
10 private Elvis() { beltSize = CURRENT که - 1930; }
11 public int beltSize() { return beltSize; }
12
13 public static void main(String[] args) {
14 System.out.println("Elvis wears size " +
15 INSTANCE. beltSize() + " belt.");
16 1
17 3
صفحه 112:
متسس
How Do You Fix It?
01 public class Elvis {
02 private final int beltSize;
03
04 private static final int CURRENT YEAR =
05 Calendar. getInstance() .get (Calendar. YEAR) ;
06
07 / Make instance after other initialization complete
08 public static final Elvis INSTANCE = new Elvis();
09
10 private Elvis() { beltSize = CURRENT_YEAR — 1930; }
11 public int beltSize() { return beltSize; }
22
13 public static void main(String[] args) {
14 System.out.println("Elvis wears size " +
15 INSTANCE. beltSize() + " belt.");
16 }
17 }
صفحه 113:
0011 الس م
The Moral
¢ Watch out for circularities in static
initialization
One or more classes may be involved
Circularities aren’t necessarily wrong but...
" Constructors can run before class fully initialized
" Static fields can be read before they’re initialized
e Several common patterns are susceptible
0 Singleton (Effective Java, Item 2)
OTypesafe Enum (Effective Java, Item 21)
O Service Provider Framework (Effective Java,
Item 1)
صفحه 114:
a >
20. “What’s the Point?”
01 class Point {
02 protected final int x, y;
03 private final string name; // Cached at construction time
04 protected String makeName() { return "["+x+","4+y4"]"7 }
05 public final String toString() { return name; }
06 Point(int x, int y) {
07 this.x = x; this.y = y;
os this.name = makeName() ;
09 1
10}
11
12 public class ColorPoint extends Point {
13 private final string color;
14 protected String makeName() { return super.makeName() + ":" +
color; }
15 ColorPoint (int x, int y, String color) {
16 super(x, y);
17 this.color = color;
18 }
19 public static void main(String[] args) {
20 System.out.println(new ColorPoint (4, 2, "purple")) ;
21 1
22
صفحه 115:
ee oS:
What Does It Print?
(a) [4,2] :purple
)0( [4,2] :null
(c) Throws exception at runtime
(d) None of the above
صفحه 116:
ee oS:
What Does It Print?
(a) [4,2] :purple
)0( [4,2] :null
(c) Throws exception at runtime
(d) None of the above
Superclass constructor runs a subclass
method
before the subclass instance is
initialized.
صفحه 117:
re ©
ی Look
protected final int x, y;
= private final string name;
04 protected String makeName() { return "[" + x+","+y + ۱
05 public final string tostring() { return name; }
06 Point(int x, int y) {
07 this.x = x; this.y = y;
08 this.name = makeName(); // (3) Invokes subclass method
09 }
10}
11
12 public class ColorPoint extends Point {
13 private final string color;
14 // (4) Subclass method executes before subclass constructor body!
15 protected String makeName() { return super.makeName() + " +
color; }
16 ColorPoint (int x, int y, String color) {
17 super (x, y); // (2) Chains to superclass constructor
18 this.color = color; // (5) Initializes blank final instance
field
19 1
20 public static void main(string[] args) { // (1) Invoke subclass cons.
21 System.out.printin(new ColorPoint (4, 2, "purple")) ;
22 1
صفحه 118:
a >
How Do You Fix It?
class Point {
02 protected final int x, y;
03 private String name; // Lazily initialized (cached on first use)
04 protected String makeName() { return "[" + x4 "," 4+ y + "]"7 }
05 public final synchronized String toString()
06 { return (name == null ? (name = makeName()) : name); }
07 Point(int x, int y) {
08 this.x = x; this.y =
09 // (name initialization removed)
10 1
11
12
13 public class ColorPoint extends Point {
14 private final string color;
15 protected String makeName() { return super.makeName() + ":" +
color; }
16 ColorPoint (int x, int y, String color) {
17 super(x, y);
18 this.color = color;
19 }
20 public static void main(string[] args) {
21 System.out.printin(new ColorPoint (4, 2, "purple")) ;
22 1
23 (
صفحه 119:
The Moral
« Never call overridable methods
from constructors, directly or
indirectly
٠ Also applies to “pseudo-constructors”
— readObject ()
— clone ()
° See Effective Java, Item 15
صفحه 120:
متسس
21. “Long Division”
01 public class LongDivision {
02 private static final long MILLIS PER_DAY
03 = 24 * 60 * 60 * 1000;
۷ ۳۳۳ 110805 ودما 1دسدع ه31غ2غؤ5 private 04
05 = 24 * 60 * 60 * 1000 * 1000;
06
07 public static void main(String[] args) {
os System. out.printin(MICROS PER_DAY / MILLIS PER_DAY) ;
09 }
10 }
صفحه 121:
re oS.
What Does It Print?
(a) 5
(b) 1000
(c) 5000
(d) Throws an exception
صفحه 122:
re oS.
What Does It Print?
(a) 5
(b) 1000
(c) 5000
(d) Throws an exception
Computation does overflow
صفحه 123:
ee oS:
Another Look
01 public class LongDivision {
02 private static final long MILLIS PER_DAY
03 = 24 * 60 * 60 * 1000;
04 private static final long MICROS PER_DAY
05 = 24 * 60 * 60 * 1000 * 1000; // >> Integer.MAX VALUE
06
07 public static void main(String[] args) {
os System.out.printin(MICROS PER_DAY / MILLIS _PER_DAY) ;
09 }
10 }
صفحه 124:
متسس
How Do You Fix It?
01 public class LongDivision {
02 private static final long MILLIS PER_DAY
03 = 24L * 60 * 60 * 1000;
04 private static final long MICROS PER_DAY
05 = 244 * 60 * 60 * 1000 * 1000;
06
07 public static void main(String[] args) {
os System.out.printin(MICROS PER_DAY / MILLIS _PER_DAY) ;
09 }
10 }
صفحه 125:
ee oS:
The Moral
¢ When working with large numbers watch
out
for overflow—it’s a silent killer
e Just because variable is big enough to hold
result doesn’t mean computation is of
correct type
¢ When in doubt, use long
صفحه 126:
ee oS:
22. “No Pain, No Gain”
01 public class Rhymes {
02 private static Random rnd = new Random() ;
03 public static void main(String[] args) {
04 StringBuffer word = null;
05 switch (rnd.nextInt(2)) {
06 case 1: word = new StringBuffer('P');
07 case 2: word = new StringBuffer('G');
08 default: word < 6۲ 51 2 عد ععنداظن ) '14' ( :
09 }
10 word.append('a');
11 word.append('i');
12 word.append('n') ;
13 System.out.println (word) ;
14 }
15 }
Thanks to madbot (also known as Mike McCloskey)
صفحه 127:
متسس
What Does It Print?
(a) Pain, Gain, Of Main (varies at
random)
(b) Pain Or Main (varies at random)
(C) Main (always)
(d) None of the above
صفحه 128:
متسس
What Does It Print?
(a) Pain, Gain, Of Main (varies at
random)
(b) Pain Or Main (varies at random)
(C) Main (always)
(d) None of the above: ain (always)
The program has three separate bugs.
One of them is quite subtle.
صفحه 129:
ee oS:
Another Look
01 public class Rhymes {
02 private static Random rnd = new Random() ;
03 public static void main(String[] args) {
04 StringBuffer word = null;
05 switch (rnd.nextInt(2)) { // No breaks!
06 case 1: word = new StringBuffer('P');
07 case 2: word = new StringBuffer('G');
08 default: word < 6۲ 51 ۳0۴۶ ده ) ۱۲ 7
09 }
10 word.append('a');
11 word.append('i');
12 word.append('n') ;
13 System.out.println (word) ;
14 }
15 }
صفحه 130:
متسس
How Do Your Fix It?
01 public class
02 private static. Random rnd = new Random() ;
03 public static void main(String[] args) {
04 StringBuffer word = null;
05 switch (rnd.nextInt(3)) {
06 case 1: word = new StringBuffer("P");
break;
7 (۱۲) ده 51100۶۶ ۵7 < ۰.010 ۰ :2 وه 07
break;
08 default: word = new StringBuffer ("M") ;
break;
09 ۱
10 word.append('a!');
11 word.append('i');
12 word.append('n') ;
13 System.out.println (word) ;
14 }
15 }
صفحه 131:
ee oS:
The Moral
¢ Use common idioms
— If you must stray, consult the documentation
¢ Chars are not strings; they’re more like ints
۰ Always remember breaks in switch
statement
¢ Watch out for fence-post errors
Watch out for sneaky puzzlers
صفحه 132:
متسس
23. “The Name Game”
01 public class NameGame {
02 public static void main(String args[]) {
03 Map m = new IdentityHashMap () ;
04 m.put ("Mickey", "Mouse") ;
05 m.put ("Mickey", "Mantle") ;
06 System.out.println (m.size()) ;
07 }
os }
صفحه 133:
What Does It Print?
(a) 0
(b) 1
(c) 2
(d) It varies
صفحه 134:
ee oS:
What Does It Print?
(a) 0
(b) 1
(c) 2
(d) It varies
We’re using an IdentityHashMap, but
string
literals are interned (they cancel each
other Sut) 7
صفحه 135:
ee oS:
Another Look
01 public class NameGame {
02 public static void main(String args[]) {
03 Map m = new IdentityHashMap () ;
04 m.put("Mickey", "Mouse") ;
05 m.put("Mickey", "Mantle") ;
06 System.out.println (m.size()) ;
07 }
os }
صفحه 136:
متسس
How Do You Fix It?
01 public class NameGame {
02 public static void main(String args[]) {
03 Map m = new HashMap () ;
04 m.put ("Mickey", "Mouse") ;
05 m.put ("Mickey", "Mantle") ;
06 System.out.println (m.size()) ;
07 }
os }
صفحه 137:
متسس
The Moral
IdentityHashMap not a general-purpose
Map
— Don’t use it unless you know it’s what
you want
— Uses identity in place of equality
— Useful for topology-preserving
transformations
e (String literals are interned)
صفحه 138:
ee oS:
24. “More of The Same”
01 public class Names {
02 private Map m = new HashMap();
03 public void Names() {
04 m.put("Mickey", "Mouse") ;
05 m.put ("Mickey", "Mantle") ;
06 }
07
08 public int size() { return m.size(); }
09
10 public static void main(String args[]) {
11 Names names = new Names() ;
12 System. out.printin(names.size());
13 }
14 }
صفحه 139:
What Does It Print?
(a) 0
(b) 1
(c) 2
(d) It varies
صفحه 140:
ne oS”
What Does It Print?
(a) 0
)0( 1
(c) 2
(d) It varies
No programmer-defined constructor
صفحه 141:
ee oS:
Another Look
01 public class Names {
02 private Map m = new HashMap () ;
03 public void Names() { // Not a constructor!
04 m.put("Mickey", "Mouse") ;
05 m.put("Mickey", "Mantle") ;
06 ۱
07
08 public int 9126) { return m.size(); }
09
10 public static void main(String args[]) {
11 Names names = new Names(); // Invokes
default!
12 System. out.printin (names.size());
13 }
14 }
صفحه 142:
متسس
How Do You Fix It?
01 public class Names {
02 private Map m = new HashMap () ;
03 public Names() { // No return type
04 m.put("Mickey", "Mouse") ;
05 m.put("Mickey", "Mantle") ;
06 ۱
07
08 public int 9126) { return m.size(); }
09
10 public static void main(String args[]) {
11 Names names = new Names () ;
12 System. out.printin (names.size());
13 ۱
14 (
صفحه 143:
ee oS:
The Moral
e It is possible for a method to have
the same name as a constructor
¢ Don’t ever do it
¢ Obey naming conventions
—field, method(), Class, CONSTANT
صفحه 144:
0011 الس م
25. “Shades of Gray”
01 public class Gray {
02 public static void main(String[] args) {
03 System. out.println(X.Y.2Z);
04 }
05 }
06
07 class X {
08 static class Y {
09 static String Z = "Black";
10 }
11 static C Y = new C();
12 }
13
14 class C {
15 String Z = "White";
16 }
Thanks to Prof. Dominik Gruntz, Fachhochschule Aargau
صفحه 145:
re oS.
What Does It Print?
(a) Black
(b) White
(c) Won't compile
(d) None of the above
صفحه 146:
ee oS:
What Does It Print?
(a) Black
(b) White
(c) Won't compile
(d) None of the above
Field y obscures member class ۶ (JLS
6.3.2)
The rule: variable > type > package
صفحه 147:
ددع _-«۰۰۰«۰ب۹_!
Another Look
01 public class Gray {
02 public static void main(String[] args) {
03 System. out.println(X.Y.Z);
04 }
05 }
06
07 class X {
08 static class Y {
09 static String Z = "Black";
10 }
11 static C Y = new C();
12 }
13
14 class C {
15 String Z = "White";
16 }
The rule: variable > type > package
صفحه 148:
متسس
How Do You Fix It?
01 public class Gray {
02 public static void main(String[] args) {
03 System. out .println(Ex.Why. z) ;
04 }
05 }
06
07 class Ex {
08 static class Why {
09 static String z = "Black";
10 }
11 static See y = new See();
12 }
13
14 class See {
15 String z = "White";
16 }
صفحه 149:
ee oS:
The Moral
¢ Obey naming conventions
—field, method(), Class, CONSTANT
— Single-letter uppercase names reserved
for type variables (new in J2SE 1.5)
e Avoid name reuse, except overriding
— Overloading, shadowing, hiding, obscuring
صفحه 150:
ص۳۳
“It’s Elementary” .26
01 public class Elementary {
02 public static void main(String[] args) {
03 System.out.printin (54321 + 54321);
04 ۱
05 }
صفحه 151:
re oS.
What Does It Print?
(a) -22430
(b) 59753
(c) 10864
(d) 108642
صفحه 152:
re oS.
What Does It Print?
(a) -22430
(b) 59753
(c) 10864
(d) 108642
Program doesn’t say what you think it
does!
صفحه 153:
ددع _-«۰۰۰«۰ب۹_!
Another Look
01 public class Elementary {
02 public static void main(String[] args) {
03 System. out.print1n (5432 1 + 54321) -
04 }
05 (
1 - the numeral one
1 - the lowercase letter el
صفحه 154:
متسس
How Do You Fix It?
We won’t insult your intelligence
صفحه 155:
ee oS:
The Moral
¢ Always use uppercase el (1) for long
literals
— Lowercase el makes the code
unreadable
— 54321 is Clearly a long, 54321 is
misleading
e Never use lowercase el aS a variable
name
—Not this: List 1 = new ArrayList ();
—But this: List list = new
ArrayList();
صفحه 156:
ee oS:
27. “Down For The Count”
01 public class Count {
02 public static void main(String[] args) {
03 final int START = 2000000000;
04 int count = 0;
05 for (float f£f = START; ۶ > START + 50; £++)
06 count++;
07 System. out.printl1n (count) ;
08 }
09 (
صفحه 157:
What Does It Print?
(a) 0
(b) 50
(c) 51
(d) None of the above
صفحه 158:
ee oS:
What Does It Print?
(a) 0
(b) 50
(c) 51
(d) None of the above
The termination test misbehaves due
to floating point “granularity.”
صفحه 159:
ee oS:
Another Look
01 public class Count {
02 public static void main(String[] args) {
03 final int START = 2000000000;
04 int count = 0;
05 for (float f = START; f£ < START + 50; £++)
06 count++;
07 System. out.printl1n (count) ;
08 }
09 (
// (float) START == (float) (START + 50)
صفحه 160:
متسس
How Do You Fix It?
01 public class Count {
02 public static void main(String[] args) {
03 final int START = 2000000000;
04 int count = 0;
05 for (int f = START; f < START + 50; £++)
06 count++;
07 System. out.printl1n (count) ;
08 }
09 (
صفحه 161:
0011 الس م
The Moral
٠ Don’t use floating point for loop
indices
e Not every int can be expressed as a
float
e Not every long can be expressed as a
double
e If you must use floating point, use
double
—unless you’re certain that float provides
enough precision and you havea
compelling performance need (space or
صفحه 162:
0011 الس م
28. “Classy Fire”
01 public class Classifier 1
02 public static void main(String[] args) {
03 System.out.print1n (
04 classify('n') + classify('+') + classify('2'));
05 }
06 static String classify(char ch) {
07 if ("0123456789".indexOf(ch) >= 0)
08 return "NUMERAL ";
09 aif ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)
10 return "LETTER ";
11 /* (Operators not supported yet)
12 * if ("+-*/&|!=".indexOf(ch) >= 0)
13 * return "OPERATOR ";
14 7
15 return "UNKNOWN ";
16 }
17 (
صفحه 163:
ee oS:
What Does It Print?
(a) LETTER OPERATOR NUMERAL
(Ob) LETTER UNKNOWN NUMERAL
(c) Throws an exception
(d) None of the above
صفحه 164:
ee oS:
What Does It Print?
(a) LETTER OPERATOR NUMERAL
(Ob) LETTER UNKNOWN NUMERAL
(c) Throws an exception
(d) None of the above
As for the intuition, you'll see ina
moment...
صفحه 165:
ee oS:
Another Look
01 public class Classifier 1
02 public static void main(String[] args) {
03 System.out.print1n (
04 classify('n') + classify('+') + classify('2'));
05 }
06 static String classify(char ch) {
07 if ("0123456789".indexOf(ch) >= 0)
08 return "NUMERAL ";
09 aif ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)
10 return "LETTER ";
11 /* (Operators not supported yet)
12 * if ("+-*/&|!=".indexOf(ch) >= 0)
13 * return "OPERATOR ";
14 7
15 return "UNKNOWN ";
16 }
17 (
صفحه 166:
متسس
How Do You Fix It?
01 public class Classifier 1
02 public static void main(String[] args) {
03 System.out.print1n (
04 classify('n') + classify('+') + classify('2'));
05 }
06 static String classify(char ch) {
07 if ("0123456789".indexOf(ch) >= 0)
08 return "NUMERAL ";
09 aif ("abcdefghijklmnopqrstuvwxyz".indexOf(ch) >= 0)
10 return "LETTER ";
11 if (false) { // (Operators not supported yet)
12 if ("+-*/&|!=".indexOf(ch) >= 0)
13 return "OPERATOR ";
14 }
15 return "UNKNOWN ";
16 }
17 (
صفحه 167:
re oS.
The Moral
¢ You cannot reliably block-comment
out code
—Comments do not nest
e Use “if (false)” idiom or “//”
comments
صفحه 168:
ee 5”
29. “The Joy of Hex”
01 public class JoyOfHex {
02 public static void main(String[] args) {
03 System. out.println(
04 Long. toHexString(0x100000000L +
Oxcafebabe) ) ;
05 }
06 }
صفحه 169:
ee oS:
What Does It Print?
(a) cafebabe
(b) lcafebabe
)6( ۶۶۶۶ ۶۶ ۶ ۶ ۰2۴ هطدطه
(d) Throws an exception
صفحه 170:
ee oS:
What Does It Print?
(a) cafebabe
(b) lcafebabe
)6( ۶۶۶۶ ۶۶ ۶ ۶ ۰2۴ هطدطه
(d) Throws an exception
Oxcafebabe is a negative number
صفحه 171:
ee oS:
Another Look
01 public class JoyOfHex {
02 public static void main(String[] args) {
03 System. out.println(
04 Long. toHexString(0x100000000L +
Oxcafebabe) ) ;
05 }
06 }
4 4 4 م1 4
OxffffffffcafebabeL
+ 026000000010 ب00000001
0x00000000cafebabeL
صفحه 172:
متسس
How Do You Fix It?
01 public class JoyOfHex {
02 public static void main(String[] args) {
03 System. out.println(
04 Long. toHexString(0x100000000L + OxcafebabeL) ) ;
05 }
06 }
صفحه 173:
ee oS:
The Moral
° Decimal literals are all positive; not
so for hex
> Negative decimal constants have minus
sign
> Hex literals are negative if the high-order
bit is set
» Widening conversion can cause sign
extension
e Mixed-mode arithmetic is tricky—
avoid it
صفحه 174:
متسس
30. “Animal Farm”
01 public class AnimalFarm {
02 public static void main(String[] args) {
03 final String pig = "length: 10";
04 final String dog = "length: "+pig.length() ;
05 System.out.printin("Animals are equal: "
06 + pig == dog);
(07 }
08 (
صفحه 175:
ee oS:
What Does It Print?
(a) Animals are equal: true
(0) Animals are equal: false
(c) It varies
(d) None of the above
صفحه 176:
ee oS:
What Does It Print?
(a) Animals are equal: true
(0) Animals are equal: false
(c) It varies
(d) None of the above: false
The + operator binds tighter than ==
صفحه 177:
ee oS:
Another Look
01 public class AnimalFarm {
02 public static void main(String[] args) {
03 final String pig = "length: 10";
04 final String dog = "length: "+pig.length() ;
05 System.out.println("Animals are equal: "
06 + pig == dog);
07 ۱
os }
System.out.printin(
("Animals are equal:
+ pig) == dog);
صفحه 178:
متسس
How Do You Fix It?
01 public class AnimalFarm {
02 public static void main(String[] args) {
03 final String pig = "length: 10";
04 final String dog = "length: "+pig.length() ;
05 System.out.printin("Animals are equal: "
06 + (pig == dog));
07 ۱
08 (
صفحه 179:
ee oS:
The Moral
¢ Parenthesize when using string
concatenation
- Spacing can be deceptive; parentheses
never lie
¢ Don’t depend on interning of string
constants
° Use equals, not ==, for strings
صفحه 180:
ص۳۳
“A Tricky Assignment” .31
01 public class Assignment {
02 public static void main(String[] a) throws Exception {
03 int tricky = 0;
04 for (int i = 0; i < 3; itt)
05 tricky += tricky++;
06 System. out.println (tricky) ;
07 }
08 }
صفحه 181:
What Does It Print?
(a) 0
(b) 3
(c) 14
(d) None of the above
صفحه 182:
ee oS:
What Does It Print?
(a) 0
(b) 3
(c) 14
(d) None of the above
Operands are evaluated left to right.
Postfix increment returns old value.
صفحه 183:
ee oS:
Another Look
01 public class Assignment {
02 public static void main(String[] a) throws Exception {
03 int tricky = 0;
04 for (int i = 0; i < 3; itt)
05 tricky += tricky++;
06 System. out.println (tricky) ;
07 }
08 }
صفحه 184:
Another Look
01 public class ignment {
02 public sta > void main(String[] a) throws Exception {
3 aint tr. y= 0;
04 for (int i = 0; i < 3; i++)
05 tricky += tricky++;
06 System. out.println (tricky) ;
07 }
08 }
صفحه 185:
Another Look
05 tricky += tricky++;
(0) (tricky == 0)
صفحه 186:
Another Look
05 tricky += trickyt++;
(0) (tricky == 0)
صفحه 187:
Another Look
05 tricky += tricky++;
0 0 (tricky == 1)
صفحه 188:
Another Look
05 tricky += tricky++;
0 0 (tricky == 1)
صفحه 189:
Another Look
05 tricky += tricky++;
0 0 (tricky == 0)
صفحه 190:
ee oS:
Another Look
01 public class Assignment {
02 public static void main(String[] a) throws Exception {
03 int tricky = 0;
04 for (int i = 0; i < 3; itt)
05 tricky += tricky++;
06 System. out.println (tricky) ;
07 }
08 }
صفحه 191:
متسس
How Do You Fix It?
01 public class Assignment {
02 public static void main(String[] a) throws Exception {
03 int tricky = 0;
04 for (int i = 0; i < 3; itt) {
05 tricky++;
06 tricky += tricky; // or tricky *= 2;
07 }
08 System. out.println (tricky) ;
09 }
10 }
صفحه 192:
متسس
The Moral
۰ Don’t depend on details of expression
evaluation
۰ Don’t assign to a variable twice in
one expression
٠ Postfix increment returns old value
« (Operands are evaluated left to right)
صفحه 193:
متسس
32. “Thrown for a Loop”
01 public class Loop {
02 public static void main(String[] args) {
03 int[][] tests = ) { 6, 5, 4, 3, 2, 1}, { 1, 2 },
04 { رن 2, 3 Fe { Lp 2, 3p A Jy
) 1 (١ ۶
05 int successCount = 0;
06 try 4
O7 int i=0;
os while (true) {
09 if (thirdElementIsThree(tests[i++]))
10 successCount++;
11 }
12 } catch (ArrayIndexOutOfBoundsException e) { }
1.3) System. out.println(successCount) ;
14 }
15 private static boolean thirdElementIsThree(int[] a) {
16 return a.length >= 3 & a[2] == 3;
17 }
18 }
صفحه 194:
What Does It Print?
(a) 0
(b) 1
(c) 2
(d) None of the above
صفحه 195:
ee oS:
What Does It Print?
(a) 0
(b) 1
(c) 2
(d) None of the above
Not only is the program repulsive, but it has a
bug
صفحه 196:
ee oS:
Another Look
01 public class Loop {
02 public static void main(String[] args) {
03 int[][] tests = ) { 6, 5, 4, 3, 2, 1}, { 1, 2 },
04 { رن 2, 3 Fe { Lp 2, 3p A Jy
) 1 (١ ۶
05 int successCount = 0;
06 try 4
O7 int i=0;
os while (true) {
09 if (thirdElementIsThree(tests[i++]))
10 successCount++;
11 }
12 } catch (ArrayIndexOutOfBoundsException e) { }
1.3) System. out .println(successCount) ;
14 }
15 private static boolean thirdElementIsThree(int[] a) {
16 return a.length >= 3 & a[2] == 3;
17 }
18 }
صفحه 197:
متسس
How Do You Fix It?
01 public class Loop {
02 public static void main(String[] args) {
03 int[][] tests = ) { 6, 5, 4, 3, 2,1}, { 1, 2},
04 {1, 2,3}, (1, 2, 3,4}, {1343
05 int successCount = 0;
06 for (int[] test : tests)
07 if (thirdElementIsThree (test) )
08 successCount++;
09 System. out.println(successCount) ;
10 }
11
12 private static boolean thirdElementIsThree(int[] a) {
13 return a.length >= 3 && a[2] == 3;
14 }
15 }
صفحه 198:
ee oS:
The Moral
° Use exceptions only for exceptional
conditions
> Never use exceptions for normal
control flow
٠ Beware the logical AND and OR
operators
> Document all intentional uses of « and |
On boolean
صفحه 199:
متسس
“Sum Fun” .33
01 class Cache {
02 static { initIfNecessary(); }
03 private static int sum;
04 public static int getSum() {
05 initIfNecessary () ;
06 return sum;
07 }
08 private static boolean initialized = false;
09 private static synchronized void initIfNecessary() {
10 if (!initialized) {
11 for (int i = 0; i < 100; i++)
12 sum +=
13 initialized = true;
14 }
15 }
16 public static void main(String[] args) {
17 System. out.println(getSum() ) ;
18 }
19 }
صفحه 200:
re oS.
What Does It Print?
(a) 4950
(b) 5050
(c) 9900
(d) None of the above
صفحه 201:
re oS.
What Does It Print?
(a) 4950
(b) 5050
(c) 9900
(d) None of the above
Lazy initialization + eager initialization = a
mess
صفحه 202:
ee oS:
Another Look
01 class Cache {
02 static { initIfNecessary(); }
03 private static int sum;
04 public static int getSum() {
: () 7ت 2116655 12111 05
06 return sum;
07 }
08 private static boolean initialized = false;
09 private static synchronized void initIfNecessary() {
10 if (!initialized) {
11 for (int i i < 100; i++)
12 sum += i;
13 initialized = true;
14 }
15 }
16 public static void main(String[] args) {
17 System. out.printin (getSum());
18 }
19 }
صفحه 203:
ee oS:
Another Look
01 class Cache {
02 static { initIfNecessary(); }
03 private static int sum;
04 public static int getSum() {
: () 7ت 2116655 12111 05
06 return sum;
07 }
08 private static boolean initialized = false; // Ouch!
09 private static synchronized void initIfNecessary() {
10 if (!initialized) {
11 for (int i i < 100; i++)
12 sum += i;
13 initialized = true;
14 }
15 }
16 public static void main(String[] args) {
17 System. out.printin (getSum());
18 }
19 }
صفحه 204:
متسس
How Do You Fix It?
01 class Cache {
02 private static final int SUM = computeSum() ;
03
04 private static int computeSum() {
05 int result = 0;
06 for (int i = 0; i < 100; i++)
07 result += 1;
os return result;
09 }
10
11 public static int getSum() {
12 return SUM;
13 }
14
15 public static void main(String[] args) {
16 System. out.println(getSum() ) ;
L7 }
18 }
صفحه 205:
ee oS:
The Moral
¢ Use eager or lazy initialization, not
both
> Prefer eager initialization to lazy
e Think about class initialization
٠ Avoid complex class initialization
sequences
صفحه 206:
ee 5”
34. “The Mod Squad”
01 public class Mod {
02 public static void main(String[] args) {
03 final int MODULUS = 3;
04 int[] histogram = new int [MODULUS] ;
05
06 int i= Integer .MIN_ VALUE;
07 // This loop iterates over all int values
os do {
09 histogram[Math.abs(i) % MODULUS]++;
10 } while (i++ != Integer.MAX VALUE) ;
11
12 for (int j = 0; j < MODULUS; j++)
13 System.out.print (histogram[j] + " ");
14 }
15 }
صفحه 207:
متسس
What Does It Print?
(a) 1431655765 1431655765
1431655765
(b) 1431655765 1431655766
1431655765
(c) Throws an exception
(d) None of the above
Hint: (23?/ 30= 1,431,655,765
صفحه 208:
متسس
What Does It Print?
(a) 1431655765 1431655765
1431655765
(b) 1431655765 1431655766
1431655765
(c) Throws an exception: array out of
bounds
(d) None of the above
Math.abs doesn’t always return a nonnegative
صفحه 209:
ee oS:
Another Look
01 public class Mod {
02 public static void main(String[] args) {
03 final int MODULUS = 3;
04 int[] histogram = new int [MODULUS] ;
05
06 int i= Integer .MIN_ VALUE;
07 // This loop iterates over all int values
os do {
09 histogram[Math.abs(i) % MODULUS]++;
10 } while (i++ != Integer.MAX VALUE) ;
11
12 for (int j = 0; j < MODULUS; j++)
13 System.out.println(histogram[j] +" ");
14 }
15 }
صفحه 210:
متسس
How Do You Fix It?
Replace:
histogram[Math.abs(i) % MODULUS]++;
With:
histogram[mod(i, MODULUS) ]++;
private static int mod(int i, int modulus) {
int result = i % modulus;
return result < 0 ? result + modulus : result;
صفحه 211:
ee oS:
The Moral
٠ Math.abs can return a negative value
٠ Two’s-complement integers are
asymmetric
* int arithmetic overflows silently
۰ ۲۱۵۵ ه ۶ (1) وطد . 121 ۶۶ در
صفحه 212:
oS!
35. “Package Deal”
01 package click;
02 public class CodeTalk {
03 public void doIt() { printMessage(); }
04 void printMessage() { System.out.println("Click"); }
05 (
01 package hack;
02 import click.CodeTalk;
03 public class TypelIt 1
04 private static class ClickIt extends CodeTalk ۲
05 void printMessage()
{ System.out.println("Hack"); }
06 }
07 public static void main(String[] args) {
os new ClickIt() .doIt();
09 }
صفحه 213:
re oS.
What Does It Print?
(a) Click
(b) Hack
(c) Won't compile
(d) None of the above
صفحه 214:
ee oS:
What Does It Print?
(a) Click
(b) Hack
(c) Won't compile
(d) None of the above
There is no overriding in this program
صفحه 215:
ee oS:
Another Look
01 package click;
02 public class CodeTalk {
03 public void doIt() { printMessage(); }
04 void printMessage() { System.out.println("Click"); }
05 (
01 package hack;
02 import click.CodeTalk;
03 public class TypelIt 1
04 private static class ClickIt extends CodeTalk ۲
05 void printMessage()
{ System.out.println("Hack"); }
06 }
07 public static void main(String[] args) {
os new ClickIt() .doIt();
09 }
صفحه 216:
متسس
How Do You Fix It?
° If you want overriding
° Make printMessage public or protected
- Use @Override to ensure that you got
overriding
صفحه 217:
ee oS:
The Moral
٠ Package-private methods can’t be
overridden by methods outside their
package
° If you can’t see it, you can’t
override it
صفحه 218:
متسس
36. “Lazy Initialization”
01 public class Lazy {
02 private static boolean initialized = false;
03 static {
04 Thread t = new Thread(new Runnable() {
05 public void run() {
06 initialized = true;
07 }
08 he
09 t. start();
10 try {
11 t.join();
12 } catch (InterruptedException e) ]
13 throw new AssertionError(e) ;
14 }
15 }
16 public static void main(String[] args) {
17 System. out.println (initialized) ;
18 }
19 }
صفحه 219:
re oS.
What Does It Print?
(a) true
(b) false
(c) It varies
(d) None of the above
صفحه 220:
ee oS:
What Does It Print?
(a) true
(b) false
(c) It varies
(d) None of the above: it deadlocks
Intuition: You wouldn't believe us if we told
you.
صفحه 221:
ee oS:
Another Look
01 public class Lazy {
02 private static boolean initialized = false;
03 static {
04 Thread t = new Thread(new Runnable() {
05 public void run() {
06 initialized = true; // Deadlocks here!
07 }
08 he
09 t. start();
10 try {
11 t.join();
12 } catch (InterruptedException e) ]
13 throw new AssertionError(e) ;
14 }
15 }
16 public static void main(String[] args) {
17 System. out.println (initialized) ;
18 }
19 }
صفحه 222:
متسس
How Do You Fix It?
¢ Don’t use background threads in class
initialization
> If it hurts when you go like that, don’t go
like that!
صفحه 223:
ee oS:
The Moral
¢ Never use background threads in class
initialization
° Keep class initialization simple
¢ Don’t code like my brother
صفحه 224:
متسس
“Odd Behavior” .37
01 public class OddBehavior {
02 public static void main(String[] args) {
03 List<Integer> list = Arrays.asList(-2, -1, 0, 1, 2);
04
05 boolean foundOdd = false;
06 for (Iterator<Integer> it=list.iterator();it.hasNext(); )
07 foundOdd = foundOdd || isOdd(it.next());
08
09 System. out .println (found0dd) ;
10 }
11
182 private static boolean isOdd(int i) {
13 return (i & 1) != 0;
14 }
صفحه 225:
ee oS:
What Does It Print?
01 public class OddBehavior {
02 public static void main(String[] args) {
03 List<Integer> list = Arrays.asList(-2, -1, 0, 1, 2);
04
05 boolean foundOdd = false;
06 for (Iterator<Integer> it=list.iterator(); it.hasNext(); )
07 foundOdd = foundOdd || isOdd(it.next());
08
09 System. out .println (found0dd) ;
10 }
11
182 private static boolean isOdd(int i) {
13 return (i & 1) != 0; (a) true
14 }
15 } (b) false
(c) Throws exception
(d) None of the above
صفحه 226:
متسس
What Does It Print?
(a) true
(b) false
(c) Throws exception
(d) None of the above: Nothing—
Infinite loop
Conditional OR operator (| |) short-
circuits iterator
صفحه 227:
ee oS:
Another Look
public class OddBehavior {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(-2, -1, 0, 1, 2);
boolean foundOdd = false;
for (Iterator<Integer> it = list.iterator(); it.hasNext();
foundOdd = foundOdd || isOdd(it.next());
System. out .print1n (foundodd) ;
}
private static boolean isOdd(int i) {
return (i & 1) != 0;
}
صفحه 228:
a پ ده
You Could Fix it Like This....
public class OddBehavior {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(-2, -1, 0, 1, 2);
boolean foundOdd = false;
for (int i : list)
foundOdd = foundOdd || isOdd(i);
System. out.println (foundOdd) ;
}
private static boolean isOdd(int i) {
return (i & 1) != 0;
1
صفحه 229:
ee oS:
...But This Is Even Better
public class OddBehavior {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(-2, -1, 0, 1, 2);
System. out.println(contains0dd(list));
}
private static boolean contains0dd(List<Integer> list) {
for (int i: list)
if (isOdd(i))
return true;
return false;
}
private static boolean isOdd(int i) {
return (i & 1) != 0;
1
صفحه 230:
oS!
The Moral
¢ Use for-each wherever possible
> Nicer and safer than explicit iterator or
index usage
- If you must use an iterator, make
sure you Call next () exactly once
٠ Conditional operators evaluate their
right operand only if necessary to
determine result
> This is almost always what you want
Ss lf not voir can ica tha حم ارم مها
صفحه 231:
متسس
List” .38
public class SetList {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<Integer>() ;
List<Integer> list = new ArrayList<Integer>() ;
for (int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
for (int i = 0; i <3; i++) {
set. remove (i) ;
list. remove (i) ;
1
System.out.println(set + " " + list);
صفحه 232:
ee ده
]1= رفح رقع زد رهد ردت رقع
What Does It Print? [52 2 11د ۵ ۵, 2(
(c) Throws exception
(d) None of the above
public class SetList {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<Integer>() ;
List<Integer> list = new ArrayList<Integer>() ;
for (int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
for (int i = 0; i <3; i++) {
set. remove (i) ;
list. remove (i) ;
1
System.out.println(set + " " + list);
صفحه 233:
ee oS:
What Does It Print?
(a) [-3, -2, -1] [-3, -2, -1]
(b) [-3, -2, -1] [-2, 0, 2]
(c) Throws exception
(d) None of the above
Autoboxing + overloading = confusion
صفحه 234:
ee oS:
Another Look
public class SetList {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<Integer>() ;
List<Integer> list = new ArrayList<Integer>() ;
for (int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
for (int i = 0; i <3; i++) {
set. remove (i) ;
list.remove(i); // List.remove (int)
1
System.out.println(set + " " + list);
صفحه 235:
متسس
How Do You Fix It?
public class SetList {
public static void main(String[] args) {
Set<Integer> set = new LinkedHashSet<Integer>() ;
List<Integer> list = new ArrayList<Integer>() ;
for (int i = -3; i < 3; i++) {
set.add(i);
list.add(i);
for (int i = 0; i <3; i++) {
set. remove (i) ;
list.remove((Integer) i);
1
System.out.println(set + " " + list);
صفحه 236:
ee oS:
The Moral
¢ Avoid ambiguous overloadings
¢ Harder to avoid in release 5.0
> Autoboxing, varargs, generics
° Design new APIs with this in mind
> Old rules no longer suffice
° Luckily, few existing APIs were
compromised
> Beware List<Integer>
صفحه 237:
متسس
39. “Powers of Ten”
public enum PowerOfTen {
ONE (1), TEN(10),
HUNDRED (100) {
@Override public String toString() {
return Integer.toString (val) ;
}
1۶
private final int val;
PowerOfTen(int val) { this.val = val; }
@Override public String toString() {
return name() .toLowerCase() ;
}
public static void main(String[] args) {
System.out.println(ONE + " " + TEN + " " + HUNDRED) ;
1
صفحه 238:
متسس
What Does It Print? (a) ONE TEN HUNDRED
(b) one ten hundred
public enum PowerOfTen { (c) one ten 100
ONE (1), TEN(10),
HUNDRED (100) { (d) None of the above
@override public String toString )
return Integer.toString (val) ;
}
1۶
private final int val;
PowerOfTen(int val) { this.val = val; }
@Override public String toString() {
return name() .toLowerCase() ;
}
public static void main(String[] args) {
System.out.println(ONE + " " + TEN + " " + HUNDRED) ;
1
صفحه 239:
متسس
What Does It Print?
(a) ONE TEN HUNDRED
(b) one ten hundred
(c) one ten 100
(d) None of the above: Won't compile
Non-static variable val can’t be referenced from static context
return Integer.toString(val) ;
A
Private members are never inherited
صفحه 240:
متسس
Another Look
public enum PowerOfTen {
ONE (1), TEN(10),
HUNDRED (100) { // Creates static anonymous class
@Override public String toString() {
return Integer.toString(val) ;
}
1۶
private final int val;
PowerOfTen(int val) { this.val = val; }
@Override public String toString() {
return name() .toLowerCase() ;
}
public static void main(String[] args) {
System.out.println(ONE + " " + TEN + " " + HUNDRED) ;
1
صفحه 241:
متسس
How Do You Fix It?
public enum PowerOfTen {
ONE (1), TEN(10),
HUNDRED (100) {
@Override public String toString() {
return Integer. toString(super.val) ;
}
1۶
private final int val;
PowerOfTen(int val) { this.val = val; }
@Override public String toString() {
return name() .toLowerCase() ;
}
public static void main(String[] args) {
System.out.println(ONE + " " + TEN + " " + HUNDRED) ;
1
صفحه 242:
متسس
The Moral
¢ Nest-mates can use each others’ private
members
¢ But private members are never inherited
° Constant-specific enum bodies define static
anonymous classes
* Compiler diagnostics can be confusing
صفحه 243:
oS!
40. “Testy Behavior’
import java.lang.reflect.*;
@interface Test { }
public class Testy {
@Test public static void test () { return; }
@Test public static void test2() { new RuntimeException(); }
public static void main(String[] args) throws Exception {
for (Method m : Testy.class.getDeclaredMethods()) {
if (m.isAnnotationPresent (Test.class)) {
try {
m.invoke (null) ;
System.out.print("Pass ");
} catch (Throwable ex) {
System.out.print ("Fail ");
}
صفحه 244:
What Does It Print? (a) Pass Fail
(b) Pass Pass
import java.lang.reflect.*; (c) It varies
@interface Test { } (d) None of the above
public class Testy {
@Test public static void test () { return; }
@Test public static void test2() { new RuntimeException(); }
public static void main(String[] args) throws Exception {
for (Method m : Testy.class.getDeclaredMethods()) {
if (m.isAnnotationPresent (Test.class)) {
try {
m.invoke (null) ;
System.out.print("Pass ");
} catch (Throwable ex) {
System.out.print ("Fail ");
}
صفحه 245:
ee oS:
What Does It Print?
(a) Pass Fail
(b) Pass Pass
(c) It varies
(d) None of the above: In fact,
nothing!
The program contains two bugs, both
subtle
صفحه 246:
ee oS:
Another Look
import java.lang.reflect.*;
@interface Test { } // By default, annotations are discarded at runtime
public class Testy {
@Test public static void test() { return; +
@Test public static void test2() { new RuntimeException(); }
public static void main(string[] args) throws Exception {
for (Method m : Testy.class.getDeclaredMethods()) {
if (m.isAnnotationPresent (Test.class)) {
try {
m. invoke (null) ;
System. out.print ("Pass") ;
} catch (Throwable ex) {
System. out.print ("Fail ");
// Oops !
۱
صفحه 247:
متسس
How Do You Fix It?
import java.lang.reflect.*;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @interface Test { }
public class Testy {
@Test public static void test() { return; 1
@Test public static void test2() { throw new RuntimeException(); }
public static void main(String[] args) throws Exception {
for (Method m : Testy.class.getDeclaredMethods()) {
if (m.isAnnotationPresent (Test.class)) {
try {
m. invoke (null) ;
System.out.print ("Pass ");
} catch (Throwable ex) {
System.out.print ("Fail "
۱
صفحه 248:
ee oS:
The Moral
° By default, annotations are discarded
at runtime
> If you need annotations at runtime, use
@Retention (RetentionPolicy .RUNTIME
)
> If you want them omitted from class file,
use
@Retention (RetentionPolicy . SOURCE)
٠ No guarantee on order of reflected
entities
صفحه 249:
oS!
41. “What the Bleep?”
public class Bleep {
String name = "Bleep";
void setName(String name) {
this.name = name;
void backgroundSetName() throws InterruptedException {
Thread t = new Thread() {
@Override public void run() { setName("Blat"); }
te
t.start();
t.join();
System. out.print1n(name) ;
}
public static void main(String[] args) throws InterruptedException
{
new Bleep() .backgroundSetName() ;
}
صفحه 250:
ee oS:
What Does It Print? laynicep
public class Bleep { (b) Blat
String name = "Bleep"; 3
void setName(String name) { (c) It varies
this.name = name; (d) None of the above
void backgroundSetName() throws InterruptedException {
Thread t = new Thread() {
@Override public void run() { setName("Blat"); }
te
t.start();
t.join();
System. out.print1n(name) ;
}
public static void main(String[] args) throws InterruptedException
{
new Bleep() .backgroundSetName() ;
}
صفحه 251:
متسس
What Does It Print?
(a) Bleep
(b) Blat
(c) It varies
(d) None of the above
Bleep.setName isn't getting called
صفحه 252:
متسس
Another Look
public class Bleep {
String name = "Bleep";
void setName(String name) { // Does this look familiar?
this.name = name;
void backgroundSetName() throws InterruptedException {
Thread t = new Thread() {
// Invokes Thread.setName (shadowing)
@Override public void run() { setName("Blat"); }
te
t.start();
t.join();
System. out.print1n(name) ;
}
public static void main(String[] args) throws InterruptedException
{
new Bleep() .backgroundSetName() ;
صفحه 253:
متسس
How Do You Fix It?
public class Bleep {
String name = "Bleep";
void setName(String name) {
this.name = name;
void backgroundSetName() throws InterruptedException {
Thread t = new Thread(new Runnable() {
public void run() { setName("Blat"); }
21
t.start();
t.join();
System. out.print1n(name) ;
1
public static void main(String[] args) throws InterruptedException
new Bleep() .backgroundSetName() ;
صفحه 254:
ee oS:
The Moral
e Don't extend Thread
> Use new Thread (Runnable) instead
۰ Often the Executor Framework is
better still
> Much more flexible
> See java.util.concurrent for more
information
* Beware of shadowing
صفحه 255:
000 SN
42. “Beyond Compare”
public class BeyondCompare {
public static void main(String[] args) {
Object o = new Integer (3);
System. out.println(new Double(3).compareTo(o) == 0);
صفحه 256:
ددع _-«۰۰۰«۰ب۹_!
What Does It Print?
public class BeyondCompare {
public static void main(String[] args) {
Object o = new Integer (3);
System. out.println(new Double(3).compareTo(o) == 0);
(a) true
(b) false
(c) Throws exception
(d) None of the above
صفحه 257:
متسس
What Does It Print?
(a) true
(b) false
(c) Throws exception
(d) None of the above: Won't compile (it did in 1.4)
compareTo(Double) in Double cannot be applied to (Object)
System.out.println(new Double(3).compareTo(o) == 0);
A
The Comparable interface was generified in 5.0
صفحه 258:
متسس
Another Look
public class BeyondCompare {
public static void main(String[] args) {
Object o = new Integer (3);
System. out.println(new Double(3).compareTo(o) == 0);
}
// Interface Comparable was generified in release 5.0
public interface Comparable<T> {
int compareTo(T t); // Was Object
1
public class Double extends Number
implements Comparable<Double>
صفحه 259:
متسس
How Do You Fix It?
// Preserves 1.4 semantics
public class BeyondCompare {
public static void main(String[] args) {
Object o = new Integer (3);
System. out. println(
new Double (3) .compareTo( (Double) 0) == 0);
// Fixes the underlying problem
public class BeyondCompare {
public static void main(String[] args) {
Double d = 3.0;
System. out.println (Double.valueOf (3) .compareTo(d) == 0);
صفحه 260:
متسس
The Moral
¢ Binary compatibility is preserved at all costs
* Source compatibility broken for good cause
(rare)
* Comparable<T> alerts you to errors at compile
time
* Take compiler diagnostics seriously
> Often there is an underlying problem
صفحه 261:
ee 5”
43. “Fib O’Nacci”
public class Fibonacci {
private static final int LENGTH = 7;
public static void main(String[] args) {
int[] fib = new int[LENGTH] ;
f£ib[0] = fib[1] =1; // First 2 Fibonacci numbers
for (int i = 2; i < LENGTH; i++)
fib[i] = fib[i - 2] + fib[i - 1];
System. out.println (Arrays.asList (fib) );
صفحه 262:
ee oS:
What Does It Print?
public class Fibonacci {
private static final int LENGTH = 7;
public static void main(String[] args) {
int[] fib = new int[LENGTH] ;
f£ib[0] = fib[1] =1; // First 2 Fibonacci numbers
for (int i = 2; i < LENGTH; i++)
fib[i] = fib[i - 2] + fib[i - 1];
System. out.println (Arrays.asList (fib) );
(a) [1,4 ,.2, 3, 5, آله
(b) Throws exception
(c) It varies
(d) None of the above
صفحه 263:
ee oS:
What Does It Print?
(a) [1, 1, 2, 3, 5, 8, 13]
(b) Throws exception
(c) It varies: Depends on hashcode
[[I@ad3ba4]
(d) None of the above
Arrays.asList only works on arrays of
object refs
صفحه 264:
ee oS:
Another Look
public class Fibonacci {
private static final int LENGTH = 7;
public static void main(String[] args) {
int[] fib = new int[LENGTH] ;
f£ib[0] = fib[1] =1; // First 2 Fibonacci numbers
for (int i = 2; i < LENGTH; i++)
fib[i] = fib[i - 2] + fib[i - 1];
// Idiom only works for arrays of object references
System. out.println(Arrays.asList (fib) );
صفحه 265:
متسس
How Do You Fix It?
public class Fibonacci {
private static final int LENGTH = 7;
public static void main(String[] args) {
int[] fib = new int[LENGTH] ;
f£ib[0] = fib[1] =1; // First 2 Fibonacci numbers
for (int i = 2; i < LENGTH; i++)
fib[i] = fib[i - 2] + fib[i - 1];
System. out.println(Arrays.toString(fib));
صفحه 266:
ee oS:
The Moral
¢ Use varargs Sparingly in your APIs
> It can hide errors and cause confusion
> This program wouldn't compile under 1.4
* Arrays.asList printing idiom is
obsolete
> uS@ Arrays. toString instead
> Prettier, safer, and more powerful
۰ A full complement of array utilities
added in 5.0
* equals, hashCode, toString for all array
صفحه 267:
متسس
44. “Parsing Is Such Sweet Sorrow”
public class Parsing {
[kk
* Returns Integer corresponding to s, or null if s is null.
* @throws NumberFormatException if s is nonnull and
* doesn't represent a valid integer
*/
public static Integer parseInt (String s) {
return (s == null) ?
(Integer) null : Integer.parseInt(s) ;
}
public static void main(String[] args) {
System.out.println(parseInt("-1") + " " +
parseInt(null) +" "+
parseInt("1"));
صفحه 268:
متسس
2 (a) -1 null 1
What Does It Print? Tee
public class Parsing { (c) Throws exception
[kk (d) None of the above
* Returns Integer corresponding to s, or nu. 11 s is nu.
* @throws NumberFormatException if s is nonnull and
* doesn't represent a valid integer
*/
public static Integer parseInt (String s) {
return (s == null) ?
(Integer) null : Integer.parseInt(s) ;
}
public static void main(String[] args) {
System.out.println(parseInt("-1") + " " +
parseInt(null) +" "+
parseInt("1"));
صفحه 269:
متسس
What Does It Print?
(a) -1 null 1
)0( -1 0 1
(c) Throws exception:
NullPointerException
(d) None of the above
Program attempts to auto-unbox null
صفحه 270:
ee oS:
Another Look
public class Parsing {
22
* Returns Integer corresponding to s, or null if s is null.
* Qthrows NumberFormatException if s is nonnull and
* doesn't represent a valid integer.
*/
public static Integer parseInt(String s) {
return (s == null) ? // Mixed-type computation: Integer and int
(Integer) null : Integer.parseInt(s) ;
}
public static void main(String[] args) {
System. out.println(parseInt("-1") +" "+
parseInt(null) + " " +
parseInt("1"));
صفحه 271:
متسس
How Do You Fix It?
public class Parsing {
22
* Returns Integer corresponding to s, or null if s is null.
* Qthrows NumberFormatException if s is nonnull and
* doesn't represent a valid integer.
*/
public static Integer parseInt (String s) {
return (s == null) ? null : Integer.valueOf(s);
}
public static void main(String[] args) {
System. out.println(parseInt("-1") +" " +
parseInt(null) +" " +
parseInt("1"));
صفحه 272:
ee oS:
The Moral
¢ Mixed-type computations are
confusing
e Especially true for 2: expressions
¢ Avoid null where possible
e Auto-unboxing and null area
dangerous mix
صفحه 273:
Resources and Summary
solaris ۷
صفحه 274:
ee oS:
Resources
«Send more puzzles
— puzzlers@javapuzzles.com
صفحه 275:
متسس
Conclusion
* Java platform is simple and elegant
- But it has a few sharp corners — avoid
them!
٠ Keep programs simple
- Avoid name reuse: overloading, hiding,
shadowing
: If you aren't sure what a program
does,
it probably doesn't do what you
want it to