forked from giantray/stackoverflow-java-top-qa
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request giantray#61 from owen1190/master
what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java.md lookup-enum-by-string-value.md
- Loading branch information
Showing
3 changed files
with
175 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,80 @@ | ||
## 比较java枚举成员使用equal还是== | ||
|
||
### 问题 | ||
我知道Java枚举会被编译成一个包含私有构造参数和一堆静态方法的类,当去比较两个枚举的时候,总是使用equals()方法,例如: | ||
```java | ||
public useEnums(SomeEnum a) | ||
{ | ||
if(a.equals(SomeEnum.SOME_ENUM_VALUE)) | ||
{ | ||
... | ||
} | ||
... | ||
} | ||
``` | ||
除此之外,我也可以使用 == 替代equals() 方法 | ||
```java | ||
public useEnums2(SomeEnum a) | ||
{ | ||
if(a == SomeEnum.SOME_ENUM_VALUE) | ||
{ | ||
... | ||
} | ||
... | ||
} | ||
``` | ||
我有5年以上的java编程经验,并且我想我也懂得 == 和 equals() 之间的区别,但是我仍然觉得很困惑,哪一个操作符才是我该使用的。 | ||
|
||
### 答案 | ||
|
||
二者皆对,如果你看过枚举的源码,你会发现在源码中,equals也仅仅非常简单的 == 。 | ||
我使用 == ,因为无论如何,这个左值是可以为 null的 | ||
|
||
|
||
译者补充 java.lang.Enum 中Equals 代码: | ||
```java | ||
public final boolean equals(Object other) { | ||
return this==other; | ||
} | ||
``` | ||
|
||
|
||
### 额外答案 | ||
#### 能在枚举中使用 == 进行判断? | ||
答案是肯定的,因为枚举有着严格的实例化控制,所以你可以用 == 去做比较符,这个用法,在官方文档中也有明确的说明。 | ||
|
||
>JLS 8.9 Enums | ||
>An enum type has no instances other than those defined by its enum constants. | ||
>It is a compile-time error to attempt to explicitly instantiate an enum type. The final clone method in Enum >ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures >that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types >is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by >the enum constants. | ||
>Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the >equals method when comparing two object references if it is known that at least one of them refers to an enum ?>constant. (The equals method in Enum is a final method that merely invokes super.equals on its argument and ?>returns the result, thus performing an identity comparison.) | ||
#### 什么时候 == 和 equals 不一样? | ||
As a reminder, it needs to be said that generally, == is NOT a viable alternative to equals. When it is, however (such as with enum), there are two important differences to consider: | ||
通常来说 == 不是一个 equals的一个备选方案,无论如何有2个重要的不同处需要考虑: | ||
|
||
##### == 不会抛出 NullPointerException | ||
```java | ||
enum Color { BLACK, WHITE }; | ||
|
||
Color nothing = null; | ||
if (nothing == Color.BLACK); // runs fine | ||
if (nothing.equals(Color.BLACK)); // throws NullPointerException | ||
``` | ||
##### == 在编译期检测类型兼容性 | ||
```java | ||
enum Color { BLACK, WHITE }; | ||
enum Chiral { LEFT, RIGHT }; | ||
|
||
if (Color.BLACK.equals(Chiral.LEFT)); // compiles fine | ||
if (Color.BLACK == Chiral.LEFT); // DOESN'T COMPILE!!! Incompatible types! | ||
``` | ||
|
||
#### 什么时候使用 == ? | ||
Bloch specifically mentions that immutable classes that have proper control over their instances can guarantee to their clients that == is usable. enum is specifically mentioned to exemplify. | ||
具体来说,那些提供恰当实例控制的不可变类能够保证 == 是可用的,枚举刚好符合这个条件。 | ||
|
||
> Item 1: Consider static factory methods instead of constructors | ||
[...] it allows an immutable class to make the guarantee that no two equal instances exist: a.equals(b) if and only if a==b. If a class makes this guarantee, then its clients can use the == operator instead of the equals(Object) method, which may result in improved performance. Enum types provide this guarantee. | ||
|
||
总而言之,在枚举比较上使用 == , 因为: | ||
1. 能正常工作 | ||
2. 更快 | ||
3. 运行时是安全的 | ||
4. 编译期也是安全的 | ||
|
||
stackoverlfow链接:http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals | ||
# 比较java中枚举成员是用“==”还是equals() | ||
|
||
## 问题 | ||
java枚举被编译成带有私有构造器和一堆public的静态成员的类。当比较枚举中的两个成员时,经常使用.equals()方法,例如 | ||
public useEnums(SomeEnum a) | ||
{ | ||
if(a.equals(SomeEnum.SOME_ENUM_VALUE)) | ||
{ | ||
... | ||
} | ||
... | ||
} | ||
然而,偶然间使用“==”代替equals方法 | ||
public useEnums2(SomeEnum a) | ||
{ | ||
if(a == SomeEnum.SOME_ENUM_VALUE) | ||
{ | ||
... | ||
} | ||
... | ||
} | ||
应该使用哪个呢? | ||
## 解答 | ||
### 回答1 | ||
技术上来说,都是对的,如果你看了equals的源码,它简单地遵从“==” ,然而我一般使用“==” 因为它对于空指针,比较安全 | ||
### 回答2 | ||
#### 能在枚举时使用用“==”吗? | ||
|
||
可以,枚举值有小型实例控制,允许你用“==”去比较实例,在文档中有说明: | ||
|
||
JLS 8.9 枚举 | ||
一个枚举类型除了定义的那些枚举常量外没有其他实例了。 | ||
试图明确地说明一种枚举类型是会导致编译期异常。在枚举中final clone方法确保枚举常量从不会被克隆,而且序列化机制会确保从不会因为反序列化而创造复制的实例。枚举类型的反射实例化也是被禁止的。总之,以上内容确保了除了定义的枚举常量之外,没有枚举类型实例。 | ||
|
||
因为每个枚举常量只有一个实例,所以如果在比较两个参考值,至少有一个涉及到枚举常量时,允许使用“==”代替equals()。(equals()方法在枚举类中是一个final方法,在参数和返回结果时,很少调用父类的equals()方法,因此是一种恒等的比较。) | ||
|
||
这足够强力地支持Josh的建议,如果你坚持使用单例模式,最好的方法是用枚举类型强化单例属性(见Effective Java第二版中的第三条:用私有构造器或者枚举类型强化Singleton属性,或者单例模式的线程安全 | ||
>http://stackoverflow.com/questions/2912281/thread-safety-in-singleton/ ) | ||
#### “==”和equals的区别 | ||
通常情况下,==并不是可以替换equals,然而在枚举中是可以的。它们之间有两个重要的不同: | ||
|
||
“==”从不会抛出空指针异常 | ||
|
||
|
||
enum Color { BLACK, WHITE }; | ||
|
||
Color nothing = null; | ||
|
||
if (nothing == Color.BLACK); // 正常运行 | ||
|
||
if (nothing.equals(Color.BLACK)); // 抛出空指 | ||
针异常 | ||
|
||
在编译期,"=="会检查其类型的兼容性 | ||
|
||
enum Color { BLACK, WHITE }; | ||
enum Chiral { LEFT, RIGHT }; | ||
|
||
if (Color.BLACK.equals(Chiral.LEFT)); // 编译正常 | ||
if (Color.BLACK == Chiral.LEFT); // 无法编译,类型不兼容 | ||
|
||
#### 在适用时,“==”可以被使用吗 | ||
|
||
Bloch(effective java的作者)明确指出不可变类可以控制它们实例保证客户端“==”是可用的。枚举就被明确地证明了 | ||
|
||
考虑静态工厂方法代替构造器 | ||
它使得不可变的类可以确保不会存在两个相等的实例,即当且仅当a==b的时候才有a.equals(b)为true。如果类保证了这一点,它的客户端可以使用“==”操作符来代替equals(Object)方法,这样可以提升性能。枚举类型保证了这一点 | ||
|
||
总之,在枚举中使用“==”优势: | ||
|
||
- 能运行 | ||
- 更快 | ||
- 在运行期更安全 | ||
- 在编译期更安全 | ||
|
||
备注:强有力的反击了那些认为foo.equals(bar)比foo==bar更有可读性的人们。 | ||
|
||
原文地址: | ||
> http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
...what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Java中软引用和弱引用的区别 | ||
## 问题 | ||
题目就是问题 | ||
|
||
## 解答 | ||
### 回答1 | ||
从Ethan Nicholas的《Understanding Weak References》中 | ||
|
||
弱引用: | ||
放置一个弱引用的作用,不是强有力强制一个对象保存在内存中。弱引用允许利用垃圾收集者的能力去决定可达性,所以你不需要自己做,你只需要创建一个软引用: | ||
|
||
WeakReference weakWidgt = new WeakReference(widgt); | ||
|
||
然后在代码别的地方你可以使用 `weakWidget.get()` 来获取真实的 `Widgt` 对象,当然弱引用足以强大能抵制垃圾收集器,所以你也许发现(如果没有强引用指向widget)`weakWidget.get()`突然开始返回null | ||
|
||
软引用 | ||
|
||
软引用就像弱引用一样,除了它不会着急将引用的对象扔出去。只有弱可达性的对象(这样的对象最强的引用只能是弱引用)将在下一次垃圾收集处理中被抛弃,但是软可达性的对象通常可以坚持一会。 | ||
|
||
软引用不要求与弱引用有什么不同,但是实际中,只要内存足够,软可达的对象通常会维持下去。对于缓存来说,这是个不错的基础,就像以上图像缓存描述,虽然可以让垃圾收集者担心对象是如何可达(一个强可达性的对象从不会从缓存中移除)和她们需要消耗多少内存 | ||
|
||
而且Peter Kessler备注到 | ||
|
||
Sun JRE 对待软引用和弱引用是不同的。如果内存是够用的。我们应坚持用软引用引用对象。一个细节是:对于客户端和服务器,JRE的政策是不同的:客户端,JRE试图保持通过清除软引用而不是扩大堆内存来使改变小点,而服务器端,JRE通过扩大堆内存让性能更好。没有一种通用的方法。 | ||
|
||
### 回答2 | ||
弱引用对象很快被收集。如果GC发现一个对象是弱引用(只能通过弱引用可达),它会立刻清除弱引用对象。同样的,对于在程序保持关联信息的对象保持一个引用是不错的,像关于类的缓存存储的反射信息或一个对象的包装器等等。没有意义地跟随相连对象的任何事物都会被清除掉。当弱引用清除掉时,它会进入到引用队列中,同时丢弃关联的对象。你保持关于对象额外的信息,但是一旦对象引用不要了,信息也就不需要了。总之,在某些情境下,你可以创建WeakReference的子类,保持在WeakReference的子类中对象的额外信息。WeakReference的其他典型应用是与Map连接,以保持规范化的例子。 | ||
|
||
在另一方面,软引用有利于外部缓存,再创造资源,因为GC会延迟清理他们。它能保证所有软引用会在内存溢出之前被清除,所以它们不会造成内存溢出。 | ||
|
||
典型的使用例子是保持从一个文件内容解析形式。在你载入文件,解析和与解析过代表的根对象保持一个软引用的地方扩展系统。在你下次需要文件时,你试图通过软引用恢复。如果可以恢复,你会在其他地方载入、解析你分享的文件,如果同时GC清理掉,你也可以重新载入。这样的话,你利用空内存可以做到性能最优化,但是不要内存溢出。 | ||
光保持一个软引用不会造成溢出。如果在另一方面你误用软引用,且弱引用被使用了(也就是说,你保持与较强引用的对象相连的信息,然后当引用对象被清除,你也丢弃信息),你可能会内存溢出,因为在进入引用队列时,也许碰巧没有及时丢弃相连的对象。 | ||
|
||
所以,使用软引用还是弱引用是取决于用法的。如果你的信息构造起来较为复杂,但是尽管如此仍想从别的数据再构造信息,使用软引用。如果你对一些数据的规范化实例保持引用,或者你想对一个“不拥有的”对象保持引用(就是防止被垃圾回收),这样就使用弱引用。 | ||
|
||
|
||
原文: | ||
> http://stackoverflow.com/questions/299659/what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java |