In Java, constructors are used to initialize the attributes of an object, making the language more reflective of real-world scenarios. By default, Java provides a no-argument constructor that is automatically invoked if no constructors are defined. However, if you create a custom constructor, such as a parameterized one, you must explicitly define the default constructor, as it will no longer be provided automatically.
Note:
If a base class has a no-argument constructor, it is called automatically when a constructor of the derived class is invoked.
Example:
// Java Program to Demonstrate
// Constructor Invocation Without Using super Keyword
// Parent class
class Parent {
// Constructor of the parent class
Parent() {
System.out.println("Parent Class Constructor Called");
}
}
// Child class
class Child extends Parent {
// Constructor of the child class
Child() {
System.out.println("Child Class Constructor Called");
}
}
// Main class
public class Main {
public static void main(String[] args) {
// Creating an object of the child class
Child childObj = new Child();
// Note: The constructor of the parent class is invoked first,
// followed by the constructor of the child class.
}
}
Output:
Parent Class Constructor Called
Child Class Constructor Called
In Java, constructors are used to initialize the attributes of an object, making the language more reflective of real-world scenarios. By default, Java provides a no-argument constructor that is automatically invoked if no constructors are defined. However, if you create a custom constructor, such as a parameterized one, you must explicitly define the default constructor, as it will no longer be provided automatically.
Note:
If a base class has a no-argument constructor, it is called automatically when a constructor of the derived class is invoked.
Example:
// Java Program to Demonstrate
// Constructor Invocation Using super Keyword
// Base class
class Vehicle {
int speed;
// Parameterized constructor of the base class
Vehicle(int spd) {
speed = spd;
}
}
// Subclass
class Car extends Vehicle {
String model;
// Constructor of the subclass
Car(int spd, String mdl) {
// Using super to call the base class constructor
super(spd);
model = mdl;
}
// Method to display details
void displayDetails() {
System.out.println("Speed: " + speed + ", Model: " + model);
}
}
// Main class
public class Main {
public static void main(String[] args) {
// Creating an object of the subclass
Car carObj = new Car(120, "Sedan");
// Displaying details of the car
carObj.displayDetails();
}
}
Output:
Speed: 120, Model: Sedan
Explanation:
In this example, the super() keyword is used to call the base class (Vehicle) constructor with a parameter (speed). This call must be the first statement in the subclass (Car) constructor. Afterward, the model attribute is initialized, and the displayDetails() method prints the values of speed and model.
Key Points:
The base class constructor is always called before the subclass constructor.
The super() keyword is used to explicitly invoke the base class constructor and must be the first line in the subclass constructor.
If super() is not used, the default constructor of the base class is invoked automatically.
Multiple Inheritance
Multiple inheritance is an object-oriented concept where a class can inherit from more than one parent class. However, a problem arises when both parent classes have methods with the same signature. In such cases, the compiler is unable to decide which method to execute, leading to ambiguity. Java avoids these complexities by not supporting multiple inheritance through classes.
Note:
Java does not support multiple inheritance through classes, but it handles this scenario for interfaces using default methods introduced in Java 8.
Example 1:
// Java Program to Demonstrate Lack of Support for Multiple Inheritance
// First parent class
class Parent1 {
void display() {
System.out.println("Parent1");
}
}
// Second parent class
class Parent2 {
void display() {
System.out.println("Parent2");
}
}
// Class trying to inherit from both Parent1 and Parent2 (Invalid)
class Child extends Parent1, Parent2 {
public static void main(String[] args) {
Child obj = new Child();
obj.display(); // Ambiguity issue
}
}
Output:
Compilation Error
Explanation:
Java does not support multiple inheritance using classes. If you try to inherit from both Parent1 and Parent2, the compiler will throw an error because it cannot determine which display() method to call.
How Java Handles Multiple Inheritance with Interfaces
While Java doesn’t allow multiple inheritance through classes, it allows it through interfaces. Java 8 introduced default methods, which allow interfaces to provide default implementations of methods. If a class implements multiple interfaces with default methods that have the same signature, it must resolve the conflict by overriding the method.
Example 2: Handling Multiple Inheritance with Interfaces
// Interface 1
interface Interface1 {
default void show() {
System.out.println("Default Interface1");
}
}
// Interface 2
interface Interface2 {
default void show() {
System.out.println("Default Interface2");
}
}
// Implementation class that implements both interfaces
class MyClass implements Interface1, Interface2 {
// Overriding the show method to resolve ambiguity
@Override
public void show() {
Interface1.super.show(); // Explicitly calling Interface1's show method
Interface2.super.show(); // Explicitly calling Interface2's show method
}
// Methods to call specific interface methods
public void showInterface1() {
Interface1.super.show();
}
public void showInterface2() {
Interface2.super.show();
}
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.show(); // Resolving ambiguity
System.out.println("Calling individual interface methods:");
obj.showInterface1();
obj.showInterface2();
}
}
In this example, MyClass implements both Interface1 and Interface2, which both have a default show() method. By overriding the show() method in MyClass, we use Interface1.super.show() and Interface2.super.show() to specify which interface’s method to call. Additionally, the class provides methods to call individual interface methods if needed.
Example 3: Diamond Problem with Default Methods in Interfaces
// Root interface with a default method
interface RootInterface {
default void display() {
System.out.println("Default RootInterface");
}
}
// First child interface extending RootInterface
interface ChildInterface1 extends RootInterface {
}
// Second child interface extending RootInterface
interface ChildInterface2 extends RootInterface {
}
// Class implementing both child interfaces
class MyClass implements ChildInterface1, ChildInterface2 {
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.display(); // No ambiguity, RootInterface's method is called
}
}
Output:
Default RootInterface
Explanation:
In this case, both ChildInterface1 and ChildInterface2 extend the same RootInterface, which has a default display() method. Since neither ChildInterface1 nor ChildInterface2 overrides the method, there is no ambiguity, and the RootInterface method is called directly.
Interfaces and Inheritance in Java
In Java, a class can extend another class and implement one or more interfaces. This relationship has a significant role in understanding Java’s approach to Multiple Inheritance.
Key Concepts:
1. Inheritance Hierarchy: Java enforces a clear hierarchy, where a class can inherit from another class using the extends keyword, and implement interfaces using the implements keyword. The hierarchy cannot be reversed; that is, a class cannot extend an interface, as doing so would violate the core principles of class-based inheritance.
Example of Class Implementing Multiple Interfaces
// Java program to demonstrate that a class can
// implement multiple interfaces
interface InterfaceA {
void method1();
}
interface InterfaceB {
void method2();
}
// class implements both interfaces
// and provides implementation for the methods
class ExampleClass implements InterfaceA, InterfaceB {
@Override
public void method1() {
System.out.println("Executing method1 from InterfaceA");
}
@Override
public void method2() {
System.out.println("Executing method2 from InterfaceB");
}
}
public class Main {
public static void main(String[] args) {
ExampleClass obj = new ExampleClass();
// calling the methods implemented in the class
obj.method1();
obj.method2();
}
}
2. Interface Inheritance: In Java, an interface can extend another interface, allowing for inheritance of method signatures, which can later be implemented in classes.
Example of Interface Inheritance
// Interface inheritance demonstration
interface InterfaceA {
void display();
}
interface InterfaceB extends InterfaceA {
void show();
}
class DemoClass implements InterfaceB {
@Override
public void display() {
System.out.println("Display method from InterfaceA");
}
@Override
public void show() {
System.out.println("Show method from InterfaceB");
}
}
public class Main {
public static void main(String[] args) {
DemoClass obj = new DemoClass();
obj.display();
obj.show();
}
}
Output:
Display method from InterfaceA
Show method from InterfaceB
Types of Inheritance in Java
Java supports different types of inheritance, such as single, multilevel, and hierarchical inheritance, while restricting multiple and hybrid inheritance through interfaces.
1. Single Inheritance: When a class inherits from only one superclass.
class A {
int num1;
void setNum1(int x) {
num1 = x;
}
}
class B extends A {
int num2;
void setNum2(int y) {
num2 = y;
}
void displayProduct() {
System.out.println("Product: " + (num1 * num2));
}
}
public class Main {
public static void main(String[] args) {
B obj = new B();
obj.setNum1(3);
obj.setNum2(4);
obj.displayProduct();
}
}
Output:
Product: 12
2. Multilevel Inheritance: Involves a chain of inheritance where a class is derived from another derived class.
class A {
int num1;
void setNum1(int x) {
num1 = x;
}
}
class B extends A {
int num2;
void setNum2(int y) {
num2 = y;
}
}
class C extends B {
void displaySum() {
System.out.println("Sum: " + (num1 + num2));
}
}
public class Main {
public static void main(String[] args) {
C obj = new C();
obj.setNum1(5);
obj.setNum2(10);
obj.displaySum();
}
}
Output:
Sum: 15
3. Hierarchical Inheritance: Multiple classes inherit from the same superclass.
class A {
void greet() {
System.out.println("Hello from Class A");
}
}
class B extends A {
void greetFromB() {
System.out.println("Greetings from Class B");
}
}
class C extends A {
void greetFromC() {
System.out.println("Greetings from Class C");
}
}
public class Main {
public static void main(String[] args) {
B objB = new B();
C objC = new C();
objB.greet();
objB.greetFromB();
objC.greet();
objC.greetFromC();
}
}
Output:
Hello from Class A
Greetings from Class B
Hello from Class A
Greetings from Class C
Inheritance in Interfaces
Java interfaces can inherit from multiple interfaces, enabling classes to implement complex behavior while avoiding ambiguity.
Employee Name: John
Department: IT
Role: Developer
Association, Composition and Aggregation in Java
In object-oriented programming, relationships between classes are fundamental for defining interactions between objects. Java, as an object-oriented language, allows modeling these relationships using association, aggregation, and composition. These concepts describe how instances of classes relate and interact with one another.
Association
Association represents a general relationship between two independent classes, where one class may use or interact with another. This relationship can be one-to-one, one-to-many, many-to-one, or many-to-many, without implying ownership. Classes in association are independent of each other.
Types of Association
Unidirectional Association: One class knows and interacts with another, but the reverse is not true. For example, a Customer class may be associated with an Order class, but the Order class does not need to be aware of the Customer.
Bidirectional Association: Both classes are aware of and interact with each other. For example, a Player class and a Team class might be associated in a bidirectional relationship, where a player belongs to a team, and the team knows which players are on it.
Example of Association:
// Java program illustrating Association
import java.util.*;
class Library {
private String libraryName;
private Set<Book> books;
public Library(String libraryName) {
this.libraryName = libraryName;
}
public String getLibraryName() {
return this.libraryName;
}
public void setBooks(Set<Book> books) {
this.books = books;
}
public Set<Book> getBooks() {
return this.books;
}
}
class Book {
private String title;
public Book(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
}
public class AssociationExample {
public static void main(String[] args) {
// Creating Book objects
Book book1 = new Book("Java Basics");
Book book2 = new Book("Advanced Java");
// Adding books to a set
Set<Book> bookSet = new HashSet<>();
bookSet.add(book1);
bookSet.add(book2);
// Creating a Library object
Library library = new Library("City Library");
// Setting books for the library
library.setBooks(bookSet);
// Displaying library books
for (Book book : library.getBooks()) {
System.out.println(book.getTitle() + " is available at " + library.getLibraryName());
}
}
}
Output:
Java Basics is available at City Library
Advanced Java is available at City Library
In this example, the Library and Book classes are associated, where a library contains multiple books, forming a one-to-many relationship.
Aggregation
Aggregation is a specialized form of association that represents a “has-a” relationship. In aggregation, one class (the whole) contains other classes (the parts), but the lifecycle of the parts is independent of the whole. For instance, a University may contain multiple Departments, but a department can exist independently of the university.
Example of Aggregation:
// Java program illustrating Aggregation
import java.util.*;
class Course {
private String courseName;
private int courseId;
public Course(String courseName, int courseId) {
this.courseName = courseName;
this.courseId = courseId;
}
public String getCourseName() {
return this.courseName;
}
public int getCourseId() {
return this.courseId;
}
}
class Department {
private String deptName;
private List<Course> courses;
public Department(String deptName, List<Course> courses) {
this.deptName = deptName;
this.courses = courses;
}
public List<Course> getCourses() {
return this.courses;
}
}
class University {
private String universityName;
private List<Department> departments;
public University(String universityName, List<Department> departments) {
this.universityName = universityName;
this.departments = departments;
}
public int getTotalCoursesInUniversity() {
int totalCourses = 0;
for (Department dept : departments) {
totalCourses += dept.getCourses().size();
}
return totalCourses;
}
}
public class AggregationExample {
public static void main(String[] args) {
// Creating Course objects
Course c1 = new Course("Data Structures", 101);
Course c2 = new Course("Algorithms", 102);
Course c3 = new Course("Operating Systems", 103);
// Creating lists of courses
List<Course> csCourses = Arrays.asList(c1, c2);
List<Course> itCourses = Arrays.asList(c3);
// Creating Department objects
Department csDept = new Department("Computer Science", csCourses);
Department itDept = new Department("Information Technology", itCourses);
// Creating a list of departments
List<Department> departments = Arrays.asList(csDept, itDept);
// Creating a University object
University university = new University("Tech University", departments);
// Printing total courses in university
System.out.println("Total courses in university: " + university.getTotalCoursesInUniversity());
}
}
Output:
Total courses in university: 3
In this example, a university contains multiple departments, each having courses. The university and department are in an aggregation relationship, where departments can exist independently of the university.
Composition
Composition is a strong form of association where the lifecycle of the contained objects is dependent on the container object. If the container object is destroyed, the contained objects are also destroyed. This represents a “part-of” relationship, like a Car and its Engine. If the car is destroyed, the engine also ceases to exist.
Example of Composition:
// Java program illustrating Composition
import java.util.*;
class Engine {
private String engineType;
public Engine(String engineType) {
this.engineType = engineType;
}
public String getEngineType() {
return this.engineType;
}
}
class Car {
private String carName;
private Engine engine;
public Car(String carName, String engineType) {
this.carName = carName;
this.engine = new Engine(engineType); // Composition
}
public String getCarDetails() {
return this.carName + " has an engine of type " + engine.getEngineType();
}
}
public class CompositionExample {
public static void main(String[] args) {
// Creating a Car object with composition
Car car = new Car("Tesla", "Electric");
// Displaying car details
System.out.println(car.getCarDetails());
}
}
Output:
Tesla has an engine of type Electric
In this example, the Car and Engine have a composition relationship. The Engine cannot exist without the Car, representing strong ownership.
Key Differences Between Association, Aggregation, and Composition
Feature
Association
Aggregation
Composition
Definition
General relationship between two classes
“Has-a” relationship
“Part-of” relationship
Dependency
Classes can exist independently
Parts can exist independently of the whole
Parts depend on the whole
Lifecycle
Independent lifecycles
Independent lifecycles
Dependent lifecycles
Ownership
No ownership implied
Shared ownership
Exclusive ownership
Strength
Weak
Moderate
Strong
These relationships play a key role in designing well-structured, reusable, and maintainable software systems.
Object Oriented Programming (OOPs) Concept in Java
Object-Oriented Programming (OOP) in Java refers to a programming approach where objects are used to represent and execute the code’s functionality. Objects are the core components, performing specific tasks as defined by the programmer.
OOP is designed to model real-world entities, such as inheritance, encapsulation, polymorphism, etc., in code. The primary objective is to bind data and the functions that operate on the data, ensuring that no other part of the program can directly access this data except through those functions.
Key OOP Concepts in Java
Java is built on the foundation of Object-Oriented Programming. Understanding key OOP concepts such as inheritance, encapsulation, abstraction, and polymorphism is critical to writing scalable and maintainable Java code.
Prerequisites
Before diving into the pillars of OOP, let’s review the essentials of method declaration and message passing in Java.
Method Declaration
A method in Java consists of six main components:
1. Access Modifier: Defines the accessibility of the method within the application. The common types are:
public: Accessible in all classes.
protected: Accessible within the package and in subclasses.
private: Accessible only within the class.
Default (no modifier): Accessible only within the same package.
2. Return Type: Specifies the data type returned by the method, or void if no value is returned. 3. Method Name: Follows the same naming conventions as fields, but typically starts with a lowercase letter. 4. Parameter List: The input parameters (if any), defined as a comma-separated list within parentheses. 5. Exception List: Specifies any exceptions that the method might throw. 6. Method Body: Contains the block of code that is executed when the method is called.
Message Passing
Objects in Java communicate with one another by sending messages, which involve calling methods. A message consists of the object’s name, the method to be executed, and any required information.
Java OOP Concepts
OOP in Java is centered around several key concepts:
1. Class: A class is a blueprint or prototype that defines the properties and behaviors common to all objects of a specific type. A class typically consists of fields (attributes) and methods (behaviors). In Java, a class can be defined as:
public class Employee {
// Fields
String name;
int salary;
// Methods
void setDetails(String n, int s) {
name = n;
salary = s;
}
void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Salary: " + salary);
}
}
2. Object: An object is an instance of a class. It represents a specific entity in a Java program, with its own state and behavior.
public class Main {
public static void main(String[] args) {
Employee emp = new Employee();
emp.setDetails("John Doe", 50000);
emp.displayDetails();
}
}
Output:
Name: John Doe
Salary: 50000
The Four Pillars of OOP
1. Abstraction: Abstraction involves hiding unnecessary details and showing only the essential features of an object. In Java, abstraction is achieved using abstract classes and interfaces.
Example of an abstract class:
abstract class Vehicle {
abstract void start();
}
class Car extends Vehicle {
void start() {
System.out.println("Car is starting");
}
}
2. Encapsulation: Encapsulation is the practice of wrapping data and methods into a single unit (class). It restricts direct access to the data by making the fields private and providing public getter and setter methods to modify and access them.
class Person {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
3. Inheritance: Inheritance allows a class to inherit properties and methods from another class. It promotes reusability and a hierarchical class structure. Inheritance is achieved using the extends keyword.
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
4. Polymorphism: Polymorphism allows methods or objects to behave in different ways based on the context. It is of two types: compile-time (method overloading) and runtime (method overriding).
Method Overloading (Compile-time Polymorphism):
class Calculator {
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
}
Advantages of OOP over Procedural Programming
Code Reusability: By using classes and objects, you can reuse code efficiently without repetition.
Code Organization: Object-oriented code is better structured, making it easier to understand and maintain.
DRY Principle: OOP promotes the “Don’t Repeat Yourself” principle by allowing common code to be reused.
Faster Development: OOP speeds up development by encouraging modular components that can be reused across projects.
Java Classes and Objects
In Java, classes and objects are core concepts of Object-Oriented Programming (OOP), used to represent real-world entities and behaviors. A class acts as a blueprint for creating objects, while an object is an instance of a class. For example, “Dog” can be considered a class, while a specific dog named “Bruno” would be an object of that class.
In this article, we’ll explore Java classes, objects, and how to implement them in your programs.
Java Classes
A class in Java is a collection of objects with common properties and behaviors. It is essentially a user-defined prototype from which objects are created. For instance, “Car” is a class, while “BMW” is an object.
Properties of Java Classes
A class is not a physical entity but a blueprint used to create objects.
A class itself does not occupy memory; only objects do.
It groups variables (attributes) and methods (behaviors) under a common structure.
A class in Java can include the following components:
In this example, the Student class has two data members, id and name, with default values 0 and null, respectively.
Components of Java Classes
A class declaration typically contains the following:
Modifiers: A class can be public or have default access.
Class keyword: Used to declare a class.
Class name: Starts with an uppercase letter by convention.
Superclass: The parent class (if any), specified with the extends keyword.
Interfaces: Any implemented interfaces, separated by commas and declared with the implements keyword.
Body: The class body is enclosed in curly braces {}.
Constructors
Constructors initialize new objects. They have the same name as the class and no return type. Fields (data members) define the state of objects, while methods define the behavior.
Java Objects
An object in Java is an instance of a class, representing a specific entity or concept. Each object has:
State: Represented by the attributes (data members) of the object.
Behavior: Represented by the methods of the object.
Identity: A unique identifier that allows interaction between different objects.
For example, in a shopping system, objects could include “ShoppingCart”, “Product”, and “Customer”.
Declaring and Initializing Java Objects
When an object is created, the class is instantiated. The values of the object’s attributes (state) are unique for each instance.
Dog myDog; // Declaration
myDog = new Dog(); // Instantiation
Example of an Object Initialization
public class Dog {
// Instance variables
String name;
String breed;
int age;
String color;
// Constructor
public Dog(String name, String breed, int age, String color) {
this.name = name;
this.breed = breed;
this.age = age;
this.color = color;
}
@Override
public String toString() {
return "My dog's name is " + name + ", breed: " + breed + ", age: " + age + ", color: " + color;
}
public static void main(String[] args) {
Dog myDog = new Dog("Buddy", "Golden Retriever", 3, "Golden");
System.out.println(myDog.toString());
}
}
Output:
My dog's name is Buddy, breed: Golden Retriever, age: 3, color: Golden
Memory Allocation in Java Objects
When an object is created, it is allocated memory on the heap. All classes have at least one constructor; if none is explicitly defined, Java provides a default constructor.
Methods to Create Objects
There are several ways to create objects in Java:
1. Using the new keyword:
Car myCar = new Car();
2. Using Class.forName(String className):
Car obj = (Car)Class.forName("com.example.Car").newInstance();
3. Using clone() method:
Car car1 = new Car();
Car car2 = (Car)car1.clone();
4. Using Deserialization:
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Car car = (Car)in.readObject();
Anonymous Objects
Anonymous objects are objects created without a reference and are often used for immediate method calls. These objects are destroyed after the method call completes.
new Car().drive();
Difference Between Class and Object
Class
Object
A blueprint for creating objects.
An instance of the class.
Does not occupy memory.
Occupies memory when instantiated.
Logical entity.
Physical entity.
Declared only once.
Multiple objects can be created from the same class.
Java Naming Conventions
In software development, especially in Java, writing clean and readable code is essential. One key aspect of this is following proper naming conventions. This practice ensures that your code is easy to read and understand, both for yourself and for other developers who may work on the same project. While at a smaller scale these conventions may not seem critical, they become increasingly important in large, industrial-level projects where maintaining clean, organized code can significantly reduce development time and confusion.
For example, when naming a variable meant to store displacement, a meaningful name like “displacement” should be used, rather than something unclear like “x” or “d”. As the project grows, meaningful names enhance readability and reduce errors.
Key Naming Guidelines
Classes: When naming a class, it should be a noun, reflecting the purpose it serves in the program. The name should describe what the class is about without needing to read its contents. Examples of good class names include AddNumbers, ReverseString, etc. Poor names would be generic or meaningless like A1 or Programming.
Interfaces: Interfaces usually describe capabilities and are often named with adjectives. For example, common Java interfaces like Runnable and Serializable describe behavior. It’s also a good practice to use the suffix “able” (e.g., Readable), though it’s not mandatory.
Methods: Methods, being actions, should be named as verbs. Their names should clearly describe what they do. For example, the main() method in Java signifies the starting point of the program and is a good method name conventionally.
Constants: Constants are fixed values and should be named in uppercase with words separated by underscores (_). Examples include PI, MAX_VALUE, MIN_VALUE.
Java Naming Conventions Overview
In Java, it is considered best practice to name classes, variables, and methods according to their intended functionality. This approach enhances the readability and maintainability of the code. Java follows the CamelCase convention for naming classes, methods, and variables, where words are written together without spaces, and each word after the first starts with an uppercase letter. For example, firstName or calculateArea.
However, there are a few exceptions:
Packages: Package names should be written in all lowercase, even if they contain multiple words.
Constants: Constants should be written in uppercase, with words separated by underscores.
Naming Conventions for Specific Java Elements
1. Classes and Interfaces
Classes: Class names should be nouns, using CamelCase, with each internal word starting with a capital letter. Avoid abbreviations or acronyms, and instead use meaningful words.Example: Student, Integer, DataProcessor
Interfaces: Interfaces should follow the same convention as classes, but should often reflect actions or behaviors, typically in the form of adjectives.Example: Runnable, Serializable
2. Methods
Method Names: Methods should be verbs, following the camelCase convention. The first word is in lowercase, and each subsequent word starts with an uppercase letter.Example: calculateTotal, findMaximum, printDetails
3. Variables
Variable Names: Variables should have meaningful names and be short but descriptive. They should not start with an underscore (_) or dollar sign ($), even though Java permits it. Single-character variable names (like i, j, k) should generally be reserved for temporary variables in loops or similar short-term uses.Example: int score, double interestRate, String username
4. Constants
Constant Names: Constants are named in all uppercase letters, with words separated by underscores (_).Example: MAX_LIMIT, PI, DEFAULT_TIMEOUT
5. Packages
Package Names: Package names should always be written in lowercase, with each part separated by dots (.). The first part of the package name should usually be the top-level domain name (e.g., com, org), followed by the company’s domain and additional parts.Example: com.example.projectname, org.utilities.math
Importance of Naming Conventions
Adopting proper naming conventions improves code clarity, making it easier for other developers to understand the purpose of each class, method, variable, and constant without having to examine the underlying implementation. Following these guidelines also helps avoid confusion and errors in larger codebases. Furthermore, adhering to established naming conventions is a sign of professionalism and helps teams maintain a consistent coding style across projects.
These conventions, though simple, are critical in producing clean, readable, and maintainable Java code—allowing teams to work more effectively and reducing the chances of misinterpretation or mistakes during development.
Methods in Java
A method in Java is a collection of statements designed to perform a specific task and, optionally, return a result. Methods can also execute tasks without returning any value. By using methods, Java allows code reuse, eliminating the need to rewrite similar logic multiple times. Unlike languages such as C, C++, or Python, every method in Java must belong to a class.
Key Points about Methods:
A method is similar to a function and is used to describe the behavior of an object.
It is a block of code that performs a particular task.
Syntax of a Method:
<access_modifier> <return_type> <method_name>(list_of_parameters) {
// body of the method
}
Advantages of Methods:
Code Reusability: Methods allow code to be written once and reused as needed, saving time and effort.
Code Optimization: Methods simplify complex operations and improve the structure of the code.
Method Declaration
A method declaration generally has six components:
1. Modifier: Defines the access level of the method (e.g., public, private, protected, default).
public: Accessible in all classes.
protected: Accessible within the class and its subclasses.
private: Accessible only within the defining class.
default: Accessible within the same class and package, with no modifier.
2. Return Type: Specifies the data type of the value returned by the method or void if no value is returned. 3. Method Name: The name given to the method, following the same rules as variable names but typically being a verb. It is required. 4. Parameter List: A comma-separated list of input parameters (preceded by their data types). If no parameters are needed, empty parentheses are used. This is optional. 5. Exception List: Specifies any exceptions the method can throw. This is optional. Method Body: The actual code executed by the method, enclosed in braces. This is also optional.
Types of Methods in Java
1. Predefined Methods: These are methods already provided by Java libraries, also known as standard or built-in methods. We can directly call these methods within our program.
2. User-defined Methods: Methods written by the programmer, tailored to specific tasks according to the program’s needs.
Ways to Create Methods in Java
1. Instance Methods: Access instance data using the object name. These methods are declared within a class.
void methodName() {
// method body
}
2. Static Methods: Access static data using the class name. These methods are declared with the static keyword.
static void methodName() {
// method body
}
Method Signature
A method signature consists of the method name and its parameter list (the number, type, and order of parameters). The return type and exceptions are not part of the method signature.
Example:
int max(int x, int y) // Method signature
In this example, the method max has two parameters of type int.
Naming a Method
The convention for naming methods in Java is to use verbs in lowercase or multi-word names starting with a verb. If the name contains multiple words, the first letter of each word after the first should be capitalized (CamelCase).
Rules:
Method names should be verbs and start with a lowercase letter.
If the method name contains more than one word, the first word must be a verb, followed by an adjective or noun.
In multi-word names, capitalize the first letter of each subsequent word (e.g., findMax, computeSum).
Method Calling
Methods need to be called to execute. They can be called in three situations:
The method completes all its statements.
The method reaches a return statement.
The method throws an exception.
Example:
class Calculator {
public int add(int a, int b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
int result = calc.add(5, 10);
System.out.println("Sum: " + result);
}
}
Output:
Sum: 15
Passing Parameters to Methods
Parameters can be passed in two ways:
1. Passing Arrays: Arrays can be passed as arguments to methods.
2. Varargs (Variable Arguments): When the number of parameters is unknown, we can use the varargs feature by specifying the parameter type followed by an ellipsis (...).
Method Overloading
Method overloading allows multiple methods with the same name but different parameter lists to coexist in the same class. This enables methods to handle various types of inputs.
Memory Allocation for Methods
Method calls are implemented using a stack. When a method is invoked, a stack frame is created to store its arguments, local variables, and return value. Once the method completes, its stack frame is removed from the stack.
Example:
class Example {
private int number;
private String name;
// Getter and Setter methods
public int getNumber() { return number; }
public String getName() { return name; }
public void setNumber(int number) { this.number = number; }
public void setName(String name) { this.name = name; }
// Other methods
public void printDetails() {
System.out.println("Number: " + number);
System.out.println("Name: " + name);
}
}
public class Main {
public static void main(String[] args) {
Example example = new Example();
example.setNumber(42);
example.setName("Java Example");
example.printDetails();
}
}
Output:
Number: 42
Name: Java Example
Access Modifiers in Java
Access modifiers in Java are essential for controlling the visibility and accessibility of classes, constructors, methods, variables, and data members. They provide a way to enforce security and manage how components of a program can interact with each other based on the access modifier used. In this section, we’ll explore the types of access modifiers available in Java, along with examples that demonstrate their use.
Types of Access Modifiers in Java
There are four access modifiers in Java:
1. Default (No keyword required) 2. Private 3. Protected 4. Public
1. Default Access Modifier
If no access modifier is specified, the default modifier is used. Members with the default access modifier are accessible only within the same package.
Example:
// Java program demonstrating default access modifier
package package1;
class ExampleClass {
void showMessage() {
System.out.println("This is a default access modifier example.");
}
}
// Attempting to access a default class from another package
package package2;
import package1.*;
public class TestClass {
public static void main(String[] args) {
ExampleClass example = new ExampleClass(); // Compile-time error
example.showMessage();
}
}
Output:
Compile-time error
2. Private Access Modifier
The private keyword is used to restrict access to class members. Members declared as private are accessible only within the class where they are defined.
Example:
// Java program illustrating private access modifier
package package1;
class ExampleClass {
private void displayMessage() {
System.out.println("This is a private method.");
}
}
public class TestClass {
public static void main(String[] args) {
ExampleClass example = new ExampleClass();
example.displayMessage(); // Compile-time error
}
}
Output:
error: displayMessage() has private access in ExampleClass
example.displayMessage();
3. Protected Access Modifier
The protected keyword allows access to members within the same package and also in subclasses, even if they are in different packages.
Example:
// Package 1 - Parent class with protected method
package package1;
public class ParentClass {
protected void displayMessage() {
System.out.println("This is a protected method.");
}
}
// Package 2 - Subclass inheriting from ParentClass
package package2;
import package1.ParentClass;
public class ChildClass extends ParentClass {
public static void main(String[] args) {
ChildClass child = new ChildClass();
child.displayMessage();
}
}
Output:
This is a protected method.
4. Public Access Modifier
The public keyword gives the widest access. Members declared as public can be accessed from any class, in any package.
Example:
// Java program demonstrating public access modifier
package package1;
public class ExampleClass {
public void showMessage() {
System.out.println("This is a public method.");
}
}
// Accessing a public method from another package
package package2;
import package1.ExampleClass;
public class TestClass {
public static void main(String[] args) {
ExampleClass example = new ExampleClass();
example.showMessage();
}
}
Output:
This is a public method.
Key Points:
Default access is package-private, meaning it’s accessible only within the same package.
Private access is the most restrictive, limiting access only to the class in which the member is declared.
Protected access allows visibility in the same package and in subclasses across different packages.
Public access provides unrestricted access throughout the program.
Best Practices for Using Access Modifiers
Always prefer the most restrictive access level for class members. For example, use private unless there’s a specific reason to expose a member.
Avoid using public fields, as this breaks encapsulation. Instead, use getter and setter methods to control access to fields.
Algorithm for Using Access Modifiers in Java
1. Define the class: Create a class representing your object or functionality. 2. Declare instance variables: Define the data members that represent the object’s state. 3. Choose access modifiers:
Use private for variables that should not be accessible outside the class.
Use protected for variables that can be accessed by subclasses, even in different packages.
Use public for variables that need to be accessed from any part of the program. Implement getter and setter methods: Even for public variables, it’s good practice to use accessors and mutators to control how values are accessed and modified.
4. Test visibility: Ensure that your chosen access levels make sense for the structure and interaction of your classes.
Java Constructors
In Java, a constructor is a special type of method used to initialize an object. Constructors are called when an object of a class is created, allowing developers to set initial values for the object’s attributes.
Whenever you create an object using the new keyword, a constructor is invoked to allocate memory for the object and initialize it.
Understanding constructors can greatly enhance your Java programming skills, particularly when working with large applications. Mastery of constructors is crucial for developing scalable, maintainable code, serving as a stepping stone toward more advanced programming concepts.
Example of a Java Constructor
Below is a simple demonstration of how constructors work in Java:
// Java Program to demonstrate
// Constructor usage
public class MyClass {
// Constructor
MyClass() {
System.out.println("Constructor called");
}
public static void main(String[] args) {
// Creating an object which calls the constructor
MyClass obj = new MyClass();
}
}
Output:
Constructor called
Differences Between Constructors and Methods
Name: A constructor must have the same name as the class, whereas methods can have any name.
Return Type: Constructors do not have a return type, while methods can return values (or be void if they return nothing).
Invocation: Constructors are called only once when an object is created, whereas methods can be called multiple times.
Syntax Example of a constructor:
class MyClass {
// A constructor
MyClass() {
// Initialization code here
}
}
// Creating an object, which invokes the constructor
MyClass obj = new MyClass();
Output:
Constructor called
Differences Between Constructors and Methods
Name: A constructor must have the same name as the class, whereas methods can have any name.
Return Type: Constructors do not have a return type, while methods can return values (or be void if they return nothing).
Invocation: Constructors are called only once when an object is created, whereas methods can be called multiple times.
Syntax example of a constructor:
class MyClass {
// A constructor
MyClass() {
// Initialization code here
}
}
// Creating an object, which invokes the constructor
MyClass obj = new MyClass();
Why Do We Need Constructors?
Constructors are used to initialize objects at the time of creation. For example, if we think of a class that represents a box, it might have fields like length, breadth, and height. When an object of this class is created, it wouldn’t make sense for it to have undefined dimensions, so constructors ensure these values are set.
When Is a Constructor Called?
A constructor is called whenever an object is instantiated using the new keyword. Some rules for writing constructors include:
The constructor must have the same name as the class.
A constructor cannot be abstract, final, static, or synchronized.
Access modifiers can be used with constructors to control which classes can instantiate objects.
1. Default Constructor : A default constructor is one without parameters. If no constructor is defined explicitly, Java automatically provides a default constructor.
Example:
// Java Program to demonstrate Default Constructor
public class MyClass {
// Default Constructor
MyClass() {
System.out.println("Default constructor called");
}
public static void main(String[] args) {
MyClass obj = new MyClass();
}
}
Output:
Default constructor called
2. Parameterized Constructor : A parameterized constructor takes arguments, allowing you to set object properties with specific values at the time of creation.
Example:
// Java Program to demonstrate Parameterized Constructor
public class MyClass {
String name;
int id;
// Parameterized Constructor
MyClass(String name, int id) {
this.name = name;
this.id = id;
}
public static void main(String[] args) {
MyClass obj = new MyClass("John", 101);
System.out.println("Name: " + obj.name + ", ID: " + obj.id);
}
}
Output:
Name: John, ID: 101
3. Copy Constructor : A copy constructor is used to create a new object as a copy of an existing object. While Java does not provide a built-in copy constructor, you can create one manually by passing an object of the same class to the constructor.
Example:
// Java Program to demonstrate Copy Constructor
public class MyClass {
String name;
int id;
// Parameterized Constructor
MyClass(String name, int id) {
this.name = name;
this.id = id;
}
// Copy Constructor
MyClass(MyClass obj) {
this.name = obj.name;
this.id = obj.id;
}
public static void main(String[] args) {
// Creating an object using a parameterized constructor
MyClass obj1 = new MyClass("Alice", 202);
// Creating a new object using the copy constructor
MyClass obj2 = new MyClass(obj1);
System.out.println("Name: " + obj2.name + ", ID: " + obj2.id);
}
}
Output:
Name: Alice, ID: 202
Constructor Overloading
Just like methods, constructors can also be overloaded by defining multiple constructors with different parameter lists. This allows for flexibility when creating objects with varying initial values.
Example:
// Java Program to demonstrate Constructor Overloading
public class MyClass {
// Constructor with one parameter
MyClass(String name) {
System.out.println("Name: " + name);
}
// Constructor with two parameters
MyClass(String name, int age) {
System.out.println("Name: " + name + ", Age: " + age);
}
public static void main(String[] args) {
// Calling different constructors
MyClass obj1 = new MyClass("Alice");
MyClass obj2 = new MyClass("Bob", 25);
}
}
Output:
Name: Alice
Name: Bob, Age: 25
Inheritance in Java
Java Inheritance Overview
Inheritance is one of the core concepts in Object-Oriented Programming (OOP), allowing a class to inherit properties and behaviors (fields and methods) from another class. In Java, this mechanism enables the creation of new classes that reuse, extend, and modify the functionality of existing ones. A class that inherits from another class can access the fields and methods of the parent class, while also adding its own methods and fields.
Why Do We Need Java Inheritance?
Inheritance offers several benefits, such as promoting code reusability, method overriding (which helps in achieving runtime polymorphism), and abstraction, allowing us to work with classes without needing to know the full details of their implementations. By leveraging inheritance, developers can create flexible and easily maintainable code.
Key Benefits:
Code Reusability: Common code in the superclass can be reused in the child classes, reducing redundancy.
Method Overriding: Enables the child class to provide specific implementations for methods defined in the parent class, facilitating runtime polymorphism.
Abstraction: Hides complex details from the user and only shows relevant functionalities.
Important Terms
Class: A blueprint for creating objects that share common attributes and behaviors.
Super Class (Parent Class): The class whose properties are inherited by another class.
Sub Class (Child Class): The class that inherits from another class. It can have additional fields and methods specific to itself.
Reusability: One of the major advantages of inheritance, where existing fields and methods from a parent class can be used in the child class without duplicating code.
How to Implement Inheritance in Java?
Inheritance in Java is implemented using the extends keyword. This keyword allows the subclass to extend the functionality of the superclass.
Syntax:
class SubClass extends SuperClass {
// fields and methods
}
Example of Java Inheritance
In this example, we have a base class Vehicle and a derived class Car that extends the Vehicle class. The TestDrive class is used to demonstrate the usage of inheritance.
// Base class
class Vehicle {
public int speed;
public int fuel;
// Constructor
public Vehicle(int speed, int fuel) {
this.speed = speed;
this.fuel = fuel;
}
// Methods
public void accelerate(int increment) {
speed += increment;
}
public void brake(int decrement) {
speed -= decrement;
}
@Override
public String toString() {
return "Speed: " + speed + " km/h, Fuel: " + fuel + " L";
}
}
// Derived class
class Car extends Vehicle {
public int numberOfDoors;
// Constructor
public Car(int speed, int fuel, int numberOfDoors) {
super(speed, fuel); // Calling the constructor of the superclass
this.numberOfDoors = numberOfDoors;
}
// Additional method for the Car class
public void lockDoors() {
System.out.println("Doors locked.");
}
@Override
public String toString() {
return super.toString() + ", Doors: " + numberOfDoors;
}
}
// Driver class
public class TestDrive {
public static void main(String[] args) {
Car myCar = new Car(80, 50, 4);
System.out.println(myCar.toString());
}
}
Output:
Speed: 80 km/h, Fuel: 50 L, Doors: 4
In this example, when an object of Car is created, the fields and methods from the Vehicle class are inherited, allowing the car to access properties like speed and fuel. The toString() method is overridden in the Car class to display additional information about the car.
Types of Inheritance in Java
Java supports several types of inheritance, each with its own structure and use cases:
1. Single Inheritance: A subclass inherits from one superclass. 2. Multilevel Inheritance: A chain of classes where a subclass inherits from a superclass, and another class inherits from that subclass. 3. Hierarchical Inheritance: One superclass is inherited by multiple subclasses. 4. Multiple Inheritance (Through Interfaces): In Java, a class can implement multiple interfaces, which allows it to inherit features from multiple sources. Java doesn’t support multiple inheritance with classes directly to avoid complexity, but interfaces provide a way to achieve this. 5. Hybrid Inheritance: A combination of multiple and other forms of inheritance. Java supports this through interfaces and combinations of single and hierarchical inheritance. Example:
In the following example, Dog is a subclass that inherits from the Animal superclass.
// Superclass
class Animal {
public void sound() {
System.out.println("This is an animal sound.");
}
}
// Subclass
class Dog extends Animal {
public void bark() {
System.out.println("The dog barks.");
}
}
// Driver class
public class TestAnimal {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.sound(); // Inherited from Animal
myDog.bark(); // Defined in Dog
}
}
Output:
This is an animal sound.
The dog barks.
Abstraction in Java
Abstraction in Java refers to the practice of showing only the necessary details and functionalities to the user while hiding the underlying implementation. By doing so, unnecessary complexities are kept out of sight, making it easier to work with the code.
Real-World Example of Abstraction:
A remote control for a TV is a great example of abstraction. You press buttons to change channels or adjust the volume, without needing to understand the inner workings of the TV or how the remote communicates with it.
What is Abstraction in Java?
In Java, abstraction is implemented using abstract classes and interfaces. If you want complete (100%) abstraction, interfaces are the tool of choice.
Data Abstraction is the process of focusing on the important characteristics of an object while ignoring irrelevant details. It helps in defining the key behaviors and properties of an object, distinguishing it from others in a meaningful way.
Real-Life Example of Abstraction:
Imagine driving a car. You know pressing the accelerator increases the speed, and pressing the brakes slows it down, but you don’t need to understand the detailed mechanism behind it. This is how abstraction simplifies interaction.
Java Abstract Classes and Abstract Methods
An abstract class is defined with the abstract keyword.
An abstract method is declared without any implementation.
An abstract class can have both abstract methods and regular methods.
If a class contains abstract methods, it must be declared as abstract.
Abstract classes cannot be instantiated directly; they must be extended.
Abstract classes can have constructors, both parameterized and default.
How to Implement Abstraction in Java
1. Define an abstract class or interface to represent the abstraction. 2. Declare common behaviors and properties as abstract methods within the class or interface. 3. Extend the abstract class or implement the interface in concrete classes. 4. Provide the specific implementations for the abstract methods in the concrete classes. 5. Use these concrete classes to achieve the desired functionality in your program.
When to Use Abstract Classes and Methods?
Abstract classes are useful when you want to define a template that outlines the structure of an abstraction but leave some details to be implemented by subclasses. A common example is the Shape hierarchy in design or simulation software, where shapes like circles, squares, and triangles share some characteristics but differ in how they calculate their areas.
Java Abstraction Example
Example 1:
// Abstract class for Shape
abstract class Shape {
String color;
// Abstract methods
abstract double area();
public abstract String toString();
// Constructor for Shape
public Shape(String color) {
this.color = color;
}
// Concrete method
public String getColor() {
return color;
}
}
// Circle class extending Shape
class Circle extends Shape {
double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
double area() {
return Math.PI * Math.pow(radius, 2);
}
@Override
public String toString() {
return "Circle color is " + getColor() + " and area is: " + area();
}
}
// Rectangle class extending Shape
class Rectangle extends Shape {
double length, width;
public Rectangle(String color, double length, double width) {
super(color);
this.length = length;
this.width = width;
}
@Override
double area() {
return length * width;
}
@Override
public String toString() {
return "Rectangle color is " + getColor() + " and area is: " + area();
}
}
// Main class
public class Main {
public static void main(String[] args) {
Shape circle = new Circle("Red", 5.0);
Shape rectangle = new Rectangle("Blue", 4.0, 6.0);
System.out.println(circle.toString());
System.out.println(rectangle.toString());
}
}
Output:
Circle color is Red and area is: 78.53981633974483
Rectangle color is Blue and area is: 24.0
Using Interfaces for Abstraction
Interfaces provide a way to achieve complete abstraction in Java. They contain method declarations but no method implementations.
Example:
// Shape interface
interface Shape {
double calculateArea();
}
// Circle class implementing Shape interface
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
// Rectangle class implementing Shape interface
class Rectangle implements Shape {
private double length, width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double calculateArea() {
return length * width;
}
}
// Main class
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5.0);
Shape rectangle = new Rectangle(4.0, 6.0);
System.out.println("Area of Circle: " + circle.calculateArea());
System.out.println("Area of Rectangle: " + rectangle.calculateArea());
}
}
Output:
Area of Circle: 78.53981633974483
Area of Rectangle: 24.0
Advantages of Abstraction
1. Simplifies Code: Reduces complexity by hiding implementation details. 2. Increases Reusability: Encourages code reuse and avoids duplication. 3. Enhances Security: Provides essential details while hiding the rest. 4. Improves Maintainability: Easier to update and maintain. 5. Supports Modularity: Breaks down complex systems into smaller parts.
Disadvantages of Abstraction
1. Increased Complexity: May add unnecessary layers if not used properly. 2. Debugging Challenges: Can make debugging more difficult due to hidden layers. 3. Potential Performance Overhead: Additional abstraction layers might affect performance.
Encapsulation in Java
Encapsulation is a core principle of object-oriented programming (OOP) in Java. It refers to the bundling of data (variables) and methods (functions) that operate on that data into a single unit, typically a class. Encapsulation ensures that the internal implementation of a class is hidden from outside access, only exposing a public interface that allows interaction with the class through methods. This technique enhances security and data integrity, as the internal state of an object can only be modified in controlled ways.
In Java, encapsulation is achieved by declaring instance variables as private, which means they cannot be accessed directly from outside the class. To provide access to these variables, public getter and setter methods are used, which enable controlled access and modification of the private variables.
Key Aspects of Encapsulation
Data hiding: By using private variables, you ensure that the internal details of a class are hidden.
Access through methods: Public getter and setter methods allow controlled access to the variables.
Modularity: It promotes better design by keeping data and methods together in a single unit.
Security and validation: Setters can include validation logic to prevent invalid data from being assigned to variables.
Java Encapsulation Example
// Employee Class demonstrating encapsulation
class Employee {
// Private fields, not accessible outside the class
private String name;
private int id;
// Getter method for name
public String getName() {
return name;
}
// Setter method for name
public void setName(String name) {
this.name = name;
}
// Getter method for id
public int getId() {
return id;
}
// Setter method for id
public void setId(int id) {
this.id = id;
}
}
// Main class to test encapsulation
public class Main {
public static void main(String[] args) {
// Creating an object of the Employee class
Employee emp = new Employee();
// Using setter methods to assign values
emp.setName("Alice");
emp.setId(101);
// Using getter methods to retrieve and display values
System.out.println("Employee Name: " + emp.getName());
System.out.println("Employee ID: " + emp.getId());
}
}
Output:
Employee Name: Alice
Employee ID: 101
Advantages of Encapsulation
Data Hiding: Encapsulation prevents direct access to sensitive data, making it more secure.
1. Improved Flexibility: You can make instance variables read-only or write-only by providing only a getter or setter method, depending on the requirement. 2. Reusability: Encapsulated code is easier to maintain, reuse, and extend because it minimizes interdependencies. 3. Easy Testing: Since encapsulated code separates data and functions, it is easier to test individual components. 4. Adaptability: The internal implementation can change without affecting code that interacts with the class.
Disadvantages of Encapsulation
Increased Complexity: Encapsulation may lead to more boilerplate code, such as writing getter and setter methods for each private variable.
Difficult to Understand: Excessive use of encapsulation can make code more difficult to follow, especially if it adds layers of abstraction.
Limited Flexibility: Over-encapsulation can sometimes restrict the flexibility of your design, making it harder to quickly implement new features.
Java Encapsulation Example (Area Calculation)
Here’s another example that demonstrates encapsulation in a different context, where it is used to calculate the area of a rectangle:
// Rectangle Class to calculate area using encapsulation
class Rectangle {
// Private fields for length and breadth
private int length;
private int breadth;
// Constructor to initialize length and breadth
public Rectangle(int length, int breadth) {
this.length = length;
this.breadth = breadth;
}
// Getter for length
public int getLength() {
return length;
}
// Setter for length
public void setLength(int length) {
this.length = length;
}
// Getter for breadth
public int getBreadth() {
return breadth;
}
// Setter for breadth
public void setBreadth(int breadth) {
this.breadth = breadth;
}
// Method to calculate and print area
public void calculateArea() {
int area = length * breadth;
System.out.println("Area of the Rectangle: " + area);
}
}
// Main class to test encapsulation in rectangle class
public class Main {
public static void main(String[] args) {
// Creating a rectangle object
Rectangle rect = new Rectangle(5, 10);
// Accessing and modifying private fields via getters and setters
rect.setLength(8);
rect.setBreadth(12);
// Calculating and printing the area
rect.calculateArea();
}
}
Output:
Area of the Rectangle: 96
What are Interfaces in Java?
In Java, an interface is an abstract type used to specify a set of behaviors that a class must implement. It provides a blueprint for a class, defining static constants and abstract methods (methods without a body). An interface is primarily used to achieve abstraction and multiple inheritance. Traditionally, interfaces in Java could only contain abstract methods and final variables, but with the introduction of Java 8, interfaces can also contain default and static methods. Interfaces help define a “contract” or “is-a” relationship between classes, specifying the methods they must implement, without worrying about the internal details.
Syntax for Java Interfaces
To declare an interface in Java, use the interface keyword. By default, all methods declared in an interface are abstract and public, and all fields are public, static, and final.
A class that implements an interface must provide implementations for all the methods declared in the interface, using the implements keyword.
Features of Interfaces
1. Achieves total abstraction: An interface allows complete abstraction since it contains no method implementation. 2. Multiple inheritance: While Java does not support multiple inheritance with classes, an interface allows classes to implement multiple interfaces. 3. Loose coupling: Interfaces enable loose coupling between classes as they provide a level of abstraction. 4. Final variables: All variables declared in an interface are final, static, and public by default.
Relationship Between Class and Interface
In Java, a class can implement one or more interfaces, but an interface can only be implemented by a class, not the other way around. Classes must implement all the methods defined by the interfaces they implement. Additionally, interfaces can extend other interfaces, allowing for a flexible hierarchy of behavior definitions.
Example of a Simple Java Interface
interface Player {
int id = 10; // Constant by default
void move(); // Abstract method
}
class TestClass implements Player {
public void move() {
System.out.println("Player moves");
}
public static void main(String[] args) {
TestClass player = new TestClass();
player.move();
System.out.println("Player ID: " + Player.id);
}
}
Output:
Player moves
Player ID: 10
Example: Vehicle Interface
Consider the example of vehicles like bicycles and cars that have common functionalities. We can create a Vehicle interface to define the general behaviors that every vehicle must implement, and let each vehicle type provide its specific implementation.
interface Vehicle {
void changeGear(int gear);
void speedUp(int increment);
void applyBrakes(int decrement);
}
class Bicycle implements Vehicle {
int speed;
int gear;
public void changeGear(int newGear) {
gear = newGear;
}
public void speedUp(int increment) {
speed += increment;
}
public void applyBrakes(int decrement) {
speed -= decrement;
}
public void display() {
System.out.println("Speed: " + speed + " Gear: " + gear);
}
}
class Car implements Vehicle {
int speed;
int gear;
public void changeGear(int newGear) {
gear = newGear;
}
public void speedUp(int increment) {
speed += increment;
}
public void applyBrakes(int decrement) {
speed -= decrement;
}
public void display() {
System.out.println("Speed: " + speed + " Gear: " + gear);
}
}
public class Main {
public static void main(String[] args) {
Bicycle bike = new Bicycle();
bike.changeGear(2);
bike.speedUp(10);
bike.applyBrakes(3);
System.out.println("Bicycle state:");
bike.display();
Car car = new Car();
car.changeGear(3);
car.speedUp(20);
car.applyBrakes(5);
System.out.println("Car state:");
car.display();
}
}
Java doesn’t allow multiple inheritance with classes, but interfaces provide a way to achieve it. A class can implement multiple interfaces, inheriting behaviors from each one.
interface Machine {
void start();
}
interface Sound {
void playSound();
}
class Robot implements Machine, Sound {
public void start() {
System.out.println("Robot started.");
}
public void playSound() {
System.out.println("Robot playing sound.");
}
}
public class Main {
public static void main(String[] args) {
Robot r = new Robot();
r.start();
r.playSound();
}
}
Output:
Robot started.
Robot playing sound.
‘this’ reference in Java
In Java, this is a reference variable that refers to the current object instance. It helps in distinguishing between instance variables and parameters with the same name and can be used for various purposes such as invoking class methods, passing the current object as a parameter, and improving code readability.
Java this Reference Example:
In Java, this refers to the object on which a method or constructor is being invoked. It allows access to the instance variables and methods of the current object.
Here’s an example demonstrating the usage of this reference:
// Java program demonstrating the use of 'this' reference
class Employee {
String name;
int id;
// Constructor
Employee(String name, int id) {
this.name = name; // 'this' refers to the instance variable 'name'
this.id = id; // 'this' refers to the instance variable 'id'
}
// Method to display employee details
public void displayDetails() {
System.out.println("Employee Name: " + this.name);
System.out.println("Employee ID: " + this.id);
}
// Main method
public static void main(String[] args) {
Employee emp1 = new Employee("John", 101);
Employee emp2 = new Employee("Alice", 102);
emp1.displayDetails();
emp2.displayDetails();
}
}
Output:
Employee Name: John
Employee ID: 101
Employee Name: Alice
Employee ID: 102
Explanation:
In the above example, this is used in the constructor to refer to the instance variables name and id, differentiating them from the constructor’s parameters. The displayDetails method prints out the details of each employee using the this reference.
Different Uses of this in Java:
1. Referring to the Current Class Instance Variables :You can use this to differentiate between instance variables and parameters with the same name.
class Test {
int x;
Test(int x) {
this.x = x; // 'this' is used to differentiate the instance variable from the constructor parameter
}
}
2. Invoking the Current Class Constructor :this() can be used to call another constructor in the same class.
class Test {
int x;
Test() {
this(10); // Calls the parameterized constructor
}
Test(int x) {
this.x = x;
}
}
3. Returning the Current Class Instance: this can be used to return the current instance of the class.
class Test {
int x;
Test(int x) {
this.x = x;
}
Test getObject() {
return this; // Returns the current object
}
}
4. Passing the Current Class Instance as a Method Parameter: this can be passed as an argument to methods or constructors.
class Test {
void display(Test obj) {
System.out.println("Object received: " + obj);
}
void sendThis() {
display(this); // Passes the current object as a parameter
}
}
5. Invoking the Current Class Method:this can be used to call a method from within another method.
class Test {
void display() {
this.show(); // Calls the show method
}
void show() {
System.out.println("Inside show method");
}
}
Operators are the foundation of any programming language, enabling us to perform various computations, logic evaluations, and functions. Java offers several types of operators that are categorized based on the functions they perform.
Array Initialization in C
Initialization in C involves assigning initial values to variables. When an array is declared or memory is allocated for it, its elements initially contain garbage values. To give these elements meaningful values, we initialize the array. There are several methods for initializing an array in C.
1. Array Initialization During Declaration :This method involves initializing the array at the time of its declaration. We use an initializer list, which is a set of values enclosed in curly braces { } and separated by commas, to assign values to the array.
Examples:
int[] numbers; // Declaring an integer array
This declares an integer array numbers. However, it does not allocate memory yet.
2. Creating an Array :Allocate memory using the new keyword:
numbers = new int[5]; // Creates an array of 5 integers
This initializes the array to hold 5 integers, with default values of 0.
3. Accessing Array Elements :You can access and modify array elements using their index (starting from 0):
numbers[0] = 10; // Setting the first element to 10
int firstElement = numbers[0]; // Accessing the first element
4. Changing Array Elements :To update an element, assign a new value:
numbers[0] = 20; // Changes the first element to 20
5. Array Length :You can get the length of an array using its length property:
int length = numbers.length; // Returns 5 for this array
6. Array Initialization :You can declare and initialize arrays in different ways:
7. Iterating Through Arrays :You can loop through arrays using a for loop or for-each loop:
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
for (int number : numbers) {
System.out.println(number); // For-each loop
}
9. Array of Objects ;Arrays can also hold objects of a class:
Student[] students = new Student[3]; // Array of Student objects
students[0] = new Student("John", 1);
Output:
num1 = 20
num2 = 10
The product = 200
10. Passing Arrays to Methods :You can pass arrays to methods:
public class MultiplicationExample {
public static void main(String[] args) {
int num1 = 20, num2 = 10;
int product = num1 * num2;
System.out.println("The product = " + product);
}
}
Calling the method:
printArray(numbers);
11. Returning Arrays from Methods :A method can return an array:
public static int[] getArray() {
return new int[] {1, 2, 3};
}
12. Cloning Arrays :To clone an array (create a shallow copy):
int[] cloneArray = numbers.clone();
For multidimensional arrays, the cloning creates a shallow copy, meaning only the references are copied, not the actual elements.
13. Handling Array Exceptions :If you try to access an element outside the array size, Java throws an ArrayIndexOutOfBoundsException:
System.out.println(numbers[5]); // Throws an exception if the array has fewer elements
Arrays class in Java
The Arrays class in Java, part of the java.util package, provides several static methods to help developers perform operations on arrays in a more optimized and efficient manner. Here are some of the most common methods:
Key Methods in Arrays Class:
1. asList(): Converts an array to a fixed-size list.
Integer[] arr = {1, 2, 3};
List<Integer> list = Arrays.asList(arr);
2. binarySearch(): Searches for a specific element using the binary search algorithm.
int[] arr = {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(arr, 3); // Returns index of 3
3. compare(): Compares two arrays lexicographically.
int result = Arrays.compare(arr1, arr2);
4. copyOf(): Copies the array to a new array of a specified length.
int[] newArr = Arrays.copyOf(arr, 10); // Extends or truncates
5. copyOfRange(): Copies a range of an array.
int[] newArr = Arrays.copyOfRange(arr, 1, 3);
6. deepEquals():Compares two arrays deeply for nested arrays.
boolean isEqual = Arrays.deepEquals(arr1, arr2);
7. deepHashCode(): Returns the hash code based on the “deep contents” of an array.
int hashCode = Arrays.deepHashCode(arr);
8. deepToString(): Converts an array to a string representation, handling nested arrays.
String arrStr = Arrays.deepToString(arr);
9. equals(): Compares two arrays for equality.
boolean isEqual = Arrays.equals(arr1, arr2);
10. fill(): Fills an array with a specified value.
Arrays.fill(arr, 100); // Fills all elements with 100
11. hashCode(): Returns the hash code for an array.
int hash = Arrays.hashCode(arr);
12. mismatch(): Finds the first index where two arrays differ.
int mismatchIndex = Arrays.mismatch(arr1, arr2);
13. parallelSort(): Sorts the array in parallel for faster sorting.
Arrays.parallelSort(arr);
14. sort(): Sorts an array in ascending order.
Arrays.sort(arr);
15. spliterator(): Returns a Spliterator covering the array.
16. stream(): Converts an array into a sequential stream.
Stream<int[]> stream = Arrays.stream(arr);
17. toString(): Converts an array to a string representation.
String arrStr = Arrays.toString(arr);
Multidimensional Arrays
Multidimensional arrays, simply put, are arrays made up of arrays. Data within these arrays are stored in a tabular structure, typically in row-major order.
Syntax:
data_type[1st_dimension][2nd_dimension][]...[Nth_dimension] array_name = new data_type[size1][size2]...[sizeN];
Where:
data_type: The type of data stored in the array (e.g., int, char, etc.).
dimension: Specifies the dimension of the array (e.g., 2D, 3D).
array_name: The name assigned to the array.
size1, size2,…, sizeN: Dimensions defining the size of the array.
Examples:
Two-dimensional array:
int[][] twoD_arr = new int[10][20];
The total number of elements a multidimensional array can store is the product of its dimensions. For example, an array int[][] x = new int[10][20] can hold a total of 10×20=20010 \times 20 = 20010×20=200 elements. Similarly, int[][][] x = new int[5][10][20] can store 5×10×20=10005 \times 10 \times 20 = 10005×10×20=1000 elements.
Applications of Multidimensional Arrays
Tabular Data: These arrays are often used to store tabular data, such as a student’s roll number and marks. A more complex use is to store images in 3D arrays.
Dynamic Programming: Many dynamic programming problems leverage multidimensional arrays to store intermediate states.
Algorithms: Common applications include matrix multiplication, adjacency matrices in graphs, and grid-based search problems.
Two-Dimensional Array (2D Array)
A 2D array is the most basic form of a multidimensional array and can be viewed as an array of one-dimensional arrays.
Declaration (Indirect Method):
Example:
int[][] arr = new int[10][20];
Initialization:
arr[0][0] = 1;
Examples:
public class TwoDArrayExample {
public static void main(String[] args) {
int[][] arr = new int[10][20];
arr[0][0] = 1;
System.out.println("arr[0][0] = " + arr[0][0]);
}
}
Output:
arr[0][0] = 1
Example: 2D array with default values in a 4×4 matrix:
public class TwoDArray {
public static void main(String[] args) {
int rows = 4;
int columns = 4;
int[][] array = new int[rows][columns];
int value = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
array[i][j] = value++;
}
}
System.out.println("The 2D array is:");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}
Output:
The 2D array is:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Declaration (Direct Method):
int[][] arr = {{1, 2}, {3, 4}};
Output:
After adding: 8
Example:
public class DirectTwoDArray {
public static void main(String[] args) {
int[][] arr = { { 1, 2 }, { 3, 4 } };
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
System.out.println("arr[" + i + "][" + j + "] = " + arr[i][j]);
}
}
}
}
Different Ways To Declare And Initialize 2-D Array
A multi-dimensional array is an array with more than one dimension, commonly used as 2D or 3D arrays. Essentially, a multi-dimensional array is an array of arrays. A typical example of a 2D array is a chessboard, which consists of a grid of 64 square boxes arranged in 8 rows and 8 columns. Similarly, a 2D array can be visualized as a grid, where each element is identified by a row and column number. Accessing elements in a 2D array is similar to working with an Excel sheet, using row and column indices.
Two-dimensional arrays (2D arrays) are useful for implementing structures like games (Tic-Tac-Toe, Chess) or storing image pixels.
Declaring a 2D Array in Java
A 2D array can be declared in two common ways:
data_type array_name[][]; // OR
data_type[][] array_name;
data_type: This defines the type of elements the array will store, such as int, String, boolean, etc. Java, being statically typed, requires the data type to be declared.
array_name: This is the name you assign to the array.
Example: Declaring Different Types of 2D Arrays
data_type[][] array_Name = new data_type[no_of_rows][no_of_columns];
Here, no_of_rows and no_of_columns define the number of rows and columns in the array. The total number of elements in a 2D array is calculated by multiplying the number of rows by the number of columns. For instance:
int[][] myArray = new int[4][5]; // A 2D array with 4 rows and 5 columns
By default, Java assigns default values to the array elements depending on the data type. Below are various approaches to initialize a 2D array.
Different Approaches for Initializing 2D Arrays
Approach 1: Declaration and Initialization
In this approach, we declare the array and immediately initialize it.
public class Example {
public static void main(String[] args) {
int[][] integer2DArray = new int[3][4];
System.out.println("Default value of int array element: " + integer2DArray[0][0]); // Outputs 0
String[][] string2DArray = new String[2][3];
System.out.println("Default value of String array element: " + string2DArray[0][0]); // Outputs null
boolean[][] boolean2DArray = new boolean[2][2];
System.out.println("Default value of boolean array element: " + boolean2DArray[0][0]); // Outputs false
}
}
Approach 2: Initialization with Values
Here, we initialize the array elements directly without specifying the number of rows and columns. Java automatically deduces the size.
Example:
public class Example {
public static void main(String[] args) {
String[][] courses = {
{ "Math", "Science", "History" }, // Row 1
{ "Biology", "Physics", "Chemistry" }, // Row 2
{ "English", "Art" } // Row 3
};
System.out.println("Course in first row: " + courses[0][0]); // Math
System.out.println("Course in second row: " + courses[1][2]); // Chemistry
System.out.println("Course in third row: " + courses[2][1]); // Art
}
}
Approach 3: Initializing Each Element Separately
This method allows you to initialize elements individually.
Example:
public class Example {
public static void main(String[] args) {
int[][] marks = new int[2][2];
marks[0][0] = 85;
marks[0][1] = 90;
marks[1][0] = 78;
marks[1][1] = 88;
System.out.println("marks[0][0] = " + marks[0][0]);
System.out.println("marks[1][1] = " + marks[1][1]);
}
}
Approach 4: Using Loops for Initialization
When dealing with large arrays, initializing elements manually can be cumbersome. A more efficient approach is using loops.
Example:
public class Example {
public static void main(String[] args) {
int rows = 4, columns = 3;
int[][] array = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
array[i][j] = i + j;
}
}
// Printing array elements
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println();
}
}
}
Approach 5: Jagged Arrays (Different Number of Columns per Row)
A jagged array allows rows to have different numbers of columns.
Example:
public class Example {
public static void main(String[] args) {
int[][] jaggedArray = new int[2][];
jaggedArray[0] = new int[3]; // First row has 3 columns
jaggedArray[1] = new int[2]; // Second row has 2 columns
jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;
jaggedArray[0][2] = 3;
jaggedArray[1][0] = 4;
jaggedArray[1][1] = 5;
// Printing the jagged array
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}
Jagged Arrays in Java
A jagged array is a type of multidimensional array where the number of columns varies from row to row. This makes the jagged array more flexible compared to a rectangular 2D array. Here’s a simplified representation of a jagged array in memory:
Row 1: [ ]
Row 2: [ ]
Row 3: [ ]
...
Declaring and Initializing a Jagged Array
Syntax:
data_type array_name[][] = new data_type[n][];
array_name[0] = new data_type[n1]; // n1 = no. of columns in row-1
array_name[1] = new data_type[n2]; // n2 = no. of columns in row-2
...
Alternative Ways to Initialize a Jagged Array:
int[][] arr = new int[][] {
new int[] {10, 20, 30, 40},
new int[] {50, 60, 70, 80, 90, 100},
new int[] {110, 120}
};
public class Main {
public static void main(String[] args) {
// Declare a 2D array with 2 rows
int[][] jaggedArray = new int[2][];
// First row has 3 columns
jaggedArray[0] = new int[3];
// Second row has 2 columns
jaggedArray[1] = new int[2];
// Initializing the array
int value = 0;
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
jaggedArray[i][j] = value++;
}
}
// Displaying the values of the jagged array
System.out.println("Contents of the Jagged Array:");
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}
Output:
Contents of the Jagged Array:
0 1 2
3 4
Example 2: Creating a Jagged Array with Incremental Row Sizes
In this example, the first row contains one element, the second row contains two elements, and so on.
public class Main {
public static void main(String[] args) {
int rows = 5;
// Declaring a jagged array with 5 rows
int[][] jaggedArray = new int[rows][];
// Creating the jagged array with varying columns per row
for (int i = 0; i < jaggedArray.length; i++) {
jaggedArray[i] = new int[i + 1]; // ith row has i+1 columns
}
// Initializing the array
int value = 0;
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
jaggedArray[i][j] = value++;
}
}
// Displaying the values of the jagged array
System.out.println("Contents of the Jagged Array:");
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}
Output:
Contents of the Jagged Array:
0
1 2
3 4 5
6 7 8 9
10 11 12 13 14
Final Arrays
In Java, the final keyword prevents reassigning a reference to another object, but it doesn’t make the referenced object itself immutable. This is applicable to arrays as well. Once an array is declared as final, the reference to that array cannot be changed, but the elements within the array can be modified. This means we can change the state of the object (the contents of the array), but not the reference to the object itself.
Illustration:
// Java Program Demonstrating Final Arrays
public class FinalArrayDemo {
public static void main(String[] args) {
final int[] arr = { 1, 2, 3, 4, 5 };
// Modifying an element in the final array
arr[3] = 10;
// Displaying the updated array
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
Output:
1
2
3
10
5
Implementation: Here’s another example showing how you can manipulate the contents of a final array:
// Java Program Demonstrating Final Arrays
public class FinalArrayExample {
public static void main(String[] args) {
final int[] arr = { 2, 4, 6, 8, 10 };
// Modifying array elements
for (int i = 0; i < arr.length; i++) {
arr[i] = arr[i] * 2;
System.out.println(arr[i]);
}
}
}
Output:
4
8
12
16
20
Explanation:
Even though the array arr is declared as final, you can still change its individual elements. The final keyword simply means that the reference to the array cannot be reassigned to another array. This behavior is consistent with how object references work in Java: when you declare an object as final, the reference can’t be changed, but the object’s internal state can still be modified.
Example 1:
// Program demonstrating modification of object fields
class Test {
int value = 100;
public static void main(String[] args) {
final Test obj = new Test();
obj.value = 200; // Modifying the internal state
System.out.println(obj.value);
}
}
Output:
200
util.Arrays vs reflect.Array in Java with Examples
The Array class in the java.lang.reflect package is part of Java Reflection and provides static methods to dynamically create and access Java arrays. This class is final, meaning it cannot be instantiated or extended. All its methods are static and accessed via the class name itself. On the other hand, the Arrays class in the java.util package is part of the Java Collection Framework and contains various utility methods for manipulating arrays, such as sorting and searching.
While both classes deal with arrays, the key difference is their usage. The Array class ensures type safety and is mainly used for reflective access to arrays. The Arrays class, on the other hand, offers a variety of methods for array operations.
Here is a breakdown of the differences between Array and Arrays:
Factor
Array
Arrays
Package
Belongs to java.lang.reflect
Belongs to java.util
Class Hierarchy
java.lang.Object → java.lang.reflect.Array
java.lang.Object → java.util.Arrays
Immutability
Immutable and final
Not immutable
Declaration
public final class Array extends Object
public class Arrays extends Object
Usage
Provides methods to create and access arrays reflectively, ensuring type safety
Contains utility methods for array manipulation (sorting, searching, etc.)
Example: Illustrating the Usage of Array vs Arrays
import java.lang.reflect.Array;
import java.util.Arrays;
public class ArrayVsArraysExample {
public static void main(String[] args) {
// Creating an integer array of size 5
int[] intArray = new int[5];
// Adding an element to the array using Array class
Array.setInt(intArray, 0, 42);
// Printing the array using Arrays class
System.out.println(Arrays.toString(intArray));
}
}
Operators are the foundation of any programming language, enabling us to perform various computations, logic evaluations, and functions. Java offers several types of operators that are categorized based on the functions they perform. These include:
Arithmetic Operators
Unary Operators
Assignment Operator
Relational Operators
Logical Operators
Ternary Operator
Bitwise Operators
Shift Operators
This section focuses on Arithmetic Operators, which allow us to carry out mathematical operations on basic data types. These operators can either be unary (applied to one operand) or binary (applied to two operands). Let’s dive into each arithmetic operator in Java.
Arithmetic Operators in Java
1. Addition (+)
This binary operator is used to add two operands.
Syntax:
num1 + num2
Example:
int num1 = 10, num2 = 20;
int sum = num1 + num2;
Output:
num1 = 10
num2 = 20
The sum = 30
Java Code Example:
public class AdditionExample {
public static void main(String[] args) {
int num1 = 10, num2 = 20;
int sum = num1 + num2;
System.out.println("The sum = " + sum);
}
}
2. Subtraction (-)
This binary operator is used to subtract the second operand from the first operand.
Syntax:
num1 - num2
Example:
int num1 = 20, num2 = 10;
int difference = num1 - num2;
Output:
num1 = 20
num2 = 10
The difference = 10
Java Code Example:
public class SubtractionExample {
public static void main(String[] args) {
int num1 = 20, num2 = 10;
int difference = num1 - num2;
System.out.println("The difference = " + difference);
}
}
3. Multiplication (*)
This binary operator multiplies two operands.
Syntax:
num1 * num2
Example:
int num1 = 20, num2 = 10;
int product = num1 * num2;
Output:
num1 = 20
num2 = 10
The product = 200
Java Code Example:
public class MultiplicationExample {
public static void main(String[] args) {
int num1 = 20, num2 = 10;
int product = num1 * num2;
System.out.println("The product = " + product);
}
}
4. Division (/)
This binary operator divides the first operand (dividend) by the second operand (divisor) and returns the quotient.
Syntax:
num1 / num2
Example:
int num1 = 20, num2 = 10;
int quotient = num1 / num2;
Output:
num1 = 20
num2 = 10
The quotient = 2
Java Code Example:
public class DivisionExample {
public static void main(String[] args) {
int num1 = 20, num2 = 10;
int quotient = num1 / num2;
System.out.println("The quotient = " + quotient);
}
}
5. Modulus (%)
This binary operator returns the remainder when the first operand (dividend) is divided by the second operand (divisor).
Syntax:
num1 % num2
Example:
int num1 = 5, num2 = 2;
int remainder = num1 % num2;
Output:
num1 = 5
num2 = 2
The remainder = 1
Java Code Example:
public class ModulusExample {
public static void main(String[] args) {
int num1 = 5, num2 = 2;
int remainder = num1 % num2;
System.out.println("The remainder = " + remainder);
}
}
Example Program Implementing All Arithmetic Operators
The following Java program takes user input and performs addition, subtraction, multiplication, and division:
import java.util.Scanner;
public class ArithmeticOperators {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter the first number: ");
double num1 = sc.nextDouble();
System.out.print("Enter the second number: ");
double num2 = sc.nextDouble();
double sum = num1 + num2;
double difference = num1 - num2;
double product = num1 * num2;
double quotient = num1 / num2;
System.out.println("The sum of the two numbers is: " + sum);
System.out.println("The difference of the two numbers is: " + difference);
System.out.println("The product of the two numbers is: " + product);
System.out.println("The quotient of the two numbers is: " + quotient);
}
}
Input:
Enter the first number: 20
Enter the second number: 10
Output:
The sum of the two numbers is: 30.0
The difference of the two numbers is: 10.0
The product of the two numbers is: 200.0
The quotient of the two numbers is: 2.0
Java Unary Operator
Unary operators in Java operate on a single operand. These operators are used for tasks such as incrementing, decrementing, and negating values. Let’s explore the various unary operators and how they function.
Operator 1: Unary Minus (-)
This operator is used to reverse the sign of a value, converting a positive value into a negative one, or vice versa.
Syntax:
-(operand)
Example:
// Java Program demonstrating Unary Minus
class UnaryMinus {
public static void main(String[] args) {
int num = 20;
System.out.println("Number = " + num);
// Applying unary minus
num = -num;
System.out.println("After applying unary minus = " + num);
}
}
Output:
Number = 20
After applying unary minus = -20
Operator 2: NOT Operator (!)
This operator negates a boolean expression, flipping true to false and vice versa.
Syntax:
!(operand)
Example:
// Java Program demonstrating NOT Operator
class NotOperator {
public static void main(String[] args) {
boolean flag = true;
int a = 10, b = 1;
System.out.println("Initial flag: " + flag);
System.out.println("a = " + a + ", b = " + b);
// Applying NOT operator
System.out.println("Negated flag: " + !flag);
System.out.println("!(a < b) = " + !(a < b));
System.out.println("!(a > b) = " + !(a > b));
}
}
Output:
Initial flag: true
a = 10, b = 1
Negated flag: false
!(a < b) = true
!(a > b) = false
Operator 3: Increment (++)
The increment operator increases the value of an operand by one. It can be used in two forms:
Post-Increment: The operand is incremented after its current value is used.
Pre-Increment: The operand is incremented before its current value is used.
Example:
int num = 5;
System.out.println("Post-increment: " + (num++)); // Uses current value, then increments
System.out.println("Pre-increment: " + (++num)); // Increments, then uses new value
Operator 4: Decrement (--)
Similar to the increment operator, the decrement operator decreases the operand’s value by one and can also be used in two forms:
Post-Decrement: Decrements the operand after its current value is used.
Pre-Decrement: Decrements the operand before its current value is used.
Example:
int num = 5;
System.out.println("Post-decrement: " + (num--)); // Uses current value, then decrements
System.out.println("Pre-decrement: " + (--num)); // Decrements, then uses new value
Operator 5: Bitwise Complement (~)
This operator inverts all the bits of the operand. It converts 0s to 1s and 1s to 0s.
Syntax:
~(operand)
Example:
// Java Program demonstrating Bitwise Complement Operator
class BitwiseComplement {
public static void main(String[] args) {
int num = 5;
System.out.println("Number: " + num);
// Applying bitwise complement
System.out.println("Bitwise complement: " + ~num);
}
}
Output:
Number: 5
Bitwise complement: -6
Example Program Demonstrating All Unary Operators
Here’s a comprehensive program that demonstrates the use of all basic unary operators with user input:
import java.util.Scanner;
public class UnaryOperatorsExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number: ");
int num = sc.nextInt();
// Unary plus
int result = +num;
System.out.println("Unary plus result: " + result);
// Unary minus
result = -num;
System.out.println("Unary minus result: " + result);
// Pre-increment
result = ++num;
System.out.println("Pre-increment result: " + result);
// Post-increment
result = num++;
System.out.println("Post-increment result: " + result);
// Pre-decrement
result = --num;
System.out.println("Pre-decrement result: " + result);
// Post-decrement
result = num--;
System.out.println("Post-decrement result: " + result);
sc.close();
}
}
Input:
Enter a number: 10
Output:
Unary plus result: 10
Unary minus result: -10
Pre-increment result: 11
Post-increment result: 11
Pre-decrement result: 11
Post-decrement result: 10
Java Assignment Operators
In Java, operators form the basic building blocks of programming, allowing developers to perform various types of calculations, comparisons, and logical operations. Assignment operators specifically help assign values to variables. They have right-to-left associativity, meaning the value on the right side of the operator is assigned to the variable on the left. Let’s dive into the different types of assignment operators used in Java.
Types of Assignment Operators:
1. Simple Assignment Operator (=): The simple assignment operator is used to assign a value to a variable. The operand on the right-hand side must match the data type of the variable on the left-hand side.
Syntax:
variable = value;
Example:
public class AssignmentOperatorExample {
public static void main(String[] args) {
int num = 15;
String name = "Java";
System.out.println("num is assigned: " + num);
System.out.println("name is assigned: " + name);
}
}
Output:
num is assigned: 15
name is assigned: Java
2. Add and Assign (+=): The compound += operator adds the value on the right to the value of the variable on the left and then assigns the result back to the variable on the left.
Syntax:
variable += value;
Example:
public class AddAssignExample {
public static void main(String[] args) {
int num1 = 5, num2 = 3;
num1 += num2;
System.out.println("After adding: " + num1);
}
}
Output:
After adding: 8
Note: This operator performs implicit type conversion if necessary. For instance, adding a double to an int using += will result in automatic narrowing conversion.
3. Subtract and Assign (-=): The compound -= operator subtracts the value on the right from the value on the left and then assigns the result back to the variable on the left.
Syntax:
variable -= value;
Example:
public class SubtractAssignExample {
public static void main(String[] args) {
int num1 = 10, num2 = 4;
num1 -= num2;
System.out.println("After subtracting: " + num1);
}
}
Output:
After subtracting: 6
4. Multiply and Assign (*=): This operator multiplies the current value of the variable by the value on the right and assigns the result back to the variable on the left.
Syntax:
variable *= value;
a *= 2; // Equivalent to a = a * 2
Example:
public class MultiplyAssignExample {
public static void main(String[] args) {
int num1 = 4, num2 = 3;
num1 *= num2;
System.out.println("After multiplying: " + num1);
}
}
Output:
After multiplying: 12
5. Divide and Assign (/=): This operator divides the current value of the variable by the value on the right and assigns the result back to the variable on the left.
Syntax:
variable /= value;
Example:
public class DivideAssignExample {
public static void main(String[] args) {
int num1 = 20, num2 = 4;
num1 /= num2;
System.out.println("After dividing: " + num1);
}
}
Output:
After dividing: 5
6. Modulus and Assign (%=): This operator performs division and assigns the remainder back to the variable on the left.
Syntax:
variable %= value;
Example:
public class ModulusAssignExample {
public static void main(String[] args) {
int num1 = 17, num2 = 5;
num1 %= num2;
System.out.println("After modulus: " + num1);
}
}
Output:
After modulus: 2
Java Relational Operators
Relational operators in Java are binary operators used to compare two operands and return a boolean value indicating the result of the comparison. These operators are often used in control flow statements such as loops and conditionals.
General Syntax:
variable1 relation_operator variable2
1. Equal to (==)
The == operator checks if two operands are equal. If they are, it returns true; otherwise, it returns false.
Logical operators are used to perform logical operations such as “AND,” “OR,” and “NOT,” similar to the functions of AND and OR gates in digital electronics. They combine two or more conditions or reverse the outcome of a given condition. An important point to remember is that in the case of the AND operator, the second condition is not evaluated if the first is false, while in the case of the OR operator, the second condition is not evaluated if the first is true. This feature is known as short-circuiting. Logical operators are commonly used in decision-making when multiple conditions need to be checked.
Logical Operators in Java
Let’s go through an example with some common logical operators in Java. Assume we have the following variables:
Syntax:
int a = 10;
int b = 20;
int c = 30;
AND Operator (&&):
This operator returns true if both conditions are true. Otherwise, it returns false.
Example:
Condition 1: c > a (true)
Condition 2: c > b (true)
Since both conditions are true, the result will be true.
Example:
if (c > a && c > b) {
System.out.println("Both conditions are true");
} else {
System.out.println("At least one condition is false");
}
Output:
Both conditions are true
OR Operator (||):
This operator returns true if at least one of the conditions is true. If both conditions are false, the result is false.
Example:
Condition 1: c > a (true)
Condition 2: c < b (false)
Since one of the conditions is true, the result will be true.
if (c > a || c < b) {
System.out.println("At least one condition is true");
} else {
System.out.println("Both conditions are false");
}
Output:
At least one condition is true
NOT Operator (!):
This unary operator returns the opposite of the condition. If the condition is true, it returns false, and vice versa.
In cases where the first condition of an AND operation is false, the second condition will not be evaluated.
Example:
int a = 10, b = 20, c = 15;
if ((a > c) && (++b > c)) {
System.out.println("Condition met");
}
System.out.println("Value of b: " + b);
Output:
Value of b: 20
Short-Circuiting in AND Operator:
In cases where the first condition of an AND operation is false, the second condition will not be evaluated.
Example:
int a = 10, b = 20, c = 15;
if ((a > c) && (++b > c)) {
System.out.println("Condition met");
}
System.out.println("Value of b: " + b);
Output:
Value of b: 20
Short-Circuiting in OR Operator:
In cases where the first condition of an OR operation is true, the second condition will not be evaluated.
Example:
int a = 10, b = 20, c = 15;
if ((a < c) || (++b < c)) {
System.out.println("Condition met");
}
System.out.println("Value of b: " + b);
Output:
Condition met
Value of b: 20
Boolean Values and Logical Operators:
Logical operators can also be applied directly to boolean values. For example:
Example:
boolean a = true;
boolean b = false;
System.out.println("a && b: " + (a && b)); // false
System.out.println("a || b: " + (a || b)); // true
System.out.println("!a: " + !a); // false
System.out.println("!b: " + !b); // true
Output:
a && b: false
a || b: true
!a: false
!b: true
Java Ternary Operator
The ternary operator is the only operator in Java that takes three operands. It serves as a concise alternative to the traditional if-else statement, allowing conditional logic in a single line. Although it operates similarly to if-else, it helps to reduce code size and improve readability.
int num1 = 10;
int num2 = 20;
int result = (num1 > num2) ? (num1 + num2) : (num1 - num2);
Since num1 < num2, the second expression is executed, so:
Syntax:
result = num1 - num2 = -10;
Example:
class TernaryExample {
public static void main(String[] args) {
int n1 = 5, n2 = 10, max;
System.out.println("First number: " + n1);
System.out.println("Second number: " + n2);
// Using ternary operator to find the maximum
max = (n1 > n2) ? n1 : n2;
System.out.println("The maximum number is: " + max);
}
}
Output:
First number: 5
Second number: 10
The maximum number is: 10
Bitwise operators
Bitwise operators are used to manipulate individual bits of a number. They are particularly useful when optimizing performance in certain cases, as they directly operate on the binary representation of numbers. Bitwise operators can be used with any integral type (e.g., char, short, int). They are often employed when performing operations on Binary Indexed Trees (BITs).
Here are the common bitwise operators in Java:
1. Bitwise OR (|)
The Bitwise OR operator is represented by the symbol |. It compares the corresponding bits of two operands, and if either of the bits is 1, the result is 1; otherwise, the result is 0. Example:
a = 6 = 0110 (In Binary)
b = 9 = 1001 (In Binary)
Bitwise OR Operation:
0110
| 1001
_________
1111 = 15 (In decimal)
2. Bitwise AND (&)
The Bitwise AND operator is represented by &. It compares the corresponding bits of two operands, and if both bits are 1, the result is 1; otherwise, the result is 0. Example:
a = 6 = 0110 (In Binary)
b = 9 = 1001 (In Binary)
Bitwise AND Operation:
0110
& 1001
_________
0000 = 0 (In decimal)
3. Bitwise XOR (^)
The Bitwise XOR operator is represented by ^. It compares the corresponding bits of two operands, and if the bits are different, the result is 1; otherwise, the result is 0. Example:
a = 6 = 0110 (In Binary)
b = 9 = 1001 (In Binary)
Bitwise XOR Operation:
0110
^ 1001
_________
1111 = 15 (In decimal)
4. Bitwise Complement (~)
The Bitwise NOT (complement) operator is represented by ~. It inverts all the bits of the operand, changing every 1 to 0 and every 0 to 1. Example:
a = 6 = 0110 (In Binary)
Bitwise NOT Operation:
~ 0110
_________
1001 = -7 (In decimal, as it returns the two's complement)
Code Example:
import java.util.Scanner;
public class BitwiseOperators {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter first number: ");
int num1 = input.nextInt();
System.out.print("Enter second number: ");
int num2 = input.nextInt();
System.out.println("Bitwise AND: " + (num1 & num2));
System.out.println("Bitwise OR: " + (num1 | num2));
System.out.println("Bitwise XOR: " + (num1 ^ num2));
System.out.println("Bitwise NOT: " + (~num1));
System.out.println("Bitwise Left Shift: " + (num1 << 2));
System.out.println("Bitwise Right Shift: " + (num1 >> 2));
System.out.println("Bitwise Unsigned Right Shift: " + (num1 >>> 2));
input.close();
}
}
Input:
Enter first number: 4
Enter second number: 10
Output:
Bitwise AND: 0
Bitwise OR: 14
Bitwise XOR: 14
Bitwise NOT: -5
Bitwise Left Shift: 16
Bitwise Right Shift: 1
Bitwise Unsigned Right Shift: 1
Decision Making in Java (if, if-else, switch, break, continue, jump).
Decision-making in programming is like making decisions in real life. When coding, we often need to execute certain blocks of code only if specific conditions are met.
Java provides several control statements to control the flow of a program based on conditions. These statements direct the flow of execution, allowing it to branch and continue based on the program’s state.
Java’s Selection Statements:
if
if-else
nested-if
if-else-if
switch-case
jump (break, continue, return)
1. if Statement:
The simplest decision-making statement. It is used to decide whether a certain block of code will be executed or not, depending on whether the condition is true.
Syntax:
if(condition) {
// Statements to execute if the condition is true
}
Here, the condition evaluates to either true or false. If true, the block of statements inside the if block is executed.
If we do not use curly braces ({}), only the first statement after the if will be considered part of the if block.
Example:
class IfDemo {
public static void main(String args[]) {
int i = 10;
if (i < 15)
System.out.println("Inside If block"); // Part of if block
System.out.println("10 is less than 15"); // Outside of if block
System.out.println("I am not in if block");
}
}
Output:
Inside If block
10 is less than 15
I am not in if block
2. if-else Statement:
The if statement alone can execute code when a condition is true. But what if we want to execute something else when the condition is false? This is where the else statement comes in.
Syntax:
if (condition) {
// Executes if condition is true
} else {
// Executes if condition is false
}
Example:
class IfElseDemo {
public static void main(String args[]) {
int i = 10;
if (i < 15)
System.out.println("i is smaller than 15");
else
System.out.println("i is greater than 15");
}
}
Output:
i is smaller than 15
3. nested-if Statement:
A nested-if is an if statement inside another if. This allows you to perform more complex decision-making scenarios.
Syntax:
if (condition1) {
if (condition2) {
// Executes when both conditions are true
}
}
Example:
class NestedIfDemo {
public static void main(String args[]) {
int i = 10;
if (i == 10 || i < 15) {
if (i < 15)
System.out.println("i is smaller than 15");
if (i < 12)
System.out.println("i is smaller than 12 too");
} else {
System.out.println("i is greater than 15");
}
}
}
Output:
i is smaller than 15
i is smaller than 12 too
4. if-else-if Ladder:
The if-else-if ladder allows you to test multiple conditions. The conditions are evaluated from top to bottom, and as soon as one of them is true, its corresponding block is executed, and the rest are skipped.
Syntax:
if (condition1) {
// Executes if condition1 is true
} else if (condition2) {
// Executes if condition2 is true
} else {
// Executes if none of the above conditions are true
}
Example:
class IfElseIfDemo {
public static void main(String args[]) {
int i = 20;
if (i == 10)
System.out.println("i is 10");
else if (i == 15)
System.out.println("i is 15");
else if (i == 20)
System.out.println("i is 20");
else
System.out.println("i is not present");
}
}
Output:
i is 20
5. switch-case Statement:
The switch statement allows you to branch execution based on the value of an expression. It’s like having multiple if-else blocks for a single expression.
Syntax:
switch (expression) {
case value1:
// Code to be executed if expression equals value1
break;
case value2:
// Code to be executed if expression equals value2
break;
// Add more cases as needed
default:
// Code to be executed if none of the cases match
}
Example:
class SwitchDemo {
public static void main(String[] args) {
int num = 20;
switch (num) {
case 5:
System.out.println("It is 5");
break;
case 10:
System.out.println("It is 10");
break;
case 15:
System.out.println("It is 15");
break;
case 20:
System.out.println("It is 20");
break;
default:
System.out.println("Not present");
}
}
}
Output:
It is 20
6. Jump Statements:
Java has three main jump statements:
break: Used to exit a loop or a switch statement.
continue: Skips the remaining code in the current iteration of a loop and starts the next iteration.
return: Exits from the current method and passes control back to the caller.
Example of continue:
class ContinueDemo {
public static void main(String args[]) {
for (int i = 0; i < 10; i++) {
if (i % 2 == 0)
continue;
System.out.print(i + " ");
}
}
}
Output:
1 3 5 7 9
If Statements with Examples
Decision Making in Java allows you to execute a specific block of code based on certain conditions. It’s a key part of controlling the flow of a program, similar to how we make decisions in real life.
Java’s if Statement:
The if statement is the simplest form of decision-making. It allows you to execute a block of code if a specific condition evaluates to true.
Syntax:
if (condition) {
// Statements to execute if the condition is true
}
How It Works:
1. Control enters the if block. 2. The condition is evaluated.
If the condition is true, the block of code within the if statement is executed.
If the condition is false, the control moves to the next part of the program.
Example:
class IfDemo {
public static void main(String args[]) {
int i = 10;
if (i < 15)
System.out.println("10 is less than 15");
System.out.println("Outside if-block");
}
}
Output:
10 is less than 15
Outside if-block
Java if-else Statement
Decision-making in Java allows for the execution of certain blocks of code based on specific conditions. The if statement tells us that if a condition is true, it will execute a block of statements; otherwise, it won’t. By combining if and else, you can handle both outcomes—what happens when the condition is true and when it’s false.
Understanding if-else in Java:
The if-else statement is used to control the flow of your program by executing code based on whether a condition is true or false.
Syntax of if-else Statement:
if (condition) {
// Executes this block if the condition is true
} else {
// Executes this block if the condition is false
}
Example Program:
// Java program to demonstrate if-else statement
class IfElseDemo {
public static void main(String args[]) {
int i = 20;
if (i < 15) {
System.out.println("i is smaller than 15");
} else {
System.out.println("i is greater than 15");
}
System.out.println("Outside if-else block");
}
}
Output:
i is greater than 15
Outside if-else block
Java if-else-if Ladder
Decision-making in Java allows us to write condition-based statements that execute particular blocks of code depending on specific conditions. The if-else-if ladder is used to handle multiple conditions by checking each one sequentially. As soon as a condition evaluates to true, its corresponding block is executed, and the rest of the ladder is ignored. If none of the conditions are true, the final else block is executed.
Syntax:
if (condition) {
// Executes if condition 1 is true
} else if (condition) {
// Executes if condition 2 is true
}
.
.
else {
// Executes if no conditions are true
}
Working of if-else-if Ladder:
1. Control enters the if block. 2. The first condition is evaluated:If true, the associated block is executed, and the rest of the ladder is skipped. If false, the flow moves to the next condition. 3. This process repeats for each condition in the ladder. 4. If none of the conditions are met, the else block is executed.
Example :
// Java program to demonstrate if-else-if ladder
class IfElseIfLadderDemo {
public static void main(String[] args) {
// Initializing expression
int i = 20;
// Condition 1
if (i == 10) {
System.out.println("i is 10");
}
// Condition 2
else if (i == 15) {
System.out.println("i is 15");
}
// Condition 3
else if (i == 20) {
System.out.println("i is 20");
}
// Default case
else {
System.out.println("i is not present");
}
System.out.println("Outside if-else-if ladder");
}
}
Output:
i is 20
Outside if-else-if ladder
Loops in Java
Looping is an essential feature in programming that allows a set of instructions to be executed repeatedly as long as a specified condition evaluates to true. In Java, loops are implemented in three different ways, each with a unique syntax and method of checking conditions.
while Loop
Looping is an essential feature in programming that allows a set of instructions to be executed repeatedly as long as a specified condition evaluates to true. In Java, loops are implemented in three different ways, each with a unique syntax and method of checking conditions.
while (boolean condition) {
// Loop body
}
Example:
public class WhileLoopExample {
public static void main(String[] args) {
int i = 0;
while (i <= 10) {
System.out.println(i);
i++;
}
}
}
Output:
0
1
2
3
4
5
6
7
8
9
10
Working of while loop:
The loop starts by checking the boolean condition.
If the condition is true, the loop body is executed.
After each execution, the condition is rechecked before the next iteration.
The loop terminates when the condition evaluates to false.
This is an entry control loop, meaning the condition is checked before the loop body is executed.
Java do-while loop with Examples
Loops are a fundamental concept in programming, used when we need to execute a block of code repeatedly. The do-while loop is an example of an Exit Control Loop in Java, meaning the loop body will always execute at least once, as the condition is checked after the loop body has been executed, unlike in for and while loops where the condition is checked beforehand.
Syntax of do-while Loop:
do {
// Loop body
update_expression;
} while (test_expression);
Output:
Print statement
For-each loop in Java
The for-each loop in Java, introduced in Java 5, is a simplified way to traverse arrays and collections. It provides a cleaner and more readable syntax when you need to access each element of an array or a collection like ArrayList.
Key Features of the For-Each Loop:
It begins with the keyword for, similar to a regular for-loop.
Instead of initializing and maintaining a loop counter, you declare a variable (of the same type as the array elements) that iterates through each element.
The loop body uses this variable directly, without needing to reference an array index.
The for-each loop is particularly useful for iterating through arrays or classes from the Java Collection Framework, such as ArrayList.
Syntax:
for (type var : array) {
// Statements using var
}
Example: Simple Array Traversal using For-Each Loop
public class Easy {
public static void main(String[] args) {
// Array declaration
int[] ar = {10, 50, 60, 80, 90};
// For-each loop to iterate through array
for (int element : ar) {
System.out.print(element + " ");
}
}
}
Output:
10 50 60 80 90
Equivalent Syntax with Regular For Loop:
for (int i = 0; i < ar.length; i++) {
int element = ar[i];
// Statements using element
}
Example: Finding the Highest Score using For-Each Loop
// Java program to illustrate for-each loop
public class ForEachExample {
public static void main(String[] args) {
int[] marks = {125, 132, 95, 116, 110};
int highestMarks = maximum(marks);
System.out.println("The highest score is " + highestMarks);
}
public static int maximum(int[] numbers) {
int maxSoFar = numbers[0];
// For-each loop to find the maximum value
for (int num : numbers) {
if (num > maxSoFar) {
maxSoFar = num;
}
}
return maxSoFar;
}
}
Output:
The highest score is 132
Limitations of the For-Each Loop
1. Modifying Array Elements: For-each loops don’t allow modification of array elements. Changing the loop variable does not affect the array:
for (int num : marks) {
num = num * 2; // Only changes num, not the actual array element
}
2. No Access to Index: You can’t get the index of the current element using a for-each loop:
for (int num : numbers) {
if (num == target) {
return ???; // No index available
}
}
3. Only Forward Iteration: For-each loops can only iterate forward, making it impossible to iterate in reverse order:
for (int i = numbers.length - 1; i >= 0; i--) {
System.out.println(numbers[i]); // Cannot be done using for-each
}
4. Handling Multiple Decision Statements: For-each loops struggle to process multiple decision-making conditions:
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == arr[i]) {
// Hard to convert this to a for-each loop
}
}
Break Statement in Java
The break statement in Java is a control statement used to terminate the loop prematurely. Once the break statement is encountered, the loop terminates immediately, and the control moves to the next statement following the loop.
Syntax:
break;
When to Use the Break Statement:
1. When the exact number of iterations is not known in advance. 2. When you want to exit the loop based on some condition during iteration.
Use Cases for Break:
1. Terminating a sequence in a switch statement. 2. Exiting a loop. 3. Serving as a structured alternative to goto.
Example: Break in a Switch Statement
// Example of using break statement in switch
public class SwitchBreakExample {
public static void main(String[] args) {
// Assigning n an integer value
int n = 1;
// Passing n to switch
// The case matching n will execute and terminate due to break
switch (n) {
case 1:
System.out.println("Hello World");
break;
case 2:
System.out.println("Second Case");
break;
default:
System.out.println("Default Case");
}
}
}
Output:
Hello World
Using Break to Exit a Loop
With the break statement, you can force the loop to terminate immediately, skipping the remaining iterations. It’s commonly used when you want to stop the loop based on a specific condition.
Example: Breaking out of a Loop
// Java program to illustrate using break to exit a loop
public class BreakLoopDemo {
public static void main(String[] args) {
// The loop runs from 0 to 9
for (int i = 0; i < 10; i++) {
// Terminate loop when i equals 5
if (i == 5)
break;
System.out.println("i: " + i);
}
System.out.println("Loop complete.");
}
}
Output:
i: 0
i: 1
i: 2
i: 3
i: 4
Loop complete.
Time Complexity: O(1)
Auxiliary Space: O(1)
Using Break as a Form of Goto
Java doesn’t support the goto statement because it allows jumping in an unstructured manner, leading to complex and unreadable code. Instead, Java uses labels to identify a block of code. You can use the break statement to jump out of a labeled block.
Syntax:
label:
{
// Code block
statement1;
statement2;
// Break can be used to exit the block
break label;
}
Example: Break with a Label
// Java program to illustrate using break with label
public class BreakLabelDemo {
public static void main(String[] args) {
boolean condition = true;
// Label first
first: {
second: {
third: {
// Before break
System.out.println("Before the break statement");
// If condition is true, break out of the second block
if (condition)
break second;
System.out.println("This won't execute.");
}
System.out.println("This won't execute.");
}
// After exiting the second block
System.out.println("This is after second block.");
}
}
}
Output:
Before the break statement
This is after second block
return keyword in Java
In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.
1. Member Variables (Class-Level Scope) 2. Local Variables (Method-Level Scope) 3. Block Variables (Loop or Block-Level Scope)
1. Member Variables (Class-Level Scope)
Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., public, private, protected, or default). Access to member variables outside the class depends on the access modifier used.
Example:
public class Test {
// Member variables
int a; // Default access modifier
private String b; // Private member variable
char c; // Default access modifier
void method1() {
// Member variables can be accessed here
System.out.println(a);
System.out.println(b);
}
int method2() {
return a;
}
}
Public: Accessible within the class, in subclasses, and outside the class.
Protected: Accessible within the class and in subclasses but not outside the package.
Default (no modifier): Accessible within the same package but not outside it.
Private: Only accessible within the class.
2. Local Variables (Method-Level Scope)
Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.
Example:
public class Test {
void method1() {
// Local variable
int x = 10;
System.out.println(x); // Accessible inside the method
}
public static void main(String[] args) {
Test t = new Test();
t.method1();
}
}
Local variables do not retain their values once the method completes, and they are recreated each time the method is invoked.
3. Block Variables (Loop or Block-Level Scope)
Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.
Example of Block-Level Scope:
public class Test {
public static void main(String[] args) {
{
int x = 10; // x is only accessible inside this block
System.out.println(x);
}
// Uncommenting the following line will cause an error
// System.out.println(x); // x is out of scope here
}
}
Loop Variables (Block Scope)
Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.
Example:
class Test {
public static void main(String[] args) {
for (int x = 0; x < 4; x++) {
System.out.println(x); // x is accessible inside the loop
}
// Uncommenting the following line will result in an error
// System.out.println(x); // x is out of scope here
}
}
If you need to access a loop variable outside the loop, declare it before the loop:
class Test {
public static void main(String[] args) {
int x;
for (x = 0; x < 4; x++) {
System.out.println(x);
}
System.out.println(x); // x is accessible outside the loop
}
}
Output:
0
1
2
3
4
Loop Variable Scope with Overlapping Names
In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.
Incorrect Example in Java (compilation error):
class Test {
public static void main(String[] args) {
int a = 5;
for (int a = 0; a < 5; a++) { // Error: Variable 'a' is already defined
System.out.println(a);
}
}
}
Output:
Error: variable 'a' is already defined
Valid Example with Loop Variable Declaration After Loop
To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.
Example:
class Test {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i); // Loop variable i
}
int i = 20; // Declare i after the loop
System.out.println(i); // Access new i outside the loop
}
}
Java provides multiple ways to take input from users through its I/O (Input/Output) package. These streams facilitate the reading of characters, data types, and objects from input devices such as keyboards or files. The most common ways to capture user input in Java are through the BufferedReader class and the Scanner class.
Methods to Take Input in Java
There are two primary ways to get input from the user or a file in Java:
1. Using BufferedReader Class 2. Using Scanner Class
1. Using BufferedReader Class to Take Input in Java
The BufferedReader class is part of Java’s I/O package and is used for reading streams of characters. The readLine() method of this class reads input as a string. InputStreamReader is often used in conjunction with BufferedReader to convert byte streams into character streams, enabling character-based input reading.
Note: BufferedReader can throw checked exceptions, which need to be handled using try-catch blocks or by declaring them with throws.
Example of Taking Input Using BufferedReader:
import java.io.*;
public class InputExample {
public static void main(String[] args) throws IOException {
// Creating a BufferedReader object
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// Reading string input
System.out.println("Enter a string:");
String str = reader.readLine();
// Reading integer input
System.out.println("Enter an integer:");
int num = Integer.parseInt(reader.readLine());
// Output the values
System.out.println("Entered String: " + str);
System.out.println("Entered Integer: " + num);
}
}
Output:
Enter a string:
John Doe
Enter an integer:
123
Entered String: John Doe
Entered Integer: 123
Alternative Example of BufferedReader Input:
import java.io.*;
public class Example {
public static void main(String[] args) {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("Enter your name:");
String name = reader.readLine(); // Reading string input
System.out.println("Name: " + name);
} catch (IOException e) {
System.out.println("An error occurred: " + e.getMessage());
}
}
}
Sample Output:
Enter your name:
John
Name: John
2. Using Scanner Class for Taking Input in Java
The Scanner class is an advanced and user-friendly input class that is part of Java’s util package. It simplifies input handling by providing various methods like nextInt(), nextFloat(), next(), and nextLine(). These methods allow you to directly capture input without explicit parsing.
Advantages of Scanner:
Easier to use than BufferedReader.
Supports multiple data types (integers, floats, strings, etc.) directly.
No need for throws declarations as no checked exceptions are thrown.
Provides methods to read formatted input easily.
Example of Taking Input Using Scanner:
import java.util.Scanner;
class Main {
public static void main(String[] args) {
// Create Scanner object
Scanner sc = new Scanner(System.in);
// Input a String (single word)
String word = sc.next();
System.out.println("Entered word: " + word);
// Input a String (full sentence)
sc.nextLine(); // Clear the buffer
String sentence = sc.nextLine();
System.out.println("Entered sentence: " + sentence);
// Input an Integer
int num = sc.nextInt();
System.out.println("Entered Integer: " + num);
// Input a floating-point number
float f = sc.nextFloat();
System.out.println("Entered Float: " + f);
}
}
Output:
John
Hello World
123
45.67
Entered word: John
Entered sentence: Hello World
Entered Integer: 123
Entered Float: 45.67
Another Example:
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter your name:");
String name = sc.nextLine();
System.out.println("Enter your roll number:");
int rollNo = sc.nextInt();
System.out.println("Enter your marks:");
float marks = sc.nextFloat();
// Output the entered data
System.out.println("Name: " + name);
System.out.println("Roll Number: " + rollNo);
System.out.println("Marks: " + marks);
}
}
Output:
Enter your name:
Alice
Enter your roll number:
10
Enter your marks:
89.5
Name: Alice
Roll Number: 10
Marks: 89.5
Differences Between BufferedReader and Scanner
1. BufferedReader is a basic way to read input, typically used for reading streams of characters. It is faster than Scanner as it doesn’t perform any post-processing or parsing. 2. Scanner is more user-friendly for simple input, especially when you need to read different data types. However, Scanner is slower because it performs input parsing internally (like nextInt(), nextFloat()). 3. BufferedReader allows you to specify the size of the input stream to be read, making it more flexible when handling large input. 4. BufferedReader is synchronized, making it suitable for multi-threaded applications, while Scanner is not. 5. Scanner is typically preferred for smaller inputs due to its simplicity, while BufferedReader is favored for larger inputs due to better performance.
Scanner Class in Java
The Scanner class in Java is part of the java.util package and is used to obtain input from the user, including primitive data types like int, double, and boolean, as well as strings.
While the Scanner class is the simplest way to read input, it’s not the most efficient when performance is critical, such as in competitive programming, due to additional overhead.
Input Types in Java Scanner
The Scanner class can take various types of input from the user. Some of the commonly used methods for extracting data from an input stream are listed below:
Method
Description
nextBoolean()
Reads a Boolean value
nextByte()
Reads a Byte value
nextDouble()
Reads a Double value
nextFloat()
Reads a Float value
nextInt()
Reads an Integer value
nextLine()
Reads an entire line as a String
nextLong()
Reads a Long value
nextShort()
Reads a Short value
Example 1: Reading Data of Various Types
Below is a sample code that demonstrates how to read different types of data using the Scanner class.
// Java program to read data of various types using Scanner class.
import java.util.Scanner;
public class ScannerDemo1 {
public static void main(String[] args) {
// Creating a Scanner object for input
Scanner sc = new Scanner(System.in);
// Reading a String input
String name = sc.nextLine();
// Reading a Character input
char gender = sc.next().charAt(0);
// Reading numerical data
int age = sc.nextInt();
long mobileNo = sc.nextLong();
double cgpa = sc.nextDouble();
// Outputting the values to check input
System.out.println("Name: " + name);
System.out.println("Gender: " + gender);
System.out.println("Age: " + age);
System.out.println("Mobile Number: " + mobileNo);
System.out.println("CGPA: " + cgpa);
}
}
Input:
Alice
F
25
9876543210
8.9
Output:
Name: Alice
Gender: F
Age: 25
Mobile Number: 9876543210
CGPA: 8.9
Checking Input Type with hasNextXYZ() Methods
In some cases, we need to verify the type of the next input or whether the input has ended (e.g., when encountering the EOF marker). The hasNextXYZ() methods allow us to check if the next token is of the desired type. Here, XYZ represents the data type of interest.
For instance, we can check for an integer using hasNextInt() or a string using hasNextLine(). Similarly, to check for a single character, we can use hasNext().charAt(0).
Example 2: Calculating the Mean of Numbers
// Java program to read values using Scanner and calculate their mean.
import java.util.Scanner;
public class ScannerDemo2 {
public static void main(String[] args) {
// Initialize Scanner object
Scanner sc = new Scanner(System.in);
// Initialize sum and count variables
int sum = 0, count = 0;
// Read integers until non-integer input is encountered
while (sc.hasNextInt()) {
int num = sc.nextInt();
sum += num;
count++;
}
// Calculate and print the mean
if (count > 0) {
int mean = sum / count;
System.out.println("Mean: " + mean);
} else {
System.out.println("No integers were input. Mean cannot be calculated.");
}
}
}
Input:
1 2 3 4 5
Output:
Mean: 3
Key Points About the Scanner Class
1. Creating a Scanner Object: To create a Scanner object, we usually pass the predefined System.in object, which represents standard input. We can also pass a File object to read input from a file. 2. Reading Numerical Values: For each primitive data type, there is a corresponding nextXYZ() method to read its value. For example, nextShort() reads a short value, and nextInt() reads an int. 3. Reading Strings: To read strings, we use nextLine(). This method reads the entire line until a newline character is encountered. 4. Reading a Single Character: To read a single character, we can use next().charAt(0). The next() method reads the next token (a word or symbol), and charAt(0) returns the first character of that token. 5. How Scanner Reads Input: The Scanner class reads an entire line and divides it into tokens. Each token represents a meaningful piece of the input. For example, if the input string is “Hello world”, the Scanner object will treat “Hello” and “world” as two separate tokens, and we can iterate over these tokens using its various methods.
Ways to read input from console in Java
In Java, there are several ways to read input from the user in the command-line environment. Here are five methods:
1. Using BufferedReader Class
The BufferedReader class is the traditional way to take input, introduced in JDK 1.0. It wraps the standard input stream (System.in) in an InputStreamReader, which is further wrapped in a BufferedReader for efficient reading of input.
Key Points:
Input is buffered for performance.
Syntax can be a bit more complex compared to newer methods.
Example:
// Java program to demonstrate BufferedReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {
public static void main(String[] args) throws IOException {
// Using BufferedReader to get input
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// Reading a string input
String name = reader.readLine();
// Printing the input
System.out.println(name);
}
}
Input:
John
Output:
John
2. Using Scanner Class
The Scanner class, introduced in JDK 1.5, is one of the most commonly used methods to read input. It can parse primitive types and strings using regular expressions.
Advantages:
Simplifies reading primitive types like int, float, and more.
Regular expressions can be used to tokenize input.
Example:
import java.util.Scanner;
public class InputExample {
public static void main(String[] args) {
// Create Scanner object
Scanner scn = new Scanner(System.in);
// Read a single word as a string
System.out.println("Enter a word:");
String word = scn.next();
// Read a full line as a string
System.out.println("Enter a sentence:");
scn.nextLine(); // consume the leftover newline
String sentence = scn.nextLine();
// Read an integer
System.out.println("Enter an integer:");
int number = scn.nextInt();
// Read a float value
System.out.println("Enter a floating point number:");
float decimal = scn.nextFloat();
// Display the inputs
System.out.println("Word: " + word);
System.out.println("Sentence: " + sentence);
System.out.println("Integer: "
Input:
Alice
25
4.5
Output:
You entered string: Alice
You entered integer: 25
You entered float: 4.5
3. Using Console Class
Introduced in JDK 1.6, the Console class is useful for reading input from the command line, especially for secure inputs like passwords (where input isn’t displayed). However, it may not work in non-interactive environments like IDEs.
Advantages:
Can hide input (useful for password entry).
Supports formatted input and output.
Example:
// Java program to demonstrate Console class
public class Sample {
public static void main(String[] args) {
// Using Console to get input
String name = System.console().readLine();
System.out.println("You entered string: " + name);
}
}
Input:
Michael
Output:
You entered string: Michael
4. Using Command-Line Arguments
This method uses the command-line arguments passed to the program at runtime. The arguments are stored as strings in the args[] array, and can be converted to other data types using methods like Integer.parseInt().
Example:
// Program to demonstrate command-line arguments
class Hello {
public static void main(String[] args) {
// Check if arguments were passed
if (args.length > 0) {
System.out.println("The command line arguments are:");
// Loop through the args array
for (String val : args)
System.out.println(val);
} else {
System.out.println("No command line arguments found.");
}
}
}
Command Line Arguments:
java Hello John Doe
Output:
The command line arguments are:
John
Doe
5. Using DataInputStream Class
The DataInputStream class allows reading primitive data types and strings from an input stream in a machine-independent way. This class is useful when working with binary input/output, and it was introduced in JDK 1.0.
Key Points:
Reads binary data in a machine-independent format.
Often used with DataOutputStream for consistent data handling.
Example:
// Java program to demonstrate DataInputStream
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
DataInputStream reader = new DataInputStream(System.in);
// Reading an integer input
System.out.print("Enter an integer: ");
int inputInt = Integer.parseInt(reader.readLine());
// Reading a string input
System.out.print("Enter a string: ");
String inputString = reader.readLine();
// Output the input values
System.out.println("You entered integer: " + inputInt);
System.out.println("You entered string: " + inputString);
}
}
Input:
Enter an integer: 30
Enter a string: Java Programming
Output:
You entered integer: 30
You entered string: Java Programming
Java System.out.println()
The System.out.println() method is used in Java to print a message or value to the console. It is a commonly used function that prints any argument passed to it, followed by a new line.
Breakdown of System.out.println()
The statement can be split into three parts for better understanding:
1. System: This is a final class from the java.lang package. 2. out: A static member of the System class, which is an instance of the PrintStream class. 3. println(): A method of the PrintStream class that prints the passed argument and adds a newline character at the end. It’s an enhanced version of print() that automatically moves the cursor to the next line.
Syntax:
System.out.println(parameter);
Example of System.out.println()
Example : Basic Output
public class Example {
public static void main(String[] args) {
System.out.println("Hello");
System.out.println("World");
System.out.println("Java Programming");
}
}
Output:
Hello
World
Java Programming
Java’s Other Standard Streams
System.in: The standard input stream used for reading input from the keyboard.
System.err: The standard error stream used to display error messages.
Example:
System.err.print("This is an error message");
Overloads of println() Method
Java supports method overloading, allowing multiple methods with the same name but different parameter types. PrintStream provides various overloads of the println() method for different data types.
Example of Overloaded println() Methods
public class Example {
public static void main(String[] args) {
int num = 15;
char letter = 'A';
String text = "Java";
double decimal = 25.78;
float floatNum = 10.5f;
boolean flag = true;
// Various overloaded versions of println()
System.out.println(); // Prints an empty line
System.out.println(num);
System.out.println(letter);
System.out.println(text);
System.out.println(decimal);
System.out.println(floatNum);
System.out.println(flag);
}
}
Output:
15
A
Java
25.78
10.5
true
Difference Between System.out.print() and System.out.println()
System.out.print(): Prints the provided text or value on the console and keeps the cursor on the same line.
System.out.println(): Prints the provided text or value, and moves the cursor to the next line.
Example:
public class Example {
public static void main(String[] args) {
System.out.println("Using print():");
// Using print()
System.out.print("Hello ");
System.out.print("World ");
System.out.print("Java");
System.out.println(); // Moving to the next line
System.out.println("Using println():");
// Using println()
System.out.println("Hello");
System.out.println("World");
System.out.println("Java");
}
}
Output:
Using print():
Hello World Java
Using println():
Hello
World
Java
Formatted Output in Java using printf()
In programming, it is often necessary to display output in a specific format. Java’s printf() method, similar to the C language’s printf, allows formatting of output using format specifiers. In this article, we’ll cover different ways to format output in Java using printf().
Formatting Using printf()
printf() uses format specifiers to format different data types. The commonly used data types for formatting are:
1. Number Formatting 2. Decimal Number Formatting 3. Boolean Formatting 4. Character Formatting 5. String Formatting 6. Date and Time Formatting
1. Number Formatting
For formatting integers (like int, long), the format specifier used is %d.
Example:
public class Example {
public static void main(String[] args) {
int number = 10000;
// Format with commas separating thousands
System.out.printf("%,d%n", number);
}
}
Output:
10,000
2. Decimal Number Formatting
To format decimal numbers, we use the %f specifier.
Example:
public class Example {
public static void main(String[] args) {
double pi = 3.14159265359;
// Formatting decimal numbers
System.out.printf("%f\n", pi);
System.out.printf("%5.3f\n", pi);
System.out.printf("%5.2f\n", pi);
}
}
Output:
3.141593
3.142
3.14
3. Boolean Formatting
Boolean values can be formatted using %b or %B.
Example:
public class Example {
public static void main(String[] args) {
boolean boolTrue = true;
boolean boolFalse = false;
Integer nullValue = null;
System.out.printf("%b\n", boolTrue); // true
System.out.printf("%B\n", boolTrue); // TRUE
System.out.printf("%b\n", boolFalse); // false
System.out.printf("%B\n", nullValue); // FALSE
}
}
Output:
true
TRUE
false
FALSE
4. Character Formatting
Character formatting is done using the %c or %C specifiers.
Example:
public class Example {
public static void main(String[] args) {
char character = 'a';
System.out.printf("%c\n", character); // a
System.out.printf("%C\n", character); // A (uppercase)
}
}
Output:
a
A
5. String Formatting
Strings are formatted using %s or %S.
Example:
public class Example {
public static void main(String[] args) {
String text = "java programming";
System.out.printf("%s\n", text); // java programming
System.out.printf("%S\n", text); // JAVA PROGRAMMING
}
}
Output:
java programming
JAVA PROGRAMMING
6. Date and Time Formatting
Formatting date and time is more complex and requires specific knowledge of format specifiers such as %tT, %tH, %tM, etc.
Example:
import java.util.Date;
public class Example {
public static void main(String[] args) {
Date currentTime = new Date();
System.out.printf("Current Time: %tT\n", currentTime); // Full time format
System.out.printf("Hours: %tH Minutes: %tM Seconds: %tS\n",
currentTime, currentTime, currentTime); // Individual components
// Time with AM/PM, milliseconds, nanoseconds, and time zone
System.out.printf("%1$tH:%1$tM:%1$tS %1$tp %1$tL %1$tN %1$tz%n", currentTime);
}
}
Output:
Current Time: 11:32:36
Hours: 11 Minutes: 32 Seconds: 36
11:32:36 am 198 198000000 +0000
Other Methods for Formatting
1. Decimal Formatting using DecimalFormat
DecimalFormat can be used to format numbers with various patterns.
Example:
import java.text.DecimalFormat;
public class DecimalFormatting {
public static void main(String[] args) {
double num = 123.4567;
// Formatting without fraction part
DecimalFormat df = new DecimalFormat("####");
System.out.println("Without fraction part: " + df.format(num));
// Formatting to 2 decimal places
df = new DecimalFormat("#.##");
System.out.println("Formatted to 2 decimal places: " + df.format(num));
// Formatting with appended zeroes
df = new DecimalFormat("#.000000");
System.out.println("With appended zeroes: " + df.format(num));
// Formatting with leading zeroes
df = new DecimalFormat("00000.00");
System.out.println("With leading zeroes: " + df.format(num));
// Formatting currency
double income = 23456.789;
df = new DecimalFormat("$###,###.##");
System.out.println("Formatted income: " + df.format(income));
}
}
Output:
Without fraction part: 123
Formatted to 2 decimal places: 123.46
With appended zeroes: 123.456700
With leading zeroes: 00123.46
Formatted income: $23,456.79
2. Formatting Dates using SimpleDateFormat
SimpleDateFormat allows date formatting based on custom patterns.
Example:
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateFormatting {
public static void main(String[] args) {
// Formatting date to 'dd-MM-yyyy'
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
String formattedDate = sdf.format(new Date());
System.out.println("Formatted Date: " + formattedDate);
// Parsing a string date
String dateStr = "02/18/1995";
sdf = new SimpleDateFormat("MM/dd/yyyy");
try {
Date date = sdf.parse(dateStr);
System.out.println("Parsed Date: " + date);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
Formatted Date: 03-10-2024
Parsed Date: Sat Feb 18 00:00:00 UTC 1995
3. Static Variables
Static variables are shared across all instances of a class and are declared with the static keyword. Only one copy of a static variable exists, regardless of how many objects are created.
// Example of static variables
public class StaticVariableExample {
public static String company = "TechCorp"; // Static variable
public static void main(String[] args) {
System.out.println("Company: " + StaticVariableExample.company); // Accessing without object
}
}
Output:
Company: TechCorp
Java Variables
In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.
1. Member Variables (Class-Level Scope) 2. Local Variables (Method-Level Scope) 3. Block Variables (Loop or Block-Level Scope)
1. Member Variables (Class-Level Scope)
Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., public, private, protected, or default). Access to member variables outside the class depends on the access modifier used.
Example:
public class Test {
// Member variables
int a; // Default access modifier
private String b; // Private member variable
char c; // Default access modifier
void method1() {
// Member variables can be accessed here
System.out.println(a);
System.out.println(b);
}
int method2() {
return a;
}
}
Public: Accessible within the class, in subclasses, and outside the class.
Protected: Accessible within the class and in subclasses but not outside the package.
Default (no modifier): Accessible within the same package but not outside it.
Private: Only accessible within the class.
2. Local Variables (Method-Level Scope)
Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.
Example:
public class Test {
void method1() {
// Local variable
int x = 10;
System.out.println(x); // Accessible inside the method
}
public static void main(String[] args) {
Test t = new Test();
t.method1();
}
}
Local variables do not retain their values once the method completes, and they are recreated each time the method is invoked.
3. Block Variables (Loop or Block-Level Scope)
Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.
Example of Block-Level Scope:
public class Test {
public static void main(String[] args) {
{
int x = 10; // x is only accessible inside this block
System.out.println(x);
}
// Uncommenting the following line will cause an error
// System.out.println(x); // x is out of scope here
}
}
Loop Variables (Block Scope)
Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.
Example:
class Test {
public static void main(String[] args) {
for (int x = 0; x < 4; x++) {
System.out.println(x); // x is accessible inside the loop
}
// Uncommenting the following line will result in an error
// System.out.println(x); // x is out of scope here
}
}
If you need to access a loop variable outside the loop, declare it before the loop:
class Test {
public static void main(String[] args) {
int x;
for (x = 0; x < 4; x++) {
System.out.println(x);
}
System.out.println(x); // x is accessible outside the loop
}
}
Output:
0
1
2
3
4
Loop Variable Scope with Overlapping Names
In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.
Incorrect Example in Java (compilation error):
class Test {
public static void main(String[] args) {
int a = 5;
for (int a = 0; a < 5; a++) { // Error: Variable 'a' is already defined
System.out.println(a);
}
}
}
Output:
Error: variable 'a' is already defined
Valid Example with Loop Variable Declaration After Loop
To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.
Example:
class Test {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i); // Loop variable i
}
int i = 20; // Declare i after the loop
System.out.println(i); // Access new i outside the loop
}
}
Java is an object-oriented programming language, which means that it consists of objects that interact with each other through method calls to perform various tasks. Here’s an overview of some essential concepts in Java:
Basic Terminologies in Java:
1. Class:A class is a blueprint for objects. It defines a logical template that shares common properties and methods.
2. Object: An object is an instance of a class. It represents an entity with a behavior and state.
3. Method: A method defines the behavior of an object.
4. Instance Variables: Each object has its own unique set of instance variables. These variables represent the state of an object, defined by the values assigned to them.
Example: Compiling and Running a Java Program in a Console
import java.util.*;
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Output:
Hello, World!
5. Comments in Java: There are three types of comments in Java:
Single-line Comment:
// This is a single-line comment
Multi-line Comment:
/*
This is a multi-line comment
*/
Documentation Comment:
/** This is a documentation comment */
6. Source File Name: The source file name should exactly match the public class name with the extension .java. If there is no public class, the file name can differ.
Example:
GFG.java // valid
gfg.java // invalid if public class is GFG
7. Case Sensitivity: Java is case-sensitive, meaning identifiers like AB, Ab, aB, and ab are considered different.
8. Class Names: The first letter of a class name should be uppercase.If multiple words are used, each word should start with an uppercase letter.
Example:
class MyClass // valid
class 1Program // invalid
class My1Program // valid
class $Program // valid but discouraged
9. Main Method: The main() method is the entry point of every Java program:
public static void main(String[] args) {
// program logic
}
10. Method Names: Method names should start with a lowercase letter.If multiple words are used, the first letter of each word (after the first one) should be uppercase. Example:
public void calculateSum() // valid
11. Identifiers in Java: Identifiers are names given to classes, methods, variables, etc. They must follow certain rules:Can begin with a letter, underscore (_), or currency symbol. Subsequent characters can be letters, digits, or underscores. Java keywords cannot be used as identifiers. Legal identifiers: myVar, hello_world, $amount. Illegal identifiers: 1Var, -amount.
12. White Spaces in Java: Blank lines, spaces, and comments are ignored by the Java compiler.
13. Access Modifiers: Java provides access control to classes and methods through access modifiers:
Access Modifier
Within Class
Within Package
Outside Package by Subclass
Outside Package
Private
Yes
No
No
No
Default
Yes
Yes
No
No
Protected
Yes
Yes
Yes
No
Public
Yes
Yes
Yes
Yes
14. Java Keywords: Keywords in Java have predefined meanings and cannot be used as identifiers. Examples include class, interface, void, int, public, static, etc.
Java Hello World Program
Java is one of the most popular and widely-used programming languages, known for its speed, reliability, and security. Java applications can be found everywhere—from desktop software to web applications, scientific supercomputers to gaming consoles, and mobile phones to the Internet. In this guide, we’ll explore how to write a simple Java program.
Steps to Implement a Java Program
To implement a Java application, follow these key steps:
Creating the Program
Compiling the Program
Running the Program
If you’re looking to dive deeper into Java and gain a strong understanding of the entire development process, consider enrolling in a structured Java programming course. These courses provide hands-on experience and cover everything from basic to advanced topics, allowing you to develop efficient and scalable applications.
Example of a Simple Java Program
public class Main {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Output:
Hello, World!
Primitive data type vs. Object data type in Java with Examples
Java is known as a statically and strongly typed language because all data types (such as integers, characters, etc.) are predefined. Additionally, every constant or variable must be explicitly declared with a data type.
Data Types in Java
Java’s data types vary in size and in the values they can store. These types are categorized into two main groups:
Primitive Data Types: Includes boolean, char, int, short, byte, long, float, and double. For example, Boolean is a wrapper class for the primitive boolean type.
Non-Primitive Data Types (Reference types): Examples include String, Array, and more.
Effectively understanding and using these data types is crucial for writing efficient and error-free Java code. If you’re aiming to become proficient in Java, it’s worth exploring detailed learning materials or taking courses to deepen your knowledge of data types and other core Java concepts.
Primitive Data Types
Primitive data types represent basic values and lack any special properties. Java supports eight primitive data types, as shown in the table below:
Type
Description
Default
Size
Example Literals
Range
1. boolean
Represents true or false
false
8 bits
true, false
N/A
byte
8-bit signed integer
0
8 bits
(none)
-128 to 127
char
16-bit Unicode character
\u0000
16 bits
'a', '\u0041', 'β'
0 to 65,535
short
16-bit signed integer
0
16 bits
(none)
-32,768 to 32,767
int
32-bit signed integer
0
32 bits
-2, 1, 2
-2,147,483,648 to 2,147,483,647
long
64-bit signed integer
0
64 bits
-2L, 0L, 1L
-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
float
32-bit floating-point
0.0
32 bits
1.23e10f, -1.23e-100f
Up to 7 decimal digits
double
64-bit floating-point
0.0
64 bits
1.2345e300d, 1e1d
Up to 16 decimal digits
Below is a detailed breakdown of each data type:
1. boolean Data Type: Represents logical values (true or false). Actual size depends on the virtual machine implementation.
Syntax:
boolean isAvailable;
2. byte Data Type: An 8-bit signed integer, often used to save memory when working with large arrays.
Syntax:
byte age;
3. short Data Type: A 16-bit signed integer. This is similar to byte, but used when larger ranges are required.
Syntax:
short population;
4. int Data Type: A 32-bit signed integer and one of the most commonly used data types for numerical values.
Syntax:
int salary;
5. long Data Type: A 64-bit signed integer, suitable for larger numerical values.
Syntax:
long distance;
6. float Data Type: A 32-bit single-precision floating-point, typically used when saving memory is a priority for large floating-point arrays.
Syntax:
long distance;
7. double Data Type: A 64-bit double-precision floating-point, typically the default choice for decimal values.
Syntax
double price;
8. char Data Type: A 16-bit Unicode character. Java uses the Unicode system rather than ASCII, which allows it to represent a wide range of characters.
Syntax:
char initial;
Non-Primitive (Reference) Data Types
Non-Primitive data types store references to memory locations where data is stored. These include strings, arrays, and objects.
1. String: A string is a sequence of characters. In Java, strings are objects, not primitive data types. They can be declared either with or without the new keyword.
Example:
String message = "Hello, World!";
2. Class: A class in Java is a blueprint used to create objects. A class can contain fields (attributes) and methods to describe the behavior of the objects it represents.
3. Object: An object is an instance of a class, representing real-world entities with states (fields) and behaviors (methods).
4. Interface: An interface defines a set of methods that a class must implement. Interfaces provide a way to achieve abstraction in Java.
5. Array: Arrays are used to store multiple values of the same type in a single variable. Java arrays are objects, and their size is fixed upon creation.
Example:
int[] numbers = {1, 2, 3, 4, 5};
Java Identifiers
In Java, identifiers are used to name various entities like classes, methods, variables, or labels. These names help in uniquely identifying different elements within a Java program.
Example of Java Identifiers
public class Test {
public static void main(String[] args) {
int a = 20;
}
}
In the above code, we have 5 identifiers:
Test: This is the class name.
main: This is the method name.
String: This is a predefined class name.
args: This is a variable name.
a: This is also a variable name.
Rules for Defining Java Identifiers
There are specific rules for defining valid Java identifiers. Violating these rules will lead to a compile-time error. These rules are also similar in other programming languages like C and C++.
1. Allowed Characters: Identifiers can contain letters (both uppercase and lowercase), digits ([0-9]), the dollar sign ($), and the underscore (_). Special characters such as @, %, or & are not allowed. Example: “my@name” is not a valid identifier because @ is not allowed. 2. Starting Character: Identifiers cannot begin with a digit. Example: “123variable” is invalid. Case Sensitivity: Java is case-sensitive, so identifiers like MyVariable and myvariable are treated as distinct. 3. Length: There is no restriction on the length of an identifier, but it’s recommended to keep it between 4 and 15 characters for readability. Reserved Words: Keywords or reserved words in Java cannot be used as identifiers. Example: int while = 20; is invalid because while is a reserved keyword in Java.
Examples of Valid Identifiers:
MyVariable
MYVARIABLE
myvariable
x
i
x1
i1
_myvariable
$myvariable
sum_of_array
name123
Examples of Invalid Identifiers:
My Variable // Contains a space.
123name // Begins with a digit.
a+c // Contains a special character (+).
variable-2 // Contains a hyphen (-).
sum_&_difference // Contains an ampersand (&).
Reserved Words in Java
Programming languages reserve certain words to represent built-in functionalities. These are known as reserved words, and in Java, they fall into two categories: keywords (50) and literals (3). Keywords represent functions, while literals represent values. Identifiers are utilized by compilers during various phases of program analysis like lexical, syntax, and semantic analysis.
Here are some reserved words in Java:
Keyword
Keyword
Keyword
Keyword
abstract
default
package
super
continue
goto
private
case
for
public
class
enum
protected
try
byte
extends
transient
boolean
double
interface
assert
do
implements
short
static
if
strictfp
switch
throws
break
else
catch
return
void
long
finally
char
final
int
synchronized
volatile
float
native
this
const
throw
instanceOf
while
These reserved words cannot be used as identifiers.
Java provides various operators that are categorized based on their functionality, making it easier to perform tasks like arithmetic operations, logical comparisons, and bitwise manipulations. In this guide, we will explore the different types of Java operators and their uses.
What are Java Operators?
Operators in Java are symbols that trigger specific operations on operands. They simplify complex tasks such as arithmetic operations, logical evaluations, and bitwise manipulations, enhancing the efficiency of the code.
Types of Java Operators
There are several types of operators in Java, each serving a unique purpose:
3. Assignment Operators: Assignment operators assign values to variables. You can combine them with other operations to simplify code, such as += or -=.
public class AssignmentOperators {
public static void main(String[] args) {
int a = 10;
a += 5;
System.out.println("a after += 5: " + a);
a *= 2;
System.out.println("a after *= 2: " + a);
}
}
Output:
a after += 5: 15
a after *= 2: 30
4. Relational Operators: Relational operators compare two values and return a boolean result (true or false).
== : Equal to
!= : Not equal to
< : Less than
> : Greater than
<= : Less than or equal to
>= : Greater than or equal to
Example:
public class RelationalOperators {
public static void main(String[] args) {
int a = 10, b = 5;
System.out.println("a > b: " + (a > b));
System.out.println("a == b: " + (a == b));
}
}
5. Logical Operators: Logical operators are used to combine multiple boolean expressions.
&& : Logical AND
|| : Logical OR
! : Logical NOT
Example:
public class LogicalOperators {
public static void main(String[] args) {
boolean x = true, y = false;
System.out.println("x && y: " + (x && y));
System.out.println("x || y: " + (x || y));
}
}
Output:
x && y: false
x || y: true
6. Ternary Operator: The ternary operator is a shorthand for an if-else statement.
public class TernaryOperator {
public static void main(String[] args) {
int a = 10, b = 20;
int max = (a > b) ? a : b;
System.out.println("Max value: " + max);
}
}
Output:
Max value: 20
7. Bitwise Operators: Bitwise operators operate on binary representations of integers.
& : Bitwise AND
| : Bitwise OR
^ : Bitwise XOR
~ : Bitwise NOT
Example:
public class BitwiseOperators {
public static void main(String[] args) {
int a = 5; // 0101 in binary
int b = 3; // 0011 in binary
System.out.println("a & b: " + (a & b)); // AND operation
System.out.println("a | b: " + (a | b)); // OR operation
}
}
Output:
a & b: 1
a | b: 7
8. Shift Operators: Shift operators shift bits left or right.
<< : Left shift
>> : Right shift
>>> : Unsigned right shift
Example:
public class ShiftOperators {
public static void main(String[] args) {
int a = 8;
System.out.println("Left Shift: " + (a << 1));
System.out.println("Right Shift: " + (a >> 1));
}
}
Output:
Left Shift: 16
Right Shift: 4
9. instanceof Operator:The instanceof operator checks whether an object is an instance of a class or an interface.
Example:
class Animal {}
class Dog extends Animal {}
public class InstanceOfExample {
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(a instanceof Dog); // true
System.out.println(a instanceof Animal); // true
}
}
Output:
true
true
Java Variables
In Java, variables serve as containers to hold data values during the execution of a program. Each variable is assigned a specific data type that determines the kind and amount of data it can store. Essentially, a variable is a reference to a memory location that stores the data.
Variables are crucial for storing and manipulating data in a program, and their values can be altered during program execution. Operations on the variable impact the referenced memory location. It’s important to note that all variables in Java must be declared before use.
Declaring Variables in Java
Variables in Java can be declared by specifying the data type followed by the variable name. The following two key elements must be considered during declaration:
datatype: The type of data that the variable can hold.
variable_name: The name given to the memory location.
Example:
// Example of variable declaration:
float interestRate; // Declaring a float variable
int time = 10, speed = 20; // Declaring and initializing integer variables
char grade = 'A'; // Declaring and initializing a character variable
Types of Variables in Java
1. Local Variables 2. Instance Variables 3. Static Variables
1. Local Variables: A local variable is declared within a method, constructor, or block, and its scope is limited to that block or method. Local variables must be initialized before use.
// Example of local variables
public class LocalVariableExample {
public static void main(String[] args) {
int x = 10; // Local variable
String message = "Hello, world!"; // Another local variable
System.out.println("x = " + x);
System.out.println("Message: " + message);
if (x > 5) {
String result = "x is greater than 5"; // Local variable within 'if' block
System.out.println(result);
}
for (int i = 0; i < 3; i++) {
String loopMessage = "Iteration " + i; // Local variable within 'for' loop
System.out.println(loopMessage);
}
}
}
Output:
x = 10
Message: Hello, world!
x is greater than 5
Iteration 0
Iteration 1
Iteration 2
2. Instance Variables: Instance variables are non-static and are declared outside of any method, constructor, or block. These variables are created when an object is instantiated and are destroyed when the object is destroyed. They can have access specifiers and do not need to be initialized explicitly.
// Example of instance variables
public class InstanceVariableExample {
public String name;
public int age;
public InstanceVariableExample(String name) {
this.name = name; // Initializing instance variable
}
public static void main(String[] args) {
InstanceVariableExample person = new InstanceVariableExample("Alice");
System.out.println("Name: " + person.name);
System.out.println("Age: " + person.age); // Default value for int is 0
}
}
Output:
Name: Alice
Age: 0
3. Static Variables: Static variables are shared across all instances of a class and are declared with the static keyword. Only one copy of a static variable exists, regardless of how many objects are created.
// Example of static variables
public class StaticVariableExample {
public static String company = "TechCorp"; // Static variable
public static void main(String[] args) {
System.out.println("Company: " + StaticVariableExample.company); // Accessing without object
}
}
Output:
Company: TechCorp
Scope of a Variables
In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.
1. Member Variables (Class-Level Scope) 2. Local Variables (Method-Level Scope) 3. Block Variables (Loop or Block-Level Scope)
1. Member Variables (Class-Level Scope)
Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., public, private, protected, or default). Access to member variables outside the class depends on the access modifier used.
Example:
public class Test {
// Member variables
int a; // Default access modifier
private String b; // Private member variable
char c; // Default access modifier
void method1() {
// Member variables can be accessed here
System.out.println(a);
System.out.println(b);
}
int method2() {
return a;
}
}
Public: Accessible within the class, in subclasses, and outside the class.
Protected: Accessible within the class and in subclasses but not outside the package.
Default (no modifier): Accessible within the same package but not outside it.
Private: Only accessible within the class.
2. Local Variables (Method-Level Scope)
Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.
Example:
public class Test {
void method1() {
// Local variable
int x = 10;
System.out.println(x); // Accessible inside the method
}
public static void main(String[] args) {
Test t = new Test();
t.method1();
}
}
3. Block Variables (Loop or Block-Level Scope)
Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.
Example of Block-Level Scope:
public class Test {
public static void main(String[] args) {
{
int x = 10; // x is only accessible inside this block
System.out.println(x);
}
// Uncommenting the following line will cause an error
// System.out.println(x); // x is out of scope here
}
}
Loop Variables (Block Scope)
Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.
Example:
class Test {
public static void main(String[] args) {
for (int x = 0; x < 4; x++) {
System.out.println(x); // x is accessible inside the loop
}
// Uncommenting the following line will result in an error
// System.out.println(x); // x is out of scope here
}
}
If you need to access a loop variable outside the loop, declare it before the loop:
class Test {
public static void main(String[] args) {
int x;
for (x = 0; x < 4; x++) {
System.out.println(x);
}
System.out.println(x); // x is accessible outside the loop
}
}
Output:
0
1
2
3
4
Loop Variable Scope with Overlapping Names
In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.
Incorrect Example in Java (compilation error):
class Test {
public static void main(String[] args) {
int a = 5;
for (int a = 0; a < 5; a++) { // Error: Variable 'a' is already defined
System.out.println(a);
}
}
}
Output:
Error: variable 'a' is already defined
Valid Example with Loop Variable Declaration After Loop
To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.
Example:
class Test {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i); // Loop variable i
}
int i = 20; // Declare i after the loop
System.out.println(i); // Access new i outside the loop
}
}
Java is a high-level, class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible. It is intended to let application developers “write once, run anywhere” (WORA), meaning that compiled Java code can run on all platforms that support Java without the need for recompilation. Java applications are typically compiled to bytecode that can run on any Java Virtual Machine (JVM) regardless of the underlying computer architecture.
Key Features of Java:
Object-Oriented: Encourages the development of modular and reusable code.
Platform-Independent: The compiled bytecode can run on any platform with a JVM.
Simple and Familiar:Easier to learn and use compared to some other languages.
Secure: Provides a secure execution environment and prevents many security threats.
Robust: Strong memory management and exception handling.
Multithreaded:Supports concurrent execution of two or more parts of a program for maximum utilization of CPU.
High Performance:Includes Just-In-Time (JIT) compiler for improved performance.
C++ vs Java vs Python
Feature
C++
Java
Python
Type
Compiled language
Compiled to bytecode, runs on JVM
Interpreted language
Memory
Manual memory management
Automatic garbage collection
Automatic garbage collection
Syntax
Complex, supports multiple paradigms
Cleaner, more consistent than C++
Very clean, highly readable
Performance
High performance, close to hardware
Slower than C++ but highly portable
Slower than C++ and Java
Use Cases
System/embedded programming, game dev
Web applications, enterprise apps
Web development, data science
Libraries
Standard Template Library (STL)
Rich standard library and frameworks
Extensive standard library
Multi-threading
Supported but complex
Built-in support with synchronization
Supported with Global Interpreter Lock (GIL)
Just-In-Time (JIT) Compiler
The Just-In-Time (JIT) compiler is a component of the Java Runtime Environment (JRE) that improves the performance of Java applications by compiling bytecode into native machine code at runtime. This allows Java programs to run faster as they are executed directly by the CPU rather than being interpreted by the JVM.
Advantages:
Improved Performance: Converts frequently executed bytecode to native code.
Optimizations: Applies various optimizations to the native code for better performance.
Adaptive Compilation: Compiles only the code that is executed frequently, reducing the overhead.
Difference between JIT and JVM in Java
JIT (Just-In-Time Compiler):
Part of the JVM.
Converts bytecode into native machine code at runtime.
Improves performance by compiling frequently executed bytecode.
Applies runtime optimizations to the code.
JVM (Java Virtual Machine):
An abstract machine that enables Java bytecode to be executed on any platform.
Responsible for interpreting bytecode, managing memory, and providing runtime environment.
Includes components like the class loader, runtime data areas, and the execution engine (which includes the JIT compiler).
Difference between Bytecode and Machine Code
Bytecode:
Intermediate code generated by the Java compiler.
Platform-independent and can be executed on any system with a JVM.
Needs to be interpreted or compiled (JIT) to machine code for execution
Machine Code:
Low-level code executed directly by the CPU.
Platform-specific and generated from bytecode by the JIT compiler.
Does not require further interpretation and runs directly on the hardware.
How is Java Platform Independent?
Java is platform-independent due to its use of the JVM and bytecode. Here’s how:
1. Source Code Compilation:Java source code (.java files) is compiled by the Java compiler (javac) into bytecode (.class files). Bytecode is an intermediate, platform-independent code. 2. Java Virtual Machine (JVM): The JVM is a platform-specific execution environment that runs Java bytecode. Every platform (Windows, macOS, Linux, etc.) has its own JVM implementation. 3. Write Once, Run Anywhere: Since the bytecode is platform-independent and the JVM is platform-specific, Java applications can run on any device or operating system that has a JVM. This allows developers to write Java programs once and run them anywhere without modification.
Java is a high-level, object-oriented, platform-independent programming language widely used for building enterprise applications, web applications, mobile apps, and backend systems.
Backup and recovery processes are critical for data protection, ensuring that data can be restored after physical or logical failures.
1. Backup Strategies
Definition: Backup strategies involve creating copies of data that can be used to restore the original after a data loss event.
Example:
-- Creating a full database backup
BACKUP DATABASE YourDatabase TO DISK = 'C:\Backups\YourDatabase.bak';
A full database backup creates a complete copy of the database at a point in time.
1.1 Restoring Databases
Definition: Restoring databases involves returning data to a previous state by using data from a backup.
Example:
-- Restoring a database from a backup file
RESTORE DATABASE YourDatabase FROM DISK = 'C:\Backups\YourDatabase.bak';
This command restores the YourDatabase from a backup file, bringing all data back to the state when the backup was taken.
1.2 Point-in-Time Recovery
Definition: Point-in-time recovery allows the database to be restored to a specific point in time, usually before a failure or corruption occurred.
Example:
-- Performing a point-in-time recovery
RESTORE DATABASE YourDatabase FROM DISK = 'C:\Backups\YourDatabase.bak'
WITH STOPAT = '2023-07-01T14:00:00';
This command restores the database to the state it was at a specific time, useful for recovering from errors that occurred after that time.
These optimization and recovery techniques are essential for maintaining efficient, reliable, and secure database systems. By optimizing performance and ensuring robust backup and recovery procedures, you can help safeguard your data and ensure that your database environment supports quick and effective data retrieval and manipulation.