2010-08-02 73 views
7

可能重复:
Why is String final in Java?为什么String类是final?

有在我的编程生活中的各种时刻,我希望在String类一直没最终/密封/ NotInheritable。

什么是语言建筑师试图阻止我这样做,将扔在工程中的猴子扳手。

相反,语言建筑师想要通过限制我扩展String类来防止我投入作品中的猴子扳手是什么?

您能否列出可扩展字符串类的优缺点列表?

+0

我意识到还有其他类,如最终密封的数字。我们可以先通过分析字符串开始,但是您的注释不需要限制为字符串。 – 2010-08-02 01:39:39

+0

+1 ...我也想在我的生活中扩展字符串类,尽管我不记得为什么 – 2010-08-02 01:41:40

+0

正如你所提到的java(标签),这已被问到之前:http://stackoverflow.com/questions/2068804 /为什么是字符串最终在java中 – 2010-08-02 01:42:54

回答

5

字符串是一个immutable class这意味着如果您创建它后无法修改其状态。如果您可以在输入另一个库或字符串后修改字符串,则结果将不可预知。

Java API的一个错误是,BigIntegerBigDecimal不是最终的,这意味着您需要在从非受信任代码接收这些对象时执行这些对象的防御副本。相反,您始终可以相信String将保持一致。

不可信的BigInteger:

public class DestructiveBigInteger extends BigInteger { 

    public DestructiveBigInteger(String value) { 
     super(value); 
    } 

    public BigInteger add(BigInteger val) { 
     return BigInteger.ONE; // add() method does not behave correctly 
    } 

    public BigInteger subtract(BigInteger val) { 
     throw new UnsupportedOperationException("subtract is broken"); 
    } 
} 

同样的事情是不可能的String。正如Effective Java说,你需要这些类型的对象的防守副本:

public void setValue(BigInteger value) { 
    this.value = new BigInteger(value.toByteArray()); 
} 
+0

详细说明,请。 – 2010-08-02 01:50:52

+1

确保您知道* final *关键字和* sealed *关键字之间的差异。标有* final *的类也是有效密封的*,但这不是* final *关键字的真正点。 * final *类是**不可变的**,这意味着它在创建后不能被修改。不可变的类也必须被封闭,否则可以继承,重写并添加一些非不可变的行为。 字符串在Java中是不可变的,因为可变字符串**是危险的**,坦率地说,比他们的价值更麻烦。大多数现代语言(Python,Javascript,C#,Java)使用不可变的字符串。 – Ender 2010-08-02 03:23:49

4

字符串是最后的,因为它代表一个不可改变的数据类型。因为有很多库依赖于String对象的不变性,因此天真地扩展String会导致歧义性的可怕性。

扩展字符串以使其可变将对Sting所经过的任何代码都是不可见的,但会产生非常令人惊讶和讨厌的副作用,例如突然不能从HashMaps加载值,即使您字面上的字符串因为hashCode会被劫持。

+0

如果我想使用字符串作为地图的键,我会使用字符串。如果我想使用扩展字符串作为映射关键字,那正是我想要做的 - 以防止它被基本String对象访问。不变论据似乎并不适合我。 – 2010-08-02 01:49:55

+0

但是扩展的String *会是一个String。所以你可以使用它作为String的映射关键字。不能派生不会阻止你编写扩展字符串(使用合成)功能的类。它只是阻止你将该类的实例转换为字符串。 – jwg 2013-08-02 12:03:47

相关问题