Effective Java's own interpretation. I tried to interpret item 6 of the 3rd edition by writing my own code.
--Be aware of where the object is created. --Know the existence of the prepared object. --Constant objects that are reused with the same value over and over again. --Note that boxing creates objects unintentionally.
String
String s = new String("hoge");
This code first creates an object with the letters ” hoge ”
, then a new String (“hoge”)
creates another object with the letters”hoge”
.
In short, objects with the same contents are created twice. By doing the following, you can create the object only once.
String s = "hoge";
Boolean
The Boolean
object can actually be created by taking the String
object as an argument, as shown below.
Boolean b = new Boolean("true");
However, in the first place, Boolean
takes only three values, null
, true
, and false
. In the Boolean
class, true
and false
objects are prepared in advance in the form of constants.
** Part of Boolean class **
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
There is also a valueOf
method that returns these constants.
public static Boolean valueOf(String s) {
return parseBoolean(s) ? TRUE : FALSE;
}
So, if you declare a Boolean
object using the valueOf
method as shown below, you don't need to refer to the object originally prepared in the Boolean
class and create a new one.
Boolean b = Boolean.valuOf("true");
Consider the following method to determine if a string is a correct Roman numeral.
static boolean isRomanNumeral(String s) {
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
Since String.matches
internally creates a Pattern
object, a new Pattern
object will be created each time this method is called.
If the Pattern
object is defined as a constant in advance, the Pattern
object can be created only once at the time of class initialization.
public class RomanNumerals {
private static final Pattern ROMAN = Pattern.compile(
"^(?=.)M*(C[MD]|D?C{0,3})"
+ "(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s) {
return ROMAN.matcher(s).matches();
}
}
String.matches
internally creates a Pattern
object and calls .matcher (judgment target string) .matches ()
from that object, so the entire Pattern
object generation part is omitted. It becomes the shape that was made.Consider the following code.
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++)
sum += 1;
return sum;
}
Since sum + = 1
is internally cast and calculated like Long sum = sum + (Long) 1
every time, a Long
object is created every time.
In the first place, this method does not require sum
to be of type Long
, so simply declaring sum
of type long
can greatly improve speed.
This is a straightforward example, but you should always be aware of whether you need to use wrapper classes (need to take null
, possible situations, etc.).
The idea is that the object of a method argument should not change state inside the method. This is because it is difficult to see what the object is in now, and the risk of bugs increases. Unless performance is required very much, in this case, we should give priority to reducing the risk of bug occurrence by creating a new object in the method and copying the contents of the argument object.
Recommended Posts