Thursday, March 26, 2026

Java Variable Types With Examples

In this guide, we’ll explore the different types of variables in Java, their scopes, visibility, and practical examples to help you master the concept.

We’ll also see what is meant by declaring a variable and what is meant by initialization of a variable in Java.

Declaring and Initializing a variable in Java

In Java, every variable must be declared before use. Declaration specifies the type of the variable, which can be either a primitive data type (such as int, double, char), or having class or interface as type (reference variable).

Examples of variable declaration

int age, number; // two int variables declared

double amount; // a double variable declared

Person person; // reference type variable declared

As you see here, in the first statement two variables of type int are declared. Note that you can declare two or more variables of same type as a comma separated list.

In the third statement a variable person is declared which is of type Person. Here Person is a class.

Java 10 introduced a new feature called local variable type inference where the type of the variable is inferred from the variable initializer. A new reserved type name “var” is added in Java to define and initialize local variables, read more about var type here- Var type in Java - Local Variable Type Inference

Initialization of a variable in Java

Initialization means providing initial value of the variable. Generally, both declaration and initialization are done in a single statement.

 
int age = 30;

char grade = 'A';

But that is not necessary, you can also declare a variable first and initialize it later.

 
int age;

...... 
......
age = 50;

Variables can also be initialized using expressions:

 
double amount;

amount = 67/9;

Here amount will have the value of 67 divided by 9.

Types of variables in Java

The Java programming language defines the following kinds of variables:

  1. Instance Variables (Non-Static Fields)–Instance variables are declared inside a class but outside any method, constructor, or block, and they are not marked as static. Each object of the class gets its own copy of these variables, meaning their values are unique to each instance.

    For example, if you have a class Person and two objects of it person1 and person2 then the instance variables of these two objects will have independent values.

    public class Person {
     private String firstName;
     private String lastName;
     private int age;
     private char gender;
     public Person(String firstName, String lastName, int age, char gender){
      this.firstName = firstName;
      this.lastName = lastName;
      this.age = age;
      this.gender = gender;
     }
     
     public String getFirstName() {
      return firstName;
     }
    
     public String getLastName() {
      return lastName;
     }
    
     public int getAge() {
      return age;
     }
     public char getGender() {
      return gender;
     }
    }
    
    public class InstanceDemo {
    
     public static void main(String[] args) {
      Person person1 = new Person("Ram", "Mishra", 23, 'M');
      Person person2 = new Person("Amita", "Chopra", 21, 'F');
      
      System.out.println("Values in object person1 - " + 
        person1.getAge() + " " + person1.getFirstName() + " " + 
        person1.getLastName()+ " " + person1.getGender());
      System.out.println("Values in object person2 - " + 
        person2.getAge() + " " + person2.getFirstName() + " " + 
        person2.getLastName()+ " " + person2.getGender());
    
     }
    
    }
    

    Output

    Values in object person1 - 23 Ram Mishra M
    Values in object person2 - 21 Amita Chopra F
    

    Here you can see how using the constructor of the class, variables are initialized for both the objects and output shows that each instance of the class has its own values for the fields.

  2. Class Variables (Static Fields)- A class variable in Java is any field declared with the static modifier. As the name suggests class variable is at the class level. Unlike instance variables, there is only one copy of a static variable per class, shared across all objects. Doesn’t matter how many instances (objects) of the class you have, the class variable will have the same value. You can access class variables directly using the class name, without creating an object.

    Java class variables example

    One common use of static fields is to create a constant value that's at a class level and applicable to all created objects.

    public class Employee {
     int empId;
     String name;
     String dept;
     // static constant
     static final String COMPANY_NAME = "XYZ";
     Employee(int empId, String name, String dept){
      this.empId = empId;
      this.name = name;
      this.dept = dept;
     }
     
     public void displayData(){
      System.out.println("EmpId = " + empId + " name= " + name + " dept = " + 
      dept + " company = " + COMPANY_NAME);
     }
     public static void main(String args[]){  
      Employee emp1 = new Employee(1, "Ram", "IT");
      Employee emp2 = new Employee(2, "Krishna", "IT");
      emp1.displayData();
      emp2.displayData();
     }
    }
    

    Output

    EmpId = 1 name= Ram dept = IT company = XYZ
    EmpId = 2 name= Krishna dept = IT company = XYZ
    
  3. Local Variables– Local variables are variables declared within a method, constructor, or block. They represent the temporary state of a method and exist only during the execution of that method. Once the method finishes, the local variables are destroyed, and their values are no longer accessible.

    Scope of Local Variables

    The scope of a local variable is limited to the block of code enclosed by curly braces {} where it is declared. This means:
    • A local variable declared inside a method is accessible only within that method.
    • If you declare a variable inside a nested block (such as an if statement or loop), its scope is restricted to that block.

    One more thing to note is that you can have a local variable with the same name as class level variable in the method, with in the method the local variable will take priority.

    Java local variables example

    public class InstanceDemo {
     // class level variable
     int x = 8;
     public static void main(String[] args) {
      
      InstanceDemo id = new InstanceDemo();
      
      id.display();
      System.out.println("value of class level variable x " + id.x);
     }
     
     public void display(){
      int x = 5;  // local variable
      boolean flag = true;
      System.out.println("value of local variable x " + x);
      if (flag){
       int y = 10; // nested scope variable
       System.out.println("value of local variable y inside if " + y);
      }
      // This will cause compile-time error
      //System.out.println("value of local variable y inside if " + y); 
     }
     
    }
    

    Output

    value of local variable x 5
    value of local variable y inside if 10
    value of class level variable x 8
    

    Here you see there is a class level variable and again it the method display() there is a variable with the same name x. With in the method value of local variable x takes priority and that is printed. Once out of the method, x that is recognized is the class level variable x.

    Another thing to note is the nested scope created by the if condition with in the display() method. Scope of variable y is in between the starting and closing braces of the if condition. Once you are out of if condition y won’t be recognized. Any attempt to print value of y outside the if condition scope will result in compile-time error.

  4. Parameters- Variables passed to any method are known as parameters. Any changes made to the primitive types parameter won’t change the original value.

    Java parameters example

    public class InstanceDemo {
     public static void main(String[] args) {
      
      InstanceDemo id = new InstanceDemo();
      int x = 10;
      id.display(x);
      System.out.println("value of x after method call " + x);
     }
     
     public void display(int x){
      
      x++;
      System.out.println("value of local variable x " + x);
     }
     
    }
    

    Output

    value of local variable x 11
    value of x after method call 10
    

    Here you have a variable x that is passed to display method as an int parameter. With in the method display() value of x is changed. But that change is local only and doesn’t change the original value of x. This is because copy of a variable is passed as a method parameter.

    If an object is passed as a parameter and any of that object’s field is changed, that change will be visible in other scopes too.

