Showing posts with label Why in Java. Show all posts
Showing posts with label Why in Java. Show all posts
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.
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.

In my previous articles Why Should We Follow Method Overloading Rules, I discussed about method overloading and rules we need to follow to overload a method. I have also discussed why we need to follow these rules and why some method overloading rules are necessary and others are optional.

In a similar manner in this article, we will see what rules we need to follow to override a method and why we should follow these rules.

Method Overriding and its Rules

As discussed in Everything About Method Overloading Vs Method Overriding, every child class inherits all the inheritable behaviour from its parent class but the child class can also define its own new behaviours or override some of the inherited behaviour.

Overriding means redefining a behaviour (method) again in the child class which was already defined by its parent class but to do so overriding method in the child class must follow certain rules and guidelines.

With respect to the method it overrides, the overriding method must follow following rules.
Why We Should Follow Method Overriding Rules

To understand these reasons properly let's consider below example where we have a class Mammal which defines readAndGet method which is reading some file and returning an instance of class Mammal.

Class Human extends class Mammal and overrides readAndGet method to return instance of Human instead of instance of Mammal.

class Mammal {
    public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}

class Human extends Mammal {
    @Override
    public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}

And we know in case of method overriding we can make polymorphic calls. Which means if we assign a child instance to a parent reference and call an overridden method on that reference eventually the method from child class will get called.

Let's do that

Mammal mammal = new Human();
try {
    Mammal obj = mammal.readAndGet();
} catch (IOException ex) {..}

As discussed in  How Does JVM Handle Method Overloading and Overriding Internally till compilation phase compiler thinks the method is getting called from the parent class. While bytecode generation phase compiler generates a constant pool where it maps every method string literal and class reference to a memory reference

During runtime, JVM creates a vtable or virtual table to identify which method is getting called exactly. JVM creates a vtable for every class and it is common for all the objects of that class. Mammal row in a vtable contains method name and memory reference of that method.

First JVM creates a vtable for the parent class and then copy that parent's vtable to child class's vtable and update just the memory reference for the overloaded method while keeping the same method name.

You can read it more clearly on  How Does JVM Handle Method Overloading and Overriding Internally if it seems hard.
So as of now we are clear that
  • For compiler mammal.readAndGet() means method is getting called from instance of class Mammal
  • For JVM mammal.readAndGet() is getting called from a memory address which vtable is holding for Mammal.readAndGet() which is pointing to a method call from class Human.

Why overriding method must have same name and same argument list

Well conceptually mammal is pointing to an object of class Human and we are calling readAndGet method on mammal, so to get this call resolved at runtime Human should also have a method readAndGet. And if Human have inherited that method from Mammal then there is no problem but if Human is overriding readAndGet, it should provide the same method signature as provided by Mammal because method has been already got called according to that method signature.

But you may be asking how it is handled physically from vtables so I must tell you that, JVM creates a vtable for every class and when it encounters an overriding method it keeps the same method name (Mammal.readAndGet()) while just update the memory address for that method. So both overridden and overriding method must have same method and argument list.

Why overriding method must have same or covariant return type

So we know, for compiler the method is getting called from class Mammal and for JVM call is from the instance of class Human but in both cases, readAndGet method call must return an object which can be assigned to obj. And since obj is of the type Mammal it can either hold an instance of Mammal class or an instance of a child class of Mammal (child of Mammal are covariant to Mammal).

Now suppose if readAndGet method in Human class is returning something else so during compile time mammal.readAndGet() will not create any problem but at runtime, this will cause a ClassCastException because at runtime mammal.readAndGet() will get resolved to new Human().readAndGet() and this call will not return an object of type Mammal.

And this why having a different return type is not allowed by the compiler in the first place.

Why overriding method must not have a more restrictive access modifier

The same logic is applicable here as well, call to readAndGet method will be resolved at runtime and as we can see readAndGet is public in class Mammal, now suppose
  • If we define readAndGet as default or protected in Human but Human is defined in another package
  • If we define readAndGet as private in Human
In both cases code will compile successfully because for compiler readAndGet is getting called from class Mammal but in both cases, JVM will not be able to access readAndGet from Human because it will be restricted.

So to avoid this uncertainty, assigning restrictive access to the overriding method in the child class is not allowed at all.

Why overriding method may have less restrictive access modifier

If readAndGet method is accessible from Mammal and we are able to execute mammal.readAndGet() which means this method is accessible. And we make readAndGet less restrictive Human which means it will be more open to get called.

