diff --git a/contents/comparing-java-enum-members-or-equals.md b/contents/comparing-java-enum-members-or-equals.md index 287f68c..0bd407f 100644 --- a/contents/comparing-java-enum-members-or-equals.md +++ b/contents/comparing-java-enum-members-or-equals.md @@ -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 \ No newline at end of file diff --git a/contents/lookup-enum-by-string-value.md b/contents/lookup-enum-by-string-value.md index 99f83c4..05fd890 100644 --- a/contents/lookup-enum-by-string-value.md +++ b/contents/lookup-enum-by-string-value.md @@ -1,3 +1,59 @@ +<<<<<<< HEAD +#通过String值查找enum中常量 +## 问题 +假设有一个枚举值 + public enum Blah + { + A,B,C,D + } +想通过一个String类型,找到所需要的枚举值。 +例如“A”->Blah.A +是使用Enum.valueOf()方法吗?该如何使用 +## 回答 +Blah.valueOf("A")会得到Blah.A +虽然api文档确实有静态方法valueOf()和values(),但是二者在编译期时才出现,而且在没出现在源程序中。 +例如可以采用Dialog.ModalityType显示了两种方法来处理这种情况。 +备注:Blah.valueOf("A")的方法是区分大小写,且不能含有空格。 + +如果String值与enum中不相同的查找方法: + + public enum Blah + { + A("text1"), + B("text2"), + C("text3"), + D("text4"); + private String text; + Blah(String text) + { + this.text = text; + } + public String getText() + { + return this.text; + } + + public static Blah fromString(String text) + { + if (text != null) + { + for (Blah b : Blah.values()) + { + if (text.equalsIgnoreCase(b.text)) + { + return b; + } + } + } + return null; + } + } + +备注:throw new IllegalArgumentException("No constant with text"+text+"found")会比直接抛出null更好 + +原文链接: +> http://stackoverflow.com/questions/604424/lookup-enum-by-string-value# +======= ## Java 中如何将 String 转换为 enum ###问题 @@ -104,3 +160,4 @@ stackoverflow链接 http://stackoverflow.com/questions/604424/lookup-enum-by-string-value _译者:[MagicWolf](https://github.com/DaiDongLiang)_ +>>>>>>> upstream/master diff --git a/contents/what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java.md b/contents/what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java.md new file mode 100644 index 0000000..eb01281 --- /dev/null +++ b/contents/what-is-the-difference-between-a-soft-reference-and-a-weak-reference-in-java.md @@ -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 \ No newline at end of file