Some time back I have written one article Java Lambda Expression Explained with Example but it was easy for me to explore and Java 8 because I was using it in my project and I was allowed to install and use it. But in my current project, we are still using Java 8 and now I want to upgrade myself and learn Java 11 but can not install it.

And this happens with a lot of Java developers, Sometimes you want to learn and explore latest version of Java e.g. Java 11 but you can not install it on your machine because you and your team is working on some older version e.g. Java 8, and you do not want to break your project.

Or suppose you are working on multiple projects some of which use Java 8 and some new projects are using Java 11. So in order to work on these projects parallelly, you will need to install multiple JDK on your machine and you should be able to switch between them.

What if there is a way and what if you are enabled to install multiple versions of Java and turn off and turn on them according to your need.

Well there is a tool called SDKMan which allow us to do the same and according to the official website:

SDKMan! is a tool for managing parallel versions of multiple Software Development Kits on most Unix based systems. It provides a convenient Command Line Interface (CLI) and API for installing, switching, removing and listing Candidates.

Some points about SDKMan are as following:
  1. SDKMan is free to use and it is developed by the open source community.
  2. SDKMan is written in bash and it only requires curl and zip/unzip programs to be present on your system.
  3. SDKMan can install around 29 Software Development Kits for the JVM such as Java, Groovy, Scala, Kotlin and Ceylon. Ant, Gradle, Grails, Maven, SBT, Spark, Spring Boot, Vert.x.
  4. We do not need to worry about setting the _HOME and PATH environment variables because SDKMan handles it automatically.

Installing SDKMan

SDKMan can run on any UNIX based platforms such as Mac OSX, Linux, Cygwin, Solaris and FreeBSD and we can install it using following commands:

Simply open a new terminal and enter:

$ curl -s "" | bash
$ source "$HOME/.sdkman/bin/"

We can verify the installation using sdk version and sdk help command will us complete help about the usage of sdk command.

Because SDKMan is written in bash and only requires curl and zip/unzip to be present on your system. You can install SDKMan on windows as well either by first installing Cygwin or Git Bash for Windows environment and then running above commands.

Installing Java Using SDKMan

SDKMan supports installations of 29 Software Development Kits for the JVM e.g. Java, Groovy, Scala, Kotlin and Ceylon, Grails, SBT, Spark, Spring Boot. We can get the complete list using sdk list command.

SDKMan also helps us install build tools such as Ant, Maven and Gradle, You can read more about these build tools on Java Build Tools Comparisons: Ant vs Maven vs Gradle.

Command sdk list java will give us a list of java versions which we can install using SDKMan like below:

$ sdk list java

Available Java Versions
     13.ea.02-open       1.0.0-rc-10-grl                                        
     12.ea.26-open       1.0.0-rc-9-grl                                         
     11.0.2-zulu         1.0.0-rc-8-grl                                         
+ - local version
* - installed
> - currently in use

Now Suppose we want to install OpenJDK version of Java v9 then we will execute below command in our terminal which will also update the PATH and JAVA_HOME variables:

$ sdk install java 9.0.4-open

The command will take some time to execute because it will be downloading the JDK on our machine and the command will output something like:

Downloading: java 9.0.4-open
In progress...
######################################################################## 100.0%

Repackaging Java 9.0.4-open...

Done repackaging...
Cleaning up residual files...

Installing: java 9.0.4-open
Done installing!

Setting java 9.0.4-open as default.

Now if we check our Java version and JAVA_HOME, we can see Java has been updated to 9.0.4

$ java -version
openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+11)
OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)

$ echo $JAVA_HOME

We can follow the same process to install any version which we can see in the above list, let us suppose we want to install Java V11 version then we can execute the command:

$ sdk install java 11.0.2-open
Downloading: java 11.0.2-open
In progress...
######################################################################## 100.0%

Repackaging Java 11.0.2-open...

Done repackaging...
Cleaning up residual files...

Installing: java 11.0.2-open
Done installing!

Do you want java 11.0.2-open to be set as default? (Y/n): Y

Setting java 11.0.2-open as default.

Now if we again check our Java version and JAVA_HOME, we can see Java has been updated to 11.0.2:

$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

$ echo $JAVA_HOME

