Effective Java Flashcards
(104 cards)
What is the difference between final, finally, and finalize
- 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
What are the Access Modifiers?
- 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
What are the threading modifiers?
- volatile - Indicates the variable may be changed by multiple threads
- synchronized - Restricts access to one thread at a time
What are other visibility modifiers?
- 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.
What are the lesser used modifiers?
- 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
What are boxed primitives?
Primitive - Wrapper (Boxed) Class
int - Integer
long - Long
float - Float
double - Double
boolean - Boolean
char - Character
byte - Byte
short - Short
What happens when comparing and object that didn’t override the equals function?
It will only equal itself.
What are varargs?
- Variable length of arguments
- e.g.
public static int sum(int... numbers) {}
What are mixins?
- 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.
What are the steps to make a class immutable?
- Don’t provide methods that modify the object’s state (known as
mutators). - Ensure that the class can’t be extended (make class final or private constructor)
- Make all fields final.
- Make all fields private.
- Ensure exclusive access to any mutable components.
How does inheritance break enacpsulation?
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.
What are the 4 kinds of nested classes?
- 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.
What are the important Generic terms.
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>
Item 1: Consider static factory methods instead of constructors
- 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.
Item 2: Consider a builder when faced with many constructor parameters
- 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.
Item 3: Enforce the singleton property with a private constructor or an enum type
Fun Facts
- private contructor singleton can be broken when implementing serializable. Variables must be labeled transient.
Item 4: Enforce noninstantiability with a private constructor
- When using something like a static helper class that you never want to be instantiated, remember to mark the constructor private.
Item 5: Prefer dependency injection to hardwiring resources
- 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.
Item 6: Avoid creating unnecessary objects
- 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})$"); }
Item 7: Eliminate obsolete object references
- Basically, even though there is garbage collection, memory leaks can still happen.
Item 8: Avoid finalizers and cleaners
- 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.
Item 9: Prefer try-with-resources to try-finally
- 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.
Item 10: Obey the general contract when overriding
equals
- 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
Item 11: Always override hashCode when you override equals
- 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.