So making the overriding method less restrictive cannot create any problem in the future and that's it is allowed.

Why overriding method must not throw new or broader checked exceptions

Because IOException is a checked exception compiler will force us to catch it whenever we call readAndGet on mammal

Now suppose readAndGet in Human is throwing any other checked exception e.g. Exception and we know readAndGet will get called from the instance of Human because mammal is holding new Human().

Because for compiler the method is getting called from Mammal, so the compiler will force us to handle only IOException but at runtime we know method will be throwing Exception which is not getting handled and our code will break if the method throws an exception.

That's why it is prevented at the compiler level itself and we are not allowed to throw any new or broader checked exception because it will not be handled by JVM at the end.

Why overriding method may throw narrower checked exceptions or any unchecked exception

But if readAndGet in Human throws any sub-exception of IOException e.g., FileNotFoundException, it will be handled because catch (IOException ex) can handle all child of IOException.

And we know unchecked exception (subclasses of RuntimeException) are called unchecked because we don't need to handle them necessarily.

And that's why overriding methods are allowed to throw narrower checked and other unchecked exceptions.

To force our code to adhere method overriding rules we should always use @Override annotation on our overriding methods, @Override annotation force compiler to check if the method is a valid override or not.

You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
In my previous articles, Everything About Method Overloading Vs Method Overriding and How Does JVM Handle Method Overloading and Overriding Internally, I have discussed what is method overloading and overriding, how both are different than each other, How JVM handles them internally and what rules we should follow in order to implement these concepts.

In order to overload or override a method we need to follow certain rules, some of them are mandatory while others are optional and to become a good programmer we should always try to understand the reason behind these rules.

I am going to write two articles where I will try to look into the method overloading and overriding rules and try to figure out why we need to follow them.

In this article, we will see what rules we should follow to overload a method and we will also try to know why we should follow these rules.

Method Overloading

In general, method overloading means reusing same method name to define more than one method but all methods must have a different argument list.

We can take the example of the print method present in PrintStream class which gets called when we call System.out.print() to print something. By calling this method on several data types it seems like there is just one print method which is accepting all types and printing their values.

But actually, there are 9 different print methods as shown in below image

method-overloading

Well, the PrintStream class creator could have created methods like printBoolean or printInt or printFloat, but the idea behind naming all the 9 methods same is to let the user think that there is only one method which is printing whatever we pass to it.

Which sounds like polymorphism but as discussed in the article How Does JVM Handle Method Overloading and Overriding Internally that how method overloading get resolved at compile time, some people also term method overloading as compile-time polymorphism.

Method Overloading Rules

While defining a method we need to provide it with a proper method signature which includes access specifier, return type, method name, argument list, exceptions method might throw. Based on these five things method overloading has some mandatory rules and some optional rules, which we are going to see below.

Mandatory Rules

  • Overloaded methods must have same method name: Having the same name let us reuse the same method name for different purposes and let the user believe that there is only one method which is accepting different kinds of input and doing the work according to the input.
  • Overloaded methods must have different argument lists: Since all overloaded methods must have the same name, having a different argument list becomes necessary because it is the only way to differentiate the methods from each other. Java compiler differentiates a method from other based on its method name and argument list, So different argument list helps the compiler to differentiate and recognize methods from each other so the compiler will know which method is getting called at compile time only.

Optional Rules

The compiler knows that at the time of method calling JVM needs to know the method name and JVM will pass some arguments to that method so it must also know the argument list. While other method signature elements e.g. return type, access modifier, the exception method throwing also matter but at the time of method call they become optional.

So the different argument list is sufficient for the compiler to differentiate between the methods even if they have the same name so the rules mentioned below are optional and we are free to follow or not follow them. Going with below rules totally depends on your requirements and they are there to just provide us with additional functionality.
  • Overloaded methods can have different return types: Return type matters when the method call is finished and JVM assigning back the value returned by that method call to some variable. But it is not required while calling the method and JVM cannot use it to differentiate between methods based on just return type. So we can either return the same as the overloaded method did or return something different or return nothing.
  • Overloaded methods can have different access modifiers: If a method is getting called by the JVM it means it has passed the compilation phase because executing the bytecode which is already compiled. So access specifier of a method is useful for the compiler but it is useless for JVM and JVM cannot differentiate between methods based on access modifier. So an overloading method can have any access modifier and we can use it according to our need.
  • Overloaded methods can throw different checked or unchecked exceptions: Again what exceptions a method might throw cannot differentiate a method from another method. And also overloaded methods are different from each other but usually, they perform the same operation on different data set and in order to do so overloaded methods may do some different operation as well which may throw a different exception.
