Getting Started with JAVA


Hey folks! Welcome back to my learning journey. In this article, we're building on our last discussion about computers and the fundamental need for programming languages, where we looked at binary and assembly examples.
What We'll Cover Today
What is Java
How is Java able to tell the computer to perform some actions?
Wrapping Up & What's Next
What is Java
So, what exactly is Java? At its heart, Java is a high-level programming language, a tool we use to give instructions to a computer, telling it to perform specific actions. We've already established that a programming language provides a set of human-readable instructions. Now, the question arises: how do we actually structure these instructions to solve problems effectively?
Over time, through many iterations and collaborative efforts, the programming community developed different approaches or programming paradigms. Think of these paradigms as distinct philosophies or styles for organizing code and thinking about problems. Some common paradigms include Object-Oriented Programming (OOP), Functional Programming, and Procedural Programming. Different programming languages are often designed with one or more of these paradigms in mind. A paradigm, simply put, dictates how a problem is viewed and how the solution is structured.
Java is fundamentally an Object-Oriented Programming (OOP) language. This means that in Java, the primary way we model and solve problems is by thinking in terms of "objects." These objects are designed to represent real-world entities or abstract concepts. For example, in the real world, I myself could be considered an "object" of a "Man" category (or "class" in programming terms), which itself might be a more specific type of a general "Human" category. Similarly, a car, a bank account, or even a user interface button can all be represented as objects in Java, each with its own characteristics (data) and behaviors (actions it can perform).
How is Java able to tell the computer to perform some actions?
So now we know that programming languages, like Java, provide a human-readable way for us to write instructions. The next logical question is: if a computer only truly understands ones and zeros (binary), how can it possibly follow the instructions we've written in this more understandable, human-friendly format? Clearly, we need a translator – something that can convert our human-readable instructions into the low-level code that the computer's hardware can actually execute.
For every programming language, there's a mechanism or a set of tools responsible for this translation. You might have heard that for the C programming language, a popular translator is a compiler called GCC. Similarly, for Java, the primary "translator" that starts this process is the Java compiler, known as javac.
Now, a fascinating question arises: where does this javac translator "live," and how does it perform its magic of converting our Java code into something the computer can work with? Well, javac itself is a program, and like any other program, it runs on the computer. You can almost think of it (and other essential system software) as being ultimately built up from, or interacting with, instructions that are already in a form the computer can understand (perhaps, at the very-very bottom, even binary, through layers of operating system services). So, the computer can understand and execute javac.
When javac processes your Java code, it's been designed with a deep understanding of the Java language's rules and structure. For example, when javac encounters a + symbol used for adding two numbers in your Java code, it knows to translate this into a specific Java bytecode instruction that represents an addition operation. It doesn't immediately go to binary for a specific CPU. Instead, it creates these universal bytecode instructions.
Then, as we discussed before, the Java Virtual Machine (JVM) takes over. The JVM, also a program running on your computer, is specifically designed to understand and execute this Java bytecode. The JVM, in turn, translates these bytecode instructions (like the one for addition) into the actual low-level binary machine code that your specific computer's CPU can execute to perform the addition. So, it's a two-step translation: Java code to bytecode (by javac), and then bytecode to specific machine code (by the JVM).
Now, you might be wondering, "Why bother with this intermediate Java bytecode step? Couldn't we just translate the Java code directly into the binary machine code for my specific computer? Wouldn't that avoid the overhead of another translation by the JVM?" That's an excellent question, and the answer reveals one of Java's most significant advantages: platform independence, often summarized by the mantra "Write Once, Run Anywhere" (WORA).
If javac translated your Java code directly into the binary machine code for, say, an Intel processor running Windows, that compiled program would only run on computers with a similar setup. To run it on a Mac with an Apple Silicon processor or a Linux server, you'd have to recompile your original Java source code specifically for each platform.
By compiling to Java bytecode first, Java introduces a brilliant layer of abstraction. Bytecode is a universal, intermediate language not tied to any specific operating system or hardware. The Java Virtual Machine (JVM) then acts as the specialized interpreter for each specific platform. You provide the same bytecode (.class files) to any system with the appropriate JVM. That JVM translates the universal bytecode into the correct native machine code for its particular hardware and OS.
So, while there's a step where the JVM interprets or JIT-compiles bytecode at runtime, this "overhead" is the price for incredible flexibility. You write your Java code once, compile it into bytecode once, and that same bytecode can run on a vast array of different devices and operating systems without changing your original source code. This dramatically simplifies development for applications meant to run across diverse environments, a huge reason for Java's widespread use.
Wrapping Up & What's Next
And that brings us to the end of this exploration into how Java bridges the gap between our human-readable code and the computer's native language. We've seen that Java isn't just a language; it's an entire platform, with the Java Compiler (javac) transforming our source code into universal bytecode, and the Java Virtual Machine (JVM) masterfully translating that bytecode into action on any compatible device. This two-step process is the key to Java's celebrated "Write Once, Run Anywhere" philosophy, making it a powerful choice for building versatile applications.Understanding this compilation and execution flow is fundamental as we continue our "Java & Spring Deep Dive Series." It sets the stage for appreciating many other aspects of Java development.
Subscribe to my newsletter
Read articles from Krishna Prasad A directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