That's all for this topic Java Variable Types With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Java is a Strongly Typed Language
  2. Primitive Data Types in Java
  3. Access Modifiers in Java - Public, Private, Protected and Default
  4. What Are JVM, JRE And JDK in Java
  5. Object Creation Using new Operator in Java

You may also like-

  1. String in Java Tutorial
  2. Array in Java
  3. Count Number of Words in a String Java Program
  4. Ternary Operator in Java With Examples
  5. Java Multithreading Interview Questions And Answers
  6. Java Exception Handling Tutorial
  7. ConcurrentHashMap in Java With Examples
  8. TreeMap in Java With Examples

What is LangChain - An Introduction

LangChain is an open-source framework which is designed to simplify the creation of LLM powered applications. Through its tools and APIs, it allows you to refine and customize information, making LLM generated responses more precise and contextually meaningful. For example, using LangChain you can link LLMs to external data sources and computation to enhance LLM model’s capabilities. By leveraging these capabilities, developers can build powerful AI applications like smart chatbots, advanced Q&A systems, summarization services.

LangChain Installation

LangChain framework is available as libraries in Python and JavaScript.

  • To install the LangChain package in Python you can use the following command
  • pip install -U langchain
        

    Prerequisite is Python 3.10+ installation for the LangChain version 1.2.13

  • For Typescript installation, you can use the following command
  • npm install langchain @langchain/core
        

    Prerequisite is Node.js 20+ installation for the LangChain version 1.2.13

