The following is a study guide for information that any self-proclaimed Java programmer should know.
Java Language Features and Overview
Equality Operators ==, !=, and Object.equals(other)
- On primitives it is a comparison of the value of the primitive
- On objects it determines whether or not the references point to the same object on the heap (or null).
- Object.equals(other) determines the quantitative comparison of the two objects value not the reference on the heap.
String s1 = "moo";
String s2 = "moo";
if (s1 == s2) {
// This is true because both of the references point to the same
// String in the string pool.
}
MyObj m1 = new MyObj(1);
MyObj m2 = m1
if (m1 == m2) {
// True because both references point to the same object on the heap.
}
String t1 = new String("moo");
String t2 = new String("moo");
if (!t1 == t2) {
// This is false because each reference points to a different object
// on the heap.
}
int x = 4;
int y = 7;
if (x == y) {
// True because x and y are both primitives and they have the same value.
}
Covariant Return Type
Since 1.5; this means that you can override a method that returns a value that is a child of the parent return type. This is not allowed for primitive types.
public class CovariantReturn {
public static void main(String[] args) {
System.out.printf("A.doSomething=%s%n", A.doSomething().toString()); // A.doSomething=3
System.out.printf("B.doSomething=%s%n", B.doSomething().toString()); // B.doSomething=3.14
}
public static class A {
protected static Number doSomething() {
Integer retVal = 3;
return retVal;
}
}
public static class B extends A {
protected static Double doSomething() {
Double retVal = 3.14D;
return retVal;
}
}
}
Method Hiding
If a child contains a static method that is also defined in the parent then that child method hides the parent but does not override it. Instance methods are overridden and static methods are hidden.
Nested Classes
There are four types of nested classes
- Member Inner Classes: Also know as a non-static nested class. They cannot declare static fields or methods
List list = Collections.synchronizedList(new LinkedList(…));
Generics
Static Classes and Methods
public static <T> Deque<T> maxPathSum(Node<T> node, T target)
Enums
public enum MyEnum {
FOO;
BAR;
BAZ;
}
public static void main(String[] args) {
System.out.println(MyEnum.FOO.toString()); // "FOO"
System.out.println(MyEnum.FOO.ordinal()); // "0"
}
Concurrency and Threading
Basics
Executors
Fork/Join Framework
A key distinction between using the fork/join framework and other threading idioms in Java is that fork/join is designed with the goal of parallel execution of a task and not just concurrent execution. Whereby we can define parallel execution where each thread is running on a separate core and concurrent execution where the threads are running on the same core sharing the core and being context switched during execution.
The basic concept is that a larger problem is recursively broken down into smaller parts (divide and conquer) until a predefined threshold is reached and the problem is solved with the given input. Each part is executed in parallel and then all of the results are joined together to generate the final result.
The API provides the following abstraction and heavy lifting for the programmer:
- It handles the creating and management of threads
- Automates scaling of the program threads to utilize all available cores
Links
- https://www.baeldung.com/java-fork-join
- https://www.codejava.net/java-core/concurrency/understanding-java-fork-join-framework-with-examples
- https://www.onlinetutorialspoint.com/java/fork-join-java-7.html
Volatile
Key concept: without synchronization or using a declared volatile variable the Thread doesn’t know that there might be other Threads accessing the variable and it can cache the value of the variable outside of main memory in a register or in it’s local memory, thus causing inconsistency problems.
It is essentially about visibility and not synchronization. Meaning, a volatile variable is one who’s value cannot be cached local to the Thread and must always be reading the data from the variable in main memory. It also ensures that the reordering of statements does not occur and that operations that occur before the mutation of the volatile variable are guaranteed to occur before such mutation to maintain a happens-before guarantee.
. Explain “synchronizing cached variables with main memory”: The process by which the locally cached variables in a Thread’s scope are read and written back to main memory from inside the synchronized block of code. Meaning, the reads and writes to main memory have to happen inside the block of synchronized code in the right order to maintain consistency between Threads.
. common mistake is to allow reads to happen outside of a synchronized block and only synchronize writes. You can still get some problems with this one. see http://www.javamex.com/tutorials/synchronization_concurrency_synchronized2.shtml
. volatile variables:
. a variable’s value will be modified by different threads.
. never be cached thread-locally, all r/w directly to main memory.
. access acts as though it is enclosed in a synchronized block, synchronized on itself.
. can declare a primitive (instead of synchronizing on an object)
. can never block
. not suitable for read-update-write, unless OK with missing and update
. volatile variable that is null can be null because you are synchronizing on the reference not the actual object
. When to use:
. w a variable in one thread and read in another
. a w does not depend on the current value
. or you don't care about missing an update
. One-off variable in a class instantiated a small number of time, AtomicInteger (or like) clas
. large number of instances of classes, volatile and access via AtomicReferenceFieldUpdater
Links
- https://neolithic.blog/2018/11/03/java-concurrency-with-volatile/
- https://knpcode.com/java/multi-threading/volatile-keyword-in-java/
ThreadLocal Class
TBD
Articles articles on multi-threading in Java
- http://tutorials.jenkov.com/java-concurrency/index.html
- http://tutorials.jenkov.com/java-util-concurrent/lock.html
- http://tutorials.jenkov.com/java-concurrency/read-write-locks.html
- http://tutorials.jenkov.com/java-concurrency/starvation-and-fairness.html
- https://knpcode.com/java/multi-threading/difference-between-sleep-and-wait-methods-in-java/
- https://knpcode.com/java/multi-threading/difference-between-sleep-and-yield-methods-in-java/
Concurrent Programming in Java: Design Principles and Pattern (2nd
Edition) by Doug Lea. A comprehensive work by a leading expert, who’s also the
architect of the Java platform’s concurrency framework.
Java Concurrency in Practice by Brian Goetz, Tim Peierls, Joshua Bloch,
Joseph Bowbeer, David Holmes, and Doug Lea. A practical guide designed to be
accessible to the novice.
Effective Java Programming Language Guide (2nd Edition) by Joshua Bloch.
Though this is a general programming guide, its chapter on threads contains
essential “best practices” for concurrent programming.
Concurrency: State Models & Java Programs (2nd Edition), by Jeff Magee and
Jeff Kramer. An introduction to concurrent programming through a combination
of modeling and practical examples.
Java Concurrent Animated: Animations that show usage of concurrency
features.
APIs to Be Familiar With
- Map
- Adding and removing elements
- Iterating over
- keys and values
Map.Entry<T, T> entry : map.entrySet()
- keys only
T key : map.keySet()
- keys and values
- Deque: The Queue and Stack common API.
- size(): To indicate if there are any more items in the data structure
- Queue:
- add(e) to add an element to the queue
- remove() to remove the next element from the queue
- Stack:
- push(e) to push an element onto the stack
- pop() to remove the next element from the top of the stack
- CharacterSequence interface:
- Commonly used concrete classes of StringBuffer, StringBuilder, and CharBuffer
- charAt(int index)
- IntStream chars()
- subSequence(int start, int end); Key to remember is that end is index – 1, exclusive so that you can use the semantic of
subSequence(idx, charSequence.length())
if you want to get the subsequence from a given index all of the way to the end conveniently without worrying about stepping off the edge.
- Character class:
Character.getNumericValue(char c)
will return the integral val of the character provided
- String class:
- indexOf: There are multiple overloads of this method.
- indexOf(int ch): returns the index of the first occurrence of a given char
- indexOf(int ch, int fromIndex): returns the index of the first occurrence of a given char starting search at specified index
- indexOf(String str): returns index of the first occurrence of the given string
- substring(int beginIndex): returns a substring of the given string from the given index to the end of the string.
- substring(int beginIndex, int endIndex): The key thing to remember here is that the endIndex is exclusive.
- indexOf: There are multiple overloads of this method.
Questions
Strings
- What is the difference between a)
String foo = "foo";
and b)String foo = new String("foo");
?- a) creates the string in the string pool, b) creates the string on the heap
- What is the string pool?
- A “pool” of strings stored on the heap. Before Java 7 the pool was in the permanent generation area of the heap. From Java 7 the string pool is stored on the heap to allow for it to be garbage collected.
- Its purpose is to save space for the JVM by enabling multiple pointers to the same, immutable, Strings on the heap.
- How do you “add” a String to the string pool?
- String.intern()
- What is the regex used to search for any whitespace character?
\\s+
- Further Java String study questions.
Comparison and Collections
- What is the difference between == and .equals()?
==
tests whether or not the two object reference variables refer to the exact same instance of an object..equals(T other)
tests whether or not the two objects being compared are quantitatively equivalent to each other, but they do not need to be the same object.==
operating on boolean or primitive types compares the value of those primitives to each other similarly to the .equals() method of Objects
- What is the relationship between hashCode, equals, and compareTo?
- hashCode: a unique identifier for a given object as an int. The business logic for generating such an int can be user defined.
- equals: returns a boolean as to whether or not the two objects are equal based on user defined business logic.
- compareTo: Comparable interface implementation that allows for the sorting of items with the Collections. util.
- All three should be in sync so that an object that equals another should return 0 for compareTo as well as the same hashCode value.
- What is the sole member of the Comparable interface? Explain its purpose and use-cases.
compareTo(Object other)
.- It is similar to
hashCode
andequals
, but not quite. It enables a means of fully ordering objects. - It is the implementation of an algorithm tied to a specific class, and/or child classes, that allows objects to be sorted similar to sorting a database result set on a composite key.
- Consistency with equals is highly recommended, but can be modified based on the business logic. If you want to use it in a sorted collection, you must ensure that
x.compareTo(y) == 0
, if and only ifx.equals(y)
. - It enables:
- The sorting of objects in Collections by calling
- Collections.sort
- Collections.binarySearch
- Arrays.sort
- Arrays.binarySearch
- Using objects as keys in TreeMap
- Using objects as elements in TreeSet
- How should floats and doubles (primitives) be compared for equality?
- Using
Double.compare(double, double)
, andFloat.compare(float, float)
- Using
- How should booleans be compared?
- In almost all cases you should NOT use the wrapper Boolean class as it opens up the potential for
NullPointerException
.
- In almost all cases you should NOT use the wrapper Boolean class as it opens up the potential for
- What are the differences between
final
,finally
,finalize
(deprecated in Java 17)?- final
- final method cannot be overridden
- final field once set a value cannot be assigned again
- final class cannot be extended. Variables declared outside of and used in an inner anonymous class, must be declared final.
- finally.
- Part of a try-catch statement. The code in a finally block always executes
- What if there is a return statement in a catch, or try?
- The finally block will still execute before returning
- finalize
- A method that invoked on an object just before it is garbage collected. Similar to a destructor in C++.
- final
- What is the difference between RuntimeException (and sub-classes) and Exception (and sub-classes)?
- You are not required to throw or catch RuntimeExceptions.
- Explain the difference between Interfaces and Abstract classes.
Inheritance
- Can a method be declared “abstract”?
- Yes, in an abstract class. Any concrete sub-class must provide an implementation of the method.
- How are all method signatures in an interface implicitly declared?
- public abstract
- Can an interface declare static methods? No.
- What access level must all fields in an interface be declared?
public static final
- *How can a Java class exhibit multiple inheritance? Java 8 introduced the concept of a default method that can be defined on an interface. Thus, you can create two different interfaces that have a default implementation of two different methods. If you then write a concrete class that implements both of the interfaces you have effectively inherited the methods from both “classes/interfaces”. If, both of the interfaces define the same method, you will need to override that method signature in your concrete implementation class and either override the functionality completely or call the method in one of the parent interfaces.
Java Specific
NIO
IO
Comparable interface
boolean compareTo(Object o)
int equals(Object o)
int hashCode()
Java 8 specifics
Java Lambdas:
Both approaches have the same effect: a Runnable-implementing object whose run() method is being invoked to print something to the console. Under the hood, however, the Java 8 version is doing a little more than just generating an anonymous class that implements the Runnable interface—some of which has to do with the invoke dynamic bytecode that was introduced in Java 7. We won’t get to that level of detail here, but know that this is more than “just” an anonymous class instance.
From http://www.oracle.com/technetwork/articles/java/architect-lambdas-part1-2080972.html
. Figure out exactly what is meant by the invoke dynamic bytecode that is mentioned above.
Java Big-O:
get add contains next remove Iterator.remove
Array: O(1) O(1) O(n) O(1) O(1)
ArrayList: O(1) O(1) O(n) O(1) O(1) O(n)
O(n) if
create new
LinkedList: O(n) O(1) O(n) O(1) O(1) O(1)
HashMap: O(1) O(1) O(n/h) [h is table capacity], more
probably is that it is O(1), but O(n/h) is worst
LinkedHashMap: O(1) O(1) O(1)
TreeMap: O(log n) O(log n) O(log n)
ConcurrentH: O(1) O(1) O(h/n)
http://www.leepoint.net/notes-java/algorithms/big-oh/bigoh.html
HashSet: O(1) O(1) O(h/n) [h is table capacity]
LinkedHashSet: O(1) O(1) O(1)
TreeSet: O(log n) O(log n) O(log n)
Type bits ranges
byte 8 -128 – 127
short 16 -32,768 – 32,767
char 16 ‘\u0000’ (or 0) and a maximum value of ‘\uffff’ (or 0 – 65,535 inclusive)
int 32 -2,147,483,648 – 2,147,483,647 (2.147 Billion)
long 64 -9,223,372,036,854,775,808 – 9,223,372,036,854,775,807 (9.223 quintillion)
float 32
double 64
. Formatting output
. Format specifiers for gen char and numeric syntax: %[argument_index$][flags][width][.precision]conversion
. Format specifiers for dates and times syntax: %[argument_index$][flags][width]conversion
. Format specifiers which do not correspond to arguments syntax: %[flags][width]conversion
. Strings:
. http://www.homeandlearn.co.uk/java/java_formatted_strings.html
. Formatting output with leading spaces: | 45foo| -> |45 foo|
. String.format("%4sfoo", 45);
. String.format("%-4sfoo", 45);
. Calendar/Dates:
. Sample data formatting: String.format("%1$tY-%1$tm-%1$td", new Date()) = 2013-01-22
. Go over regex Pattern.compile(“regex”) syntax
. Basic methods of String and Array
. Basic I/O