Presentation is loading. Please wait.

Presentation is loading. Please wait.

12. Common Errors, a few Puzzles. © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.2 Common Errors, a few Puzzles Sources  Cay Horstmann, Computing.

Similar presentations


Presentation on theme: "12. Common Errors, a few Puzzles. © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.2 Common Errors, a few Puzzles Sources  Cay Horstmann, Computing."— Presentation transcript:

1 12. Common Errors, a few Puzzles

2 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.2 Common Errors, a few Puzzles Sources  Cay Horstmann, Computing Concepts with Java Essentials, Wiley, 1998  The Java Report, April 1999

3 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.3 Roadmap  Common errors … —Typical programming traps  A few Java puzzles... —The darker side of Java

4 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.4 Roadmap  Common errors … —Typical programming traps  A few Java puzzles... —The darker side of Java

5 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.5 Trap 1 What does this print? 25.0 Don’t assume that floating point numbers are exact representations of mathematical values! double f = 2e15 + 0.13; double g = 2e15 + 0.02; println(100*(f-g));

6 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.6 static void test(String name, boolean bool) { println(name + ": " + (bool?"true":"false")); } Trap 2 When are two Strings equal? == tests object identity; equals() tests object equality String s1 = new String("This is a string"); String s2 = new String("This is a string"); test("String==", s1 == s2); test("String.equals", s1.equals(s2)); String==: false String.equals: true

7 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.7 Trap 3 When are two Objects equal? object==: false object.equals: false The default implementation of equals() is ==, and should normally be overwritten Object x = new Object(); Object y = new Object(); test("object==", x == y); test("object.equals", x.equals(y));

8 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.8 Trap 4 When are two Strings equal? String==: true String.equals: true Literal strings with the same content refer to the same object! Always use equals() or compareTo() to compare strings. String s3 = "This is a string"; String s4 = "This is a string"; test("String==", s3 == s4); test("String.equals", s3.equals(s4));

9 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.9 Trap 5 Is “now” really before “later”? see you now Date later = new Date(now.getTime()); Explicitly create a clone if you need one: Calendar now = Calendar.getInstance(); Calendar later = now; later.set(Calendar.HOUR_OF_DAY, 1 + now.get(Calendar.HOUR_OF_DAY)); if (now.before(later)) { println("see you later"); } else { println("see you now"); }

