In an interview, one of my friends was asked that if we have two Integer objects, Integer a = 127; Integer b = 127; Why a == b evaluate to true when both are holding two separate objects? In this article, I will try to answer this question and also try to explain the answer.

Short Answer

The short answer to this question is, direct assignment of an int literal to an Integer reference is an example of auto-boxing concept where the literal value to object conversion code is handled by the compiler, so during compilation phase compiler converts Integer a = 127; to Integer a = Integer.valueOf(127);.

The Integer class maintains an internal IntegerCache for integers which by default ranges from -128 to 127 and Integer.valueOf() method returns objects of mentioned range from that cache. So a == b returns true because a and b both are pointing to the same object.


Long Answer

In order to understand the short answer let's first understand the Java types, all types in Java lies under two categories

  1. Primitive Types: There are 8 primitive types (byte, short, int, long, float, double, char and boolean) in Java which holds their values directly in the form of binary bits.
    For example, int a = 5; int b = 5; here a and b directly holds the binary value of 5 and if we try to compare a and b using a == b we are actually comparing 5 == 5 which returns true.

  2. Reference Types: All types other than primitive types lies under the category of reference types e.g. Classes, Interfaces, Enums, Arrays etc. and reference types holds the address of the object instead of the object itself.
    For example, Integer a = new Integer(5); Integer b = new Integer(5), here a and b do not hold the binary value of 5 instead a and b holds memory addresses of two separate objects where both objects contain a value 5. So if we try to compare a and b using a == b, we are actually comparing those two separate memory addresses hence we get false, to perform actual equality on a and b we need to perform a.euqals(b).

    Reference types are further divided into 4 categories Strong, Soft, Weak and Phantom References.

And we know that Java provides wrapper classes for all primitive types and support auto-boxing and auto-unboxing.

// Example of auto-boxing, here c is a reference type
Integer c = 128; // Compiler converts this line to Integer c = Integer.valueOf(128); 

// Example of auto-unboxing, here e is a primitive type
int e = c; // Compiler converts this line to int e = c.intValue();

Now if we create two integer objects a and b, and try to compare them using the equality operator ==, we will get false because both references are holding different-different objects

Integer a = 128; // Compiler converts this line to Integer a = Integer.valueOf(128);
Integer b = 128; // Compiler converts this line to Integer b = Integer.valueOf(128);

System.out.println(a == b); // Output -- false

But if we assign the value 127 to both a and b and try to compare them using the equality operator ==, we will get true why?

Integer a = 127; // Compiler converts this line to Integer a = Integer.valueOf(127);
Integer b = 127; // Compiler converts this line to Integer b = Integer.valueOf(127);

System.out.println(a == b); // Output -- true

As we can see in the code that we are assigning different objects to a and b but a == b can return true only if both a and b are pointing to the same object.

So how the comparison returning true? what's actually happening here? are a and b pointing to the same object?

Well till now we know that the code Integer a = 127; is an example of auto-boxing and compiler automatically converts this line to Integer a = Integer.valueOf(127);.

So it is the Integer.valueOf() method which is returning these integer objects which means this method must be doing something under the hood.

And if we take a look at the source code of Integer.valueOf() method, we can clearly see that if the passed int literal i is greater than IntegerCache.low and less than IntegerCache.high then the method returns Integer objects from IntegerCache. Default values for IntegerCache.low and IntegerCache.high are -128 and 127 respectively.

In other words, instead of creating and returning new integer objects, Integer.valueOf() method returns Integer objects from an internal IntegerCache if the passed int literal is greater than -128 and less than 127.