Note: Some times you will require to close and reopen your terminal in order to see the changes.


Pointing SDKMan to your existing installed Java version

First, we need to find out where on your machine Java is installed. On my machine, it is installed in the folder jdk1.8.0_172.jdk which lies under the folder /Library/Java/JavaVirtualMachines, let's refer to this folder by <java-folder>.

The second thing we want to do is to set up a symbolic link between our installed <java-folder> and SDKMan, we can do it by running below commands:

$ ln -s /Library/Java/JavaVirtualMachines/<java-folder>  ~/.sdkman/candidates/java/<java-folder>

$ sudo ln -s /Library/Java/JavaVirtualMachines/<java-folder>/Contents/Home/bin  ~/.sdkman/candidates/java/<java-folder>/bin

Now if we again execute sdk list java command, we will get:

Available Java Versions
   + jdk1.8.0_172.jd     8.0.201-zulu                                           
     13.ea.02-open       8.0.201-oracle                                         
     12.ea.26-open       8.0.192-zulufx                                         
     11.0.2-zulu         7.0.181-zulu                                           
 > * 11.0.2-open         1.0.0-rc-12-grl                                        
     11.0.2.j9-adpt      1.0.0-rc-11-grl                                        
     11.0.2.hs-adpt      1.0.0-rc-10-grl                                        
     11.0.1-zulufx       1.0.0-rc-9-grl                                         
     10.0.2-zulu         1.0.0-rc-8-grl                                         
   * 9.0.4-open                                                                 

+ - local version
* - installed
> - currently in use

We can clearly see that we have 3 JDK installed on our machine and JDK 11.0.2-open is in use as of now. However, if we want to switch between them or install a new one we can do that very easily by using sdk use java <version_which_you_want_to_use> like the following:

Using Java 9

$ sdk use java 9.0.4-open
Using java version 9.0.4-open in this shell.

$ java -version
openjdk version "9.0.4"
OpenJDK Runtime Environment (build 9.0.4+11)
OpenJDK 64-Bit Server VM (build 9.0.4+11, mixed mode)

Using locally installed Java 8

$ sdk use java jdk1.8.0_172.jdk
Using java version jdk1.8.0_172.jdk in this shell.

$ java -version
java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)

Using Java 11

$ sdk use java 11.0.2-open
Using java version 11.0.2-open in this shell.

$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

Using sdk use command will only enable you to use a specified version of JDK in the same terminal shell where you are executing the sdk use command. And if you close the terminal and open it again you will be on the previously installed version.

But if you want to activate one version of JDK for all terminals and applications, you can use the command sdk default java <your_version>

$ sdk default java 11.0.2-open
Default java version set to 11.0.2-open

$ java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)

Or you can uninstall that version and install it again like below which will set that version to the current JDK.

Uninstalling a JDK Version

In case you want to uninstall any JDK version e.g., 11.0.2-open you can do that as follows:

$ sdk uninstall java 11.0.2-open

And in case you want to install the uninstalled version back again, you can install it again and this time SDKMan will not download it because it already has that on your machine (unless you do not delete that manually).

$ sdk install java 11.0.2-open

Found a previously downloaded java 11.0.2-open archive. Not downloading it again...

Installing: java 11.0.2-open
Done installing!

Do you want java 11.0.2-open to be set as default? (Y/n): y

Setting java 11.0.2-open as default.

Using SDMan installed JDK from IntelliJ IDEA

SDKMan installs all JDK under .sdkman/candidates/java/ folder and you can find .sdkman folder in your home directory.

After opening any Java project in IntelliJ, you can press Command + : to open the project structure window. In that window you will need to click on New... under Project SDK section and there you can enter .sdkman/candidates/java/ in browse window and can select any JDK from .sdkman/candidates/java/.

Because .sdkman is a hidden folder and in case you face some problem in finding it, you can always create a symbolic link to it with a non-hidden folder using below command.

$ ln -s ~/.sdkman ~/sdkman

You can find the complete source code for my articles on this Github Repository and please feel free to provide your valuable feedback.

Git is a most widely used and powerful version control system for tracking changes in computer files and coordinating work on those files among multiple people. It is primarily used for source code management in software development, but it can be used to keep track of changes in any set of files.

