Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java Puzzlers Presentation

Joe Rowley
February 22, 2016

Java Puzzlers Presentation

This talk is meant to be a very informal discussion going over a few select puzzles from Joshua Bloch and Neal Gafter's Java Puzzlers book. Very much just a "Did you know..." or "Gee-Whiz" kind of presentation.

The book "Java Puzzlers - Traps, Pitfalls and Corner Cases" is available through Amazon and I highly recommend you order it if you are interested in some of the fine points of Java. (Another must-have, also authored by Joshua Bloch is Effective Java)

There are 95 puzzlers in the book. This talk will go over just a few of those that seemed most useful, interesting or surprising to me.

Joe Rowley

February 22, 2016
Tweet

More Decks by Joe Rowley

Other Decks in Programming

Transcript

  1. Java Puzzlers https://github.com/alphonzo79/JavaPuzzlersTalk (Shamelessly stolen from Java Puzzlers — Traps,

    Pitfalls and Corner Cases by Joshua Bloch and Neal Gafter http://amzn.com/032133678X
  2. Oddity • Java’s % operator satisfies the following
 (a /

    b) * b + (a % b) == a • The result of % will have the same sign as the left argument
  3. Long Division • Java does not have Target Typing •

    Watch out for overflow — it might sneak up on you when you don’t expect it!
  4. In The Loop • “If you need a loop that

    iterates near the boundaries of int values, you are better off using a long variable as the loop index.” • Be aware of the boundary conditions
  5. Looper • Infinity + 1 is still Infinity • double

    i = 1.0 / 0.0; • double i = Double.POSITIVE_INFINITY • ulp — The distance between adjacent floating point values. Unit in Last Place • “Floating-point operations return the floating-point value that is closest to their exact mathematical result. Once the distance between adjacent floating-point values is greater than 2, adding 1 to a floating-point value will have no effect, because the half-way point between values won’t be reached.” • double i = 1.0e40
  6. Bride of Looper • NaN is not equal to any

    floating-point value, including itself — JLS 15.21.1 • double i = 0.0 / 0.0; • double i = Double.NaN; • “Once it generates NaN, a computation is damaged, and no further computation can repair the damage”
  7. Down For the Count • The start value of 2,000,000,000

    is near Integer.MAX_VALUE, which “requires 31 bits to express precisely, and the float type provides only 24 bits of precision.” • You may lose precision when converting an int or a long to a float, or a long to a double. • When you use floating-point, use double rather than float. • Don’t use floating-point loop indices.
  8. Minute By Minute • % takes precedence over multiplication •

    Watch your formatting • Don’t depend on spacing to express groupings — use parenthesis • Replace all magic numbers with appropriately- named constants
  9. Indecision • “In a try/finally block, the finally block is

    always executed when control leaves the try block. This is true whether the try block completes normally or abruptly.” • “Never exit a finally block with a return, break, continue or throw,and never allow a checked exception to propagate out of a finally block.”
  10. Hello Goodbye • “The System.exit method halts the execution of

    the current thread and all others dead in their tracks.” • “Use shutdown hooks for behavior that must occur before the VM exits” • “Never call System.runFinalizersOnExit or Runtime.runFinalizersOnExit for any reason: They are among the most dangerous methods in the Java libraries” and were deprecated long ago.
  11. Exhausting Workout • Finally is called even when unwinding the

    stack after a StackOverflowError. • Looks like a Binary Tree • My VM’s stack overflows somewhere after 11,000 entries • Will finally die after 2 x 1011,000 exceptions. • My VM executes this at about 37,500 per second, or 1,182,600,000,000 per year. This would need to spin for about 1.60 x 101,000 years (if I did my math right, which is dubious). The lifetime of our sun is estimated at 2 x 1010 years! • Not an infinite loop, but it might as well be.
  12. The Confusing Constructor • Java’s Overload Resolution Process: • First,

    selects all methods/constructors that are accessible and applicable • Second, selects the most specific of the methods/constructors selected in the first phase • The test for which method/constructor is most specific does not use the actual parameters • To force one, cast the actual parameters to the declared types of the formal parameters in the method you want • Avoid overloading a method by simply changing one parameter type. Instead use a unique name for the method
  13. All I Get Is Static • Java has no Dynamic

    Dispatch for static methods • Never qualify a static method invocation with an expression • Do not hide static methods
  14. Larger Than Life • Be careful of class initialization cycles

    • Static fields are initialized to their defaults • Static initializers are executed in order of appearance • It is possible to observe a final static field before it is initialized • “To fix a class initialization cycle, reorder the static field initializers so that each initializer appears before any initializers that depend on it
  15. Not Your Type • instanceof is defined to return false

    if the left operand is null. • If both operands are of class types, one must be a subtype of the other. • The type system is not powerful enough to know that a run-time type will not be a subtype of the type in the cast
  16. What’s the Point • Order of instantiation is important! •

    It is possible to observe the value of a final instance field before its value has been assigned. • Circular instance initialization can and should always be avoided • Never call overridable methods from constructors
  17. Sum Fun • Use eager initialization or lazy initialization, never

    both. • Initialization order matters • Static initializers are executed in order of appearance
  18. Null And Void • A qualifying expression for a static

    method is evaluated, but its value is ignored • Better — access static methods using the class qualifier or no qualifier at all
  19. What’s the Difference • Integer literals beginning with a 0

    are interpreted as octal values • Never pad an integer literal with zeros
  20. Shades of Gray • When a variable and a type

    have the same name and both are in scope, the variable name takes precedence. • Similarly, variable and type names can obscure package names. • Obey Java naming conventions to avoid everything demonstrated in this puzzle. • Even acronyms should be mixed case in class names • Counter-examples in the core libraries: UUID, URL, URI (should be Uuid, Url and Uri). “Don’t do what Donny Don’t Does”.
  21. Dyslexic Monotheism • Be careful and aware of when you

    are implementing Serializable, either explicitly or by virtue of a super class. • A singleton class that implements Serializable must have a readResolve method that returns its sole instance.
  22. Raw Deal • Raw Type, Generic Type, Parameterized Type •

    With a raw type declaration, all instance members are replaced by their erased counterparts • Raw types are still supported for backward compatibility (no generics before Java 5.0 • Don’t use them if you are working in 5.0 or higher
  23. Generic Drugs • Avoid shadowing type parameters • An inner

    class of a generic class has access to the type parameters of its outer class • …But change instance fields of a class only in its own instance methods. • Prefer static member classes over non static
  24. Class Warfare • References to constant fields are resolved at

    compile time to the constant values they denote • null is not a compile-time constant • Think long and hard before exporting a constant field • Instead, consider using identity methods
  25. Java Puzzlers https://github.com/alphonzo79/JavaPuzzlersTalk (Shamelessly stolen from Java Puzzlers — Traps,

    Pitfalls and Corner Cases by Joshua Bloch and Neal Gafter http://amzn.com/032133678X