Java is an object-oriented programming language that was the primary language of the Android SDK for over a decade. Despite Google's official transition to Kotlin, Java remains an important part of the ecosystem: legacy projects, enterprise applications and millions of lines of code on Google Play continue to run on Java. According to the JetBrains Developer Ecosystem report (2025), about 35% of Android projects still use Java. Read more about current trends in the official JetBrains report.
Key Takeaways
Java is a general-purpose programming language created by Sun Microsystems in 1995. The main principle is "Write Once, Run Anywhere": compiled Java bytecode runs on any platform with a JVM virtual machine installed. In the context of mobile development, Java became the first official language of the Android SDK, released by Google in 2008.
The Java architecture is based on three components: JDK (Java Development Kit) — a set of developer tools, JRE (Java Runtime Environment) — the runtime environment, and JVM (Java Virtual Machine) — the virtual machine. Android uses its own JVM implementation — Android Runtime (ART), which replaced Dalvik in version 5.0 (Lollipop). ART executes DEX bytecode, which is compiled from Java bytecode via the dx/d8 utility.
A key feature of Java is automatic memory management through the Garbage Collector (GC). The developer does not need to explicitly free memory — the GC tracks unused objects and removes them. In Android ART, Concurrent Mark Sweep (CMS) and Generational GC are used, optimized for limited mobile device resources. This reduces the developer's workload but can cause "lags" during garbage collection on the UI thread.
Android supports a subset of Java API that expands with each new OS version. Android 12 (API 31) added support for Java 11, including lambda variable capture, the JPMS module system, and the java.net.http HTTP client. Android 14 (API 34) introduced experimental support for Java 17 through D8/R8 desugaring — some features (records, sealed classes) are translated into compatible code for older versions.
| Java Version | Android API (min) | Android Version | Key Features |
|---|---|---|---|
| Java 7 | API 19 | 4.4 KitKat | try-with-resources, multi-catch |
| Java 8 | API 24 | 7.0 Nougat | Lambdas, Stream API, Optional |
| Java 11 | API 31 | 12 | HTTP Client, Local-Variable Syntax |
| Java 17 | API 34 | 14 | Records, Sealed Classes (D8) |
Android SDK includes the Java compiler, dex utility (d8), aapt (Asset Packaging Tool), emulator, and android.* and java.* libraries. The developer writes code in Java, compiles it into .class files (JVM bytecode), then d8 converts them into .dex files (Dalvik Executable), which are packaged into APK along with resources and AndroidManifest.xml.
Gradle is the Android project build system. The build.gradle (Groovy) or build.gradle.kts (Kotlin DSL) file describes dependencies, SDK versions, product flavors and signatures. Android Gradle Plugin (AGP) version 8.x automates desugar — translation of modern Java features into backward-compatible code. For example, java.time.LocalDate is converted into API 21+ compatible code without changes in the developer's source.
// Simple Android Activity in Java
package com.example.myapp;
import android.os.Bundle;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.textView);
tv.setText("Hello from Java!");
}
// Method to handle button click
public void onButtonClick(View view) {
TextView tv = findViewById(R.id.textView);
tv.setText("Button clicked");
}
}The MainActivity class extends AppCompatActivity — a base class from AndroidX for backward compatibility. The onCreate method is called when the Activity is created; it sets the layout via setContentView. findViewById connects a Java variable to an element from the XML layout. The onButtonClick method is bound to the button via the android:onClick attribute in XML.
The Activity lifecycle in Java is a sequence of callbacks: onCreate → onStart → onResume (active), onPause → onStop → onDestroy (termination). The developer overrides these methods to manage resources. onCreate — initialization, onPause — data saving, onDestroy — resource release. Android calls these methods during screen rotation, entering the background, and receiving a phone call.
// Activity lifecycle with state management
public class DetailActivity extends AppCompatActivity {
private String itemId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
itemId = getIntent().getStringExtra("ITEM_ID");
loadData(itemId);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("item_id", itemId);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
itemId = savedInstanceState.getString("item_id");
loadData(itemId);
}
private void loadData(String id) {
// Loading data by identifier
}
}The onSaveInstanceState method saves the Activity state during screen rotation or task switching. Bundle contains key-value pairs — simple types, Parcelable or Serializable objects. onRestoreInstanceState restores the saved state. This pattern is critical for Android, as the system can destroy the Activity when memory is low and restore it when the user returns.
Java syntax is C-like, strongly typed, object-oriented. Each .java file contains one public class whose name matches the file name. Java does not support functions outside classes — everything is a method. The entry point is the static method public static void main(String[] args) for console applications or Android Activity lifecycle methods for mobile.
Java divides types into primitives (int, double, boolean, char, byte, short, long, float) and reference types (classes, interfaces, arrays, enum). Primitives are stored on the stack and passed by value. Objects are stored in the heap, passed by reference. Autoboxing automatically converts a primitive into a wrapper object (Integer, Double, Boolean), but creates extra objects — in Android this is critical for UI performance.
// Java data types and structures examples
public class DataTypes {
// Primitives
int count = 42;
double price = 19.99;
boolean isActive = true;
char grade = 'A';
// Reference types
String name = "Android";
Integer boxed = 100; // autoboxing
List<String> items = new ArrayList<>();
// Method with Generics
public <T> T getFirst(List<T> list) {
return list.isEmpty() ? null : list.get(0);
}
// Enum for fixed set of values
public enum Status {
PENDING, LOADING, SUCCESS, ERROR
}
}Generics List<T> provide type safety for collections. The getFirst method returns an element of any type — the specific type is determined at the call site. Enum Status compiles into a class with a fixed set of constants, each instance is a singleton. In Android, enum is used less often due to memory consumption: ProGuard/R8 optimizes enum into int constants where possible.
Comparing Java and Kotlin for Android development has been one of the main topics since 2019, when Google declared Kotlin the priority language. Kotlin is fully compatible with Java — both compile to JVM bytecode, can call each other, and use the same libraries. However, approaches to writing code differ dramatically.
Kotlin eliminates the verbosity of Java: data class replaces 50+ lines of Java class with getters, setters, equals, hashCode, toString and copy. Null safety is built into Kotlin's type system — NullPointerException is practically impossible. Extension functions allow adding methods to existing classes without inheritance. Smart Casts automatically cast types after checking.
| Aspect | Java | Kotlin |
|---|---|---|
| Null safety | @Nullable / @NonNull annotations | String? / String — built-in |
| Data class | 50+ lines with Lombok | data class User(val name: String) |
| Extension | Static utility classes | fun String.isEmail(): Boolean |
| Coroutines | AsyncTask / ExecutorService | suspend + Structured Concurrency |
| Lambdas | FunctionalInterface + ::method | Lambdas by default |
| DI annotations | @Inject, @Module, @Provides | Similar, but less code |
In terms of performance, Java and Kotlin are identical — both compile to JVM bytecode, which Android ART executes the same way. The difference lies in APK size: Kotlin adds ~200-400 KB for the kotlin-stdlib library. Java projects have a smaller APK size due to the absence of additional runtime, but when using Java Stream API and Optional, APK size may increase due to desugaring.
Java developer tools for Android include Android Studio, Gradle, profiler and emulator. Android Studio is the official IDE, based on IntelliJ IDEA Community, featuring a Java autocomplete editor, code analyzer (lint), refactoring and a visual layout editor (Layout Editor).
Android Gradle Plugin (AGP) version 8.x manages the build: Java compilation into classes, desugaring, ProGuard/R8 minification, packaging into APK/AAB. R8 is an updated desugaring and obfuscator, replacing ProGuard. Build variants (debug/release + product flavors) are configured via build.gradle. Gradle Daemon speeds up subsequent builds through caching.
// build.gradle (app) — Java module configuration
android {
compileSdk 34
defaultConfig {
applicationId "com.example.myapp"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
testImplementation 'junit:junit:4.13.2'
}The compileOptions block specifies the Java version for compilation — Java 17 is available with AGP 8.x. The minimum SDK (minSdk) determines the minimum Android version the application runs on. Target SDK is the version the application was tested against. The difference between compileSdk and targetSdk: compileSdk is the API for compilation, targetSdk is the runtime behavior.
Limitations of Java in Android led to Google's transition to Kotlin. NullPointerException is the most common exception in Java Android applications, since the type system does not distinguish between nullable and non-null references. Google recommends @Nullable and @NonNull annotations from the androidx.annotation package, but the compiler does not check them — only lint does.
The absence of coroutines is another limitation: asynchronous operations in Java require callbacks, AsyncTask (deprecated since API 30), ExecutorService or RxJava. This leads to callback hell and memory leaks during screen rotation. Kotlin coroutines with Structured Concurrency solve this problem at the language level: a coroutine is cancelled when the Activity is destroyed without manual management.
Boilerplate code in Java is a source of errors when manually writing equals/hashCode, Parcelable implementations and ViewHolder for RecyclerView. Android KTX libraries and Jetpack Compose are oriented towards Kotlin. New Android APIs (Room, Navigation, Compose) publish examples in Kotlin by default, although Java versions exist.
Frequently Asked Questions
Java is an object-oriented programming language from Sun Microsystems (1995), running on the JVM virtual machine. It was the primary language of the Android SDK until 2019. It is used in mobile development for legacy projects, server-side (Spring) and enterprise applications. It features strong typing, automatic garbage collection and cross-platform bytecode.
Google declared Kotlin the priority language for Android in 2019. New AndroidX libraries, Jetpack Compose, architecture recommendations, and documentation are by default provided in Kotlin. Java remains fully supported, but APIs are designed with a Kotlin-first approach. Java projects require more boilerplate code and do not receive new language features first.
Android fully supports Java 8, Java 11 partially since Android 12+, and Java 17 experimentally through D8 desugaring. Android Gradle Plugin (AGP) 8.x translates modern bytecode into compatible code for older APIs via desugar. Developers can write in Java 11+, using lambdas, Optional and DateTime API, but records and sealed classes are only available through D8.
Kotlin requires less code: data class replaces dozens of lines of Java boilerplate, null safety is built into types, coroutines simplify async operations. Java offers simpler syntax for beginners, a proven library ecosystem and stable tooling. Runtime performance is identical — both compile to JVM bytecode executed by Android ART.
Android Studio is the standard IDE for Android development with support for Java and Kotlin. It includes an emulator, profiler (CPU, memory, network), Layout Inspector, APK Analyzer. IntelliJ IDEA is suitable for server Java. Eclipse ADT is deprecated and not supported by Google. Android Studio also provides tools for migrating Java code to Kotlin through the built-in converter.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also