Have attended as well as taken couple of Java tech interviews over the course of my career, some good some not so good either ways.
However what baffles me the most is that lot of folks that I had evaluated seem to stumble on the very basic core concepts, these are profiles with a good 8 to 10 years of Java experience and when asked how many constructors does java.lang.Object class have they go hmm..... None or 1 or 2 or famously do not remember, come on - we call ourselves Java professional the least we can do give java.lang.Object some respect after all its the big daddy of all java classes.
Will try to sum up some of the basic core Java concepts that I personally feel every Java professional should know, again these are solely my opinions based on my reading and posts over the internet, please feel free to comment on others that you feel are important as well.
1. Know your Object
From the JavaDocs - "Class Object is the root of the class hierarchy. Every class has Object as a
superclass. All objects, including arrays, implement the methods of this class"
Methods from Object class which one should know top of their head- toString() equals() hashCode()
finalize() clone() getClass() wait() notify()
finalize() clone() getClass() wait() notify()
Rules for the equals method - reflexive symmetric transitive consistent. Josh Bloch's Effective
Java talks superbly about equals and hashCode. A must have for every Java Professional.
What does hashCode method do - Its returns a hashCode, a generated integer/long value which
by default is obtained by converting the internal address of the object into an integer. HashCode aids
when the objects are stored in hash based collections - HashMap, HashTables. Hashing it Out a nice one
I came across about equals and hashCode.
2. Know your Access Modifiers
Yes the code shown is very valid Java code, yet many fell for the private static final trap.
Need to clearly understand that the reference variable aMap is final, however the Map itself is not and can be manipulated.
We are aware of public, private, protected and default (friendly) access modifiers, not just what they are but understand their practicalities. Familiarize with Access Modifiers if not done in a while.
3. Know your Memory
Java Memory Model includes the Heap and Stack. Stack is the memory allocation where methods
and local variables live, these are generally short lived. Heap is where Objects and member variables or
instance variables live these generally live longer. Java 6 though may have some optimization and the JVM
may allocate objects on the stack.
may allocate objects on the stack.
In multi-threaded programs, each thread will have its own stack allocations but all threads will share a
common heap, so need to be extra cautious when dealing with mutable objects all residing on the same
shared heap.
Heap is divided into Eden, Survivor Spaces, Old Generation and Perm Generation.
Eden - When new Objects are created memory allocation first takes place in the Eden.
Survivor Spaces - As the Objects survive Garbage Collection they move to Survivor spaces, there are 2
of them from and to Survivor Spaces.
Eden and the Survivor spaces together make up the Young Generation or Young gen for short.
Old Generation - As the Survivor spaces gets crowded, older objects move to the Old Generation.
These are objects which have survived multiple GC's, hence "old" generation as in OLD objects.
Perm Generation - This stores VM and Class Meta Data Details, these are used internal by the
VM. Perm Gen is in the process of being eliminated, Java 8 may no longer support Perm Gen moving
forward.
Java Heap is nothing but the combination of the Young Gen and Old Gen. Minor GC's happen when
Objects are reclaimed or move from Eden to the Survivor Spaces. Major GC's (Stop the World
GC) happens when Old Gen starts getting over crowed and memory needs to be freed. There are lot of
implications in the way we create our Objects. Even though we do not directly deal with memory we still
have to be very conservative when creating and maintaining object references in our programs, after all
nothing is really free in this world, there's always a catch.
Charlie Hunt's - Java Performance Talk, an excellent talk about Java Performance tuning has a very nice
intro to the Java Memory Model.
4. Know your Collections
Java Collections are data structures that allow you to easily work and manipulate collection of data. They
pretty easy to use and probably the best example of re-use, cannot think of any real world java
applications that can do without the use of collections.
Collections API is made up of 7 core interfaces (Collection, Set, SortedSet, List, Queue, Map,
SortedMap)
Collection interface is the root interface of the collection hierarchy. A Collection contains groups of
objects which are called as elements. Set, List and Queue are sub-interfaces from the root Collection
interface.
Set is a collection that cannot contain duplicate elements, models the mathematical set construct to
represents sets like a deck of cards comprising a poker hand. When objects are stored in a set collection
the equals and hashCode methods must be correctly overridden to make sure that objects obey set
construct rules.
SortedSet is a special kind of set which maintains its unique elements in an ascending order or natural
ordering of the elements. A comparator may also be used at creation time of the sorted set when sorting
the elements.
List is an ordered or sequenced collection of elements. Lists can contain duplicate elements. The order in
which the elements are added to the list are maintained. List provides for positional indexed access to list
elements. SubList returns a view of the portion of this list between the specified fromIndex, inclusive, and
toIndex, quite handy when dealing with large lists and concurrent implementations.
Queue is a collection that holds multiple elements prior to processing, think of Queue literally like a queue
or line at a bus stand, by default people standing in the queue get into the bus in the order they are in
the queue. Queues by default order elements in a FIFO (first-in, first-out) manner
Map is a type of collection in which elements are stored using keys. Map cannot contain duplicate keys
and each key can point to only one value/element.
SortedMap maintains mappings in ascending key order. Sorted maps are used for naturally ordered
collections of key/value pairs
Some handy collections implementations:
ArrayList - Resizable-array implementation of the List interface.
CopyOnWriteArrayList - A thread-safe variant of ArrayList in which all mutative operations (add, set,
and so on) are implemented by making a fresh copy of the underlying array.
Stack - Represents a last-in-first-out (LIFO) stack of objects.
Vector - Synchronized growable array of objects.
CopyOnWriteArraySet - A Set that uses an internal CopyOnWriteArrayList for all of its operations.
EnumSet - A specialized Set implementation for use with enum types.
HashSet - Set implementation backed by a HashMap instance.
HashMap - Hash table based implementation of the Map interface which is not synchronized
WeakHashMap - A hashtable-based Map implementation with weak keys. Entries will automatically be
removed when its key is no longer in use.
Collections Trail is still the best place for brushing up on Java Collection API.
Collections class (Collections ending with s) consists exclusively of static methods that operate on or
return collections -
binarySearch methods searches the specified list for the specified object using the binary search
algorithm.
Sort methods sorts specified list into ascending order, according to the natural ordering of its
elements or according to the order induced by the specified comparator.
Synchronized methods returns synchronized (thread-safe) collection backed by the
specified collection.
Unmodifiable methods returns an unmodifiable view of the specified collection.
Iterator enables to traverse through a collection in the forward direction only, for obtaining or removing
elements. ListIterator extends Iterator, and allows bidirectional traversal of list and also allows the
modification of elements.
Implementations of the Comparator interface can be used to sort/order implements in collections by
overriding the compare method which takes in two objects.
Implementations of the Comparable interface are used for natural or default ordering of elements.
Ideally if you are the author of the elements being stored in a collection, then the elements can implement
the comparable interface and compareTo method can be overridden, however if you have no control over
the elements in a collection, comparator is the only way.
5. Know your IO (and NIO)
Java IO package stands for Input and Output. The java io package deals with reading data from one input
source and writing data to some destination. Most typical data sources and destinations include -
Files,Pipes,Network Connections,System.in, System.out.
A program that reads data needs an Input stream or Reader. A program writes data needs an
Output Stream or Writer. Java IO package is made up of Streams, Readers and Writers. Streams
deal with raw bytes of data while Readers/Writers deal with characters.
Root Abstract Classes - InputStream and OutputStream
When dealing with Arrays - ByteArrayInputStream and ByteArrayOutputStream
When working with Files - FileInputStream RandomAccessFile and FileOutputStream
RandomAccessFile
When working with Pipes - PipedInputStream and PipedOutputStream
When working with chunks using buffers - BufferedInputStream and BufferedOutputStream
When in need of filters - FilterInputStream and FilterOutputStream
For Object Serializations - ObjectInputStream and ObjectOutputStream
When working with raw data streams reading primitive Java data types from an underlying streams -
DataInputStream and DataOutputStream
Character Based
Root Abstract Classes - Reader and Writer
Bridge classes that bridge Byte streams to Character stream - InputStreamReader and
OutputStreamWriter
When dealing with Arrays - CharArrayReader and CharArrayWriter
When working with Files - FileReader and FileWriter
When working with Pipes - PipedReader and PipedWriter
When working with chunks using buffers - BufferedReader and BufferedWriter
When working with Filters - FilterReader and FilterWriter
When dealing with Strings - StringReader and StringWriter
Java IO Trail which gives a good overview of the IO package.
Java NIO Java New IO supplements the java IO API and provides improved performance in the
areas of buffer management, scalable network and file I/O.
Channels and Buffers
In contrast to byte streams and character streams in java io, nio provides channels and buffers. Program
read from a channel to a buffer and similarly when writing, data is written from a buffer to a channel.
FileChannel - A channel for reading, writing, mapping, and manipulating a file.
SocketChannel -A selectable channel for stream-oriented connecting sockets.
ServerSocketChannel -A selectable channel for stream-oriented listening sockets.
ByteBuffer - Byte buffer.
CharBuffer - Char buffer
DoubleBuffer - Double buffer
FloatBuffer - Float buffer
IntBuffer - Int Buffer
LongBuffer - Long Buffer
ShortBuffer - Short Buffer
Asynchronous IO
NIO supports asynchronous IO for example, when a processing thread works with a channel to read
data into a buffer, as the channel reads data into the buffer, the thread can do something else, Once data
is available in the buffer, the thread can continue processing same applies when writing data as well
data into a buffer, as the channel reads data into the buffer, the thread can do something else, Once data
is available in the buffer, the thread can continue processing same applies when writing data as well
Selectors
A selector is an object that can monitor multiple channels for events for example - connection opened,
data available in buffer. This way a single thread can monitor multiple channels for data.
When using a Selector, one must register the various Channels, that this selector will monitor for events,
then the select() method is called which will cause the method to block until there is an event ready for
one of the channels registered.
6. Know your Threads.
Threads are essentially sub-processes, informally these are tasks belonging to a larger program that
run simultaneously.A program is a process and threads are sub-processes that run in parallel to
speed up the entire process. The thread scheduler of the CPU decides which thread to allocate CPU
time based on the priority of the threads.
Program Concurrency indicates how effectively an application allows multiple jobs to run simultaneously
Runnable should be implemented in-order to execute tasks concurrently by threads. The class must define
a method of no arguments called run.
Thread class is a thread of execution in a program. One extends the Thread class and overrides the run
method.
Object's wait method causes the current to wait or until another thread invokes the notify or notifyAll
method or until the wait timeout if provided elapses.
ThreadLocal supports Thread-Local variables, which means each thread that accesses the variable via
its get or set method has its own independent initialized copy of the variable. ThreadLocal instances are
typically private static fields in classes that wish to associate state with a thread example userID.
Volatile keyword used with variables is a flag to the JVM indicating that the variable can be modified by
multiple threads. Volatile means the value of the variable will never be cached by a thread locally, all
read writes will go straight to the main memory.
Synchronization means sharing of data between multiple processes or threads. However care needs to be
taken that each thread sees the correct version of the data as multiple threads try to access this piece of
data. Synchronized keyword is used to provide such thread safety on shared data so that only one thread
will have access to the shared data at any given time, this is achieved by objects locks, in which an object
acquire a lock on the shared data and is allowed to work on the shared data while other threads wait until
the lock is released.
Java Synchronization mechanism has some limitations, a thread could potentially block forever waiting to
acquire a lock on the object, which could lead to a deadlock where two or more thread block forever
waiting on each other.
Multi-Threading in java is no easy piece of cake and surely not for the faint-hearted. The simplest way to
avoid problems with concurrency is to share only immutable data between threads. Immutable data is
data which can not changed, or another alternative is to make defensive copies of the data being used in
multi-threaded applications.
The java concurrent package is what one will use most of the time when writing multi-threaded idioms for
our applications. The concurrent package provides the following constructs.
Locks:
To overcome synchronization limitations using the synchronized keyword, java concurrent.locks package
contains sophisticated locking idioms.
Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks,
only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism
The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to
acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout
expires (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before
the lock is acquired.
Lock - Root interface of of locking implementations
ReadWriteLock - Maintains a pair of associated locks, one for read-only operations and one for
writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no
writers. The write lock is exclusive.
Conditions - Where a Lock replaces the use of synchronized methods and statements, a Condition
replaces the use of the Object monitor methods (wait and notify).
Executors:
Executor is an object that executes submitted Runnable tasks. Executor provides a way of decoupling
task submission from the mechanics of how each task will be run, including details of thread use,
scheduling, etc. An Executor is normally used instead of explicitly creating threads.
Callable - is similar in concept to Runnable interface, which represents task to be executed. The only
difference is that its call() method returns a value when it is done executing.
Executor - abstracts the Thread creation and executes all Runnable tasks. An Executor is normally
used instead of explicitly creating threads. For example, rather than invoking new
Thread(new(RunnableTask())).start() for each of a set of tasks, you might use:
Executor executor = anExecutor;
executor.execute(new RunnableTask1());
ExecutorService - extends the Executor and is able to execute Callable tasks in addition to Runnable
tasks. It also contains life cycle management methods. An ExecutorService can be shut down, which
will cause it to stop accepting new tasks. After being shut down, the executor will eventually terminate,
at which point no tasks are actively executing, no tasks are awaiting execution, and no new tasks can
be submitted.
ScheduledExecutorService - allows us to schedule the asynchronous tasks thereby adding support
for delayed and periodic task execution. The schedule methods create tasks with various delays
and return a task object that can be used to cancel or check execution. The scheduleAtFixedRate
and scheduleWithFixedDelay methods create and execute tasks that run periodically
until cancelled.
Future - represents the result of the asynchronous task which itself could be represented as Callable.
The ExecutorService which can execute Callable tasks returns a Future object to return the result of the
Callable task. A Future represents the result of an asynchronous computation. Methods are provided
to check if the computation is complete, to wait for its completion, and to retrieve the result of the
computation.
Concurrent Collections:
The java concurrent package provides some new additions that supplement the java collections
framework to provide multi-threaded support for collections.
ConcurrentHashMap - is a hash based Map like HashMap, but it uses a different locking strategy
that offers better concurrency and scalability. Instead of synchronizing every method on a common
lock, restricting access to a single thread at a time, it uses a finer-grained locking mechanism called
lock striping. When writing to a ConcurrentHashMap only a portion of the map is locked, reads
generally happen without any locking.
CopyOnWriteArrayList - is a concurrent replacement for a synchronized List that offers better
concurrency and eliminates the need to lock or copy the collection during iteration, similarly,
CopyOnWriteArraySet is a concurrent replacement for a synchronized Set. These allow for multiple
concurrent reads, however during a write a brand new copy of the list/sit is created, only one write can
occur at a time. CopyOnWrite collections makes good sense when reads outnumber the frequency of
writes.
BlockingQueue - is a Queue implementation supporting the first in first out (FIFO) order but with the
added guarantee that any attempt to retrieve an item from an empty queue will block the calling thread
until the item is ready to be retrieved. Likewise, any attempt to insert an item into a queue that is full will
block the calling thread until space becomes available in the queue's storage. BlockingQueue neatly
solves the problem of how to "hand off" items gathered by one thread to another thread for processing,
without explicit concern for synchronization issues.
SynchronousQueues - is similar to a BlockingQueue, however this queue does not have any internal
capacity not even one. Essentially it gives us an extremely lightweight way to exchange single elements
from one thread to another, using the blocking semantics offered by BlockingQueue.
Atomic Variables:
The concurrent atomic package defines classes that support atomic operations on single variables. All
classes have get and set methods that work like reads and writes on volatile variables.
AtomicBoolean - A boolean value that may be updated atomically.
AtomicInteger - An int value that may be updated atomically.
AtomicLong - A long value that may be updated atomically.
AtomicLongArray - A long array in which elements may be updated atomically.
AtomicReference
AtomicIntegerArray - An int array in which elements may be updated atomically.
CountDown Latch:
Allows to co-ordinate starting and stopping of threads, this is used when several threads need to start at
the same time and then wait at a common point for all the threads to complete. A latch is a type of trigger
or switch, the latch is set up with a particular count value, the count is then counted down, threads will wait
for the countdown to reach zero before continuing to perform other operations. Once reset the latch
cannot be reset. CountDownLatch enables a Thread or Threads to wait for completion of Children
Threads. But there is no waiting amongst the Children until they finish each others tasks. Children may
execute asynchronously and after their work is done will exit making a countdown.
CyclicBarrier:
CyclicBarrier can be used to create a set of Children Threads if the size of the Threads created is known
forehand. CyclicBarrier can be used to implement waiting amongst Children Threads until all of them finish.
This is useful where parallel threads needs to perform a job which requires sequential execution. Cyclic
barrier can be reset after all Threads are finished execution.
Java Concurrency trail is an essential to grasp concurrency concepts.
Concurrency Guru's Dough Lea and Brian Goetz and are masters at their craft when it comes to Java
Concurrency.
Victor Grazi's Java Concurrent Animated has been around for a while now and offer's an animated look
into the internal working of concurrency.
7. Know your java/bin.
We all know where java ,javac and javadoc is, yep under /bin/ directory of our Java installations. We use
java, javac and javadoc directly or indirectly in our every day work, very likely through the use of some
Java IDE's, however I am pretty sure more of us may not be aware of other goodies that come along
with the java/bin directory.
Just a few days ago, was having a discussion about WebServices and someone goes hey can you tell me
where to download the wsimport utility tool, yep IDE's tends to spoil us sometimes. So i guess its worth
a mention of the tools that come along under java/bin
Following are java tools/utilities available under java/bin for (jdk1.7.0_03)
appletviewer - Has been from the start allows to view Applets (doubt if anyone still works with Applets).
apt - Annotation Processing Tool. finds and executes annotation processors based on the annotations
present in the set of specified source files being examined.
extcheck - The extcheck utility checks a specified Jar file for title and version conflicts with any
extensions installed in the JavaTM 2 SDK. Before installing an extension, you can use this utility to see if
the same or a more recent version of the extension is already installed.
idlj - Generates Java bindings from a given IDL file, where IDL is interface definition language, one can
define interface using OMG (Object Management Groups - CORBA fame) constructs and then generate
java bindings using idlj.
jar - Combines multiple files into a single JAR archive file.
jarsigner - Generates signatures for Java ARchive (JAR) files, and verifies the signatures of signed JAR
files.
javah - Produces C header files and C source files from a Java class. These files provide the connective
glue that allow your Java and C code to interact.
javap - Disassembles class files, Decompiler.
java-rmi - Accepts RMI-over-HTTP requests and forwards them to an RMI server listening on any
port.
javaw - Java Applications Launcher, similar to java, however javaw will not open a console window for
the application.
javaws - Java Web Start launcher command.
jconsole - Graphical user interface is a monitoring tool that complies to the Java Management Extensions
(JMX) specification.
jdb - Helps you find and fix bugs in Java language programs.
jhat - Java Heap Analysis Tool.
jinfo - Java Configuration Info, used in core dumps and debugging info.
jmap - Java Memory Map,
jps - Java Virtual Machine Process Status Tool.
jrunscript - Command line script shell. By default, JavaScript is the language used, but the -l option can
be used to specify a different language. This tool is experimental and may not be available in future
versions of the JDK.
jsadebugd - Attaches to a Java process or core file and acts as a debug server.
jstack - Stack Trace.
jstat and jstatd- Java Virtual Machine Statistics Monitoring Tool and Daemon process.
jvisualvm - Java Virtual Machine Monitoring, Troubleshooting, and Profiling Tool.
keytool - Key and Certificate Management Tool.
kinit , klist and ktab Obtain and cache Kerberos ticket-granting ticket. Kerberos display entries in
credentials cache and keytab. Kerberos key table manager.
native2ascii - Converts a file with native-encoded characters (characters which are non-Latin 1 and
non-Unicode) to one with Unicode-encoded characters.
orbd - The Object Request Broker Daemon.
pack200 - To increase server and network availability and band-width, two new compression formats
are available to Java deployment of applications and applets: gzip and Pack200.
policytool - Creates and modifies the external policy configuration files that define your installation's Java
security policy.
rmic, rmid and rmiregistry - RMI compiler, daemon and RMI Registry.
schemagen - schema generator simply creates a schema file for each namespace referenced in your Java
classes.
serialver - The Serial Version Command. Returns the
serialVersionUID
for one or
more classes in aform suitable for copying into an evolving class. When invoked with no arguments it prints a usage line.
servertool - Provides a command-line interface for application programmers to register, unregister,
startup, and shutdown a persistent server.
tnameserv - Transient Naming Service, used in conjunction with IDL and CORBA Object Request
Broker Daemon.
unpack200 - JAR Unpacking tool.
wsgen - The
wsgen
tool generates JAX-WS portable artifacts used in
JAX-WS web services. The toolreads a web service endpoint implementation class (SEI) and generates all the required artifacts for web
service deployment, and invocation.
wsimport - The wsimport tool generates JAX-WS portable artifacts such as Service Endpoint Interface
(SEI), Service.
xjc - The binding compiler can be launched using the appropriate xjc shell script in the bin directory for
your platform.
Until next time, Thank you
Malcolm
Back to Java Thoughts
No comments:
Post a Comment