Git was developed by Linus Torvalds in 2005 as an distributed open source software version control software and of course it is free to use. As a distributed revision control system it is aimed at speed, data integrity, and support for distributed, non-linear work flows.

While other version control systems e.g. CVS, SVN keeps most of their data like commit logs on central server, every git repository on every computer is a full-fledged repository with complete history and full version tracking abilities, independent of network access or a central server.

However almost all IDEs support git out of the box and we do not require submit the git commands manually but it is always good to understand these commands. Below is a list of some git commands to work efficiently with git.

Git Help

The most useful command in git is git help which provides us all the help we require. If we type git help in terminal, we will get:
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add        Add file contents to the index
   mv         Move or rename a file, a directory, or a symlink
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect     Use binary search to find the commit that introduced a bug
   grep       Print lines matching a pattern
   log        Show commit logs
   show       Show various types of objects
   status     Show the working tree status

grow, mark and tweak your common history
   branch     List, create, or delete branches
   checkout   Switch branches or restore working tree files
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   merge      Join two or more development histories together
   rebase     Reapply commits on top of another base tip
   tag        Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch      Download objects and refs from another repository
   pull       Fetch from and integrate with another repository or a local branch
   push       Update remote refs along with associated objects

'git help -a' and 'git help -g' list available sub-commands and some concept guides.
See 'git help <command>' or 'git help <concept>' to read about a specific sub-command or concept.

Command git help -a will give us complete list of git commands:
Available git commands in '/usr/local/git/libexec/git-core'
  add                     gc                      receive-pack
  add--interactive        get-tar-commit-id       reflog
  am                      grep                    remote
  annotate                gui                     remote-ext
  apply                   gui--askpass            remote-fd
  archimport              gui--askyesno           remote-ftp
  archive                 gui.tcl                 remote-ftps
  askpass                 hash-object             remote-http
  bisect                  help                    remote-https
  bisect--helper          http-backend            repack
  blame                   http-fetch              replace
  branch                  http-push               request-pull
  bundle                  imap-send               rerere
  cat-file                index-pack              reset
  check-attr              init                    rev-list
  check-ignore            init-db                 rev-parse
  check-mailmap           instaweb                revert
  check-ref-format        interpret-trailers      rm
  checkout                log                     send-email
  checkout-index          ls-files                send-pack
  cherry                  ls-remote               sh-i18n--envsubst
  cherry-pick             ls-tree                 shortlog
  citool                  mailinfo                show
  clean                   mailsplit               show-branch
  clone                   merge                   show-index
  column                  merge-base              show-ref
  commit                  merge-file              stage
  commit-tree             merge-index             stash
  config                  merge-octopus           status
  count-objects           merge-one-file          stripspace
  credential              merge-ours              submodule
  credential-manager      merge-recursive         submodule--helper
  credential-store        merge-resolve           subtree
  credential-wincred      merge-subtree           svn
  cvsexportcommit         merge-tree              symbolic-ref
  cvsimport               mergetool               tag
  daemon                  mktag                   unpack-file
  describe                mktree                  unpack-objects
  diff                    mv                      update
  diff-files              name-rev                update-git-for-windows
  diff-index              notes                   update-index
  diff-tree               p4                      update-ref
  difftool                pack-objects            update-server-info
  difftool--helper        pack-redundant          upload-archive
  fast-export             pack-refs               upload-pack
  fast-import             patch-id                var
  fetch                   prune                   verify-commit
  fetch-pack              prune-packed            verify-pack
  filter-branch           pull                    verify-tag
  fmt-merge-msg           push                    web--browse
  for-each-ref            quiltimport             whatchanged
  format-patch            read-tree               worktree
  fsck                    rebase                  write-tree
  fsck-objects            rebase--helper

And command git help -g will give us a list git concepts which git think is good for us:
The common Git guides are:

   attributes   Defining attributes per path
   everyday     Everyday Git With 20 Commands Or So
   glossary     A Git glossary
   ignore       Specifies intentionally untracked files to ignore
   modules      Defining submodule properties
   revisions    Specifying revisions and ranges for Git
   tutorial     A tutorial introduction to Git (for version 1.5.1 or newer)
   workflows    An overview of recommended workflows with Git