You can find complete code on this Github Repository and please feel free to provide your valuable feedback.
This is my third article on Java Cloning series, In previous articles Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example and Java Cloning - Copy Constructor versus Cloning I had discussed Java cloning in detail and explained every concept like what is cloning, how does it work, what are the necessary steps we need to follow to implement cloning, how to use Object.clone(), what is Shallow and Deep cloning, how to achieve cloning using serialization and Copy constructors and advantages copy of copy constructors over Java cloning.

If you have read those articles you can easily understand why it is good to use Copy constructors over cloning or Object.clone(). In this article, I am going to discuss why copy constructors are not sufficient?

Why-Copy-Constructors-Are-Not-Sufficient

Yes, you are reading it right copy constructors are not sufficient by themselves, copy constructors are not polymorphic because constructors do not get inherited to the child class from the parent class. If we try to refer a child object from parent class reference, we will face problems in cloning it using the copy constructor. To understand it let’s take examples of two classes Mammal and Human where Human extends MammalMammal class have one field type and two constructors, one to create the object and one copy constructor to create a copy of an object

class Mammal {

    protected String type;

    public Mammal(String type) {
        this.type = type;
    }

    public Mammal(Mammal original) {
        this.type = original.type;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Mammal mammal = (Mammal) o;

        if (!type.equals(mammal.type)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return type.hashCode();
    }

    @Override
    public String toString() {
        return "Mammal{" + "type='" + type + "'}";
    }
}

And Human class which extends Mammal class, have one name field, one normal constructor and one copy constructor to create a copy

class Human extends Mammal {

    protected String name;

    public Human(String type, String name) {
        super(type);
        this.name = name;
    }

    public Human(Human original) {
        super(original.type);
        this.name = original.name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;

        Human human = (Human) o;

        if (!type.equals(human.type)) return false;
        if (!name.equals(human.name)) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = super.hashCode();
        result = 31 * result + name.hashCode();
        return result;
    }

