Unraveling Java's Most Common Issue
Having worked with Java for over 2 years, I've noticed some common issues that, while not too complicated, can be confusing. Inspired by Jonathan, a developer advocate at Sonar, who surveyed SonarLint telemetry for the last 2 years, covering 2.5 million issues, let's dive into these common issues from my work experience, which you might also relate to.
These issues might seem small, but their impact can be significant. Addressing them can result in several benefits:
Code will be more readable.
Code will increase maintainability.
Finding bugs can be easier.
Code will be neater and cleaner in our projects.
Ready to dive in? Let's get started!
1. Code Commented out:
We should remove commented-out code because it makes readability harder. If the code is needed again, we can retrieve it from Git.
Sometimes, it causes confusion for readers, wondering if the code is commented out temporarily or should be removed.
Problem:
public class CommentedCodeExample {
public static void main(String[] args) {
int x = 10;
int y = 20;
int result = x + y;
// commented out code
/*
System.out.println("Result: " + result);
System.out.println("This part is commented out for testing purposes.");
*/
System.out.println("Other logic in the program.");
}
}
Solution:
public class CommentedCodeExample {
public static void main(String[] args) {
int x = 10;
int y = 20;
int result = x + y;
System.out.println("Result: " + result);
System.out.println("Other logic in the program.");
}
}
2. "TODO" Tags:
Leaving 'TODO' comments in the source code leads to incomplete code that can impact several areas.
Some problems include team members being unsure which features will be included in the final release. Second one is not implementing those parts could lead to bugs in the future.
Problem:
public class TodoExample {
public static void main(String[] args) {
int x = 10;
int y = 20;
// TODO: Implement logic to calculate result
System.out.println("Other logic in the program.");
}
}
Solution:
public class TodoExample {
public static void main(String[] args) {
int x = 10;
int y = 20;
int result = x + y;
System.out.println("Result: " + result);
System.out.println("Other logic in the program.");
}
}
3. String Literals Duplicated:
Having duplicate strings will lead to extra work or missing changes when those values need to be adjusted for new conditions.
Using constants to store string literals will maintain consistency in the code base.
Problem:
public class DuplicatedStringsExample {
public static void main(String[] args) {
System.out.println("Hello");
System.out.println("Hello");
}
}
Solution:
public class DuplicatedStringsExample {
private static final String MESSAGE = "Hello";
public static void main(String[] args) {
System.out.println(MESSAGE);
System.out.println(MESSAGE);
}
}
4. Unused elements (imports, assignments, variable, private fileds, perameters) should be removed
Unused elements reduce the readability of the code, making it harder to identify the intention.
Check for unused code and remove what is no longer used.
Problem:
import java.util.List; // import not used
public class UnusedElementsExample {
private int x = 10; // private field not used
private int compute(int a, int b) { // b argument not used
return a * 10;
}
}
Solution:
public class UnusedElementsExample {
private int compute(int a) {
return a * 10;
}
}
5. Raw types should not used
Generic types without type parameters should not be used, as it avoids type checking of unsafe code during compilation.
If you don't want any surprises during runtime, avoid using raw types.
Problem:
import java.util.ArrayList;
public class RawTypesExample {
public static void main(String[] args) {
// Raw type used here
ArrayList myList = new ArrayList();
}
}
Solution:
import java.util.ArrayList;
public class RawTypesExample {
public static void main(String[] args) {
// Parameterized type used here
ArrayList<String> myList = new ArrayList<>();
}
}
6. Generic Exceptions Should Never Be Thrown:
The usage of generic exceptions prevents calling methods from handling different system-generated exceptions and application-generated errors.
Create custom system exceptions to provide callers the ability to decide what to do, ensuring a detailed and differential list of catches.
Problem:
public class GenericExceptionExample {
public static void main(String[] args) {
try {
// Some code that may throw a generic exception
} catch (Exception e) {
// Handling the generic exception
}
}
}
Solution:
public class CustomException extends Exception {
// Custom exception class with details and customization
}
public class GenericExceptionExample {
public static void main(String[] args) throws CustomException {
try {
// Some code that may throw a specific exception
throw new CustomException("Something went wrong!");
} catch (CustomException e) {
// Handling the specific exception
System.out.println("Caught a specific exception: " + e.getMessage());
}
}
}
Note: When refactoring code, first modify and commit the existing code to Git without introducing new features. Then, add new code separately to maintain clarity and flexibility in tracking changes.
Your feedback is invaluable! Please take a moment to like and share your thoughts on this post.
Subscribe to my newsletter
Read articles from Jonayed Baperi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jonayed Baperi
Jonayed Baperi
Hey, I'm Jonayed, a devoted developer with two years' experience crafting tech solutions. I thrive on tackling complex challenges and eagerly adopt new technologies. Driven by an insatiable thirst for learning, I relish mastering emerging tech to stay ahead in this dynamic field. I'm more than code – I'm an enthusiastic blogger. Through my articles, I share tech insights, problem-solving methods, and personal experiences. Join me as I document my continuous exploration in the vast tech universe. Let's connect, learn, and grow together!