We can use git help <command> or git help <concept> command to know more about about a specific command or concept.

Git Configuration

DescriptionGit Command
Configure the author name to be used with your commits.git config --global "Sam Smith"
Configure the author email address to be used with your commitsgit config --global
Will remove user credential details from the repositorygit config --local credential.helper ""
List all currently configured remote repository URLsgit remote -v
If you haven't connected your local repository to a remote server, To add a remote server to a local repositorygit remote add origin <repo_url>

Git Commit and Push

DescriptionGit Command
Create a file name with Readme content contentecho "Readme content" >>
List the files you've changed and those you still need to add or commitgit status
Add all or one file to staginggit add . OR git add file_name
Commit changes to head with messagegit commit -m 'message'
Commit any files you've added with git add, and also commit any files you've changed since thengit commit -a
Send all commits from local repository to remote repositorygit push
Do a git push and sets the default remote branch for the current local branch. So any future git pull command will attempt to bring in commits from the <remote-branch>into the current local branchgit push -u <remote-branch>
Send changes to the master branch of your remote repositorygit push origin master
Push a specific branch to your remote repositorygit push origin <branch_name>
Push all branches to your remote repositorygit push --all origin

Git Checkout And Pull

DescriptionGit Command
To create a new local repositorygit init
Clone a repository into a new directorygit clone repo_url
Clone a repository into a new directory and point to mentioned branch_namegit clone --branch branch_name repo_url
To create a working copy of a local repositorygit clone /path/to/repository
Download objects and refs from remote repository for master branchgit fetch origin master
To merge a different branch into your active branchgit merge <branch_name>
Fetch and merge changes on the remote server to your working directory:git pull
View all the merge conflicts, View the conflicts against the base file, Preview changes, before merginggit diff, git diff --base <filename>, git diff <sourcebranch> <targetbranch>

Git Branch

DescriptionGit Command
List all the branches in your repository, and also tell you what branch you're currently ingit branch
Switch from one branch to anothergit checkout branch_name
Create a new branch and switch to itgit checkout -b branch_name
Create a new branch from master branch and switch to itgit checkout -b branch_name master
Delete the feature branch from local repositorygit branch -d <branch_name>
Delete a branch on your remote repositorygit push origin :<branch_name>

Git Cleaning

DescriptionGit Command
Fetch the latest history (objects & refs) from the remote server for master branchgit fetch origin master
Clean repository to initial stagegit clean -x -d -f
Reset local repository and point your local master branch to latest history fetched from remote servergit reset --hard origin/master
To bring all changes from remote repository to local repositorygit pull origin master

Other Git commands

DescriptionGit Command
You can use tagging to mark a significant change set, such as a releasegit tag 1.0.0 <commitID>
Commit Id is the leading characters of the change set ID, up to 10, but must be unique. Get the ID usinggit log
Push all tags to remote repositorygit push --tags origin
If you mess up, you can replace the changes in your working tree with the last content in head:Changes already added to the index, as well as new files, will be keptgit checkout -- <filename>
Search the working directory for foo()git grep "foo()"

I keep these commands as notes for my future reference and you can find more on this Github Repository and please feel free to provide your valuable feedback.
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.


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() {

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";

    public void print() {

        // 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 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.

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.


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


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.


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

Proxy-based AOP support
AspectJ based aspects
Beans support, including Groovy
Application context runtime, including scheduling and remoting abstractions
Support classes for integrating common third-party libraries into a Spring application context
Core utilities, used by many other Spring modules
Spring Expression Language (SpEL)
Instrumentation agent for JVM bootstrapping
Instrumentation agent for Tomcat
JDBC support package, including DataSource setup and JDBC access support
JMS support package, including helper classes to send/receive JMS messages
Support for messaging architectures and protocols
Object/Relational Mapping, including JPA and Hibernate support
Object/XML Mapping
Support for unit testing and integration testing Spring components
Transaction infrastructure, including DAO support and JCA integration
Foundational web support, including web client and web-based remoting
HTTP-based Model-View-Controller and REST endpoints for Servlet stacks
MVC implementation to be used in a Portlet environment
WebSocket and SockJS infrastructure, including STOMP messaging support
Previous Post Older Posts Home