    @Override
    public String toString() {
        return "Human{" + "type='" + type + "', name='" + name + "'}";
    }
}

Here in both copy constructors we are doing deep cloning.

Now let’s create objects for both classes

Mammal mammal = new Mammal("Human");
Human human = new Human("Human", "Naresh");

Now if we want to create a clone for mammal or human, we can simply do it by calling their respective copy constructor

Mammal clonedMammal = new Mammal(mammal);
Human clonedHuman = new Human(human);

We will get no error in doing this and both objects will be cloned successfully, as we can see below tests

System.out.println(mammal == clonedMammal); // false
System.out.println(mammal.equals(clonedMammal)); // true

System.out.println(human == clonedHuman); // false
System.out.println(human.equals(clonedHuman)); // true

But what if we try to refer object of Human from the reference of Mammal

Mammal mammalHuman = new Human("Human", "Mahesh");

In order to clone mammalHuman, we can not use constructor Human, It will give us compilation error because type mammalHuman is Mammal and constructor of Human class accept Human.

Mammal clonedMammalHuman = new Human(mammalHuman); // compilation error

And if we try clone mammalHuman using copy constructor of Mammal, we will get the object of Mammal instead of Human but mammalHuman holds the object of Human

Mammal clonedMammalHuman = new Mammal(mammalHuman);

So both mammalHuman and clonedMammalHuman are not the same objects as you see in the output below code

System.out.println("Object " + mammalHuman + " and copied object " + clonedMammalHuman + " are == : " + (mammalHuman == clonedMammalHuman));
System.out.println("Object " + mammalHuman + " and copied object " + clonedMammalHuman + " are equal : " + (mammalHuman.equals(clonedMammalHuman)) + "\n");

Output:

Object Human{type='Human', name='Mahesh'} and copied object Mammal{type='Human'} are == : false
Object Human{type='Human', name='Mahesh'} and copied object Mammal{type='Human'} are equal : false

As we can see copy constructors suffer from inheritance problems and they are not polymorphic as well. So how can we solve this problem, Well there various solutions like creating static Factory methods or creating some generic class which will do this for us and the list will go on?

But there is a very easy solution which will require copy constructors and will be polymorphic as well. We can solve this problem using defensive copy methods, a method which we are going to include in our classes and call copy constructor from it and again override it the child class and call its copy constructor from it.

Defensive copy methods will also give us the advantage of dependency injection, we can inject dependency instead of making our code tightly coupled we can make it loosely coupled, we can even create an interface which will define our defensive copy method and then implement it in our class and override that method.

So in Mammal class, we will create a no-argument method cloneObject however, we are free to name this method anything like clone or copy or copyInstance

public Mammal cloneObject() {
    return new Mammal(this);
}

And we can override same in “Human” class

@Override
public Human cloneObject() {
    return new Human(this);
}

Now to clone mammalHuman we can simply say

Mammal clonedMammalHuman = mammalHuman.clone();

And for the last two sys out we will get below output which is our expected behaviour.

Object Human{type='Human', name='Mahesh'} and copied object Human{type='Human', name='Mahesh'} are == : false
Object Human{type='Human', name='Mahesh'} and copied object Human{type='Human', name='Mahesh'} are equal : true

As we can see apart from getting the advantage of polymorphism this option also gives us freedom from passing any argument.

You can found complete code in CopyConstructorExample Java file on Github and please feel free to give your valuable feedback.
In my previous article Java Cloning and Types of Cloning (Shallow and Deep) in Details with Example, I have discussed Java Cloning in details and answered questions about how we can use cloning to copy objects in Java, what are two different types of cloning (Shallow & Deep) and how we can implement both of them, if you haven’t read it please go ahead.

In order to implement cloning, we need to configure our classes to follow the below steps
  • Implement Cloneable interface in our class or its superclass or interface,
  • Define clone() method which should handle CloneNotSupportedException (either throw or log),
  • And in most cases from our clone() method we call the clone() method of the superclass.
Java Cloning versus Copy Constructor

And super.clone() will call its super.clone() and the chain will continue until call will reach to clone() method of the Object class which will create a field by field mem copy of our object and return it back.

Like everything Cloning also comes with its advantages and disadvantages. However, Java cloning is more famous its design issues but still, it is the most common and popular cloning strategy present today.

Advantages of Object.clone()

Object.clone() have many design issues but it is still the popular and easiest way  of copying objects, Some advantages of using clone() are
  • Cloning requires very less line of code, just an abstract class with 4 or 5 line long clone() method but we will need to override it if we need deep cloning.
  • It is the easiest way of copying object especially if we are applying it to an already developed or an old project. We just need to define a parent class, implement Cloneable in it, provide the definition of clone() method and we are ready every child of our parent will get the cloning feature. 
  • We should use clone to copy arrays because that’s generally the fastest way to do it.
  • As of release 1.5, calling clone on an array returns an array whose compile-time
    type is the same as that of the array being cloned which clearly means calling clone on arrays do not require typecasting.

Disadvantages of Object.clone()

Below are some cons due to which many developers don't use Object.clone()
  • Using Object.clone() method requires us to add lots of syntax to our code like implement Cloneable interface, define clone() method and handle CloneNotSupportedException and finally call to Object.clone() and cast it our object.
  • The Cloneable interface lacks clone() method, actually, Cloneable is a marker interface and doesn’t have any method in it and still, we need to implement it just to tell JVM that we can perform clone() on our object.
  • Object.clone() is protected so we have to provide our own clone() and indirectly call Object.clone() from it.
  • We don’t have any control over object construction because Object.clone() doesn’t invoke any constructor.
  • If we are writing the clone method in a child class e.g. Person then all of its superclasses should define clone() method in them or inherit it from another parent class otherwise super.clone() chain will fail.
  • Object.clone() support only shallow copy so reference fields of our newly cloned object will still hold objects which fields of our original object were holding. In order to overcome this, we need to implement clone() in every class whose reference our class is holding and then call their clone them separately in our clone() method like in below example.
  • We can not manipulate final fields in Object.clone() because final fields can only be changed through constructors. In our case, if we want every Person objects to be unique by id we will get the duplicate object if we use Object.clone() because Object.clone() will not call the constructor and final final id field can’t be modified from Person.clone().
class City implements Cloneable {
    private final int id;
    private String name;
    public City clone() throws CloneNotSupportedException {
    return (City) super.clone();
    }
}

class Person implements Cloneable {
    public Person clone() throws CloneNotSupportedException {
        Person clonedObj = (Person) super.clone();
        clonedObj.name = new String(this.name);
        clonedObj.city = this.city.clone();
        return clonedObj;
    }
}

Because of the above design issues with Object.clone() developers always prefer other ways to copy objects like using
  • BeanUtils.cloneBean(object) creates a shallow clone similar to Object.clone().
  • SerializationUtils.clone(object) creates a deep clone. (i.e. the whole properties graph is cloned, not only the first level), but all classes must implement Serializable.
  • Java Deep Cloning Library offers deep cloning without the need to implement Serializable.
All these options require the use of some external library plus these libraries will also be using Serialization or Copy Constructors or Reflection internally to copy our object. So if you don’t want to go with the above options or want to write our own code to copy the object then you can use
  1. Serialization
  2. Copy Constructors

Serialization

As discussed in 5 different ways to create objects in Java, deserialising a serialised object creates a new object with the same state as in the serialized object. So similar to above cloning approaches we can achieve deep cloning functionality using object serialization and deserialization as well and with this approach we do not have worry about or write code for deep cloning, we get it by default.

We can do it like it is done below or we can also use other APIs like JAXB which supports serialization.

// Method to deep clone an object using in memory serialization.
public Employee copy(Person original) throws IOException, ClassNotFoundException {
    // First serializing the object and its state to memory using ByteArrayOutputStream instead of FileOutputStream.
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream out = new ObjectOutputStream(bos);
    out.writeObject(original);

    // And then deserializing it from memory using ByteArrayOutputStream instead of FileInputStream,
    // Deserialization process will create a new object with the same state as in the serialized object.
    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
    ObjectInputStream in = new ObjectInputStream(bis);
    return (Person) in.readObject();
}

However, cloning an object using serialization comes with some performance overhead and we can improve on it by using in-memory serialization if we just need to clone the object and don’t need to persist it in a file for future use, you can read more on How To Deep Clone An Object Using Java In Memory Serialization.

Copy Constructors

This method copying object is most popular between developer community it overcomes every design issue of Object.clone() and provides better control over object construction

public Person(Person original) {
    this.id = original.id + 1;
    this.name = new String(original.name);
    this.city = new City(original.city);
}

Advantages of copy constructors over Object.clone()

Copy constructors are better than Object.clone() because they
  • Don’t force us to implement any interface or throw any exception but we can surely do it if it is required.
  • Don’t require any type of cast.
  • Don’t require us to depend on an unknown object creation mechanism.
  • Don’t require parent class to follow any contract or implement anything.
  • Allow us to modify final fields.
  • Allow us to have complete control over object creation, we can write our initialization logic in it.
By using Copy constructors strategy, we can also create conversion constructors which can allow us to convert one object to another object e.g. ArrayList(Collection<? extends E> c) constructor generates an ArrayList from any Collection object and copy all items from Collection object to newly created ArrayList object.


In a previous blog, I talked about why we can not define an outer class using private or protected keywords. If you have not read it, please go ahead and give it a look.

In this article I will talk what is the use of the static keyword, why an outer Java class can’t be static, why it is not allowed in Java to define a static outer class. In order to understand that first, we need to understand what is the static keyword used for, what purpose it solves and how does it work.

What does static keyword do

Every Java programmer knows that if we need to define some behaviour (method) or state (field) which will be common to all objects we define it as static. Because static content (behaviour or state) does not belong to any particular instance or object, it will common to all objects and all objects are free to change any static field and every change will be visible to every object.

We do not need to create an object of the class to access a static field or method, we can directly refer a static field or method by using class name and dot operator e.g. Class.forName(“ClassName”).
This happens because JVM creates a Class level object for every class when Classloader loads the class into memory. And all static content of that class belongs this Class object and all other objects of that class refer to this class level object for all static content. A class-level object is actually an object of java.lang.Class and it is referred by your_class_name.class syntax.

For Example for the below statement, two objects will get created

Employee emp =  new Employee();

One is ‘emp’ (the new Employee();) itself and another one is the ‘class level object’ of Employee class which will get created while JVM will load Employee class into memory and we can refer it by Employee.class. And this class level object holds all the static content of the Employee class either it is a variable or method. If we are accessing any static content through emp object it automatically points to Employee.class object to access that.

That is the reason why a static variable got changed for every object even if we change it for a single emp object because all emp objects are pointing same copy of that variable from Employee.class object, for more information read Why Java is Purely Object-Oriented Language Or Why Not.

Why an outer Java class can’t be static

From above we can conclude that we should define members as static which
  1. Should be common to all objects of the class.
  2. Should belong to the class and accessible by class name.
  3. Should not need an object of the class to access them.
Now suppose we are defining an outer class as static and suppose we are allowed to do so. Will this serve any purpose or provide any advantage to a developer or it will create ambiguity and complications for both developers and language creators?

Let’s check, defining an outer class as static will serve purposes which we have defined above or not?
  1. Every class is already common to all of its objects and there is no need to make it static to become available to all of its objects.
  2. We need a class name to access its static members because these members are part of class while an outer class is part of the package and we can directly access the class by just writing package_name.class_name (similar to class_name.static_field_name), So again there is no need to do which is already there by default.
  3. We do not need any object to access a class if it is visible, we can simply write package_name.class_name to access it. And by definition, a class is a blueprint for its objects and we create a class to create objects from it (exception will always be there e.g. java.lang.Math), again there is no need to define an outer class as static.
From the above points, we can say Java creators had not allowed an outer class to be static because there is no need to make it static. Allowing to make the outer class static will only increase complications, ambiguity and duplicity.

You can find the complete source code for this article on this Github Repository and please feel free to provide your valuable feedback.
As soon as we try to use private or protected keyword while declaring an outer class compiler gives a compilation error saying “Illegal modifier for the class your_class_name; only public, abstract & final are permitted”.

Here in this article, we are going to study why we are not allowed to use these keywords while declaring outer classes. But before understating the reason behind this we need to understand Java access specifiers and their use cases. There is total 4 access specifier in Java mentioned below in the order of their accessibility.

