Understanding Generics in Java
Generics in Java allow you to use type parameters in your code, providing flexibility and type safety. Here’s a detailed explanation of how they work:
Defining Generics
To create a class with a generic parameter, use the syntax <T>
after the class name. The parameter name can be any valid identifier, but single uppercase letters like T
, E
, or K
are common.
class Box<T> { }
The Diamond Operator (<>
)
The diamond operator simplifies generic declarations by inferring the type from the context. It can be used with local variables, instance variables, and one-line declarations.
Box<String> box = new Box<>();
Wildcards in Generics
<?>
: Unbounded wildcard, meaning any type.<? extends Object>
: Upper bound, allowing any type that isObject
or its subclass.<? extends MyInterface>
: Upper bound for types implementingMyInterface
.<? super Number>
: Lower bound, allowingNumber
or its superclasses.
Note: Attempting to add or remove items from a list with an unbounded or upper-bounded wildcard results in a compiler error.
Generics and Legacy Code
When working with raw types or legacy code without generics, Java issues a compiler warning. Ignoring these warnings can lead to runtime ClassCastException
. Unboxing without generics results in compiler errors.
Autoboxing and Unboxing
Java can convert between primitive types and their wrapper classes automatically:
- Primitive:
long
- Wrapper:
Long
This is called autoboxing and unboxing. When resolving method calls, Java prioritizes primitive signatures over their object equivalents.
remove(int n)
will be called over remove(Object o)
for an int
.
Java Collections Framework
The framework includes the following data structures:
- List: Ordered collection allowing duplicates
ArrayList
: Resizable listLinkedList
: Fast add/remove from beginning or endVector
: Thread-safeArrayList
Stack
: Last-in, first-out
- Set: No duplicates
HashSet
: UseshashCode()
TreeSet
: Sorted and navigable, nonull
values
- Queue: Element processing order
LinkedList
: Flexible add/removeArrayDeque
: FIFO or LIFO, nonull
values
- Map: Key-value pairs
HashMap
: UseshashCode()
for keysTreeMap
: Sorted keys, nonull
keysHashtable
: Legacy version, nonull
keys/values
Comparable and Comparator
Comparable: Defines the compareTo()
method to compare one object.
Comparator: Defines the compare()
method to compare two objects. Commonly implemented with lambdas.
Utility Methods
Key methods in the Arrays
and Collections
classes:
sort()
: Sorts elementsbinarySearch()
: Searches for elements
Note: Ensure the same sort order is used for both sorting and searching.
Collection methods that take lambdas include:
removeIf()
forEach()
merge()
Method References
A method reference is a concise way to write lambdas referring to methods. There are four types:
- Static methods
- Instance methods of a specific instance
- Instance methods with runtime-supplied instance
- Constructor references
0 Comments