Core components of LangChain

  1. Models

    LangChain’s standard model interfaces give you access to many different provider integrations. LangChain provides integration to nearly all the LLMs through a standard interface, including OpenAI, Anthropic, Google, to many open source models (like Meta AI’s LLaMa, Deepseek's Deepseek-LLM, Mistral) through HuggingFace, to locally downloaded LLMs through Ollama.

    Note that many LLM providers require an API key and you need to create an account in order to receive an API key.

    The simplest way to connect to any LLM is using the init_chat_model function in LangChain or you can use the LLM specific model classes like ChatAnthropic, ChatOpenAI, ChatGoogleGenerativeAI, ChatOllama and so on.

    Only thing you need is the integration package for the chosen model provider to be installed which is generally in the format langchain-LLM_PROVIDER_NAME. So, if you are using OpenAI then you need to install langchain-openai package.

  2. Prompt Template

    LangChain provides a PromptTemplate class to create a prompt template- a dynamic prompt with some placeholders that can be given actual values later. There is also a ChatPromptTemplate class which acts as a prompt template for chat models.

  3. Tools

    LLMs have some limitations, firstly these models are trained up to some cutoff date and they have data up to that time only. Though many LLMs now have web browsing capability to bypass their training data cutoff. Another problem is not have domain data or company specific data.

    Langchain tools can give that functionality to agents by letting them fetch real-time data, execute code, query external databases, and take actions in the world. Under the hood, tools are callable functions with well-defined inputs and outputs that get passed to a chat model. The model decides when to invoke a tool based on the conversation context, and what input arguments to provide.

  4. Agents

    LangChain agents combine LLMs with tools to create systems that can complete complex tasks step by step. Unlike a basic application where you send a prompt and get a response from an LLM, LangChain agents can think, plan, and adapt.

    They integrate language models with tools to reason about tasks and choose the right actions.

    This allows them to iteratively work toward solutions with greater intelligence and flexibility.

  5. Chains

    As the name LangChain itself suggests, chains are the main concept of LangChain. They allow developers to link multiple components together into a single workflow. Each link in the chain can handle a specific task, from prompt formatting to retrieval and reasoning. This modular design makes it easy to build complex AI applications step by step.

    With the LangChain Expression Language (LCEL), you can define these chains declaratively, using the pipe (|) symbol to connect prompts, models, retrievers, and output parsers.

  6. Memory

    For many AI applications you may need to retain information about previous interactions. For AI agents, memory is crucial because it lets them remember previous interactions, learn from feedback, and adapt to user preferences. LangChain provides both short term memory and long term memory.

    1. Short term memory- It lets your application remember previous interactions within a single thread or conversation.
    2. Long-term memory- It lets your agent store and recall information across different conversations and sessions. Long-term memory persists across threads and can be recalled at any time.

How does LangChain work

Now, when you have some idea about the components of LangChain, let us try to understand how LangChain can actually chain together different components to create a workflow for LLM powered applications.

For example, a typical Retrieval-Augmented Generation (RAG) application may have a workflow as given below-

  1. Receive the user’s query.
  2. Reformulate the query by sending it to the LLM which rephrases the user provided query into a concise search query.
  3. Retrieve the data relevant to search query, which could involve connecting to databases, APIs, or other repositories (e.g. Confluence). LangChain provides various document loaders like PyPDFLoader, TextLoader, CSVLoader, ConfluenceLoader for integrating data from numerous sources.
  4. Pass the retrieved documents to LLM to summarize the information
  5. Pass the retrieved information, along with the original query, to an LLM to get the final answer.

That's all for this topic What is LangChain - An Introduction. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java Program to Check Prime Number
  2. Armstrong Number or Not Java Program
  3. How to Display Pyramid Patterns in Java - Part2
  4. Java Program to Reverse a Number
  5. Swap or Exchange Two Numbers Without Using Any Temporary Variable Java Program

You may also like-

  1. Find Duplicate Elements in an Array Java Program
  2. Count Number of Times Each Character Appears in a String Java Program
  3. Check if Given String or Number is a Palindrome Java Program
  4. Polymorphism in Java
  5. Difference Between Abstract Class And Interface in Java
  6. Java Automatic Numeric Type Promotion
  7. Java Pass by Value or Pass by Reference
  8. finally Block in Java Exception Handling

Merge Sort Program in Java

In this post, we’ll explore how to implement a Merge Sort Program in Java. Merge sort is much more efficient than the simple sort algorithms like bubble sort and insertion sort, especially for large datasets. The only trade-off is that it requires an additional array along with the original array that is sorted.

How merge sort works

Merge sort works on the concept of merging two sorted arrays to create another array which is also sorted.

Now the question is how do you get those sorted arrays which are merged?

Merge Sort follows the Divide and Conquer paradigm. The algorithm repeatedly divides the input array into two halves until you get sub-arrays with a single element which is considered a sorted array.

At that point you start merging these sub-arrays, from two single element sub-arrays you create a sorted merged array of two elements. Then two such sorted sub-arrays of two elements are merged to create a sorted array of four elements and so on until you have a sorted array of all the elements.

Since array is recursively divided into two halves so this division process can be written as a recursive method where base case becomes the point when you have sub-arrays with only one element each.

Let’s try to understand with an example where we have an input array as given below.

int[] intArr = {21, 11, 33, 70, 5, 25, 65, 55};

The process of recursive calls to divide the array into halves can be explained using the following image.

merge sort in java

At this point merge process starts which merges two sorted arrays to create another sorted array, this merging process can be explained using the following image.

merge sort program java

Merge Sort Java program

In the merge sort program there is a method mergeSortRecursive which is called recursively to divide the array.

Merge method merges the two sub-arrays to create a sorted array.

public class MergeSort {
  public static void main(String[] args) {
    int[] intArr = {47, 85, 620, 3456, -7, 10, 4500, 106, -345, 1000, 67, 80, 5500, 34, 78, 782, 4, 0, 99, 190};
    MergeSort ms = new MergeSort();
    ms.mergeSortRecursive(intArr, 0, intArr.length-1);
    System.out.println("Sorted array after merge sort- ");
    for(int num : intArr){
      System.out.print(num + " ");
    }
  }
    
  private void mergeSortRecursive(int[] intArr, int lower, int upper){
    //base case
    if (lower == upper){
      return;
    }else{
      // get mid point for division of array
      int middle = (lower + upper)/2;
      
      mergeSortRecursive(intArr, lower, middle);        
      mergeSortRecursive(intArr, middle+1, upper);
      
      merge(intArr, lower, middle, upper);
    }
  }
    
  private void merge(int[] intArr, int lower, int middle, int upper){
      /** Create two temp arrays pertaining to two halves that 
       are being merged and add elements to them  */
      int subArrayOneLength = middle - lower + 1;
      int subArrayTwoLength = upper - middle;
      int[] temp1 = new int[subArrayOneLength];
      int[] temp2 = new int[subArrayTwoLength];
      for(int i = 0; i < subArrayOneLength; i++){
        temp1[i] = intArr[lower + i];
      }
      for(int j = 0; j < subArrayTwoLength; j++){
        temp2[j] = intArr[middle + 1 + j];
      }           
      int i =0;        
      int j = 0;
      // merging process, merge two temp arrays 
      while((i < subArrayOneLength) && (j < subArrayTwoLength)){
        if(temp1[i] < temp2[j]){
          intArr[lower] = temp1[i++];
        }else{
          intArr[lower] = temp2[j++];
        }
        lower++;
      }
      // If there are more elements
      while(i < subArrayOneLength){
        intArr[lower++] = temp1[i++];
      }
      while(j < subArrayTwoLength){
        intArr[lower++] = temp2[j++];
      }
  }
}

Output

Sorted array after merge sort- 
-345 -7 0 4 10 34 47 67 78 80 85 99 106 190 620 782 1000 3456 4500 5500 

Performance of merge sort

In merge sort there is subdivision of arrays and for each sub-division there is merging. Number of levels (subdivisions of array) can be calculated as– (logN + 1)

For example log of 8 base 2 is 3, so log8 + 1 = 4

Which is same as the number of halves for the array having 8 elements– 8 4 2 1.

At each level N elements are merged which makes the time complexity of merge sort as N*(logN + 1). we can discard the 1 so the time complexity of merge sort is O(N*logN).

Merge sort is not an in place sort algorithm as extra space is required. Auxiliary space required is equal to the number of elements in the original array so the space complexity of merge sort is O(N).

That's all for this topic Merge Sort Program in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Programs Page


Related Topics

  1. Shell Sort Program in Java
  2. Radix Sort Program in Java
  3. How to Display Pyramid Patterns in Java - Part1
  4. Arrange Non-Negative Integers to Form Largest Number - Java Program
  5. Find All Permutations of a Given String Java Program

You may also like-

  1. Running Dos/Windows Commands From Java Program
  2. Find Duplicate Elements in an Array Java Program
  3. How to Display Time in AM-PM Format in Java
  4. How to Sort an ArrayList in Descending Order in Java
  5. CopyOnWriteArrayList in Java With Examples
  6. Java Reflection API Tutorial
  7. String in Java Tutorial
  8. NameNode, DataNode And Secondary NameNode in HDFS

Wednesday, March 25, 2026

Java Program to Display Prime Numbers

In this tutorial, we’ll explore a Java Program to Display Prime Numbers up to a given range.

A prime number is a natural number greater than 1 that has no divisors other than 1 and itself. Examples include: 2, 3, 5, 7, 11, 13, 17….

Efficient Prime Check Logic

To check if a number is prime or not you don't need to run a loop starting from 2 till that number to check if number has any divisor. You can use a more efficient approach to loop only up to \( \sqrt{n}\) (square root of the number).If no divisor is found in this range, the number is prime.

Let's try to understand why looping only up to \( \sqrt{n}\) is sufficient.

If a number n is not prime, it can be expressed as a product of two factors-

\( n=a\times b\)

At least one of these factors must be less than or equal to \( \sqrt{n}\).

For example, for n = 36, factors are (6 × 6) or (4 × 9). Notice that one factor (4 or 6) is = \( \sqrt{36}\) = 6. Therefore, if no divisor is found up to \( \sqrt{n}\), there cannot be any divisor beyond \( \sqrt{n}\) either, because the corresponding smaller factor would already have been detected.

Looking for more efficient way to display prime numbers. Refer these sieving algorithms- Java Program - Sieve of Eratosthenes to Find Prime Numbers, Java Program - Sieve of Sundaram to Find Prime Numbers

How LinkedList Class Works Internally in Java

In the Java Collections Framework, two widely used implementations of the List interface are:

The difference lies in their internal data structures. ArrayList uses a dynamically resizable array of Object[], making it efficient for random access but costly for insertions and deletions in the middle.

To read more about how ArrayList works internally in Java refer this post- How ArrayList works internally in Java

In this article, I'll talk about LinkedList internal implementation in Java Collections framework and understand why it is often chosen for scenarios involving frequent insertions and deletions.


Internal implementation of LinkedList class in Java

The LinkedList class in Java implements both the List and Deque interfaces. Internally, it is built using a doubly linked list data structure.

At the core of the implementation of the LinkedList class in Java there is a private static inner class Node<E> which defines the structure of each element in the list. It has item variable for holding the value and two reference to Node class itself for connecting to next and previous nodes.

The Node class from Linked List implementation

private static class Node<E> {
  E item;
  Node<E> next;
  Node<E> prev;
  Node(Node<E> prev, E element, Node<E> next) {
    this.item = element;
    this.next = next;
    this.prev = prev;
  }
}
  • item- Stores the actual data.
  • next- Reference to the next node.
  • prev- Reference to the previous node.

Graphical representation of Java LinkedList with nodes

Here is a graphical representation of a linked list to help you better visualize how actually a node will look like and how it connects with other nodes through next and prev references.
Since reference is stored for both next and previous nodes that is why it is a doubly linked list implementation.

LinkedList internal implementation in Java

This design allows bidirectional traversal and makes insertions/deletions at both ends (head and tail) highly efficient- constant time operations.

For insertions or deletions in the middle of the list, the actual update of node references (prev and next) is still efficient. However, reaching the desired position requires traversal from either end, which makes these operations linear time (O(n)).

Though there are many methods with in the LinkedList class but here I'll try to explain the internal working of the LinkedList, how references are created and shuffled using these 3 methods-

  • private void linkFirst(E e)
  • void linkLast(E e)
  • public void add(int index, E element)

Java LinkedList internal implementation - linkFirst() method

linkFirst() method is used to add an element at the beginning of the list and it is implemented as follows in the LinkedList class

/**
 * Links e as first element.
 */
private void linkFirst(E e) {
  final Node<E> f = first;
  final Node<E> newNode = new Node<>(null, e, f);
  first = newNode;
  if (f == null)
      last = newNode;
  else
      f.prev = newNode;
  size++;
  modCount++;
}

Here one more important thing to mention is first and last Node class references which always refer to the first and last element of the linked list.

/**
 * Pointer to first node.
 * Invariant: (first == null && last == null) ||
 *            (first.prev == null && first.item != null)
 */
transient Node<E> first;
/**
 * Pointer to last node.
 * Invariant: (first == null && last == null) ||
 *            (last.next == null && last.item != null)
 */
transient Node<E> last;

With this info it is easy to see that in the linkFirst method, when the very first element is inserted into the list first and last both refer to this new node.

In case linked list already contains elements and a new element is inserted at the beginning of the list. Then f will hold the reference to the node which was the first element before this insertion. first will be assigned the reference to the newly created node (first = newNode;). The element which was the first element before this insertion is at second position now so its prev element should store reference of the first node, that's what is happening here f.prev = newNode;

And in the call to the constructor of the node class f is sent as a parameter. If you see in the Node class constructor there is a line this.next = next; that's how the newly created node is storing the reference to the second node.

Java LinkedList internal implementation - linkLast() method

linkLast() method is used to insert element as the last element of the list. In that case the node which is currently the last node of the linked list will become the second last node. So the newly created node's prev should store the reference to this second last node and the next of the second last node should store the reference to the node which is the last node now.

/**
 * Links e as last element.
 */
void linkLast(E e) {
  final Node<E> l = last;
  final Node<E> newNode = new Node<>(l, e, null);
  last = newNode;
  if (l == null)
      first = newNode;
  else
      l.next = newNode;
  size++;
  modCount++;
}

Here it is first checking if it is the very first element which is inserted in that case both first and last references point to it. If elements are already there in the linked list then the node which is currently the last node of the linked list will become the second last node now.

See the call to the constructor of the Node class (this.prev = prev;). So the newly created node's prev should store the reference to this second last node and the next of the second last node should store the reference to the node which is the last node now (l.next = newNode;).

Java LinkedList internal implementation - add(int index, E element) method

add(int index, E element) is used to Insert the specified element at the specified position in this list.

public void add(int index, E element) {
  checkPositionIndex(index);

  if (index == size)
    linkLast(element);
  else
    linkBefore(element, node(index));
}

Here it calls linkBefore method

void linkBefore(E e, Node<E> succ) {
  // assert succ != null;
  final Node<E> pred = succ.prev;
  final Node<E> newNode = new Node<>(pred, e, succ);
  succ.prev = newNode;
  if (pred == null)
    first = newNode;
  else
    pred.next = newNode;
  size++;
  modCount++;
}

And node(index) parameter with in the linkBefore() method is call to the following method to get the existing Node at the given index-

/**
* Returns the (non-null) Node at the specified element index.
*/
Node<E> node(int index) {
 // assert isElementIndex(index);

  if (index < (size >> 1)) {
    Node<E> x = first;
    for (int i = 0; i < index; i++)
      x = x.next;
    return x;
  } else {
    Node<E> x = last;
    for (int i = size - 1; i > index; i--)
      x = x.prev;
    return x;
  }
}

I am leaving it to you readers to figure out how linkBefore() method is working. It should be easy based on the explanation already provided for linkFirst() and linkLast() method.

That's all for this topic How LinkedList Class Works Internally in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How HashMap Works Internally in Java
  2. How HashSet Works Internally in Java
  3. Difference Between ArrayList And LinkedList in Java
  4. ListIterator in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. How to Convert Array to ArrayList in Java
  2. Difference between HashMap and ConcurrentHashMap in Java
  3. static import in Java
  4. finally Block in Java Exception Handling
  5. Interface Static Methods in Java
  6. Method reference in Java 8
  7. Java Program to Find First Non-Repeated Character in a Given String
  8. Synchronization in Java - Synchronized Method And Block

Tuesday, March 24, 2026

Java Pass by Value or Pass by Reference

Parameter passing in Java is pass by value or pass by reference is one question which causes a bit of confusion so let's try to clarify it in this post.

Before going into whether Java is pass by value or pass by reference let's first see what do these terms actually mean.

  • Pass by value- In this case actual value of the variable is copied into the method’s parameter. This means two independent variables exist, each with its own memory space.
  • Pass by reference- In this case instead of copying the value, the memory address of the variable is passed to the parameter of the method. Thus anytime method is using its parameter it is actually referencing the original variable.

How Java Handles Parameter Passing

Let us be clear on one thing in the beginning itself. In Java, everything is pass by value, whether you’re dealing with primitive types or objects. Java does not support true pass by reference because it doesn’t expose memory addresses or pointers.

Passing primitive types as method parameter

At least there is no confusion with primitive data types as it is easy to see that primitives are passed by value in Java. For primitive data types (int, double, char, etc.), Java simply copies the value into the method parameter. Any modification inside the method does not affect the original variable. Let's see it with an example-

public class A {
 
 void displayData(int i){  
  //value of the passed primitive variable changed
  i++;
  System.out.println("Value of i inside method "  + i);
 }  
 public static void main(String args[]){ 
  A a = new A();
  int i = 5;
  // Sending variable i as param
  a.displayData(i);  
  System.out.println("Value of i inside main "  + i);
 }  
}

Output of the program

Value of i inside method 6
Value of i inside main 5

In the code when the displayData() method is called-

  • Copy of variable i is made.
  • That copy is sent to the displayData() method.
  • Any change made to variable i with in displayData() method is local to that method and that copy of the variable.

Thus it can be seen that the changing of the passed int value in the method doesn't affect the original value.

Passing class object as method parameter

When object is passed as a method parameter, people have some confusion whether it's pass by value or pass by reference in Java.

The confusion arises because, when an object is passed as parameter in Java and any instance variable of that object is changed when in the method that change is reflected globally i.e. same value is reflected every where. Let's see an example-

public class A {
 private int i;
 //constructor
 A(int i){
  this.i = i;
 }

 void displayData(A obj){ 
  // object manipulated 
  obj.setI(7);
  System.out.println("Value of i inside method "  + obj.getI());
 }  
 public static void main(String args[]){ 
  A a = new A(5);
  System.out.println("Value of i inside main before method call "  + a.getI());
  a.displayData(a);  
  System.out.println("Value of i inside main after method call "  + a.getI());
 }
 //getter
 public int getI() {
  return i;
 }
//setter
 public void setI(int i) {
  this.i = i;
 }  
}

Output of the program

Value of i inside main before method call 5
Value of i inside method 7
Value of i inside main after method call 7

It can be seen from the output that changes done to the object in the method displayData() are reflected globally. When value of i is printed after the method call it is changed. If java is pass by value then why that?

It is because when we say

A a = new A();

The new operator allocates memory for the created object and returns a reference to that memory which is then assigned to the variable of the class type.

So, it can be said “a” is a variable which is holding a value and that value happens to be the reference to the memory address.

When the method is called with

a.displayData(a); 

copy of the reference value is created and passed into the other object which means in method void displayData(A obj), obj parameter holds the copy of the reference value thus a and obj both are references to the same memory given to the object. Refer below image to have clarity.

pass by value or pass by reference

So to make it clear, in the case of object Java copies and passes the reference by value, not the actual reference itself. That is why any manipulation of the object in the method will alter the object, since the references point to the original objects. At the same time if reference itself is changed for the object that change is not reflected to the original object, which would have happened in case of pass by reference.

Let's write a Java program to understand this statement "If reference itself is changed for the obejct that change is not reflected to the original object" in detail.

public class A {
 private int i;
 A(int i){
  this.i = i;
 }
 void displayData(A obj){
  // change the reference
  obj = new A(8);
  System.out.println("Value of i inside method "  + obj.getI());
 }  
 public static void main(String args[]){ 
  A a = new A(5);
  System.out.println("Value of i inside main before method call "  + a.getI());
  a.displayData(a);  
  System.out.println("Value of i inside main after method call "  + a.getI());
 }
 
 // getter
 public int getI() {
  return i;
 }
 // setter
 public void setI(int i) {
  this.i = i;
 }  
}

In this program the reference of the object which was copied and passed as value to the parameter in method displayData() has been changed

obj = new A(8);

but it can be seen from the output that it doesn't change the original reference as it retains the original value of the variable i.

Value of i inside main before method call 5
Value of i inside method 8
Value of i inside main after method call 5

I hope I am able to make it clear that in Java, whether primitives or objects, everything is pass by value. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Why main Method static in Java
  2. Constructor in Java
  3. static Keyword in Java With Examples
  4. Primitive Data Types in Java
  5. Core Java Basics Interview Questions And Answers

You may also like-

  1. Abstraction in Java
  2. Method overriding in Java
  3. Difference Between Abstract Class And Interface in Java
  4. What are JVM, JRE and JDK in Java
  5. Can we Start The Same Thread Twice in Java
  6. How HashMap Works Internally in Java
  7. Angular First App - Hello world Example
  8. Dependency Injection in Spring Framework

Python Exception Handling Tutorial

This Python exception handling tutorial gives an overview of Python exceptions and how to handle exceptions using Python exception handling.

Types of errors

Errors in your Python programs can be categorized into atleast two types-

  • Syntax errors
  • Exceptions

Syntax error

Syntax errors or compile time errors are the errors due to which your program fails to compile. Such errors are detected at the compile time itself, file name, line number and error description is displayed so you know where to look for the error and how to correct it.

For example if you don’t write colon after if statement-

def check_equality(str1, str2):
  if str1 > str2
    print(str1, 'is greater than', str2)

Then you get the compile time error as shown here-

Output

  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 2
    if str1 > str2
                 ^
SyntaxError: invalid syntax

Exceptions

Even if a statement or expression is syntactically correct it may result in an error at run time. Errors detected during runtime are called exceptions and they disrupt the normal execution flow of the program.

For example in the following program there is an attempt to divide by zero which results in ZeroDivisionError at runtime.

def divide_num(num1, num2):
  return num1/num2

divide_num(10, 0)

Output

Traceback (most recent call last):
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 4, in <module>
    divide_num(10, 0)
  File "F:/NETJS/NetJS_2017/Python/Test/Test.py", line 2, in divide_num
    return num1/num2
ZeroDivisionError: division by zero

When these types of runtime errors occur in Python code, an exception object is created and raised. If there is no exception handling code to handle it then the error message is displayed that shows the context where the exception happened, in the form of a stack traceback. The exception type (at least in case of built-in exception) is printed as part of the message.

Python 3 exception hierarchy

In Python all exceptions are represented as classes and derive from BaseException class. The class hierarchy for built-in exceptions in Python is as follows.

Python 3 exception hierarchy

As you can see from the Python Exception hierarchy all built-in, non-system-exiting exceptions are derived from Exception class. All user-defined exceptions should also be derived from this class.

Warning messages are typically issued in situations where it is useful to alert the user of some condition in a program, where that condition (normally) doesn’t warrant raising an exception and terminating the program.

Warning messages are typically issued in situations where it is useful to alert the user of some condition in a program. Warnings unlike exceptions are not fatal and don't terminate the program. Warning is the base class for warning categories.

Python exception handling

While writing robust code we should provide checks for the eventuality where program may fail at run time because of some condition like zero division, file not found, type error.

Default behavior for handling such exceptions in Python is for the interpreter to print the full stack traceback, that includes the exception type (at least in case of built-in exception) and error message, and then terminate the program.

By providing your own exception handling you can display an appropriate message and then continue with the program rather than terminating the program.

To handle exception in Python you can use the following procedure-

  1. Use try block to enclose code that might throw an exception.
  2. Use except block to handle the raised exceptions.
  3. Use finally clause to perform clean up like closing the opened file.

Together these three keywords constitute the Python exception handling. General form of exception handling in Python is as follows.

try: 
 try suite
               
except Exception1:
 handler suite
except Exception2:
 handler suite
else:
 else suite
finally: 
 finally suite

There can be more than one except block, based on the type of the exception raised appropriate except block is executed. Read more in this post- Python Exception Handling - try,except,finally

If no exception is raised then the statements in the else block are executed.

Statements inside the finally block are always executed whether an exception is raised or not.

Python exception handling example

def divide_num(num1, num2):
  try:
    print('Result-',num1/num2)
  except ZeroDivisionError:
    print('Division by zero')
    print('Zero is not a valid argument here')
  else:
    print('in else block')

divide_num(10, 0)
divide_num(10, 2)

Output

Division by zero
Zero is not a valid argument here
Result- 5.0
in else block

As you can see in the first call to function 0 is passed as divisor which results in ‘ZeroDivisionError’ so the except block handles that exception. Since the exception handling is done so the program doesn’t terminate and the second function is also executed. This time there is no error so an optional else block is executed.

Apart from try, except and finally other keywords used in Python exception handling are-

  • raise- Allows you to force a specified exception to occur.
  • assert- The assert statement enables you to verify if a certain condition is true or not. If it not true then it raises AssertionError.

Python built-in exceptions

Python language has several built-in exceptions, some of the important one are listed below.

Exception Class Description
ArithmeticError The base class for those built-in exceptions that are raised for various arithmetic errors: OverflowError, ZeroDivisionError, FloatingPointError.
AssertionError Raised when an assert statement fails.
EOFError Raised when the input() function hits an end-of-file condition (EOF) without reading any data.
ImportError Raised when the import statement has troubles trying to load a module.
IndexError Raised when a sequence subscript is out of range.
KeyError Raised when a mapping (dictionary) key is not found in the set of existing keys.
OverflowError Raised when the result of an arithmetic operation is too large to be represented.
RuntimeError Raised when an error is detected that doesn’t fall in any of the other categories.
SyntaxError Raised when the parser encounters a syntax error.
IndentationError Base class for syntax errors related to incorrect indentation. This is a subclass of SyntaxError.
SystemError Raised when the interpreter finds an internal error, but the situation does not look so serious to cause it to abandon all hope.
TypeError Raised when an operation or function is applied to an object of inappropriate type.
ZeroDivisionError Raised when the second argument of a division or modulo operation is zero.
FileNotFoundError Raised when a file or directory is requested but doesn’t exist.

That's all for this topic Python Exception Handling Tutorial. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. User-defined Exceptions in Python
  2. self in Python
  3. Python return Statement With Examples
  4. Constructor in Python - __init__() function
  5. Nonlocal Keyword in Python With Examples

You may also like-

  1. Changing String Case in Python
  2. Class And Object in Python
  3. Python Generator, Generator Expression, Yield Statement
  4. Convert String to int in Python
  5. What Are JVM, JRE And JDK in Java
  6. Java Concurrency Interview Questions And Answers
  7. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  8. How to Handle Missing And Under Replicated Blocks in HDFS