How Hirenix teaches
One chapter. 90 minutes.
Interview-ready.
Every concept starts with a real-world problem — the kind that actually shows up in production code. Nothing to cram; it just clicks. Every question comes with a model answer: exactly what to say in the room, and why. Then an AI mock interview on the same chapter.
- 📖Concept in 5 minutesNo jargon — straight to the point
- 🛠️Real-world problemThe kind production code throws at you
- 💬Model answerExactly what to say in the room
- 🧠FlashcardsRevise in 10 minutes
- 🤖AI mock interviewIt asks follow-ups too
- 📊Weak topicsSee exactly where you're stuck

The difference isn’t the content — it’s the filter. Only what’s actually used in production and actually asked in interviews. Textbook topics the industry never touches don’t make the cut.
What you’ll learn
- ●What is Java? JVM, JRE, JDK
- ●Anatomy of a Java program
- Data types and variablesFree account
- Operators and control flowFree account
- Strings and the String poolFree account
- ArraysFree account
- Wrapper classes and autoboxingFree account
- static and finalFree account
- Memory: heap vs stackFree account
- Garbage collectionFree account
- Pass by valueFree account
- Modern Java (11 / 17)Free account
- RecapFree account
- ●Project: Student Report Card
- Project: Text AnalyzerFree account
- Project: Console ATMFree account
What is Java? JVM, JRE, JDK
You write a recipe once, in your own handwriting. Instead of handing it to one particular cook, you convert it into a standard recipe card — a format every professional kitchen in the world already knows how to read. Delhi, Dubai, Toronto: each city has its own cook who picks up that same card and prepares the dish using whatever stove, gas and utensils that kitchen happens to have. You never rewrite the recipe for a new city. You only need a cook there.
Java is built exactly on this idea.
- Your
.javafile is the recipe — written by you, for humans to read. javacconverts it into bytecode, a.classfile. That is the standard recipe card. It is not English, and it is also not your laptop's machine code. It is a middle language that one specific program knows how to read.- The JVM (Java Virtual Machine) is the cook. There is a different JVM built for Windows, for macOS, for Linux — but all of them read the same bytecode.
In production, this is why a .jar file built on a developer's Windows laptop is copied straight onto a Linux server and simply runs. Nobody recompiles it for Linux. The bytecode did not change; only the cook did. That property has a name interviewers expect from you: WORA — Write Once, Run Anywhere.
And notice the trade-off hiding in the analogy: the dish is not cooked directly by the kitchen, it goes through a cook. That extra layer is why Java was historically called slower than C++ — and it is also why the next idea exists.
The three names people mix up: JVM, JRE, JDK
These are not three competing things. They are three boxes, one inside the other.
| What it is | What is inside | Who needs it | |
|---|---|---|---|
| JVM | The engine that runs bytecode | Just the runtime engine | Nobody installs this alone |
| JRE | Java Runtime Environment | JVM + the standard libraries (String, Math, collections…) | A machine that only needs to run Java apps — a server |
| JDK | Java Development Kit | JRE + the development tools (javac, javap, jar, debugger) |
Anyone who writes Java — you |
Read it as one sentence: JDK contains JRE, and JRE contains JVM.
A question interviewers love: your server has only a JRE — can it run your app? Yes. It can run it, but it cannot compile it, because javac lives in the JDK. That single answer proves you understand the layering instead of having memorised three definitions.
JIT — why the first few seconds are slow and then it speeds up
If the JVM read and interpreted every bytecode instruction one at a time, every time, Java really would be slow. It does not. The JVM watches which methods run over and over — the "hot" ones — and the JIT (Just-In-Time) compiler compiles those into real native machine code while the program is running. After that, the JVM stops interpreting them and calls the compiled version directly.
Back to the kitchen: the cook notices the same dish being ordered a hundred times, so he pre-preps it. The first plate takes the longest; plate number two hundred is fast.
This is a real, visible effect, not trivia. A Java service is genuinely slower for its first few seconds after a restart, then settles. When you later hear a backend engineer say the JVM needs to "warm up", this is what they mean.
ClassLoader — nothing is loaded until it is needed
The JVM does not load your entire application into memory at startup. The ClassLoader fetches a .class file the first time that class is actually referenced — like a storeroom keeper who fetches an ingredient only when the recipe first calls for it.
This is worth knowing because it explains the most common startup failure a beginner meets. If a class is missing, you do not find out at compile time — you find out at the exact moment the program first touches it, as a ClassNotFoundException or a NoClassDefFoundError. The code compiled fine; the storeroom was just empty when the cook reached for the jar.
🌍 Real-world example: You build your college project on a Windows laptop and hand over a single
.jar. Your teammate runs it on a Mac and the company deploys the same file to a Linux server. Nothing is recompiled, no code is changed. Three different machines, three different JVMs, one identical bytecode file.
💡 bytecode = the intermediate instructions inside a
.classfile — not human language, not your CPU's machine code. 💡 JVM = the program that reads bytecode and runs it; a different build exists for each operating system. 💡 JRE = JVM + the standard Java libraries. Enough to run a Java app, not to compile one. 💡 JDK = JRE + development tools such asjavac. This is what a developer installs. 💡 JIT = the compiler inside the JVM that turns frequently-used bytecode into native machine code while the program runs. 💡 ClassLoader = the JVM component that loads a class into memory the first time it is referenced. 💡 WORA = Write Once, Run Anywhere — the property that one compiled file runs on any OS that has a JVM.
Standard definition: Java is a compiled and interpreted language: source code is compiled by javac into platform-independent bytecode, which is executed by the JVM, a platform-specific runtime that also uses a JIT compiler to convert hot bytecode into native machine code at runtime.
public class Hello {
public static void main(String[] args) {
int total = 2 + 3;
System.out.println("Total: " + total);
}
}Anatomy of a Java program
Think of a large office building. A courier arrives with a parcel for the company. The courier does not wander the corridors opening doors, and does not know a single employee by name. There is exactly one reception desk — at a fixed spot, with a fixed name, open to anyone off the street, and staffed by the building itself rather than by any particular employee who may or may not be in that day. The parcel is handed over there. That single desk is the whole agreement between the outside world and the building.
When you type java Anatomy, the JVM is that courier. It has just loaded your class and knows nothing about it. It needs one door, with an agreed name and an agreed shape:
public static void main(String[] args)
Break any one word of that agreement and your program does not start.
| word | what it means | why the JVM needs it |
|---|---|---|
public |
callable from outside the class | the JVM is outside your class |
static |
belongs to the class, not to an object | at startup, no object of your class exists yet |
void |
returns nothing | the JVM has no use for a return value; exit codes go through System.exit(int) |
main |
the agreed name | the JVM looks for exactly this name |
String[] args |
array of command-line arguments | how the outside world passes input in |
static is the word that carries real weight. To call an ordinary instance method you first need an object: new Anatomy().run(). But at the instant the program starts, nothing has run yet — so nobody has created that object. If main needed an object, your program would have to already be running in order to start. static breaks that circle: a static method belongs to the class itself, and the class is loaded before any object exists.
In production, String[] args is how one jar behaves differently in different environments — java -jar report.jar 2026 sales runs the 2026 sales report without touching a line of code. It is also why a Spring Boot application still has a plain main: it is the only door the JVM will use, so SpringApplication.run(...) is simply the first line inside it.
🌍 Real-world example:
java Anatomy.java Waquar Hirenix— inside main,args.lengthis 2,args[0]is"Waquar"andargs[1]is"Hirenix". The program's own name is not in the array. If you come from C, that is the difference to unlearn: hereargs[0]is the first real argument.
💡 Entry point = the single method the JVM calls to begin your program. 💡 Command-line argument = a value typed after the class name when running, delivered as text in
args. 💡 Overloading = two methods with the same name but different parameter lists. 💡 Single-file source mode = runningjava Anatomy.javadirectly (Java 11+); the JDK compiles it in memory, so no.classfile lands on disk.
What actually breaks — measured on JDK 17
This is the part interviews probe, and a lot of published material gets it wrong. Compile with javac first, then run:
$ java NoStatic
Error: Main method is not static in class NoStatic, please define the main method as:
public static void main(String[] args)
Read that carefully: it is the launcher printing a message and exiting, not a NoSuchMethodError being thrown. Older material commonly claims NoSuchMethodError — on JDK 17 that is not what you see. The other three ways to break it, all verified:
| what you changed | JDK 17 says |
|---|---|
private static void main |
Error: Main method not found in class PrivateMain, ... |
public static int main |
Error: Main method must return a value of type void ... |
only main(int), no String[] |
Error: Main method not found in class OnlyOverload, ... |
⚠️ A nuance almost nobody mentions: run the source file directly and the message is different and shorter, because a different tool reports it — java NoStatic.java prints error: 'main' method is not declared 'public static'. Same mistake, two messages, depending on how you ran it.
main can be overloaded — it just will not auto-run
As far as the language is concerned, main is an ordinary method. You may write main(int n) beside it and Java compiles it happily. But the JVM only ever auto-calls main(String[]); your overload runs only if your own code calls it. A class with only main(int) will not start at all. Also legal: public static void main(String... args) — varargs is a String[] underneath, and it runs.
One rule you meet on day one: under javac, a public class must live in a file of the same name. public class Different inside Mismatch.java gives error: class Different is public, should be declared in a file named Different.java. In single-file source mode that check does not apply.
Standard definition: public static void main(String[] args) is the entry point of a Java application — the fixed signature the JVM invokes to start the program: public so it is accessible from outside the class, static so it can be called before any object exists, void because it returns nothing to the JVM, and String[] args to receive command-line arguments.
public class Anatomy {
public static void main(String[] args) {
System.out.println("args.length = " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = " + args[i]);
}
main(42);
System.out.println("back in main(String[])");
}
static void main(int n) {
System.out.println("overloaded main(int) ran, n = " + n);
}
}Project: Student Report Card
This is the first thing you build in this chapter, and it is deliberately the program every Indian college assignment asks for — a student marksheet. The difference is that you are going to build it the way it would actually be reviewed: a 2D array of marks, small methods that each do one thing, and columns that line up no matter what the data does.
Nothing here needs a class of your own, a collection or an interface. Those are Chapters 2 and 3. What you need is exactly what the last twelve topics gave you: arrays, loops, String formatting, static final constants, and methods.
What you are building
STUDENT Maths Physics Chemistry English CS TOTAL AVG GRADE
----------------------------------------------------------------------------------------
Waquar 88 76 91 65 95 415 83.00 A
Aisha 72 68 59 81 77 357 71.40 B
Rohit 45 30* 52 61 48 236 47.20 D
Priya 96 92 89 94 98 469 93.80 A+
----------------------------------------------------------------------------------------
SUBJ AVG 75.3 66.5 72.8 75.3 79.5
* = below pass mark of 33
Read that output before you read the code. Notice four things it does that a beginner's version usually does not: the columns are aligned by format specifiers, not by counting spaces; a failing mark is flagged inline with *; there is a per-subject average in the footer, which needs a column walk rather than a row walk; and the separator line is exactly as wide as the table, because its width is computed from the same constants.
Step 1 — The data, and why it is a 2D array
String[] names = {"Waquar", "Aisha", "Rohit", "Priya"};
int[][] marks = {
{88, 76, 91, 65, 95},
{72, 68, 59, 81, 77},
{45, 30, 52, 61, 48},
{96, 92, 89, 94, 98},
};
marks[i] is student i's row, and marks[i][j] is their mark in subject j. The two arrays are kept parallel — index i means the same student in both. That is the simplest structure that works here, and being able to say why it is the simplest is the point: with a class you would write Student[] students, which is better, and it is Chapter 2's job.
Recall from the arrays topic that a 2D array is really an array of arrays, so rows could have different lengths. Here they must not, and SUBJECTS.length is what keeps them honest.
Step 2 — Constants, so the rules live in one place
static final String[] SUBJECTS = {"Maths", "Physics", "Chemistry", "English", "CS"};
static final int PASS_MARK = 33;
static because they belong to the program, not to any object. final because nothing should reassign them. Capitals because that is the convention for constants.
⚠️ Note what final does not do here: SUBJECTS is a final array, so SUBJECTS[0] = "Hindi" still compiles and still works. final blocks reassignment of the variable, not mutation of the array — exactly as verified in static-final-keywords. Constants that must truly not change are safer as separate values or as an immutable list, which is Chapter 3.
Step 3 — One method, one job
static int sum(int[] row) {
int total = 0;
for (int m : row) total += m;
return total;
}
An enhanced for, because we need the values and not the indices. total is a local variable, so it gets no default and must be initialised — the compiler would say variable total might not have been initialized otherwise.
Step 4 — Grading, ordered high to low
static String grade(double avg) {
if (avg >= 90) return "A+";
if (avg >= 80) return "A";
...
if (avg >= PASS_MARK) return "D";
return "FAIL";
}
The order matters and it is the bug people ship: if you test avg >= 33 first, every passing student gets a D, because the first matching branch wins. Testing from the highest boundary downwards means each if only has to state its own lower bound.
Each branch returns immediately, so there is no else and no fall-through worry. This is also a place a switch cannot help you — switch matches exact values, not ranges.
Step 5 — Formatting: the part that separates a report from a printout
System.out.printf("%-10s", name);
System.out.printf("%8d%8.2f%7s%n", total, avg, grade(avg));
printf is what makes columns line up. Three specifiers carry the whole table:
| specifier | means |
|---|---|
%-10s |
a string, 10 wide, left-aligned (the -) |
%11s |
a string, 11 wide, right-aligned |
%8.2f |
a double, 8 wide, exactly 2 decimal places |
%n |
a newline — prefer it to \n, it uses the platform's line separator |
A column must be wider than its widest value. The first version of this program used %9s and Chemistry — nine characters — swallowed its own gap, leaving PhysicsChemistry jammed together in the header. Widening to %11s fixed it. That is not a detail to skip: it is the single most common reason a beginner's table looks broken.
And the separator:
System.out.println("-".repeat(10 + 11 * SUBJECTS.length + 23));
The width is computed from the same numbers the columns use, so adding a sixth subject keeps the line correct with no editing. Hard-coding 88 dashes would work today and silently break tomorrow.
Step 6 — The footer: walking columns instead of rows
for (int c = 0; c < SUBJECTS.length; c++) {
int colTotal = 0;
for (int[] row : marks) colTotal += row[c];
System.out.printf("%11.1f", (double) colTotal / marks.length);
}
Everything until now walked rows — one student at a time. A per-subject average has to walk columns, which means the outer loop is the subject and the inner loop steps through students at that fixed column. It is the same data traversed the other way, and being comfortable switching between the two is most of what 2D array questions test.
⚠️ (double) colTotal / marks.length — the cast is essential. Without it both sides are int, so 236 / 5 would be 47, not 47.2, and the decimals in your report would all be zero. This is the integer-division rule from data-types-variables showing up in real code, and it fails silently.
Step 7 — Flagging failures inline
System.out.printf("%11s", m < PASS_MARK ? m + "*" : String.valueOf(m));
The ternary picks between two strings, and both branches must produce a String — hence String.valueOf(m) rather than bare m. Because the specifier is %11s and not %11d, the column stays aligned whether or not the star is there. Verified in the output: Rohit's 30* lines up with everyone else's plain numbers.
The complete program
The code block on this page is the whole thing, and the output shown is exactly what it printed on JDK 17. Run it, then break it on purpose: remove the (double) cast and watch every average become a whole number; reverse the order of the grade branches and watch every student become a D; change %11s back to %9s and watch the header collapse. Each of those is a bug you will otherwise ship once.
Extend it
- Add a rank column — sort students by total.
Arrays.sortwill not do it directly here, because sortingmarksmust movenameswith it; think about why, and about how aStudentclass in Chapter 2 removes the problem entirely. - Print the class topper per subject, not just the average — another column walk, keeping the best value and the index it came from.
- Read the marks from
argsinstead of hard-coding them, usingInteger.parseIntand remembering that it throwsNumberFormatExceptionon anything that is not a number.
When to use it: this shape — parallel arrays plus small static methods — is the right answer when the data is fixed, small, and you are not modelling a real thing yet. It is also exactly what a written round expects when it says "no collections".
When NOT to use it: parallel arrays stop being reasonable the moment the arrays can get out of step — sorting one without the other, or adding a student to one and forgetting the other, silently corrupts the whole report with no error. That is the point at which you want a Student class (Chapter 2) or a List (Chapter 3). Do not build a growable array by hand here either; if the number of students is not known up front, you have outgrown this structure. And do not put the formatting inside sum or grade — a method that both calculates and prints cannot be reused or tested, which is why those two return a value and the three print methods do nothing else.
Standard definition: This project builds a formatted student marksheet from a 2D int array of marks and a parallel String array of names, using static final constants for the subject list and pass mark, small single-purpose methods for the total and the grade, and System.out.printf format specifiers for column alignment. Row traversal produces per-student totals and averages, and column traversal produces per-subject averages.
public class StudentReport {
static final String[] SUBJECTS = {"Maths", "Physics", "Chemistry", "English", "CS"};
static final int PASS_MARK = 33;
public static void main(String[] args) {
String[] names = {"Waquar", "Aisha", "Rohit", "Priya"};
int[][] marks = {
{88, 76, 91, 65, 95},
{72, 68, 59, 81, 77},
{45, 30, 52, 61, 48},
{96, 92, 89, 94, 98},
};
printHeader();
for (int i = 0; i < names.length; i++) {
printRow(names[i], marks[i]);
}
printFooter(marks);
}
static void printHeader() {
System.out.printf("%-10s", "STUDENT");
for (String s : SUBJECTS) System.out.printf("%11s", s);
System.out.printf("%8s%8s%7s%n", "TOTAL", "AVG", "GRADE");
System.out.println("-".repeat(10 + 11 * SUBJECTS.length + 23));
}
static void printRow(String name, int[] row) {
int total = sum(row);
double avg = (double) total / row.length;
System.out.printf("%-10s", name);
for (int m : row) System.out.printf("%11s", m < PASS_MARK ? m + "*" : String.valueOf(m));
System.out.printf("%8d%8.2f%7s%n", total, avg, grade(avg));
}
static void printFooter(int[][] marks) {
System.out.println("-".repeat(10 + 11 * SUBJECTS.length + 23));
System.out.printf("%-10s", "SUBJ AVG");
for (int c = 0; c < SUBJECTS.length; c++) {
int colTotal = 0;
for (int[] row : marks) colTotal += row[c];
System.out.printf("%11.1f", (double) colTotal / marks.length);
}
System.out.println();
System.out.println("* = below pass mark of " + PASS_MARK);
}
static int sum(int[] row) {
int total = 0;
for (int m : row) total += m;
return total;
}
static String grade(double avg) {
if (avg >= 90) return "A+";
if (avg >= 80) return "A";
if (avg >= 70) return "B";
if (avg >= 60) return "C";
if (avg >= PASS_MARK) return "D";
return "FAIL";
}
}Core Javainterview questions & answers
10 sample questions below — 184+ in the full bank inside.
What is bytecode, and is it the same as machine code?
Bytecode is the set of intermediate instructions that javac writes into a .class file. It is not human-readable source and it is not your CPU's machine code — it is a middle language that one specific program, the JVM, knows how to read. Machine code is tied to a particular processor and operating system; bytecode deliberately is not.
In simple terms: Bytecode sits between your language and the machine's language, like a standard recipe card written in neither your handwriting nor the kitchen's local dialect — a format everyone agreed on. Example: run 'javac Hello.java' and you get Hello.class; you can inspect what is inside it with 'javap -c Hello.class' and see JVM instructions like iconst_5 and istore_1, which are not x86 or ARM instructions.
What does the JIT compiler do?
The JVM starts by interpreting bytecode instruction by instruction. The JIT — Just-In-Time — compiler watches which methods run over and over, the hot ones, and compiles those into real native machine code while the program is running. After that the JVM stops interpreting them and calls the compiled version directly.
In simple terms: The cook notices the same dish being ordered a hundred times, so he pre-preps it. The first plate takes the longest; plate number two hundred comes out fast. Example: a loop that runs millions of times is exactly the kind of hot path the JIT will compile, so the later iterations are executing native code, not being interpreted.
What is the difference between isEmpty() and isBlank()?
isEmpty() is true only when the length is zero. isBlank(), added in Java 11, is true when the string is empty or contains only whitespace. So for a string of three spaces, isEmpty() returns false while isBlank() returns true — which is what you usually want when validating a form field.
In simple terms: An empty page and a page with only pencil smudges are different things: one is truly blank, the other is technically not empty. Example: " ".isEmpty() is false but " ".isBlank() is true, so a user who typed only spaces into a name field passes the first check and fails the second.
In real code, when do you pick String, StringBuilder or StringBuffer?
Use String for fixed or rarely changed text — it is immutable, poolable and safe to share. Use StringBuilder whenever you are assembling text in a loop or across several steps in one thread, which covers almost all real code. Reach for StringBuffer only when a single buffer object is genuinely being appended to from multiple threads, since its append is synchronized and that synchronization is what makes it the slower option.
In simple terms: String is a printed page, StringBuilder is your own whiteboard, StringBuffer is a shared whiteboard with a lock on the marker — you only pay for the lock if people are actually sharing. Example: building a CSV row inside a loop is StringBuilder work; storing the finished row afterwards is String work.
What is a wrapper class in Java?
A wrapper class is the object form of a primitive type — Integer for int, Character for char, Double for double, and so on. It holds the same value but is a real object, so it can be used wherever an object is required and it can also be null. The wrapper is also where the useful static helpers live, such as Integer.MAX_VALUE and Integer.parseInt.
In simple terms: A filing office only accepts envelopes — a loose coin cannot go into the drawer because there is no label on it and nothing to file it by. A wrapper is that labelled envelope around the primitive: same coin inside, but now it fits the system. Example: int n = 5; is a loose coin, Integer boxed = 5; is the same 5 inside an envelope that also gives you Integer.MAX_VALUE, which is 2147483647.
What do trim() and strip() do, and what does length() count?
Both remove leading and trailing whitespace and return a new String; the original is unchanged because String is immutable. length() counts every character including the spaces, so it is measured before any trimming. On the string " Waquar Hirenix ", length() is 18 and both trim() and strip() give "Waquar Hirenix".
In simple terms: trim and strip are like cutting the blank margins off a printed page — you get a new page back, the old one still has its margins. Example: " Waquar Hirenix ".length() is 18, and " Waquar Hirenix ".trim() gives "Waquar Hirenix".
What is the difference between JVM, JRE and JDK?
They are three layers, one inside the other: the JDK contains the JRE, and the JRE contains the JVM. The JVM is the engine that executes bytecode; the JRE is the JVM plus the standard Java libraries, which is everything needed to run a Java application; the JDK is the JRE plus the development tools such as javac, javap and jar, which is what a developer installs.
In simple terms: Think of three boxes packed inside each other. The smallest box is the JVM — just the engine that runs your compiled code. Put that engine together with a ready-made toolkit of classes like String and Math and you get the JRE, enough to run an app. Add the machine that builds code in the first place (javac) and you get the JDK. Example: a production Linux server usually carries only a JRE, because it needs to run your .jar, not compile it.
Walk me through charAt, indexOf and split on a String.
charAt(i) returns the char at a zero-based index, indexOf(text) returns the zero-based position where the text first appears, or -1 if it is absent, and split(regex) returns a String array cut at each match. On " Waquar Hirenix ", charAt(2) is W, indexOf("Hirenix") is 9 and split(" ") gives [Waquar, Hirenix]. All three read the string; none of them modify it.
In simple terms: Think of the string as numbered boxes starting at 0: charAt opens one box, indexOf tells you which box a word starts in, and split cuts the row of boxes at every separator. Example: on " Waquar Hirenix " the two leading spaces are boxes 0 and 1, which is why charAt(2) is W.
How is Java platform independent?
javac does not compile your source into machine code for one particular CPU or operating system — it produces bytecode, stored in a .class file, which is the same on every platform. Every operating system has its own build of the JVM, and all of them read that same bytecode. That is what the phrase WORA — Write Once, Run Anywhere — refers to.
In simple terms: You write one recipe and convert it into a standard recipe card that every professional kitchen in the world already knows how to read. Delhi, Dubai, Toronto — each city has its own cook who reads that same card and uses whatever stove is available there. Example: a .jar built on a Windows laptop is copied straight onto a Linux server and simply runs; nothing is recompiled, only the cook is different.
What is the ClassLoader in Java?
The ClassLoader is the part of the JVM that brings a .class file into memory. It does not load the whole application at startup — it fetches a class the first time that class is actually referenced during execution. So class loading is a runtime activity, not something javac decided.
In simple terms: Think of a storeroom keeper who fetches an ingredient only when the recipe first calls for it, instead of emptying the entire storeroom onto the counter before cooking starts. Example: if your program has a ReportGenerator class but the user never opens the reports screen, that class may never be loaded at all during that run.
174+ more Core Java questions inside
Create a free account to read the full question bank, learn every topic, and practise with an AI mock interview.
Unlock all questions — freeReady to practise Core Java?
Unlock every topic free, then face an AI interviewer that asks follow-ups and grades your answers.