  1. private: anything (field, class, method, interface etc.) defined using private keyword is only accessible inside the entity (class or package or interface) in which it is defined. 
  2. default: only accessible inside the same package and it is also known as package-private (No modifiers needed).
  3. protected: only accessible inside the same package plus outside the package within child classes through inheritance only. 
  4. public: can be accessed from anywhere.

Why an outer class can not be private

As we already know a field defined in a class using private keyword can only be accessible within the same class and is not visible to outside world.

So what will happen if we will define a class private, that class will only be accessible within the entity in which it is defined which in our case is its package?

Let’s consider below example of class A

package com.example;
class A {
    private int a = 10;

    // We can access a private field by creating object of same class inside the same class
    // But realy no body creates object of a class inside the same class
    public void usePrivateField(){
        A objA =  new A();
        System.out.println(objA.a);
    }
}

Field ‘a’ is declared as private inside ‘A’ class and because of it ‘a’ field becomes private to class ‘A' and can only be accessed within ‘A’. Now let’s assume we are allowed to declare class ‘A’ as private, so in this case class ‘A’ will become private to package ‘com.example’ and will not be accessible from outside of the package.

So defining private access to the class will make it accessible inside the same package which default keyword already do for us, Therefore there is no benefit of defining a class private it will only make things ambiguous.

Why an outer class can not be protected

Access specifier protected is sometimes got confused with the default keyword, for some programmers it becomes hard to identify the exact difference between default and protected accesses. But it is very clear as mentioned below

