- 📙 Effective Java by Joshua Bloch
- Jagged Array in Java (GeeksForGeeks)
- Cglib, Javassist, JDK dynamic proxy (Programmer Group)
- Method Overloading with Autoboxing and Widening in Java ( GeeksForGeeks)
- How to make the most of Java enums (Oracle blog)
- PECS - producer-extends, consumer-super
- invariant - default
- covariant (PE - producers extends, e.g. GET from collection/box)
List<? extends Number> l = new ArrayList<Integer>(); Number number = l.get(0); l.add(null); // nothing else - contravariant (CS - consumer super, e.g. PUT into collection/box)
List<? super Number> l = new ArrayList<Object>(); Object object = l.get(0); // always object l.add(5);
Function<? super Param1, ? super Param2, ? extends R> // contravariant in params, covariant in R
- method params are contravariant - we put arguments in
- return type is covariant - we get the result out
- don't combine - arrays are covariant and reified (type parameter is preserved at runtime)
- covariant -
Object[] objects = new String[10]; // ok compile - reified - type safety is checked at runtime (generics are not reified, type is erased at compile time)
- covariant -
Array.equalscompares just the array refs (arr1 == arr2)Arrays.equalscall equals on all elements - use for 1D arraysArrays.deepEqualsmake deep comparison - use for nested multidimensional arrays
List.toArray()- returnsObject[]List.toArray(T[] a)- returnsT[]- can't be used for primitive types (use Guava or Stream API)Arrays.binarySearch(..)- arrays must be sorted
Integer[][] array1 = {{1, 4}, null, {9, 7, 8}, {}};
// OR semantically the same
Integer[][] array2 = new Integer[4][];
array2[0] = new Integer[] {1, 4};
array2[1] = null;
array2[2] = new Integer[] {9, 7, 8};
array2[3] = new Integer[] {};
- always override
hashcodewhen overridingequals- otherwise, hash based collections will be broken (
HashSet,HashMap) - simply because hashcode will point (most likely) to a different bucket
- otherwise, hash based collections will be broken (
- equals and subclass with new components is always broken (e.g.
PointandColorPoint)- use composition
- equals rules
- reflexive
x.equals(x) - symmetric
x.equals(y)theny.equals(x) - transitive
- consistent - repeated calls return the same value
- if
x != nullthenx.equals(null)returns null
- reflexive
- hashcode rules
- consistent - repeated calls return the same value
- if
x.equals(y)then hashcodes must be the same (the opposite is not necessarily true) - distinct object may produce same hashcodes
Comparable<T>interface- imposes a total ordering (or natural ordering) on the objects of each class that implements i
Collections.sort()andArrays.sort()- objects can be used with sorted sets and maps (without explicit comparator)
- consistent with equals - iff
e1.compareTo(e2)~e1.equals(e2) - BigDecimal is not consistent with equals
"1.00 !equals "1.0"but"1.00" compareTo "1.0"
- consistent with equals - iff
Comparator<T>interface- methods
compareTo(T o1, T o2)- default methods
naturalOrderreverseOrdernullsFirstthenComparing
- examples
Comparator.nullsFirst(Comparator.reverseOrder())Comparator.nullsFirst(Comparator.comparingInt(String::length))
- methods
- allows introspecting and executing code
- code diagrams, method intellisense, framework annotations
- dynamic proxies, executing tests
- via
java.lang.Classobject - getting Class object
Class.forName(String)- dynamicanObject.getClass()aClass.class- access to primitives (void.class,int.class) and arrays (int[].class)
- creating objects that act like instances of interfaces but allow for customized method invocation
- proxy class is a class created at runtime that implements a specified list of interfaces, known as proxy interfaces
- generating bytecode at runtime
- target object - the object being proxied
- proxy object - dynamically generated proxy
Proxyclass - factory for creating proxy objectsInvocationHandler- implements proxy logic
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class ProxyExample {
// dynamically generated proxy will implement this interface
interface Person {
String hi();
}
public static void main(String[] args) {
final Person target = new Person() {
@Override
public String hi() {
return "hi";
}
};
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxying method " + method);
// custom logic
return method.invoke(target, args); // returns "hi"
// custom logic
}
};
Person proxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),
new Class<?>[]{Person.class}, // possibly multiple interfaces
handler);
proxy.hi();
}
}- similar to JDK
- differs in implementation details and some restrictions
- javassist is more general purpose (byte code manipulation)
- cglib
- writes class bytecode using the ASM framework
- no longer maintained, no docs
- Package java.lang.ref
- Weak References in Java (Baeldung)
- A weakly referenced object is cleared by the Garbage Collector when it's weakly reachable
- i.e. object has neither strong nor soft references pointing to it
WeakHashMap
- Rule of thumb - in most operations, boxed primitives gets unboxed
Integer i1 = 1000; int i2 = 1000; boolean compared = (i1 == i2); // i1 is unboxed - unboxing can throw NPE
- priority order for primitive types:
- Same type > Auto Widening > Boxing > Upcasting (Parent Class) > Super Class
- priority order for reference types:
- Same type > Upcasting (Parent Class) > Super Class > Unboxing
- Java String Pool — the special memory region where Strings are stored by the JVM (off heap, since JDK8)
"foo"- creates the String in the pool, or return the existing onenew String("foo")- avoid, it creates a new object on the heap which references to the String poolString.itern()- return the reference into String poolnew String("foo").intern() == "foo"
- if the String is known at compile time, it's created in the String pool
"a" + "b"- a new StringBuilder is created behind the scenes by the compiler
- see Types of References in Java (GeeksForGeeks)
- strong - standard reference
- weak - eligible for gc if only referenced by weak references (
WeakHashMap)
- compiled into a class extending from
java.lang.Enum- inherits
name(),ordinal(),valufOf(..)
- inherits
- enum constants become anonymous classes - they can implement their own methods
Array.length,String.length(),Collection.size()null instanceof Foo- always false, instance of null-safe (1t operator)- avoid
float == floatanddouble == double, useFloat.compareandDouble.comapre- reason isFloat.NaNandDouble.NaN - code blocks are executed before constructors