Core Java and Android Interview Concepts for Senior Developers
Data Types and Access Control
Java distinguishes between primitive and reference data types. Primitives include byte (8-bit), short (16-bit), int (32-bit), long (64-bit), float (32-bit), double (64-bit), char (16-bit), and boolean. Reference types encompass classes, interfaces, arrays, enumerations, and annotations.
Access control modifiers dictate visibility scope. Ranked from most restrictive to least, they are private (class level), default (package level), protected (subclass level), and public (universal access).
String comparison requires distinguishing between object reference equality and content equality. The == operator checks if two references point to the same memory address. The equals() method compares the actual character sequence content. For instance:
String s1 = new String("text");
String s2 = "text";
// s1 == s2 is false (different objects)
// s1.equals(s2) is true (same content)
Static methods belong to the class definition rather than an instance. While a subclass can inherit a static method from a parent, it cannot override it in the polymorphic sense; defining a method with the same signature in the subclass merely hides the parent's version.
Abstraction and Interfaces
An abstract class serves as a blueprint when a complete implementation cannot be defined. It may contain abstract methods (declared without a body) and concrete methods. Abstract classes cannot be instantiated directly and must be subclassed, with all abstract methods implemented by the child. They cannot be final, private, or static.
Interfaces define a contract of behavior. All fields in an interface are implicitly public, static, and final, while methods are public and abstract by default. Like abstract classes, interfaces cannot be instantiated.
The key differences between abstract classes and interfaces are:
- State: Abstract classes can maintain state (member variables); interfaces can only hold constants.
- Inheritance: A class can extend only one abstract class but implement multiple interfaces.
- Implementation: Abstract classes provide a partial implementation that subclasses can use; interfaces require the implementing class to provide the full logic.
Polymorphism
Polymorphism manifests primarily through method overloading and overriding. Overriding occurs when a subclass provides a specific implementation for a method already defined in its superclass. This determines runtime behavior based on the actual object type. Overloading happens within a single class, defining multiple methods with the same name but different parameter lists.
class Parent {
void show() { System.out.println("Parent"); }
}
class Child extends Parent {
@Override
void show() { System.out.println("Child"); }
}
Object Initialization
The execution Person p = new Person(); triggers the following sequence:
- The
Personclass bytecode is loaded into the method area. - Memory is allocated in the stack for the reference variable
p. - Memory is allocated in the heap for the
Personobject. - Instance variables are initialized to default values, then explicit initializers and constructors run.
- The memory address of the heap object is assigned to the stack variable
p.
String Handling
The String class is immutable; operations that appear to modify a string actually return a new object. In contrast, StringBuilder and StringBuffer represent mutable sequences of characters.
- StringBuffer: Synchronized, thread-safe, but slightly slower due to locking overhead.
- StringBuilder: Not synchronized, faster, and preferred for single-threaded scenarios.
Collections: Lists
ArrayList, Vector, and LinkedList serve different purposes.
- ArrayList: Implements a resizable array. Offers fast random access ($O(1)$) but slower insertions/deletions ($O(n)$) due to shifting elements. It is not thread-safe. When capacity is reached, it grows by approximately 50%.
- Vector: Similar to
ArrayListbut synchronized (thread-safe) and thus slower. It doubles in size when resizing. Generally,ArrayListis preferred overVector. - LinkedList: Implements a doubly-linked list. Offers fast insertions and deletions ($O(1)$ at ends) but slower random access ($O(n)$) as it must traverse nodes. It is not thread-safe.
SparseArray and ArrayMap
In Android, HashMap can be inefficient due to object overhead. Alternatives include:
- SparseArray: A map optimized for
intkeys. It avoids auto-boxing of integers, saving memory and garbage collection overhead. It stores keys and values in parallel arrays and uses binary search for lookups ($O(\log n)$). It is best for collections with fewer than 1,000 items. - ArrayMap: A general-purpose map implementation designed for memory efficiency. It manages two arrays (one for hash codes, one for keys/values) and keeps them sorted. Like
SparseArray, it uses binary search and is suitable for smaller datasets.
Map Implementations
HashMap vs HashTable:
- Thread Safety:
HashMapis unsynchronized;HashTableis synchronized. - Nulls:
HashMappermits onenullkey and multiplenullvalues;HashTabledoes not. - Performance:
HashMapis generally faster due to the lack of synchronization. - Iteration:
HashMapiterators are fail-fast;HashTableenumerators are not.
LinkedHashMap extends HashMap, maintaining a doubly-linked list running through all entries. This preserves insertion order (or access order if configured), unlike the unordered HashMap.
HashMap Internal Mechanics (JDK 8+)
- Structure: Uses an array of buckets (Node<K,V>), where each bucket is a linked list. If a list exceeds 8 elements (and the table size is >= 64), it transforms into a Red-Black tree for $O(\log n)$ lookup performance.
- Collision Resolution: Uses separate chaining with treeification for performence.
- Resizing: When the load factor (default 0.75) is exceeded, the capacity doubles. Unlike JDK 7, JDK 8 uses tail insertion during resize to prevent infinite loops in multi-threaded environments.
- Power of Two Size: Capacity is always a power of two. This allows the use of bitwise AND (
hash & (n-1)) instead of modulo operation for index calculation, which is computationally efficient.
ConcurrentHashMap
JDK 7: Uses "segmants" (ReentrantLock locks) where each segment covers a portion of the hash table, allowing concurrent reads.
JDK 8: Abandons segments. Uses CAS (Compare-And-Swap) operations for insertion and synchronized blocks only on the specific bucket head (node) during updates. The data structure is similar to HashMap (Array + Linked List + Red-Black Tree). This reduces lock contention and improves performance.
Reflection
Reflection allows runtime inspection of classes, interfaces, fields, and methods.
Obtaining Class Objects:
obj.getClass()ClassName.classClass.forName("com.example.MyClass")
Creating Objects:
Class<?> clazz = Class.forName("com.example.Person");
// Using no-arg constructor
Object instance = clazz.getDeclaredConstructor().newInstance();
Threading and Concurrency
Thread Creation
- Extending Thread:
class MyThread extends Thread { public void run() { ... } } - Implementing Runnable:
class MyTask implements Runnable { public void run() { ... } }
Wait vs Sleep
wait(): Releases the object lock. Belongs toObject. Must be called within a synchronized context.sleep(): Does not release the lock. Belongs toThread. Can be called anywhere.
Concurrency Concepts
- Atomicity: Operations appear indivisible.
- Visibility: Changes to variables are seen by other threads.
- Ordering: Instructions execute in the order expected by the code.
volatile ensures visibility and ordering but not atomicity. synchronized ensures all three.
Network Programming
HTTP Versions
- HTTP/1.0: Short-lived connections; a new TCP connection is needed for each resource.
- HTTP/1.1: Persistent connections (Keep-Alive) by default; pipelining allows sending multiple requests without waiting for responses; chunked transfer encoding.
- HTTP/2.0: Multiplexing (multiple requests over a single TCP connection), header compression (HPACK), and server push.
HTTPS
HTTPS (HTTP Secure) uses TLS/SSL for encryption. It combines HTTP with cryptography to ensure data integrity and confidentiality. It typically runs on port 443 (vs 80 for HTTP).
Handshake Process:
- Client sends
ClientHello. - Server responds with
ServerHelloand its digital certificate (containing the public key). - Client verifies the certificate.
- Client generates a pre-master secret, encrypts it with the server's public key, and sends it.
- Server decrypts the pre-master secret with its private key.
- Both parties generate the session key (symmetric key) from the pre-master secret.
- Subsequent data is encrypted using this symmetric key for performance.
Android Specifics
Data Storage
- Internal Storage: Private to the app.
- External Storage: Public or private media/files.
- SharedPreferences: Stores key-value pairs in XML files.
commit(): Synchronous, returns boolean.apply(): Asynchronous, no return value (preferred for UI thread).
- SQLite: Relational database.
- ContentProvider: Manages access to a structured set of data, enabling inter-app data sharing.
Reference Types
- Strong Reference: Default, prevents garbage collection.
- SoftReference: Cleared when memory is low.
- WeakReference: Cleared aggressively on GC cycles.
- PhantomReference: Cleared after finalization.
Activity Lifecycle
Launch Modes:
standard: Default. New instance created for every launch.singleTop: Reuses instance if it's at the top of the stack.singleTask: Reuses instance; clears other activities on top of it in the stack.singleInstance: Runs in its own unique task stack.
View Rendering
The rendering pipeline involves three steps:
- Measure:
onMeasure()determines dimensions. - Layout:
onLayout()positions children. - Draw:
onDraw()renders content.
requestLayout() triggers measure and layout. invalidate() triggers draw.
Animation
- View Animation: Tweens (alpha, scale, translate, rotate). Only alters visual drawing, not properties.
Viewlocation doesn't actually change. - Property Animation: Changes actual object properties (e.g.,
translationX). Works on any object (not just Views).
View Event Handling
Events flow in the order: dispatchTouchEvent -> onInterceptTouchEvent (ViewGroup only) -> onTouchEvent. requestDisallowInterceptTouchEvent(true) prevents parent ViewGroup from intercepting events.
IPC (Inter-Process Communication)
- AIDL (Android Interface Definition Language): Defines interfaces for clients and services to communicate using Binder IPC. Supports complex data types.
- Messenger: Handles messages via a
Handler. Simpler than AIDL but supports one-way requests (mostly). Good for low-concurrency commands. - ContentProvider: Exposes data across processes using a URI-based model.
- Binder: The underlying kernel driver for IPC. It is efficient (one memory copy), secure (UID-based checking), and stable.