    default → only accessible within the same package.
    protected → accessible within the same package as well as outside of the package in child classes  through inheritance only.

Let’s consider below example of class A

package com.example;
public class A {
    protected int a = 10;
}

And suppose there is one more class in another package

package com.experiment;
public class B extends A {

    // Outside of the package protected field can be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation of child class
    // But should we do that ? .... No
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a);

        // But not through instantiation of the class which contains the protected field
        A a = new A();
        System.out.println(a.a); // Compilation error “The field A.a is not visible”
    }
}

And suppose there is one more class in the same package

package com.experiment;
public class C {

    // We can not access protected field outside of the child class through instantiation
    public void printUsingInstantiation() {
        B b = new B();
        System.out.println(b.a); // Compilation error “The field B.a is not visible”
    }
}

And if same class 'C' extends 'B', Then again we will be able to access 'a' the same way we are able to access it in B class

package com.experiment;
public class C extends B {

    // outside of the package protected field can only be accessed through inheritance
    public void printUsingInheritance() {
        System.out.println(a);
    }

    // In child class we can access protected field through instantiation as well
    public void printUsingInstantiation() { 
        C c = new C();
        System.out.println(c.a);
    }
}

Because ‘a’ field is protected, we can access it in any way we want to inside the package but outside of the package ‘com.example’ it is only accessible through inheritance and because class ‘B’ is extending class ‘A’ we can use field ‘a’ inside class ‘B’ only as we are doing in printUsingInheritance() method. And we can not use ‘a’ outside of class ‘B’ without inheriting 'B' in another class.

