1 using == to compare primitive wrappers objects such as Integer
Integer int1_1 = Integer.valueOf(“1”);Integer int1_2 = Integer.valueOf(1);System.out.println(“int1_1 == int1_2: ” + (int1_1 == int1_2)); // trueSystem.out.println(“int1_1 equals int1_2: ” + int1_1.equals(int1_2)); // trueInteger int2_3 = Integer.valueOf(“1000”);Integer int2_2 = Integer.valueOf(1000);System.out.println(“int2_3 == int2_4: ” + (int2_3 == int2_4)); // falseSystem.out.println(“int2_3 equals int2_4: ” + int2_3.equals(int2_4)); // true
The JVM maintains a cache of Integer objects for the range -128 to 127. For values in this range, the Integer. valueOf() will return the cached value rather than creating a new one. Thus, in the first example the Integer.valueOf(1) and Integer.valueOf(“1”) calls returned the same cached Integer instance. By contrast, in the second example the Integer. valueOf(1000) and Integer. valueOf(“1000”) both created and returned new Integer objects.
JVM維護(hù)范圍為128到127的整數(shù)對(duì)象緩存。對(duì)于此范圍內(nèi)的值,為整數(shù)。valueOf()將返回緩存的值,而不是創(chuàng)建新值。因此,在第一個(gè)示例中,Integer.valueOf(1) 和 Integer.valueOf(“1”)調(diào)用返回了相同的緩存整數(shù)實(shí)例。相比之下,在第二個(gè)示例中,valueOf(1000) 和 Integer. valueOf(“1000”)創(chuàng)建并返回了新的整數(shù)對(duì)象。
The == operator for reference types tests for reference equality (i. e. the same object). Therefore, in the first example int1_1 == int1_2 is true because the references are the same. In the second example int2_1 == int2_2 is false because the references are different.
引用類型的==運(yùn)算符測(cè)試引用相等性(即相同的對(duì)象)。因此,在第一個(gè)示例中,int1_1 == int1_2是真的,因?yàn)橐檬窍嗤摹T诘诙€(gè)示例中,int2_1 == int2_2為false,因?yàn)橐貌煌?/p>
2 using == to compare strings
public class Hello { public static void main(String[] args) { if(args.length > 0) if(args[0] == “hello”) { // always false, one point to heap , another point to iteral pool System.out.println(“Hello back to you”); else System.out.println(“Are you feeling grumpy today?”); }}
The correct way to test strings is to use the equals(Object) method.
public class Hello2 { public static void main(String[] args) { if(args.length > 0) { if(args[0].equals(“hello”)) System.out.println(“Hello back to you”); else System.out.println(“Are you feeling grumpy today?”); } }}
有字符串常量出現(xiàn)時(shí),會(huì)先查找常量池,已定義的話不會(huì)再定義,引用相同空間的常量值即可:
public class Test1 { public static void main(String[] args) { String s1 = “hello”; // point to iteral pool String s2 = “hello”; // point to the same above if(s1 == s2) System.out.println(“same”); // same else System.out.println(“different”); }}
3 forgetting to free resources
private static void printFileJava6() throws IOException { FileInputStream input; try { input = new FileInputStream(“file.txt”); int data = input.read(); while(data != -1){ System.out.print((char) data); data = input.read(); } } finally { if(input != null) { input.close(); // don’t forget } }}
4 thinking of variables as objects
No Java variable represents an object.
String foo; // NOT AN OBJECT
Neither does any Java array contain objects.
String bar[] = new String[100]; // No member is an object.
The equality operator does NOT test that two objects are equal.
相等運(yùn)算符不會(huì)測(cè)試兩個(gè)對(duì)象是否相等。
Applying the equality (==) operator to reference values tests if the values refer to the same object. It does not test whether two (different) objects are “equal” in the intuitive sense.
將相等(==)運(yùn)算符應(yīng)用于引用值將測(cè)試這些值是否引用同一對(duì)象。它不測(cè)試兩個(gè)(不同)物體在直覺(jué)上是否“相等”。
Method calls do NOT pass objects at all.
方法調(diào)用根本不傳遞對(duì)象。
Java method calls use pass by value1 to pass arguments and return a result.
Java方法調(diào)用使用pass-by-value1傳遞參數(shù)并返回結(jié)果。
When you pass a reference value to a method, you’re actually passing a reference to an object by value, which means that it is creating a copy of the object reference.
向方法傳遞引用值時(shí),實(shí)際上是按值傳遞對(duì)對(duì)象的引用,這意味著它正在創(chuàng)建對(duì)象引用的副本。
As long as both object references are still pointing to the same object, you can modify that object from either reference, and this is what causes confusion for some.
只要兩個(gè)對(duì)象引用仍然指向同一個(gè)對(duì)象,就可以從任意一個(gè)引用修改該對(duì)象,這就是導(dǎo)致某些人混淆的原因。
However, you are not passing an object by reference2. The distinction is that if the object reference copy is modified to point to another object, the original object reference will still point to the original object.
但是,您沒(méi)有通過(guò)引用2傳遞對(duì)象。區(qū)別在于,如果修改對(duì)象引用副本以指向另一個(gè)對(duì)象,則原始對(duì)象引用仍將指向原始對(duì)象。
void f(Point foo) { foo.x = 42; foo = new Point(3, 4); // Point local foo at a different object.}
5 Not understanding that String is an immutable class
New Java programmers often forget, or fail to fully comprehend, that the Java String class is immutable. This leads to problems like the one in the following example:
新的Java程序員經(jīng)常忘記或無(wú)法完全理解Java字符串類是不可變的。這會(huì)導(dǎo)致以下示例中的問(wèn)題:
public class Shout { public static void main(String[] args) { for(String s : args) { s.toUpperCase(); System.out.print(s); System.out.print(” “); } System.out.println(); }}
The above code is supposed to print command line arguments in upper case. Unfortunately, it does not work, the case of the arguments is not changed.
上述代碼應(yīng)該以大寫(xiě)形式打印命令行參數(shù)。不幸的是,它不起作用,參數(shù)的情況沒(méi)有改變。
In reality, the toUpperCase() method returns a String object which is an uppercase version of the String that you call it on. This will probably be a new String object, but if s was already all uppercase, the result could be the existing string.
實(shí)際上,toUpperCase()方法返回一個(gè)字符串對(duì)象,該對(duì)象是調(diào)用它的字符串的大寫(xiě)版本。這可能是一個(gè)新的字符串對(duì)象,但如果s已經(jīng)全部大寫(xiě),則結(jié)果可能是現(xiàn)有字符串。
6 combining assignment and side-effects
i += a[i++] + b[i–]; // more sequence points and side-effects, not allowed
7 Using ‘==’ to test a boolean
Sometimes a new Java programmer will write code like this:
public void check(boolean ok) { if(ok == true) { // redundancy, Note ‘ok == true’ System.out.println(“It is OK”); }}
8 Using ‘assert’ for argument or user input validation
A question that occasionally on StackOverflow is whether it is appropriate to use assert to validate arguments supplied to a method, or even inputs provided by the user.
StackOverflow上偶爾出現(xiàn)的一個(gè)問(wèn)題是,使用assert驗(yàn)證提供給方法的參數(shù),甚至驗(yàn)證用戶提供的輸入是否合適。
The simple answer is that it is not appropriate.
簡(jiǎn)單的答案是,這是不合適的。
Better alternatives include:
更好的替代方案包括:
Throwing an IllegalArgumentException using custom code.
使用自定義代碼引發(fā)IllegalArgumentException。
Using the Preconditions methods available in Google Guava library.
使用Google Guava庫(kù)中可用的前提條件方法。
Using the Validate methods available in Apache Commons Lang3 library.
使用Apache Commons Lang3庫(kù)中可用的驗(yàn)證方法。
9 Wildcard imports can make your code fragile
Consider the following partial example:
import com.example.somelib.*; // not recommendimport com.acme.otherlib.*; //public class Test { private Context x = new Context(); // from com.example.somelib …}
10 other syntax pitfall
10.1 Missing a ‘break’ in a ‘switch’ case
10.2 Declaring classes with the same names as standard classes
10.3 Leaving out braces: the “dangling if” and “dangling else” problems
10.4 Octal literals ( 010 is not 10)
10.5 Ignoring method visibility
10.6 Misplaced semicolons and missing braces
10.7 Overloading instead of overriding
10.8 Auto-Unboxing Null Objects into Primitives
11 Threads and Concurrency related
11.1 Too many threads makes an application slower
11.2 incorrect use of wait() / notify()
11.3 Shared variables require proper synchronization
11.4 Thread creation is relatively expensive
12 Nulls and NullPointerException
12.1 Using null to represent an empty array or collection
12.2 Not checking if an I/O stream isn’t even initialized when closing it
12.3 Returning null instead of throwing an exception
12.4 Unnecessary use of Primitive Wrappers can lead to NullPointerExceptions
13 Exception usage
13.1 Catching Throwable, Exception, Error or RuntimeException
13.2 Ignoring or squashing exceptions
13.3 Throwing Throwable, Exception, Error or RuntimeException
13.4 Using exceptions for normal flowcontrol
13.5 Directly subclassing `Throwable
13.6 Catching InterruptedException
13.7 Excessive or inappropriate stacktraces
14 memory leaks related
Java manages memory automatically. You are not required to free memory manually. An object’s memory on the heap may be freed by a garbage collector when the object is no longer reachable by a live thread.
Java自動(dòng)管理內(nèi)存。您無(wú)需手動(dòng)釋放內(nèi)存。當(dāng)活動(dòng)線程無(wú)法訪問(wèn)對(duì)象時(shí),垃圾收集器可能會(huì)釋放堆上的對(duì)象內(nèi)存。
However, you can prevent memory from being freed, by allowing objects to be reachable that are no longer needed. Whether you call this a memory leak or memory packratting, the result is the same — an unnecessary increase in allocated memory.
但是,您可以通過(guò)允許不再需要的對(duì)象可以訪問(wèn)來(lái)防止內(nèi)存被釋放。無(wú)論您將其稱為內(nèi)存泄漏還是內(nèi)存打包,結(jié)果都是一樣的——分配的內(nèi)存會(huì)不必要地增加。
Memory leaks in Java can happen in various ways, but the most common reason is everlasting object references, because the garbage collector can’t remove objects from the heap while there are still references to them.
Java中的內(nèi)存泄漏可能以各種方式發(fā)生,但最常見(jiàn)的原因是永久的對(duì)象引用,因?yàn)槔占鳠o(wú)法在仍然存在對(duì)對(duì)象的引用時(shí)從堆中移除對(duì)象。
15 Performance Issues
15.1 String concatenation in a loop does not scale
15.2 Using size() to test if a collection is empty is inefficient
15.3 Interning strings so that you can use == is a bad idea
15.4 Using ‘new’ to create primitive wrapper instances is inefficient
15.5 Efficiency concerns with regular expressions
15.6 Small reads / writes on unbuffered streams are inefficient
15.7 Over-use of primitive wrapper types is inefficient
15.8 The overheads of creating log messages
15.9 Iterating a Map’s keys can be inefficient
15.10 Calling System.gc() is inefficient
15.11 Calling ‘new String(String)’ is inefficient
ref
《Java Notes For Professionals》
-End-