/**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
 public static Integer valueOf(int i) {
     if (i >= IntegerCache.low && i <= IntegerCache.high)
         return IntegerCache.cache[i + (-IntegerCache.low)];
     return new Integer(i);
 }

Java caches integer objects which fall into -128 to 127 range because this range of integers gets used a lot in day to day programming which indirectly saves some memory.

As you can see in the following image Integer class maintains an inner static IntegerCache class which acts as the cache and holds integer objects from -128 to 127 and that's why when we try to get integer object for 127 we always get the same object.

integer-cache-source-code


The cache is initialized on the first usage when the class gets loaded into memory because of the static block. The max range of the cache can be controlled by the -XX:AutoBoxCacheMax JVM option.

This caching behavior is not applicable to Integer objects only, similar to Integer.IntegerCache we also have ByteCache, ShortCache, LongCache, CharacterCache for Byte, Short, Long, Character respectively.

Byte, Short and Long have a fixed range for caching between –127 to 127 (inclusive) but for Character, the range is from 0 to 127 (inclusive). The range can be modified via argument only for Integer but not for others.

You can find the complete source code for this article on this Github Repository and please feel free to provide your valuable feedback.
When we create a variable in both parent and child class with the same name, and try to access it using parent's class reference which is holding a child class's object then what do we get?

In order to understand this, let us consider below example where we declare a variable x with the same name in both Parent and Child classes.

class Parent {
    // Declaring instance variable by name `x`
    String x = "Parent`s Instance Variable";

    public void print() {
        System.out.println(x);
    }
}

class Child extends Parent {

    // Hiding Parent class's variable `x` by defining a variable in child class with same name.
    String x = "Child`s Instance Variable";

    @Override
    public void print() {
        System.out.print(x);

        // If we still want to access variable from super class, we do that by using `super.x`
        System.out.print(", " + super.x + "\n");
    }
}


And now if we try to access x using below code, what System.out.println(parent.x) will print


Parent parent = new Child();
System.out.println(parent.x) // Output -- Parent`s Instance Variable


Well generally, we will say Child class will override the variable declared in the Parent class and parent.x will give us whatever Child's object is holding. Because it is the same thing which happens while we do same kind of operation on methods.

But actually it is not, and parent.x will give us value Parent`s Instance Variable which is declared in Parent class but why?

Because variables in Java do not follow polymorphism and overriding is only applicable to methods but not to variables. And when an instance variable in a child class has the same name as an instance variable in a parent class, then the instance variable is chosen from the reference type.

In Java, when we define a variable in Child class with a name which we have already used to define a variable in the Parent class, Child class's variable hides parent's variable, even if their types are different. And this concept is known as Variable Hiding.

In other words, when the child and parent class both have a variable with the same name, Child class's variable hides the parent class's variable. You can read more on variable hiding in the article What is Variable Shadowing and Hiding in Java.





Variable Hiding is not the same as Method Overriding

While variable hiding looks like overriding a variable similar to method overriding but it is not, overriding is applicable only to methods while hiding is applicable to variables.

In the case of method overriding, overriding methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called. You can read more about overriding and how overridden methods completely replace the inherited methods on Everything About Method Overloading Vs Method OverridingWhy We Should Follow Method Overriding Rules.

But in variable hiding child class hides the inherited variables instead of replacing which basically means is that the object of Child class contains both variables but Child's variable hides Parent's variable. so when we try to access the variable from within Child class, it will be accessed from the child class.

And if I simplify section Example 8.3.1.1-3. Hiding of Instance Variables of Java language specification:

When we declare a variable in a Child class which has the same name e.g. x as an instance variable in a Parent class then
  1. Child class's object contains both variables (one inherited from Parent class and other declared in Child itself) but child class variable hides parent class's variable.
  2. Because the declaration of x in class Child hides the definition of x in class Parent, within the declaration of class Child, the simple name x always refers to the field declared within class Child. And if code in methods of Child class want to refer to the variable x of Parent class then this can be done as super.x.
  3. If we are trying to access the variable outside of Parent and Child class, then the instance variable is chosen from the reference type. Thus, the expression parent2.x in following code gives the variable value which belongs to parent class even if it is holding the object of the Child but ((Child) parent2).x accesses the value from the Child class because we casted the same reference to Child.
Why Instance Variable Of Super Class Is Not Overridden In Sub Class due to variable shadowing

Why Variable Hiding Is Designed This Way

So we know that instance variables are chosen from the reference type, not instance type, and polymorphism is not applicable to variables but the real question is why? why variables are designed to follow hiding instead of overriding.

Because variable overriding might break methods inherited from the parent if we change its type in the child class.

We know every child class inherits variables and methods (state and behaviour) from its parent class. Imagine if Java allows variable overriding and we change the type of a variable from int to Object in the child class. It will break any method which is using that variable and because the child has inherited those methods from the parent, the compiler will give errors in child class.

For example:

class Parent {
    int x;
    public int increment() {
        return ++x;
    }
    public int getX() {
        return x;
    }
}

class Child extends Parent {
    Object x;
    // Child is inherting increment(), getX() from Parent and both methods returns an int 
    // But in child class type of x is Object, so increment(), getX() will fail to compile. 
}

If Child.x overrides Parent.x, how can increment() and getX() work? In the subclass, these methods will try to return a value of a field of the wrong type!

And as mentioned, if Java allows variable overriding then Child's variable cannot substitute Parent's variable and this would break the Liskov Substitutability Principle (LSP).

Why Instance Variable Is Chosen from Reference Type Instead Of Instance

As explained in How Does JVM Handle Method Overloading and Overriding Internally,  at compile time overriding method calls are treated from the reference class only but all overridden methods get replaced by the overriding method at the runtime using a vtable and this phenomenon is called runtime polymorphism.

Similarly, at compile time variable access is also treated from the reference type but as we discussed variables do not follow overriding or runtime polymorphism, so they are not replaced by child class variables at the runtime and still refer to the reference type.


Generally speaking, nobody will ever recommend hiding fields as it makes code difficult to read and creates confusion. This kind of confusion will not there if we always stick to General Guidelines to create POJOs and encapsulate our fields by declaring them as private and provides getters/setters as required so the variables are not visible outside that class and child class cannot access them.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In a previous article Introduction to Spring, we discussed What is Spring and why it so popular among Java developers and we also discussed how Spring has broken its complete framework into different-different modules based on the functionality.

Spring framework is organized into 20 modules which can again be grouped into Core Container, Web, Data Access/Integration, AOP, Aspect, Instrumentation, Messaging, and Test, as shown in the following diagram.
 spring-modules

Core container

The Core and Beans modules provide the most fundamental parts of the framework and provide the IoC and Dependency Injection features. The basic concept here is the BeanFactorywhich provides a sophisticated implementation of the factory pattern. It removes the need for programmatic singletons and allows you to decouple the configuration and specification of dependencies from your actual program logic.

The Context module builds on the solid base provided by the Core and Beans modules: it provides a way to access objects in a framework-style manner in a fashion somewhat reminiscent of a JNDI-registry. The Context module inherits its features from the Beans module and adds support for internationalization (I18N) (using for example resource bundles), event-propagation, resource-loading, and the transparent creation of contexts by, for example, a servlet container. The Context module also contains support for some Java EE features like EJB, JMX, and basic remoting support. The ApplicationContext interface is the focal point of the Context module that provides these features.

The Expression Language module provides a powerful expression language for querying and manipulating an object graph at runtime. It can be seen as an extension of the unified expression language (unified EL) as specified in the JSP 2.1 specification. The language supports setting and getting of property values, property assignment, method invocation, accessing the context of arrays, collections, and indexers, logical and arithmetic operators, named variables, and retrieval of objects by name from Spring's IoC container. It also supports list projection and selection, as well as common list aggregators.

Spring Web module

Spring's Web module provides basic web-oriented integration features, such as multipart file-upload functionality, the initialization of the IoC container using servlet listeners and a web-oriented application context. It also contains the web-related parts of Spring's remoting support.

The Web-Servlet module provides Spring's Model-View-Controller implementation for web-applications. Spring MVC framework is a full-featured MVC implementation for building Web applications. The MVC framework is highly configurable via strategy interfaces and accommodates numerous view technologies including JSP, Velocity, Tiles, iText, and POI. We can also create Rest APIs using the same annotation as we use in web MVC.

The Web-Portlet module provides the MVC implementation to be used in a portlet environment and mirrors what is provided in the Web-Servlet module.

Data Access & Integration

The Data Access/Integration layer consists of the JDBC, ORM, OXM, JMS and Transaction modules.

The JDBC module provides a JDBC-abstraction layer that removes the need to do tedious JDBC coding and parsing of database-vendor specific error codes.

The ORM module provides integration layers for popular object-relational mapping APIs, including JPA, JDO, Hibernate, and iBatis. Using the ORM package you can use all those O/R-mappers in combination with all the other features Spring offers, such as the simple declarative transaction management feature mentioned previously.

The OXM module provides an abstraction layer for using a number of Object/XML mapping implementations. Supported technologies include JAXB, Castor, XMLBeans, JiBX, and XStream.

The JMS module provides Spring's support for the Java Messaging Service. It contains features for both producing and consuming messages.

The Transaction module provides a way to do programmatic as well as declarative transaction management, not only for classes implementing special interfaces but for all your POJOs (plain old Java objects).

Spring AOP and Aspect

The Spring AOP module integrates Aspect Oriented Programming functionality directly into the Spring framework, which allows us to define segregate our cross-cutting functionalities from our business logic. As a result, we can easily AOP-enable any object managed by the Spring framework. The Spring AOP module provides transaction management services for objects in any Spring-based application.

There is also a separate Aspects module that provides integration with AspectJ.

Instrumentation

The Instrumentation module provides class instrumentation support and classloader implementations to be used in certain application servers.

Messaging

Spring framework's messaging module serves as a foundation for messaging-based applications. The module provides a set of classes e.g., Message, MessageChannelMessageHandler to send and receive messages from the application and it also provides a set of annotations for mapping messages to methods, similar to the Spring MVC annotation based programming model.

Test

Spring framework's Test module provides abstraction over a lot of testing and mocking framework such as TestNG, JUnit, Mockito, PowerMock which makes writing unit and integration a lot easier.

Below are the dependencies for the above modules

GroupId
ArtifactId
Description
org.springframework
spring-aop
Proxy-based AOP support
org.springframework
spring-aspects
AspectJ based aspects
org.springframework
spring-beans
Beans support, including Groovy
org.springframework
spring-context
Application context runtime, including scheduling and remoting abstractions
org.springframework
spring-context-support
Support classes for integrating common third-party libraries into a Spring application context
org.springframework
spring-core
Core utilities, used by many other Spring modules
org.springframework
spring-expression
Spring Expression Language (SpEL)
org.springframework
spring-instrument
Instrumentation agent for JVM bootstrapping
org.springframework
spring-instrument-tomcat
Instrumentation agent for Tomcat
org.springframework
spring-jdbc
JDBC support package, including DataSource setup and JDBC access support
org.springframework
spring-jms
JMS support package, including helper classes to send/receive JMS messages
org.springframework
spring-messaging
Support for messaging architectures and protocols
org.springframework
spring-orm
Object/Relational Mapping, including JPA and Hibernate support
org.springframework
spring-oxm
Object/XML Mapping
org.springframework
spring-test
Support for unit testing and integration testing Spring components
org.springframework
spring-tx
Transaction infrastructure, including DAO support and JCA integration
org.springframework
spring-web
Foundational web support, including web client and web-based remoting
org.springframework
spring-webmvc
HTTP-based Model-View-Controller and REST endpoints for Servlet stacks
org.springframework
spring-webmvc-portlet
MVC implementation to be used in a Portlet environment
org.springframework
spring-websocket
WebSocket and SockJS infrastructure, including STOMP messaging support
In order to create an object, we need to define a class that's why the class is called the blueprint of the object and an immutable class is a class which we can use to create immutable objects.

What is an immutable object

An object is called immutable if its state cannot be modified by anyone in any way after its construction, here object's state means the fields or the variables it is holding.

An immutable object does not expose its state to the outer world and neither provides any behaviour to modify its state. All wrapper classes i.e IntegerFloatLong are immutable in nature and other examples of immutable classes are String, java.util.UUID, java.net.URL.

Advantages of immutable objects

In Why String is Immutable and Final in Java, I have discussed how just by being immutable in nature, String gains lots of advantages including
  1. Thread Safety, 
  2. Hash-code caching,
  3. Object pool,
  4. Security.
Same advantages are applied to other immutable objects as well.

How to create a class for an immutable object

To create an immutable object we need to define our class in a way that it restricts every one (including itself) from changing the state of the object after its construction, and in order to do so we need to
  1. Mark your class final,
  2. Mark all the fields private,
  3. Mark all fields final as well,
  4. Provide an argument constructor with all initialization logic,
  5. Initialize all mutable fields by deep copying,
  6. Do not provide setters for your fields,
  7. Return a deep copy of mutable fields from the getters.
How-to-Create-an-Immutable-Class-in-Java-with-Example

Let's look at all these rules and the reasons to follow them

1. Why mark our class final

We should declare our class final to forbids its extension so no one can extend our class and destroy its immutability. If it is not final then in future someone might extend it and modify the behaviour to change the state.

2. Why mark all the fields private

We should mark all the fields private so no one can access them outside of the class.

3. Why mark all fields final as well

Mark all the fields final so even we will not be able to change the fields outside of the constructor.

4. Why provide an argument constructor with all initialization logic

A constructor is a place to write our object initialization logic because constructor gets called whenever we create an object.

So when we want to set our object's state during object creation only, we need to set it in the constructor and that's why we need to have an argument constructor in case of an immutable class.

As discussed in 5 different ways to create objects and creating objects through reflection, serialization and cloning also create new objects but both of them does not include a constructor call. But we do not need to worry about it because in both ways object will be constructed from an already present object which will be already immutable in nature.

5. Why initialize all mutable fields by deep copying

If our immutable object holds a reference to other immutable objects i.e. String, Integer we do not need to worry because we know they will not allow any change in their state.

But if our object holds references to some mutable objects and those mutable objects are also getting referred from somewhere else, in that case, our object's immutability is in danger.

In our example, our ImmutableEmployee class holds a reference to Date class which is mutable in nature. In below lines of code we are creating a variable dob which is holding a Date object and then we are passing it to ImmutableEmployee's constructor and creating an object which is being referred from employee.

Date dob = new Date();
ImmutableEmployee employee = new ImmutableEmployee(1, "Naresh", dob);

When we SysOut employee object we will get

ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993}

Now if we do not initialize dob fields by deep copying then both dob and employee.dob will point to a single object and if we change anything in dob, employee.dob will also reflect that change which means employee object will become mutable.

But by deep copying dob field both employee.dob and dob will point to two different objects and we will not face this problem, as you can see output of below code

dob.setMonth(1);
System.out.println(dob); // Prints - Wed Feb 10 00:12:00 IST 1993

System.out.println(employee.getDob()); // Prints - Sun Jan 10 00:12:00 IST 1993
System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993}

In our example, I have used the copy constructor this.dob = new Date(dob.getTime()); to copy our objects because there are some basic problems with Java cloning and we can not sure of either it is a deep copy or shallow copy without seeing cloning code of that class.

You can read more about cloning, cloning types and why copy constructors are better than on more detailed articles such as Java Cloning And Types Of Cloning (Shallow and Deep), Java Cloning - Copy Constructor Versus Cloning and Java Cloning - Even Copy Constructors Are Not Sufficient.

6. Why should not provide setters for your fields

Well, providing setters will allow us to modify the state of the object which we do not want.

7. Why return a deep copy of mutable fields instead of returning objects from the getters.

If we return all mutable fields directly, we will face the same scenario as discussed in point 5 and after executing below code both employee.dob and temp will point to the same object, now if we make any change in temp, employee.dob will also change which again means employee will not remain immutable.

So instead of returning mutable fields, we should return their deep copy and as we have done that, we can see in below code employee remains same and immutable at the end.

Date temp = employee.getDob();
temp.setMonth(2);
System.out.println(temp); // Prints - Wed Mar 10 00:12:00 IST 1993

System.out.println(employee.getDob()); // Prints - Sun Jan 10 00:12:00 IST 1993
System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993}

In the end, I wanted to say that all immutable objects in Java are effective immutable not completely immutable because we can modify them using reflection.

Below is the complete source code to create an immutable class which you can also find on this Github Repository and please feel free to provide your valuable feedback.

// 1. Declare your class as final, So other classes can't extend it and break its immutability
final class ImmutableEmployee {

    // 2. Make all your fields private they can't be accessed outside your class
    // 3. Mark them as final so no one can modify them anywhere else apart from the constructor, if you do not have any specific requirement to not do so
    private final int id;
    private final String name;
    private final Date dob;

    // 4. Create an constructor with argument so you can assign instantiate your object with a proper state
    public ImmutableEmployee(int id, String name, Date dob) {
        this.id = id;
        this.name = name;
        // 5. Initialise all your fields by deeply copying them if they are not immutable in nature
        this.dob = new Date(dob.getTime());
    }

    // 6. Do not provide setters for your fields, or define them private if you have some requirement
    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    // 7. Instead of returning objects from the getters return deep copy them if your objects are not immutable
    public Date getDob() {
        return new Date(dob.getTime());
    }

    @Override
    public String toString() {
        return "ImmutableEmployee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", dob=" + dob +
                '}';
    }

}

public class ImmutableClassExample {

    public static void main(String[] args) throws ParseException {
        Date dob = new SimpleDateFormat("dd-mm-yyyy").parse("10-12-1993");
        ImmutableEmployee employee = new ImmutableEmployee(1, "Naresh", dob);

        System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993}

        dob.setMonth(1);
        System.out.println(dob); // Prints - Wed Feb 10 00:12:00 IST 1993

        Date temp = employee.getDob();
        temp.setMonth(2);
        System.out.println(temp); // Prints - Wed Mar 10 00:12:00 IST 1993

        System.out.println(employee.getDob()); // Prints - Sun Jan 10 00:12:00 IST 1993
        System.out.println(employee); // Prints - ImmutableEmployee{id=1, name='Naresh', dob=Sun Jan 10 00:12:00 IST 1993}
    }
}


While coding in any programming language we always require some predefined types which we can use to write the code and every programming language provides these types in its way e.g. Java provides primitive types (int, long, char float etc) and reference types (custom types like Object, String, Thread).

For string manipulation, Java provides a class java.lang.String which gives us a way to create string objects and provides different behaviors to operate on those objects e.g. replace(), length()


String name = "Naresh";
System.out.print(name.length());
System.out.print(name.isEmpty());

Whenever we talk about String class in Java we say it is immutable in nature and all string literals are stored in String Constant Pool (SCP).

Prior to Java 7 String Constant Pool belongs to Permanent Generation area of heap which means Garbage Collector will not touch it in normal scenarios. But from Java 7 onwards string constant pool is not part of Perm Gen but live with out in heap which means now unused String objects will get garbage collected.

And in order to become a good developer, we should always know why these kinds of design decisions were taken. I mean, we should know why String is immutable or why string objects stored in SCP.

In Why String is Stored in String Constant Pool article, I have discussed why string objects are stored in a separate memory area called constant pool and in this article, I will discuss why String class was made immutable.

String is Effective Immutable not Completely Immutable

In normal scenarios, String objects are immutable and can't be modified but we can modify them by using Java reflection API. Every string object holds a char[] array as a private variable which actually holds every character from our string.

why-string-is-immutable-and-final-in-java

Due to the private nature of the char[] array, we cannot access it from outside of string object and none of the string methods modifies it.

But we can access this char[] array via reflection and then modify it, And that's why instead of calling String immutable we can call it Effective Immutable.

String string = "Naresh";

Class<String> type = String.class;
Field field = type.getDeclaredField("value");
field.setAccessible(true);

char[] value = (char[]) field.get(string);
value[0] = 'M'; // No `string` variable becomes `Maresh`


Why String is Final

As discussed in How to Create an Immutable Class in Java, in order to make a class immutable we need to make sure no one extends our class and destroy its immutability.

So String is made final to not allow others to extend it and destroy its immutability.

Why String is Immutable

However we can not be sure of what was Java designers actually thinking while designing String but we can only conclude these reasons based on the advantages we get out of string immutability, Some of which are as follows.

1. The existence of String Constant Pool

As discussed in Why String is Stored in String Constant Pool, In order provide a business functionality, every application creates too many string objects and in order to save JVM from first creating lots of string objects and then garbage collecting them. JVM stores all string objects in a separate memory area called String constant pool and reuses objects from that cached pool.

Whenever we create a string literal JVM first sees if that literal is already present in constant pool or not and if it is there, the new variable will start pointing to the same object in SCP this process is called String Interning.

String a = "Naresh";
String b = "Naresh";
String c = "Naresh";

In above example string object with value Naresh will get created in SCP only once and all variables a, b, c will point to the same object but what if we try to make change in a e.g. a.replace("a", "").

Ideally a should have value Nresh but b, c should remain unchanged because as the end user we are making change in a only. And as a developer we know a, b, c all are pointing the same object so if we make a change in a, others should also reflect the change.

string-constant-pool-in-java

But String's immutability saves us from this scenario and due to which object Naresh will never change. So when we make any change in a, JVM will create a new object assign it to a, and then make the change to that object instead of changing object Naresh.

So having a string pool is only possible because of String's immutability and if String would not have been immutable, then caching string objects and reusing them would not have been a possibility because any variable would have changed the value and corrupted others.

2. Thread Safety

An object is called thread-safe when multiple threads are operating on it but none of them is able to corrupt its state and object holds the same state for every thread at any point in time.

As we know an immutable object cannot be modified by anyone after its creation which makes every immutable object thread safe by default. We do not need to apply any thread safety measures to it such as creating synchronized methods.

So due to its immutable nature string object can be shared by multiple threads and even if it is getting manipulated by many threads it will not change its value.

3. Security

In every application, we need to pass several secrets e.g. user's user-name\passwords, connection URLs and in general, all of this information is passed as string objects.

Now suppose if String would not have been immutable in nature then it could cause serious security threats to the application because these values will be allowed to get changed and if it is allowed then these might get changed due to wrongly written code or by any other person who has access to our variable references.

4. Class Loading

As discussed in Creating objects through Reflection in Java with Example, we can use Class.forName("class_name") method to load a class in memory which again calls other methods to do so and even JVM uses these methods to load classes.

But if you see clearly all of these methods accepts the class name as a string object so Strings are used in java class loading and String's immutability makes sure that correct class is getting loaded by ClassLoader.

Suppose if String would not have been immutable and we are trying to load java.lang.Object which get changed to org.theft.OurObject in between and now all of our objects have a behavior which someone can use to do unwanted things.

5. HashCode Caching

If we are going to perform any hashing related operations on our object we must override the hashCode() method and try to generate an accurate hashcode by using the state of the object. If object's state is getting changed which means its hashcode should also change.

Because String is immutable so the value one string object is holding will never get changed which means its hashcode will also not change which gives String class an opportunity to cache its hashcode during object creation.

Yes, String object caches its hashcode at the time of object creation which makes it a great candidate for hashing related operations because hashcode doesn't need to be calculated again and again which save us some time and this is why String is the most suitable candidate to be used as HashMap keys.

Disadvantages of String Immutability


There are always two sides to a coin, whenever something is providing us some benefits it will also a have some drawbacks and String's immutability also falls into it.

1. PermGen Space Error

Due to the immutability of String, string object can't be changed and whenever we make a change on it, JVM creates a new string object. So if there are 10000 string object in an application and every string object is getting manipulated 10 times then we are left with 110000 string objects.

And as we know strings are stored in a separate constant pool which is part of Permanent Generation, which usually occupies very limited memory as compared to young and old generations. Having too many String literals will quickly fill this space, resulting in java.lang.OutOfMemoryError: PermGen Space error.

2. Keeping passwords in memory for a long time

In general, passwords are stored as strings and strings are stored in the constant pool which is exempted from normal garbage collection cycles. So our password might remain in memory for very long time and someone can take advantage of it.

This is the reason standards suggest to hold password in an char[] array instead of the string object.

3. String is not extensible

Making String final is part of making it immutable but it also becomes a disadvantage because it limits its extensibility and we cannot extend String to provide more functionality.

For some developers, it becomes a problem when they require some extra behavior for their string objects but it's not a disadvantage and it can be tacked by creating a utility method which accepts the string as a parameter.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.


In a previous article Why String is Immutable and Final in Java, I have discussed why String is immutable in nature and advantages and disadvantages String's immutability gives us.

I have also discussed that, all String literals are cached into a special memory area called String Constant Pool and how String's immutability made String constant pool possible.

But the question arises why do Java required a separate constant pool to store Strings, What's the reason, Why strings are not stored in the normal heap memory like other objects do and in this article, I will try to answer these questions.

String Interning

Well, we know String is the most popular type present in Java and almost all Java programs use it. In fact, I have not seen a single Java program which is written without using String.

In general, a normal Java business application deals with thousands of string objects, lots of them have the same value associated and lots of them are mid operations string means they are not the final result.

So if we store all those string objects in normal heap memory, lot's of the heap will be acquired by just string objects only, and the garbage collector will have to run more frequently which will decrease the performance of the application.

And that's why we have String Constant Pool and String interning process, whenever we create a string literal JVM first sees if that literal is already present in the constant pool or not and if it is there, the new variable will start pointing to the same object, this process is called String Interning.

There are two ways to create a String object
  1. Creating String Literal:: Anything which comes under "" is a string literal e.g. String s1 = "Naresh", by default all string literals interned and goes to SCP.
  1. Creating a String object using constructor: If we create a String object using the constructor e.g. String s2 = new String("Naresh"), the object is created in normal heap memory instead of SCP. And that's why creating String object using constructor is not considered a best practice. We can ask s2 to point to SCP instead of normal heap manually by calling intern() method on it i.e. s2.intern().
So in order to save memory consumed by string objects, Java allows more than one reference variable to point to the same object if they have the same value. That's why JVM creators have created a separate memory area SCP for string literals and made a rule that if more than one string variable holding same value than they will point to the same object.

String a = "Naresh";
String b = "Naresh";
String c = "Naresh";

For above code there will be only one object Naresh will be created and all reference variables a, b, c will point to the same object.

In above example string object with value Naresh will get created in SCP only once and all reference a, b, c will point to same object but what if we try to make a change in a e.g. a.replace("a", "").

Ideally, a should have value Nresh but b, c should remain unchanged because as an end user we are making the change in a only. And we know a, b, c all are pointing the same object so if we make a change in a, others should also reflect the change.

string-constant-pool-in-java

But string immutability saves us from this scenario and due to the immutability of string object string object Naresh will never change. So when we make any change in a instead of change in string object Naresh JVM creates a new object assign it to a and then make the change in that object.

So String pool is only possible because of String's immutability and if String would not have been immutable, then caching string objects and reusing them would not have a possibility because any variable would have changed the value and corrupted others.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.

Java allows us to declare a variable whenever we need it, We can categorize all our variables into 3 categories which have different-different scopes
  1. Instance Variables - are defined inside a class and have object level scope.
  2. Class Variables - are defined inside a class with static keyword, these variables have a class level scope and are common to all objects of the same class
  3. Local Variables - are defined inside a method or in any conditional block, have the block-level scope and only accessible in the block where it defined.
what-is-variable-hiding-shadowing

What is Variable Shadowing

Variable shadowing happens when we define a variable in a closure scope with a variable name and we have already defined a variable in outer scope with the same name.

In other words, when a local variable has the same name as one of the instance variable, the local variable shadows the instance variable inside the method block.

In the following example, there is an instance variable named x and inside method printLocalVariable(), we are shadowing it by the local variable x.

class Parent {

    // Declaring instance variable by name `x`
    String x = "Parent`s Instance Variable";

    public void printInstanceVariable() {
        System.out.println(x);
    }

    public void printLocalVariable() {
        // Shadowing instance variable `x` by a local variable with same name
        String x = "Local Variable";
        System.out.println(x);

        // If we still want to access instance variable, we do that by using `this.x`
        System.out.println(this.x);
    }
}

What is variable Hiding

Variable Hiding happens when we define a variable in child class with a variable name which we have already used to define a variable in the parent class. A child class can declare a variable with the same name as an inherited variable from its parent class, thus hiding the inherited variable.

In other words, when the child and parent class both have a variable with same name child class's variable hides parent class's variable.

In the below example, we are hiding the variable named x in the child class while it is already defined by its parent class.

class Child extends Parent {

    // Hiding Parent class's variable `x` by defining a variable in child class with same name.
    String x = "Child`s Instance Variable";

    @Override
    public void printInstanceVariable() {
        System.out.print(x);

        // If we still want to access variable from super class, we do that by using `super.x`
        System.out.print(", " + super.x + "\n");
    }
}

Variable Hiding is not the same as Method Overriding

While variable hiding looks like overriding a variable similar to method overriding but it is not, Overriding is applicable only to methods while hiding is applicable variables.

In the case of method overriding, overridden methods completely replaces the inherited methods so when we try to access the method from parent's reference by holding child's object, the method from child class gets called. You can read more about overriding on Everything About Method Overloading Vs Method Overriding, Why We Should Follow Method Overriding Rules, How Does JVM Handle Method Overloading and Overriding Internally.

But in variable hiding child class hides the inherited variables instead of replacing, so when we try to access the variable from parent's reference by holding child's object, it will be accessed from the parent class.

When an instance variable in a subclass has the same name as an instance variable in a super class, then the instance variable is chosen from the reference type.

public static void main(String[] args) throws Exception {

    Parent parent = new Parent();
    parent.printInstanceVariable(); // Output - "Parent`s Instance Variable"
    System.out.println(parent.x); // Output - "Parent`s Instance Variable"

    Child child = new Child();
    child.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
    System.out.println(child.x);// Output - "Child`s Instance Variable"

    parent = child; // Or parent = new Child();
    parent.printInstanceVariable();// Output - "Child`s Instance Variable, Parent`s Instance Variable"
    System.out.println(parent.x);// Output - Parent`s Instance Variable

    // Accessing child's variable from parent's reference by type casting
    System.out.println(((Child) parent).x);// Output - "Child`s Instance Variable"
}

In above example when we call overridden method printInstanceVariable() on parent while holding Child's object in it we can see the output is Child`s Instance Variable, Parent`s Instance Variable because in child class method is printing Child class's x variable and super.x.

But when we call System.out.println(parent.variable); on same parent reference which is holding child's object, it prints Parents Instance Variable because new Child() object keeps parent's x as well as child's x and hides parent's x. So, in this case, x is chosen from the class that is the reference type.

But if we wanted to access child's variable even if we are using parent reference we can do that by using (Child) parent).variable.

When our variables are private or is in another package and has default access, such variables are not visible outside that class and child class cannot access them. So there no confusion and that is why we should always stick to General Guidelines to create POJOs and declare our variables with private access and also provide proper get/set methods to access them.

Do you want to know more about variable hiding?, In the article Why Instance Variable Of Super Class Is Not Overridden In Sub Class,  I have discussed why variables do not follow overriding, why variable hiding is not designed same as method overriding and why instance variable is chosen from reference type instead of the object? Please go ahead and read it.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.

Next Post Newer Posts Previous Post Older Posts Home