5 Most Common Java Pitfalls - GeeksforGeeks

08 Oct, 2021
1. Not understanding that String is an immutable class: The Java String class is immutable (Unmodifiable). This is because String objects are cached in a String pool. The object that a String is referencing to can change, but the String objects themselves cannot. 
Example: 
Java
public class Main {    public static void main(String[] args)    {        String str = "GeeksFor";        // A new string will be returned, but the actual String will remain the same        str.concat("Geeks");        // Prints initial value "GeeksFor"        System.out.println(str);        // Now we change the reference of "str" to point to the new String returned        str = str.concat("Geeks");        // Prints the new concatenated String        System.out.println(str);    }}
Output : GeeksFor 
         GeeksForGeeks
2. Memory Leaks: One of the core benefits of Java is the Java Garbage Collector, which manages the objects memory on the heap. Whenever an object is unreachable it is automatically freed. However, a common slip for both new and experienced programmers is preventing the memory from being freed, by allowing objects to be reachable that are no longer in use. This can be a very big downside to a project since memory leaks block resources and degrades the application performance. It can even lead to java.lang.OutOfMemoryError.
Common Cases are: 
Static Fields Declaring a static field and forgetting to set it to null after its data is not longer needed
Unclosed Streams The Java Virtual Machine allocates memory for every connection opened. Forgetting to close the connection consumes memory. Such connections can be: Input Streams, Database Connections, Sessions, and others.
The finalize() method When we override the finalize() method, the object of that class is not any more directly garbage collected. The Garbage Collector is then waiting for finalization, which is happening at a later point in time.
3. Pre/Post Increment Operator and side-effects: The evaluation order of operators in Java appear to be evaluated from left to right, the side effects can be seen instantly:
Java
public class Main {    public static void main(String[] args)    {        int num = 0;        /* First case */        // The increment operator happens after the value is pushed onto the stack and assigned        num = num++;        // Prints initial value        System.out.println(num);        /* Second case */        // Increment occurs first, and then it is pushed to the stack and assigned to num        num = ++num;        System.out.println(num);    }}
Output : 0 
         1 
The execution context of the first case is as follows: 
Store previous value of operand.Increment the value.Return the previous value
Store previous value of operand.
Increment the value.
Return the previous value
The execution context of the second case is as follows:
Increment the value.Store value of operand (incremented)Return the value
Increment the value.
Store value of operand (incremented)
Return the value
4. Using the relational operator “==” for Objects comparison. Many novice programmers try to use the “==” operator to compare objects and when the behavior of their code is not as expected they are confused. A thing to be aware of is that the relational operator “==” is making a reference comparison, it checks if both objects point to the same location in memory. Using the .equals() method will eliminate the problem since it compares the values inside the objects.
Java
public class Main {    public static void main(String[] args)    {        String s1 = new String("GeeksForGeeks");        String s2 = new String("GeeksForGeeks");        // Comparing using the relational operator        if (s1 == s2) { // false            System.out.println("Both objects point to the same memory location!");        }        // Comparing using the .equals()        if (s1.equals(s2)) { // true            System.out.println("The value inside the object instances match!");        }        // Declaring a string with a reference to s1        String s3 = s1;        if (s3 == s1) { // true            System.out.println("Both objects point to the same memory location!");        }    }}
Output : The value inside the object instances match! 
         Both objects point to the same memory location! 
Although sometimes the “==” operator will give the expected answer: 
Java
public class Main {    public static void main(String[] args)    {        String s1 = "GeeksForGeeks";        String s2 = "GeeksForGeeks";        // Comparing using the relational operator        if (s1 == s2) { // true            System.out.println("The two strings are the same!");        }        else {            System.out.println("The two strings are the different!");        }    }}
Output : The two strings are the same! 
The reason is in the Java Language Specification String Literals: ‘Literal strings within the same class in the same package represent references to the same String object’. The condition in the code is true because the literals are consisting of the same characters.
5. Using raw types Before Java started using generic types, there have not been alternatives to raw types (types that are not parameterized). For backward compatibility reasons, it is still possible to define these:
Java
public class Main {    public static void main(String[] args)    {        // Defining a raw list, without specifying its type parameter        List geeksList = new ArrayList();        // Due to the unspecified type we can add any data type and the code will compile        geeksList.add(100);        geeksList.add(200);        geeksList.add("GeeksForGeeks");        // When the second element is reached the compiler will throw a runtime error        // because we are trying to cast a string to an integer        geeksList.forEach(k -> System.out.println((int)k * 2));    }}
Output : 200
         400
Exception in thread "main" java.lang.ClassCastException: 
java.base/java.lang.String cannot be cast to java.base/java.lang.Integer
This issue can be prevented by defining the generic type of the List: 
List geeksList = new ArrayList();
Now the code won’t compile since we are trying to add a String type to a collection of Integer types. Generic Types are created for a reason and prevent programmers from nasty bugs and overheads.
gabaa406
adnanirshad158
anikaseth98
java-basics
Java
Java
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Object Oriented Programming (OOPs) Concept in Java
HashMap in Java with Examples
How to iterate any Map in Java
Interfaces in Java
Initialize an ArrayList in Java
ArrayList in Java
Stack Class in Java
Multidimensional Arrays in Java
Singleton Class in Java
LinkedList in Java