Chapter 1: Item 1 - Consider static factory methods instead of constructors
* Summary: Static factory methods allow you to create objects without exposing the class's constructor. This can be useful for controlling object creation, enforcing immutability, and hiding implementation details.
* Example:
```java
public class Foo {
private Foo() { } // Private constructor
public static Foo create(int x, int y) {
return new Foo(x, y); // Use static factory method to create instance
}
}
```
Chapter 2: Item 4 - Encapsulate primitive types
* Summary: Primitive types should be encapsulated in objects to avoid boxing and unboxing, which can be expensive.
* Example:
```java
// Primitive type
int age = 25;
// Encapsulation using Integer
Integer ageObject = Integer.valueOf(25);
```
Chapter 3: Item 7 - Favor generics over unchecked warnings
* Summary: Generic types eliminate the need for unchecked warnings, which can lead to runtime errors.
* Example:
```java
// Unchecked warning
List list = new ArrayList();
list.add(new Object());
// Generic type
List list = new ArrayList<>();
list.add("Hello"); // No warning
```
Chapter 4: Item 13 - Use caution when overriding equals()
* Summary: Overriding the equals() method requires careful consideration to ensure both symmetry and transitivity.
* Example:
```java
public class Person {
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person other = (Person) o;
return this.name.equals(other.name); // Symmetry and transitivity issues
}
}
```
Chapter 5: Item 17 - Design and use fluent interfaces
* Summary: Fluent interfaces provide a more expressive and readable API by chaining method calls together.
* Example:
```java
public class WidgetBuilder {
private Widget widget;
public WidgetBuilder withSize(int x, int y) {
widget.setSize(x, y);
return this;
}
public WidgetBuilder withColor(Color color) {
widget.setColor(color);
return this;
}
public Widget build() {
return widget;
}
}
```
Chapter 6: Item 21 - Design methods with side effects carefully
* Summary: Methods with side effects can be difficult to debug and understand. They should be used judiciously and their side effects should be well-documented.
* Example:
```java
public class Util {
// Side effect: mutates the passed-in parameter
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
```
Chapter 7: Item 23 - Minimize the scope of local variables
* Summary: Minimizing the scope of local variables reduces the risk of name collisions and makes code more readable.
* Example:
```java
for (int i = 0; i < 10; i++) {
// Declare i within the loop to minimize scope
System.out.println(i);
}
```
Chapter 8: Item 26 - Use try-with-resources to manage resources
* Summary: The try-with-resources statement automatically closes resources, reducing the risk of resource leaks and improving readability.
* Example:
```java
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
```
Chapter 9: Item 32 - Prefer maps to hashtables
* Summary: Maps provide a more consistent and powerful interface for working with key-value pairs.
* Example:
```java
// Hashtable
Hashtable table = new Hashtable<>();
table.put("one", 1);
// Map
Map map = new HashMap<>();
map.put("one", 1);
```
Chapter 10: Item 37 - Prefer interfaces to classes
* Summary: Interfaces promote decoupling and extensibility by defining a contract instead of an implementation.
* Example:
```java
// Interface
public interface Shape {
double area();
}
// Class
public class Circle implements Shape {
@Override
public double area() {
return Math.PI * radius * radius;
}
}
```