Effective Java Flashcards

1
Q

What is the difference between final, finally, and finalize

A
  • final: Class cannot be overriden. No methods within the class can be overriden.
  • final: method cannot be overriden.
  • final: variable can not be changed.
  • finally: happens after a try block completes after all catch’s are done, even if no exception is thrown
  • finalize: override this function, and the code will be executed just before garbage collection
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What are the Access Modifiers?

A
  • public - Accessible from any other class
  • private - Accessible only within the same class
  • protected - Accessible within the package and subclasses
  • package-private - Accessible only within the package
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What are the threading modifiers?

A
  • volatile - Indicates the variable may be changed by multiple threads
  • synchronized - Restricts access to one thread at a time
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What are other visibility modifiers?

A
  • default - Provides a default method implementation in interfaces
  • static - Belongs to the class rather than instances
  • final - Prevents inheritance, overriding, and reassignment
  • abstract - Declares that the class cannot be instantiated or method has no body
  • sealed / non-sealed / permits - sealed class can only be extended by classes it permits.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What are the lesser used modifiers?

A
  • native - Declares a method implemented in a non-Java language
  • strictfp - guarantees that calculations strictly adhere to the IEEE 754 floating-point standard
  • transient - Prevents serialization of the field
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What are boxed primitives?

A

Primitive - Wrapper (Boxed) Class
int - Integer
long - Long
float - Float
double - Double
boolean - Boolean
char - Character
byte - Byte
short - Short

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What happens when comparing and object that didn’t override the equals function?

A

It will only equal itself.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What are varargs?

A
  • Variable length of arguments
  • e.g.
    public static int sum(int... numbers) {}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What are mixins?

A
  • A mixin is a way to add reusable functionality to a class without establishing a formal inheritance relationship
  • In JavaScript, you can do this by adding functions from one class to another as mixin functions.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What are the steps to make a class immutable?

A
  1. Don’t provide methods that modify the object’s state (known as
    mutators).
  2. Ensure that the class can’t be extended (make class final or private constructor)
  3. Make all fields final.
  4. Make all fields private.
  5. Ensure exclusive access to any mutable components.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How does inheritance break enacpsulation?

A

A subclass depends on the implementation details of its superclass for its proper function. The superclass’s implementation may change from release to release, and if it does, the subclass may break, even though its code has not been touched. As a consequence, a subclass must evolve in tandem with its superclass, unless the superclass’s authors have designed and documented it specifically for the purpose of being extended.

Snyder, Alan. 1986. “Encapsulation and Inheritance in Object-Oriented Programming Languages.” In Object-Oriented Programming Systems, Languages, and Applications Conference Proceedings, 38–45. New York, NY: ACM Press.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What are the 4 kinds of nested classes?

A
  • static member classes: Defined as a static nested class within another class.
  • nonstatic member classes: Defined as a non-static nested class within another class.
  • anonymous classes: A special type of local class without a name, often used for one-off implementations, especially for interfaces or abstract classes (e.g. Runnable)
  • local classes: Defined within a method, constructor, or initializer block of the enclosing class.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What are the important Generic terms.

A

Term, Example
Parameterized type, List<String>
Actual type parameter, String
Generic type, List<E>
Formal type parameter, E
Unbounded wildcard type, List<?>
Raw type, List
Bounded type parameter, <E>
Recursive type bound, <T extends Comparable<T>>
Bounded wildcard type, List<? extends Number>
Generic method, static <E> List<E> asList(E[] a)
Type token, String.class</E></E></T></E></E></String>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Item 1: Consider static factory methods instead of constructors

A
  • Can use named functions
  • Do not have to create a new object with each invocation
  • Can return an object of any type/subtype
  • Input parameters can determine type/subtype
  • The type/subtype returned doesn’t even have to exist today.

Fun Facts
- Since Java 8, interfaces can have static functions and default implementations. Static functions don’t need to be default since they are part of the interface. Java.util.Collections has 45 separate public classes, one for each convenience implementation. These could now just be part of the interfaces.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Item 2: Consider a builder when faced with many constructor parameters

