Java Fundamentals: Bytecode, OOP Concepts, and Programming Examples
Java Bytecode and Platform Independence
Defining Java Bytecode
Java Bytecode is the intermediate code generated by the Java compiler after compiling a Java program. When you write a Java source file (.java) and compile it using javac, the compiler converts it into a bytecode file (.class). This bytecode is not specific to any machine and can be executed by the Java Virtual Machine (JVM) on any platform.
Justification for Platform Independence
Platform independence means that a Java program can run on any operating system or hardware that has a JVM installed. The JVM interprets or just-in-time (JIT) compiles the bytecode into native machine code suitable for the host system. This concept is famously described by the phrase “Write Once, Run Anywhere” (WORA), which makes Java inherently platform independent.
Java Program: Checking for an Armstrong Number
An Armstrong number (or narcissistic number) is a number that is equal to the sum of its own digits each raised to the power of the number of digits. For a three-digit number, this means the sum of the cubes of its digits.
import java.util.Scanner;
class ArmstrongNumber {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number: ");
int num = sc.nextInt();
int temp = num, sum = 0, digit;
// Calculate the sum of the cubes of the digits
while (temp != 0) {
digit = temp % 10;
sum += digit * digit * digit;
temp /= 10;
}
// Check if the number is Armstrong
if (sum == num)
System.out.println(num + " is an Armstrong number.");
else
System.out.println(num + " is not an Armstrong number.");
}
}Java Program: Calculating Circle Area and Perimeter
This program defines a Circle class to encapsulate the radius and methods for calculating the area and perimeter.
import java.util.Scanner;
class Circle {
double radius;
// Constructor
Circle(double r) {
radius = r;
}
// Method to calculate area
double area() {
return Math.PI * radius * radius;
}
// Method to calculate perimeter (circumference)
double perimeter() {
return 2 * Math.PI * radius;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter radius: ");
double r = sc.nextDouble();
Circle c = new Circle(r);
System.out.println("Area of circle: " + c.area());
System.out.println("Perimeter of circle: " + c.perimeter());
}
}Character Class vs. String Class in Java
The fundamental difference lies in scope and purpose:
- The Character class in Java wraps a single character value (primitive
char). ACharacterobject deals only with one character and provides static methods to test or convert it (e.g., checking if a character is a digit or letter). - The String class represents a sequence of characters. A
Stringcan hold multiple characters and provides numerous methods to manipulate text, such as concatenation, comparison, substring extraction, and case conversion.
Thus, Character is for single characters, while String is for complete words or lines of text.
Program to Convert Lowercase Characters to Uppercase
import java.util.Scanner;
class ConvertCase {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a string: ");
String str = sc.nextLine();
// Using the built-in String method toUpperCase()
String upper = str.toUpperCase();
System.out.println("Uppercase String: " + upper);
}
}String vs. StringBuffer: Mutability Explained
The key distinction between String and StringBuffer is mutability:
- A String in Java is immutable, meaning that once created, its content cannot be changed. Any operation that appears to modify a
String, such as concatenation, actually results in the creation of a newStringobject. - A StringBuffer, on the other hand, is mutable, which means you can change its content without creating new objects. It provides methods such as
append(),insert(), anddelete()for modifying text efficiently.
StringBuffer is generally more efficient for repeated modifications of text, while String is more convenient and safer for fixed text data.
Interface vs. Abstract Class in Java OOP
An interface in Java is a completely abstract type used to specify a set of methods that a class must implement. It defines a contract of behavior without providing the implementation. Interfaces cannot have constructors or instance variables (except constants).
In contrast, an abstract class can have both abstract methods (without implementation) and concrete methods (with implementation). It can also have constructors and instance variables.
Key Differences
- Inheritance: A class can implement multiple interfaces, allowing a form of multiple inheritance in Java. A class can only extend one abstract class.
- Purpose: Interfaces are mainly used when we want to define behavior that can be applied to unrelated classes (defining capabilities). Abstract classes are often used to define a common base for closely related classes (defining a type hierarchy).
Passing Objects as Parameters in Java Methods
In Java, we can pass objects as parameters to methods, just like primitive data types. When an object is passed, the reference to the object is sent (pass-by-reference value), allowing the method to access or modify its data members.
class Student {
int marks;
Student(int m) {
marks = m;
}
// Method that accepts another Student object as a parameter
void compare(Student s) {
if (this.marks > s.marks)
System.out.println("Current student has higher marks.");
else
System.out.println("Passed student has higher marks.");
}
public static void main(String[] args) {
Student s1 = new Student(85);
Student s2 = new Student(90);
// Passing object s2 as a parameter to s1's compare method
s1.compare(s2);
}
}Constructors and Constructor Overloading
Defining a Constructor
A constructor is a special method in Java that is used to initialize objects. It has the same name as the class, does not have a return type, and is automatically called when an object is created.
Demonstrating Constructor Overloading
Constructor overloading occurs when a class has multiple constructors with different parameter lists (different number or type of arguments). This allows objects to be initialized in various ways.
class Demo {
int a;
String name;
// 1. Default Constructor
Demo() {
a = 0;
name = "Default";
}
// 2. Parameterized Constructor (int argument)
Demo(int x) {
a = x;
}
// 3. Parameterized Constructor (String argument)
Demo(String n) {
name = n;
}
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo(10);
Demo d3 = new Demo("BCA");
System.out.println(d1.a + " " + d1.name);
System.out.println(d2.a);
System.out.println(d3.name);
}
}Student Class with Default and Parameterized Constructors
This example further illustrates constructor overloading, including a default constructor and multiple parameterized constructors.
class Student {
String name;
// Default Constructor
Student() {
name = "Unknown";
}
// Parameterized Constructor (Single String)
Student(String n1) {
name = n1;
}
// Parameterized Constructor (Two Strings, assigns the shorter name)
Student(String n1, String n2) {
name = (n1.length() < n2.length()) ? n1 : n2;
}
void display() {
System.out.println("Student Name: " + name);
}
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student("Amit");
Student s3 = new Student("Ria", "Devansh");
s1.display();
s2.display();
s3.display();
}
}Drawing Shapes and Text Using Java Graphics (Applet)
This Java Applet program demonstrates basic drawing operations using the java.awt.Graphics class to render lines, rectangles, ovals, and text.
import java.applet.Applet;
import java.awt.*;
public class ShapesExample extends Applet {
public void paint(Graphics g) {
// Draw a line (x1, y1, x2, y2)
g.drawLine(20, 20, 100, 20);
// Draw a rectangle (x, y, width, height)
g.drawRect(20, 40, 80, 50);
// Draw an oval (x, y, width, height)
g.drawOval(20, 100, 80, 50);
// Draw text (string, x, y)
g.drawString("Hello Graphics!", 20, 180);
}
}Note: This program requires an Applet Viewer or a web browser configured to run Java Applets.
Key Java Concept Differences
Procedural Paradigm vs. Object-Oriented Paradigm (OOP)
- Procedural Paradigm: Focuses on writing procedures or functions that operate on data. Data and functions are separate, and the program’s flow is determined by function calls.
- Object-Oriented Paradigm (OOP): Focuses on objects that contain both data (attributes) and methods (behavior). It models real-world entities, promotes reusability, and supports core concepts like inheritance, polymorphism, and encapsulation.
While Loop vs. For Loop
- While Loop: Used when the number of iterations is not known in advance and depends solely on a condition being true.
- For Loop: Used when the number of iterations is known beforehand, as it conveniently handles initialization, testing, and updating a counter in a single statement.
Method Overloading vs. Method Overriding
- Method Overloading (Compile-Time Polymorphism): Occurs when multiple methods in the same class share the same name but differ in their parameter lists (number or type of arguments). It is resolved at compile-time.
- Method Overriding (Runtime Polymorphism): Occurs when a subclass provides a new definition for a method already defined in its superclass, using the exact same name and parameters. It is resolved at runtime.
Java Application vs. Java Applet
- Java Application: A standalone program that runs directly on the JVM using the operating system. It uses the
main()method as the entry point. - Java Applet: A small Java program designed to run inside a web browser or an applet viewer. It uses methods like
init()andpaint()instead ofmain().
- Java Application: A standalone program that runs directly on the JVM using the operating system. It uses the
