Effective Java: Object-Oriented Programming Best Practices, Study notes of Object Oriented Programming

Examples and explanations of effective Java programming practices as outlined in Joshua Bloch's 'Effective Java' textbook. Topics include object equality, string manipulation, constructor confusion, change handling, object creation, immutability, and more.

Typology: Study notes

2021/2022

Uploaded on 08/05/2022

nguyen_99
nguyen_99 🇻🇳

4.2

(80)

1K documents

1 / 15

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
1
CMSC 132:
OBJECT-ORIENTED PROGRAMMING II
Effective Java
Department of Computer Science
University of Maryland, College Park
Effective Java Textbook
Title
Effective Java, Second Edition
Author
Joshua Bloch
Contents
Learn to use Java language and its libraries more
effectively
Patterns and idioms to emulate
Pitfalls to avoid
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff

Partial preview of the text

Download Effective Java: Object-Oriented Programming Best Practices and more Study notes Object Oriented Programming in PDF only on Docsity!

CMSC 132:

OBJECT-ORIENTED PROGRAMMING II

Effective Java

Department of Computer Science University of Maryland, College Park

Effective Java Textbook

  • Title
    • Effective Java, Second Edition
  • Author
    • Joshua Bloch
  • Contents
    • Learn to use Java language and its libraries more effectively
    • Patterns and idioms to emulate
    • Pitfalls to avoid

What's In A Name?

public class Name { private String myName; public Name(String n) { myName = n; } public boolean equals(Object o) { if (!(o instanceof Name)) return false; Name n = (Name)o; return myName.equals(n.myName); } public static void main(String[ ] args) { Set s = new HashSet(); s.add(new Name("Donald")); System.out.println( s.contains(new Name("Donald"))); } } Output

**1. True

  1. False
  2. It Varies Name class violates Java hashCode( ) contract. If you override equals( ), must also override hashCode( )!**

You're Such A Character

public class Trivial { public static void main(String args[ ]) { System.out.print("H" + "a"); System.out.print('H' + 'a'); } }

Output

**1. Ha

  1. HaHa
  2. Neither Prints Ha 'H' + 'a' evaluated as** int , then converted to String! Use string concatenation (+) with care. At least one operand must be a String

Regarding Objects

  • Creating and destroying objects
    • Avoid creating duplicate/unnecessary objects
    • Eliminate obsolete object references
    • Avoid finalizers
  • Methods common to all objects
    • Obey the general hash contract when overriding equals
    • Always override hashCode when you override equals
    • Always override toString

Classes and Interfaces

  • Minimize the accessibility of classes and members
  • Favor immutability
  • Favor composition over inheritance
  • Prefer interfaces to abstract classes

Methods

  • Check parameters for validity
  • Make defensive copies when needed (more about

this topic later on)

  • Use overloading judiciously
  • Return zero-length arrays, not nulls
  • Write doc comments for all exposed API elements

General Programming

  • Minimize the scope of local variables
  • Prefer for-each loops to traditional for loops
  • Know and use the libraries
  • Prefer primitive types to boxed primitives
  • Avoid float and double if exact answers are required
  • Beware the performance of string concatenation
  • Adhere to generally accepted naming conventions
  • Refer to objects by their interfaces

Avoid Duplicate Object Creation

  • Reuse existing object instead
    • Reuse improves clarity and performance
  • Simplest example String s = new String("DON’T DO THIS!"); String s = "Do this instead";
    • Since Strings constants are reused
  • In loops, savings can be substantial
  • But don't be afraid to create objects
    • Object creation is cheap on modern JVMs

Immutable Classes

  • Class whose instances cannot be modified
  • Examples
    • String
    • Integer
    • BigInteger
  • How, why, and when to use them

How to Write an Immutable Class

• Don’t provide any mutators

• Ensure that no methods may be overridden

• Make all fields final

• Make all fields private

• Ensure exclusive access to any mutable

components

Immutable Fval Class Example

public final class Fval { private final float f; public Fval(float f) { this.f = f; } // ACCESSORS WITHOUT CORRESPONDING MUTATORS public float value( ) { return f; } // ALL OPERATIONS RETURN NEW Fval public Fval add(Fval x) { return new Fval(f + x.f); } // SUBTRACT, MULTIPLY, ETC. SIMILAR TO ADD

Advantage 2 – Inherently Thread-Safe

• No need for synchronization

• Internal or external

• Since no writes to shared data

• Can’t be corrupted by concurrent access

• By far the easiest approach to thread safety

Advantage 3 – Can Be Shared Freely

// EXPORTED CONSTANTS public static final Fval ZERO = new Fval(0); public static final Fval ONE = new Fval(1); // STATIC FACTORY CAN CACHE COMMON VALUES public static Fval valueOf(float f) { ... } // PRIVATE CONSTRUCTOR MAKES FACTORY MANDATORY private Fval (float f) { this.f = f; }

Advantage 4 – No Copies

• No need for defensive copies

• No need for any copies at all!

• No need for clone or copy constructor

• Not well understood in the early days

• public String(String s); // Should not exist

Advantage 5 – Composability

  • Excellent building blocks
  • Easier to maintain invariants
    • If component objects won't change

When to Make Classes Mutable

  • Class represents entity whose state changes
    • Real-world
      • BankAccount, TrafficLight
    • Abstract
      • Iterator, Matcher, Collection
    • Process classes
      • Thread, Timer
  • If class must be mutable, minimize mutability
    • Constructors should fully initialize instance
    • Avoid reinitialize methods

Defensive Copying

  • Java programming language is safe
    • Immune to buffer overruns, wild pointers, etc…
    • Unlike C, C++
  • Makes it possible to write robust classes
    • Correctness doesn’t depend on other modules
    • Even in safe language, it requires effort
  • Defensive Programming
    • Assume clients will try to destroy invariants
      • May actually be true
      • More likely – honest mistakes
    • Ensure class invariants survive any inputs

Defensive Copying

// GOAL – PERSON’S BIRTHDAY IS INVARIANT public class Person { // PROTECTS birthDate FROM MODIFICATION????? private final Date birthDate; public Person(Date birthDate){ this.birthDate = birthDate; } public Date bday() { return birthDate; } }

  • The following class is not robust!
    • Problem #1: Constructor can allow invariant to be modified // ATTACK INTERNALS OF PERSON Date today = new Date(); Person p = new Person(today); today.setYear(78); // MODIFIES P’S BIRTHDAY!

Defensive Copying

  • Problem #2: Accessor can allow invariant to be modified // ACCESSOR ATTACK ON INTERNALS OF PERSON Date today = new Date(); Person p = new Person(today); Date bday = p.bday( ); bday.setYear(78); // MODIFIES P’S BIRTHDAY!
  • Solution
  • Defensive copying in constructors and accessors public class Person { private final Date birthDate; // REPAIRED CONSTRUCTOR // DEFENSIVELY COPIES PARAMETERS public Person(Date birthDate){ this.birthDate = new Date(birthDate.getTime()); } // REPAIRED ACCESSOR DEFENSIVELY COPY FIELDS public Date bday() { (Date) birthDate.clone( ); } }