Field ‘a’ will be accessible inside class B in through inheritance only but if we try to create an instance of class ‘B’ in ‘B’ class and then try to access ‘a’ from that instance we will able to use it in a similar manner we can use a private variable in the same class by instantiation of same class.

So If we are allowed to make a class protected then we can access it inside the package very easily but for accessing that class outside of the package we first need to extend that entity in which this class is defined which is again is its package.

And since a package can not be extended (can be imported) defining a class protected will again make it similar to defining it as default which we can already do. So again there is no benefit of defining a class protected.

Please feel free to reach me if you face any problem in understanding it or found any problem in the article.
Some years back when I was learning Java, I got to know that Java follows Object Oriented Programming paradigm and everything in Java is an object either it is a String (which was a char array in C) or an array itself.

But later on I found on the internet, people are saying that Java is actually not a purely object-oriented because everything in Java is not an object, for example:
  1. All primitive types (char, boolean, byte, short, int, long, float, double) are not objects because we can not perform any object related operation (using . and calling methods) on them.
  2. I have seen some people some saying that all the static content (variables and methods) does not belong to any object so they are non-object things.
I easily accepted these reasons and started to believe that Java is not a pure object-oriented programming language.

But later on, I found that for every object JVM creates two objects
  1. The object itself.
  2. And one Class level object which gets created only once when classloader loads the class into memory. And all static content of that class belongs to this Class object and all other objects of that class refer to this class level object for all static content.
For Example for below statement, there will be two objects

Employee emp = new Employee();

One is emp itself and another one is the class level object of employee class. If we are accessing any static content through the emp object it points to the class level object to access that.

That's the reason why static variables get changed for every object even if we change it for a single emp object because all objects are pointing to the same copy of that variable from class level object.

Now 2nd point got canceled because the static content does belong to an object. But the 1st point is still there and we still have primitive data types which are not objects in Java. However wrapper classes are there and due to autoboxing (automatic unboxing-boxing, boxing-unboxing), we can directly assign a primitive literal to its Wrapper class reference.

But still, we can’t perform object related operations on primitives variables we always need to create objects of the respective wrapper class, for example

Integer obj = new Integer(5); // here we can do obj.toString()
int i = 5; // but we can't do i.toString() here

And due to these reasons, we say primitive types are not objects but what if that’s actually an elusion and it is end-user perspective (Java developers are end user to Java because we are using it not creating it).

If we dig down deep into the Java source codes we can find that JVM internally treats all primitive types as objects and proof of this can be found in source code or Javadoc of class Class, according to source code class Class

Instances of the class Class represent classes and interfaces in a running Java application. An enum is a kind of class and an annotation is a kind of interface. Every array also belongs to a class that is reflected as a Class object that is shared by all arrays with the same element type and number of dimensions. The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects

And Javadoc code of Class.isPrimitive() method says

public boolean isPrimitive()
Determines if the specified Class object represents a primitive type.
There are nine predefined Class objects to represent the eight primitive types and void. These are created by the Java Virtual Machine, and have the same names as the primitive types that they represent, namely boolean,byte, char, short, int, long, float, and double.
These objects may only be accessed via the following public static final variables, and are the only Class objects for which this method returns true.
Returns:
true if and only if this class represents a primitive type
Since:
JDK1.1
See Also:
Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE

If we open source code of class Class and do a CTRL + F for "primitive” word we will find lots of reason to believe that JVM treats all primitive types as objects internally.

Also if we open source of the Integer class search for Integer.TYPE entry, we will find

public static final Class[Integer](https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html) TYPE
The Class instance representing the primitive type int.

And if we write below the line in your program in eclipse

Integer.TYPE i = 5;

We get a compilation error saying Integer.TYPE cannot be resolved to a type with a hint from eclipse to change it to int.

So if all primitive types are objects for JVM then why should we use primitive types

primitive-type-and-wrapper-classes-in-java

If JVM creates objects for all primitive types then why do we need to use primitive types instead of creating an object of its respective wrapper classes. That’s because JVM creates these native objects for primitive types internally and those objects are very lightweight and optimized than their respective wrapper class objects and due to this, they have less functionality e.g. we can’t call methods on them because they don’t have any.