10 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.10 Trap 6  nothing  0 is even 1 is negative static void checkEven(int n) { boolean result = true; if (n>=0) if ((n%2) == 0) println(n + " is even"); else println(n + " is negative"); } What is printed when we run these checks? checkEven(-1); checkEven(0); checkEven(1); Always use braces to group nested if { } else { } statements! if (n>=0) { if ((n%2) == 0) { println(n + " is even"); } else { println(n + " is negative"); }

11 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.11 Trap 7 The binomial coefficient is Is this a correct implementation? binomial(7,3) = 21  35 To avoid off-by-1 errors: 1. Count the iterations — do we always do k multiplications? (no) 2. Check boundary conditions — do we start with n/1 and finish with (n-k+1)/k? (no) Off-by-1 errors are among the most common mistakes in implementing algorithms. static int binomial(int n, int k) { int bc = 1; for (int i=1; i<k; i++) { bc = bc * (n+1-i) / i; } return bc; }

12 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.12 Trap 8 For which values does this function work correctly? brokenFactorial(0) = 1 brokenFactorial(5) = 120 brokenFactorial(-1) =... (doesn’t terminate) Always use an inequality test to terminate a loop. static int brokenFactorial(int n) { int result=1; for (int i=0; i!=n; i++ ) { result = result*(i+1); } return result; }

13 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.13 Some other common errors Magic numbers  Never use magic numbers; declare constants instead. Forgetting to set a variable in some branch  If you have non-trivial control flow to set a variable, make sure it starts off with a reasonable default value. Underestimating size of data sets  Don’t write programs with arbitrary built-in limits (like line-length); they will break when you least expect it. Leaking encapsulation  Never return a private instance variable! (return a clone instead) Bugs are always matter of invalid assumptions not holding

14 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.14 Roadmap  Common errors … —Typical programming traps  A few Java puzzles... —The darker side of Java

15 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.15 Puzzle 1 A.p() Private methods are statically bound. A b = new B(); b.m(); class A { public void m() { this.p(); } private void p() { println("A.p()"); } } class B extends A { private void p() { println("B.p()"); } } Are private methods inherited? Which is called? A.p() or B.p()?

16 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.16 Static and Dynamic Types Consider: The static type of variable a is A — i.e., the statically declared class to which it belongs. The static type never changes. The dynamic type of a is B — i.e., the class of the object currently bound to a. The dynamic type may change throughout the program. Now the dynamic type is also A! A a = new B(); a = new A();

17 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.17 Puzzle 2 (part I) m(A,A) m(A,B) m(B,A) m(B,B) The static type of arguments is always used to resolve overloaded method calls. class A { } class B extends A { } void m(A a1, A a2) { println("m(A,A)"); }; void m(A a1, B b1) { println("m(A,B)"); }; void m(B b1, A a1) { println("m(B,A)"); }; void m(B b1, B b2) { println("m(B,B)"); }; B b = new B(); A a = b; How are overloaded method calls resolved? m(a, a); m(a, b); m(b, a); m(b, b); Which is considered: the static or dynamic argument type?

18 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.18 Puzzle 2 (part II) What happens if we comment out: Will the examples still compile? If so, which methods are called? m(a,a) won’t compile m(b,b) won’t compile Prints: m(A,A) m(B,A) m(B,B) m(A,A)? m(B,B)? m(A,B)?

19 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.19 Puzzle 3 How do static and dynamic types interact? A.m(A) B.m(B) Static types determine which message is sent. Dynamic types determine which method is called. a.m(a); a.m(b); b.m(a); b.m(b); class A { void m(A a) { println("A.m(A)"); } } class B extends A { void m(B b) { println("B.m(B)"); } } B b = new B(); A a = b; In which cases will B.m(B) be called?

20 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.20 Puzzle 4 (part I) C.i = 0 C.j = 0 C.k = 0 C.l = 0 First, default values are assigned... then constructors are evaluated. How do default values and constructors interact? class C { int i = 100, j = 100, k = init(), l = 0; C() { i = 0; k = 0; } int init() { j = 0; l = 100; return 100; } } What gets printed? 0 or 100? C c = new C(); println("C.i = " + c.i); println("C.j = " + c.j); println("C.k = " + c.k); println("C.l = " + c.l);

21 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.21 Puzzle 4 (part II) B.i = 0 B.j = 0 First all super initialization is executed, then the subclass initialization abstract class A { int j = 100; A() { init(100); j = 200; } abstract void init(int value); } class B extends A { int i = 0, j = 0; B() { super(); } void init(int value) { i = value; } } B b = new B(); println("B.i = " + b.i); println("B.j = " + b.j); What gets printed? 0, 100 or 200?

22 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.22 Puzzle 5 The finally clause always takes precedence! 3 Does try or finally return? class A { int m() { try { return 1; } catch (Exception err) { return 2; } finally { return 3; } } Prints 1, 2, or 3? A a = new A(); println(a.m());

23 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.23 What you should know!  When can you trust floating-point arithmetic?  To which “if” does an “else” belong in a nested if statement?  How can you avoid off-by-1 errors?  Why should you never use equality tests to terminate loops?  Are private methods inherited?  What are the static and dynamic types of variables?  How are they used to dispatch overloaded methods?

24 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.24 Can you answer these questions?  When is method dispatching ambiguous?  Is it better to use default values or constructors to initialize variables?  If both a try clause and its finally clause throw an exception, which exception is really thrown?

25 © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.25 License > http://creativecommons.org/licenses/by-sa/2.5/ Attribution-ShareAlike 2.5 You are free: to copy, distribute, display, and perform the work to make derivative works to make commercial use of the work Under the following conditions: Attribution. You must attribute the work in the manner specified by the author or licensor. Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one. For any reuse or distribution, you must make clear to others the license terms of this work. Any of these conditions can be waived if you get permission from the copyright holder. Your fair use and other rights are in no way affected by the above.


Download ppt "12. Common Errors, a few Puzzles. © O. Nierstrasz P2 — Common Errors, a few Puzzles 12.2 Common Errors, a few Puzzles Sources  Cay Horstmann, Computing."

Similar presentations


Ads by Google