A
  • The Builder pattern is a good choice when designing classes whose constructors or static factories would have more than a handful of parameter
  • More easily thread safe because you can create the instance in a single call by passing the building into the constructor.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Item 3: Enforce the singleton property with a private constructor or an enum type

A

Fun Facts
- private contructor singleton can be broken when implementing serializable. Variables must be labeled transient.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Item 4: Enforce noninstantiability with a private constructor

A
  • When using something like a static helper class that you never want to be instantiated, remember to mark the constructor private.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Item 5: Prefer dependency injection to hardwiring resources

A
  • Allow a client to provide a type instead of choosing up front.
  • Dependency Injection can mean something as simple as passing in an instance in a constructor.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Item 6: Avoid creating unnecessary objects

A
  • Do not do “String s = new String(foobar)”
  • Do this instead: String s = “foobar”
  • This makes it immutable and reusable.
  • Also beware of accidental autoboxing (i.e. compared an unboxed primitive to a boxed object will automatically create a boxed object from the primitive).

Example Problem
- This actually creates a new Pattern instance, uses it once, and then making it available for garbage collection.
- Instead compile your regex into a Pattern instance so it only happens once, and you can resuse.

static boolean isRomanNumeral(String s) {
  return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Item 7: Eliminate obsolete object references

A
  • Basically, even though there is garbage collection, memory leaks can still happen.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Item 8: Avoid finalizers and cleaners

A
  • Finalizers have security and performance issues, just don’t use them.
  • Cleaners are new in Java 9 but still have performance issues.
  • C++ engineers might think they are the same as destructors, but this isn’t necessary since Java has garbage collection.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Item 9: Prefer try-with-resources to try-finally

A
  • try-with-resources came in Java 7 and it allows types of AutoCloseable and Closeable.
  • This allows object owners to ensure resources are properly closed without losing the original error / stacktrace.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Item 10: Obey the general contract when overriding
equals

A
  • If it is ok for your object to only equal itself (i.e. the exact instance), then do NOT override equals.
  • How To:
  • Use == operator to check if it is the same instance
  • Use instanceof operator to check if they are the same type.
  • Cast the argument to correct type.
  • Check each significant field in the class
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Item 11: Always override hashCode when you override equals

A
  • If you don’t do this, then it is possible for two equal objects, to not have the same hashcode
  • This breaks contract for hashcode.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Item 12: Always override toString

A
  • Not mission critical
  • providing a good toString implementation makes your class much more pleasant to use and makes systems using the class easier to debug.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

Item 13: Override clone judiciously

A
  • Clone doesn’t deep a deep copy
  • Prefer constructors or static factory methods.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

Item 14: Consider implementing Comparable

A
  • when implemented, allows consistent and predictable sorting, which enhances usability and interoperability in Java’s collection frameworks.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

Item 15: Minimize the accessibility of classes and members

A
  • best practice is to make each class or member as inaccessible as possible.
  • If hidden you can:
  • decorate functions
  • change internal implementations that still meet function definitions
  • can guarantee thread safety
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

Item 16: In public classes, use accessor methods, not public fields

A
  • If a class is accessible outside its package, provide accessor methods to preserve the flexibility to change the class’s internal representation
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

Item 17: Minimize mutability

A
  • Immutable objects are inherently thread-safe; they require no synchronization
  • Immutable objects can be shared freely, even their internals
  • Immutable objects make great building blocks for other objects
  • Immutable objects provide failure atomicity for free
  • The major disadvantage of immutable classes is that they require a separate object for each distinct value.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

Item 18: Favor composition over inheritance

A

Unlike method invocation, inheritance violates encapsulation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

Item 19: Design and document for inheritance or else prohibit it

A
  • Designing a class for inheritance requires great effort and places substantial limitations on the class
  • The best solution to this problem is to prohibit subclassing in classes that are not designed and documented to be safely subclassed.
  • If you want to allow inheritance remember:
  • The class must document its self-use of overridable methods.
  • Constructors must not invoke overridable methods
  • The only way to test a class designed for inheritance is to write subclasses.
  • You must test your class by writing subclasses before you release it.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

Item 20: Prefer interfaces to abstract classes

A
  • Java allows single inheritance (i.e. one class can implement many interfaces but can only be extended by one class)
  • Existing classes can easily be retrofitted to implement a new interface.
  • Interfaces are ideal for defining mixins.
  • Interfaces allow for the construction of nonhierarchical type frameworks.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

Item 21: Design interfaces for posterity

A

Carefully design interfaces with the future in mind, as they are difficult to change once published. Since interfaces define a contract that implementing classes must follow, adding or modifying methods later can break backward compatibility. To create robust interfaces that can stand the test of time:

  • Minimize Initial Methods: Start with a small, essential set of methods to avoid overloading the interface with unnecessary functionality.
  • Use Default Methods Judiciously: Since Java 8, default methods can be added to interfaces, allowing you to introduce new methods without breaking existing implementations, but overuse can lead to bloated and confusing interfaces.
  • Consider Potential Implementations: Think about how future classes might implement the interface, ensuring flexibility and extensibility without forcing changes.

The goal is to create a minimal, stable, and flexible interface that can accommodate future needs without frequent modifications.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

Item 22: Use interfaces only to define types

A

interfaces in Java should be used solely to define types, not to hold constant values or utility methods. Using interfaces for constants or utilities can lead to confusing and cluttered code, as these interfaces often end up being implemented by unrelated classes simply to access the constants, violating the purpose of interfaces as contracts for behavior.

Key points include:

  • Avoid Constant Interfaces: Defining constants in interfaces and implementing them across classes is considered a bad practice because it pollutes the implementing class’s namespace. Instead, constants should be placed in utility classes or enums.
  • Use Interfaces as Contracts for Behavior: Interfaces should represent capabilities or behaviors that can be implemented by various classes, following the principle of polymorphism.

In summary, interfaces should focus on defining the behaviors expected from implementing classes, not as a means to share constants or unrelated static methods.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

Item 23: Prefer class hierarchies to tagged classes

A
  • eg, don’t have a Shape class that can take an Enum that defines which type of shape it becomes.
  • Instead, just have a subclass for different shapes

Reasons to Avoid Tagged Classes:
- Complexity and Error-Prone Code: Tagged classes require extensive conditional logic (e.g., if or switch statements) to handle the different cases, increasing the chance of errors and making code harder to read and maintain.

  • Reduced Extensibility: Modifying or adding a new “type” in a tagged class usually requires changes in multiple places, which violates the open-closed principle (classes should be open for extension but closed for modification).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

Item 24: Favor static member classes over nonstatic

A
  • If a nested class doesn’t need access to the outer classes members, and only needs access to static members, then use static member class.
  • Using non-static member classes can be a cause for memory leak if not careful.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

Item 25: Limit source files to a single top-level class

A
  • When you do this, the ordering of the classes determines which is the actual definition of the source file.
  • Following this rule guarantees that you can’t have multiple definitions for a single class at compile time.
  • This in turn guarantees that the class files generated by compilation, and the behavior of the resulting program, are independent of the order in which the source files are passed to the compiler.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

Item 26: Don’t use raw types

A
  • They exist primarily for compatibility with pre-generics code.
  • See Item 29 for reasons to use generic types
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

Item 27: Eliminate unchecked warnings

A
  • Generics will generate a lot of warnings.
  • Eliminate every unchecked warning that you can
  • If you can’t eliminate a warning, but you can prove that the code that provoked the warning is typesafe, then (and only then) suppress the warning with an @SuppressWarnings(“unchecked”) annotation
  • Always use the SuppressWarnings annotation on the smallest scope possible.
  • Every time you use a @SuppressWarnings(“unchecked”) annotation, add a comment saying why it is safe to do so.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

Item 28: Prefer lists to arrays

A
  • Lists allow generics, arrays to do not.
  • See Item 29 for reasons to use generic types
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

Item 29: Favor generic types

A
  • Type Safety: Generics enable compile-time type checking, catching potential type errors early, and avoiding runtime casting issues.
  • Code Reusability: Generic types allow you to write methods and classes that work with different types, making the code more versatile and reusable.
  • Readability and Maintainability: By using generics, you communicate the intended types directly in the code, making it more understandable and reducing the need for manual type casts.
43
Q

Item 30: Favor generic methods

A
44
Q

Item 31: Use bounded wildcards to increase API flexibility

A
45
Q

Item 32: Combine generics and varargs judiciously

A
46
Q

Item 33: Consider typesafe heterogeneous containers

A
47
Q

Item 34: Use enums instead of int constants

A
48
Q

Item 35: Use instance fields instead of ordinals

A
49
Q

Item 36: Use EnumSet instead of bit fields

A
50
Q

Item 37: Use EnumMap instead of ordinal indexing

A
51
Q

Item 38: Emulate extensible enums with interfaces

A
52
Q

Item 39: Prefer annotations to naming patterns

A
53
Q

Item 40: Consistently use the Override annotation

A
54
Q

Item 41: Use marker interfaces to define types

A
55
Q

Item 42: Prefer lambdas to anonymous classes

A
56
Q

Item 43: Prefer method references to lambdas

A
57
Q

Item 44: Favor the use of standard functional interfaces

A
58
Q

Item 45: Use streams judiciously

A
59
Q

Item 46: Prefer side-effect-free functions in streams

A
60
Q

Item 47: Prefer Collection to Stream as a return type

A
61
Q

Item 48: Use caution when making streams parallel

A
62
Q

Item 49: Check parameters for validity

A
63
Q

Item 50: Make defensive copies when needed

A
64
Q

Item 51: Design method signatures carefully

A
65
Q

Item 52: Use overloading judiciously

A
66
Q

Item 53: Use varargs judiciously

A
67
Q

Item 54: Return empty collections or arrays, not nulls

A
68
Q

Item 55: Return optionals judiciously

A
69
Q

Item 56: Write doc comments for all exposed API elements

A
70
Q

Item 57: Minimize the scope of local variables

A
71
Q

Item 58: Prefer for-each loops to traditional for loops

A
72
Q

Item 59: Know and use the libraries

A
73
Q

Item 60: Avoid float and double if exact answers are required

A
74
Q

Item 61: Prefer primitive types to boxed primitives

A
75
Q

Item 62: Avoid strings where other types are more appropriate

A
76
Q

Item 63: Beware the performance of string concatenation

A
77
Q

Item 64: Refer to objects by their interfaces

A
78
Q

Item 65: Prefer interfaces to reflection

A
79
Q

Item 66: Use native methods judiciously

A
80
Q

Item 67: Optimize judiciously

A
81
Q

Item 68: Adhere to generally accepted naming conventions

A
82
Q

Item 69: Use exceptions only for exceptional conditions

A
83
Q

Item 70: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

A
84
Q

Item 71: Avoid unnecessary use of checked exceptions

A
85
Q

Item 72: Favor the use of standard exceptions

A
86
Q

Item 73: Throw exceptions appropriate to the abstraction

A
87
Q

Item 74: Document all exceptions thrown by each method

A
88
Q

Item 75: Include failure-capture information in detail messages

A
89
Q

Item 76: Strive for failure atomicity

A
90
Q

Item 77: Don’t ignore exceptions

A
91
Q

Item 78: Synchronize access to shared mutable data

A
92
Q

Item 79: Avoid excessive synchronization

A
93
Q

Item 80: Prefer executors, tasks, and streams to threads

A
94
Q

Item 81: Prefer concurrency utilities to wait and notify

A
95
Q

Item 82: Document thread safety

A
96
Q

Item 83: Use lazy initialization judiciously

A
97
Q

Item 84: Don’t depend on the thread scheduler

A
98
Q

Item 85: Prefer alternatives to Java serialization

A
99
Q

Item 86: Implement Serializable with great caution

A
100
Q

Item 87: Consider using a custom serialized form

A
101
Q

Item 88: Write readObject methods defensively

A
102
Q

Item 89: For instance control, prefer enum types to readResolve

A
103
Q

Item 90: Consider serialization proxies instead of serialized instances

A
104
Q
A