We should use primitive types because:
  1. They are fast e.g. below program takes 9 seconds to run on my machine while it takes 0 seconds if I convert Long sum to long sum.
     public static void main(String[] args) {
 long millis = System.currentTimeMillis();
 Long sum = 0L; // uses Long, not long
 for (long i = 0; i <= Integer.MAX_VALUE; i++) {
  sum += i;
 }                     

 System.out.println(sum);

 System.out.println((System.currentTimeMillis() - millis) / 1000);
  1. They allow us to use native equality operator ==
     new Integer(3) == new Integer(3); // false
     new Integer(100) == new Integer(100); // false
     Integer.valueOf(5) == Integer.valueOf(5); //true
     Integer.valueOf(100) == Integer.valueOf(100); //false

4th statement gives false because the 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, they aren't cached, so a new object is created.

So there are enough reasons to say JVM treats all primitive types as objects internally, however, we can’t use them in that way and we have got Wrapper classes for that.

This is why Java is purely Object Oriented Language, Please mention in comments what do you think Java is a purely Object Oriented Language or not.
According to Java standards and common practices, we should declare every class in its own source file. And even if we declare multiple classes in the single source file (.java) still each class will have its own class file after compilation. But the fact is that we can declare more than one class in a single source file with below constraints,
  • Each source file should contain only one public class and the name of that public class should be similar to the name of the source file.
  • If you are declaring the main method in your source file then main should lie in that public class

If there is no public class in the source file then main method can lie in any class and we can give any name to the source file.
If you are not following 1st constraint then you will receive a compilation error saying “The public type A must be defined in its own file”. While if you are not following the second constraint you will receive an error “Error: Could not find or load main class User” after the execution of the program and if you will try this in Eclipse then you will not get the option to execute the program.

Here we are talking about only top level classes, we can declare more than one public inner class.

Why only one public class per source file

Now we know that we can’t declare more than one public file in the single source file, Now we will look at why we can’t do this or why it is not allowed in Java.

Well, actually it is an optional restriction according to Java Language Specification (Section 7.6, Page No. 209) but followed by Oracle Java compiler as a mandatory restriction. According to Java Language Specification,

When packages are stored in a file system (§7.2.1), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
  • The type is referred to by code in other compilation units of the package in which the type is declared.
  • The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit.
This restriction makes it easy for a Java compiler to find a named class within a package.
In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.

For example, the source code for a public type wet.sprocket.Toad would be found in a file Toad.java in the directory wet/sprocket , and the corresponding object code would be found in the file Toad.class in the same directory.

Above clarification is a little bit typical to understand, So let’s replace the “type” word with actual a class Toad to get more clarification,

Java compiler may give an error if Toad class is not found in Toad.java and either of following is true
  • Toad class is referred in other classes in same package.
  • Toad class is declared public.
This restriction implies that there must be at most one such Toad class per compilation unit.
And the reason behind this is,
This restriction makes it easy for a compiler for the Java programming language or an implementation of the Java virtual machine to find a named class within a package.

To get more clear picture let's imagine there are two public classes public class A and public class B in the same source file and class A have reference to the not yet compiled class B. And we are compiling (compiling-linking-loading) class A now while linking to class B compiler will be forced to examine each *.java files within the current package because class B doesn’t have its specific B.java file. So In above case, it is a little bit time consuming for the compiler to find which class lies under which source file and in which class the main method lies.

So the reason behind keeping one public class per source file is to actually make compilation process faster because it enables a more efficient lookup of the source and compiled files during linking (import statements). The idea is if you know the name of a class, you know where it should be found for each classpath entry and no indexing will be required.

And also as soon as we execute our application JVM by default looks for the public class (since no restrictions and can be accessed from anywhere) and also looks for public static void main(String args[]) in that public class. Public class acts as the initial class from where the JVM instance for the Java application (program) is begun. So when we provide more than one public class in a program the compiler itself stops you by throwing an error. This is because later we can’t confuse the JVM as to which class to be its initial class because only one public class with the public static void main(String args[]) is the initial class for JVM.

But why can we declare more than one non-public class (default access) in a single source file

Although there is no particular specification or reference to point why it is allowed to have more than one non-public class per source file. Presumably, the point is that developers are more likely to want to find the source code for a public class than a non-public one because developers don’t work on the same package provided by others so they don’t need to know the non-public classes. So compiler should not worry too much about linking non-public class because these are private to package.

But we should declare every class in its own file because it we will make the source short, simple, well organised and easy to understand.

You can find the complete source code for my blog on this Github Repository and please feel free to provide your valuable feedback.
Previous Post Older Posts Home