5 Most Common Java Pitfalls
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.
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:
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
The execution context of the second case is as follows:
- 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.
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:
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:
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.