Java Tips & Tricks
Know these before you step into the big game
Java…. So you all reading this know that it is one of the most popular programming languages around the world and designed to keep running on any stage incessantly. Be it Windows applications, Web Applications, Mobile, Network, consumer electronic goods, Java is everywhere. Java has witnessed consistent development in its programming efficiency for decades and shows no sign of declining in popularity and, for that reason, is worth learning for anyone willing to have a solid future as a developer. No matter whether you are an expert or a newbie to Java familiarizing with good programming practices will save tons of time. So let’s look into some java tricks and tips to save time, optimize and improve code quality.
1. String Optimization
String objects are immutable in Java which means the String content is unchangeable once created. Strings can be constructed by,
- Directly assigning a String literal to a String reference
- By a constructor
String str1 = "I am a string";
String str2 = new String("I am a string via a constructor");
The first method is a better way to create Strings. Creating Strings using constructors wastes memory space a lot as objects do not share storage even for the same content while the first method does share storage for the same content.
Especially, avoid using the second method inside loops as by now you all can understand new unnecessary objects will be created at each iteration wasting a great deal of storage.
Use StringBuffer or StringBuilder class if the content of a String is frequently modified as these classes support mutable Strings.
2. String Concatenation
At the instance, you see String Concatenation, I know concatenating strings using ‘+’ operator is the first thing that pops into most of your heads. But did you know that it is not the best and the only method to do the job? There are 4 methods to this.
- Using the ‘+’ operator
It’s the easiest way to concatenate multiple Strings but takes additional memory and slows down the performance of your program. Especially if you are concatenating multiple Strings within a loop. But this does not mean that you should avoid this method. You can still use this for concatenating Strings in one statement.
String name = "S"+"a"+"m";
- Using the concat() method
This method is hardly used. Performance is better than using ‘+’ operator but still, it’s slower.
- Using StringBuffer
This method is much faster than the above two. StringBuffer is synchronized for multi-threaded operations which means this method is thread-safe. This is slower than StringBuilder because of synchronized methods.
- Append method of StringBuilder class
This is similar to StringBuffer except for that StringBuilder is not synchronized for multi-threaded operations. If you are concatenating multiple Strings using a for-loop, then you should use StringBuilder.
String name =
new StringBuilder().append("S").append("a").append("m").toString();
Now if I summarize this for you, when creating Strings from parts use StringBuilder(single-threaded) or StringBuffer(multi-threaded). For String Concatenation using for-loops use StringBuilder and for single statement String Concatenation you can use the ‘+’ operator.
3. Use of Single and Double Quotes in Strings
In brief, single quotes are used for literal chars while double quotes are for literal Strings. In the below code snippet the letters ‘M’ and ‘Y’ will be the corresponding outputs.
System.out.println("M");
System.out.println('Y');
Now, what do you think of the code below?
System.out.println("M" +"Y");
System.out.println('M'+'Y');
The first output as you guessed is MY but second didn’t turn out to be MY, instead the output appears to be 166. Adding two chars will return an int. Here the ASCII values of the two chars will be added to return an int.
If you are wondering how to concatenate chars as a String, there are several ways to do it.
System.out.println('M'+""+'Y');
System.out.println(""+'M'+'Y');
Both the above two methods will return the String MY. In addition, there are more methods, like the StringBuffer and StringBuilder mentioned in the previous section.
4. Float vs Double
Both these data types are used to represent floating-point numbers and that double is more precise is a well-known fact.
The use of double over float is highly recommended, especially, if you can’t guarantee that your number is within floats’ specified range.
But note that double comes with a cost; it is expensive as it takes double the memory space as of what float would take.
5. Better to Avoid BigDecimal and BigInteger
You can also go with BigDecimal and BigInteger which is an exact way of representing numbers.
If you are working with floating-point numbers with different precision or if you are dealing with money where precision is a must, BigDecimal can be your pick. But it takes more memory, it’s a bit difficult to program algorithms and slows down all calculations drastically than using double.
So it is highly recommended to avoid using BigDecimal and also BigInteger, use them only if there is no other way out.
6.Use Primitives Where Possible
Wrapper classes are a great deal of help for like converting primitive data types to objects. Yet, primitives are simple, faster, and an easy way to avoid overhead. Thus, it is better to use int instead of Integer or float instead of Float.
//using primitive data type
int num = 5;//using wrapper class
Integer wrapNum = 5;
Furthermore, as Wrapper classes deal with objects, comparing them will not give desired outcomes as it is with primitives. The reason for that is that it will end up comparing objects instead of the content in those objects.
int num1 = 5;
int num2 = 5;Integer wrapNum1 = 3;
Integer wrapNum2 = 3;System.out.println(num1 == num2);
System.out.println(wrapNum1 == wrapNum2);
The first print would be true but the second print would be false as the objects are being compared there, not the values.
7. Handling Null Pointer Exception
Null pointer exception is a runtime exception that is thrown when an application is trying to use an object reference with a null value.
String fruit;
spellChecker(fruit);
Here a null reference variable is passed as an argument of a method.
positionLocator(null);
In the above code snippet, null is directly passed to a function. In both these instances, there is a high possibility of throwing the NullPointerException.
This exception can be fixed by using the if-else condition.
public class NullPointerExceptionExample{
public static void main(String args[]){
String fruit = "apple";
positionLocator(null);
}//Using an if-else condition
static void positionLocator(String fruit){
if(fruit != null){
System.out.println("Second character: "+fruit.charAt(0));
}
else {
System.out.println("NullPointerException thrown");
}
}}
8. Use Profilers to Optimize Your Code
Writing code and compiling it to get the required outputs is not just enough. We must write codes with the best performance possible. To achieve that it is better if there is a way to check what happens behind the code like, how memory is allocated, areas to improve, and effects of using one coding approach to another. For this, we can use Java Profilers.
Java Profiler is a tool that monitors Java bytecode constructs and operations at the JVM level. Using these profilers we can find out the performance, memory usage, memory leaks, etc in our programs, and then we can easily find out what to change, optimize or eliminate in the code.
There are a number of profilers available like JProfiler, XRebel, and New Relic but each of these profilers has unique characters and is better for a certain aspect of performance bugging. Therefore, profilers should be selected according to the level of analysis needed, and for better results, you can use a combination of multiple profilers.
You can find more on Java Profilers here.
9.Array vs ArrayLists
The main difference between these two is that an Array is of fixed size so once you have created an Array you cannot change it but the ArrayList is not of fixed size. You can create instances of ArrayLists without specifying its size. So if you create such instances of an ArrayList without specifying its size Java will create an instance of an ArrayList of default size.
Once an ArrayList is full it re-sizes itself. In fact, an ArrayList is internally supported by an array. So when an ArrayList is resized it will slow down its performance a bit as the contents of the old Array must be copied to a new Array.
At the same time, it’s compulsory to specify the size of an Array directly or indirectly while creating it. And also Arrays can store both primitives and objects while ArrayLists only can store objects.
I hope this article was some sort of help to you. Hope to bring more articles soon. Thank you for reading.