可以在java中编写一个可变的String吗?

时间:2021-02-25 21:38:54

As we all know, String in java is final and immutable for the sake of security and performance. But, I wonder that is it possible to write a common mutable class MyString which can be modified and inherited? Eg:

众所周知,java中的String是最终的,并且为了安全性和性能而不可变。但是,我想知道是否有可能编写一个可修改和继承的常见可变类MyString?例如:

public class MyString {
    private final char[] value;
    public void setChar(int index, char c){
        value[index] = c;
    }
}

--------UPDATE--------

I know there are a StringBuilder and StringBuffer and how they work. Here, I want to know that how java can ensure safe if I write my own MyString and use it everywhere I should use String. If I can do this, I think there is no insurance of safety. Is it?

我知道有一个StringBuilder和StringBuffer以及它们是如何工作的。在这里,我想知道如果我编写自己的MyString并且在我应该使用String的任何地方使用它,java如何确保安全。如果我能做到这一点,我认为没有安全保障。是吗?

1 个解决方案

#1


1  

You are right. If you create a MyString method and allow inheritance, your program is less safe then if you use the final immutable String class -- this is especially so if you fail to properly document the contract for Overriding methods. If your MyString is mutable, using your class may be even less desirable.

你是对的。如果您创建MyString方法并允许继承,那么如果您使用最终的不可变String类,则您的程序不太安全 - 如果您未能正确记录Overriding方法的合同,则尤其如此。如果您的MyString是可变的,那么使用您的类可能更不可取。

A primary example of an issue with inheritance occurs in the case of self-use of overridable methods. Consider the documentation for java.util.AbstractCollection::remove:

继承问题的主要示例发生在可重写方法的自我使用的情况下。考虑java.util.AbstractCollection :: remove的文档:

Removes a single instance of the specified element from this collection, if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this collection contains one or more such elements. Returns true if this collection contained the specified element (or equivalently, if this collection changed as a result of the call). This implementation iterates over the collection looking for the specified element. If it finds the element, it removes the element from the collection using the iterator's remove method.

从此集合中移除指定元素的单个实例(如果存在)(可选操作)。更正式地,如果此集合包含一个或多个此类元素,则删除元素e(o == null?e == null:o.equals(e))。如果此collection包含指定的元素,则返回true(或等效地,如果此集合因调用而更改)。此实现迭代集合以查找指定的元素。如果找到该元素,它将使用迭代器的remove方法从集合中删除该元素。

The bolded section indicates that the method relies on the iterator method. The AbstractCollection class is designed for inheritance, so the documentation makes it clear that extending classes should consider overriding iterator() with care. Failing to document this behavior can lead to clients improperly overriding methods, which can lead to undefined behavior. Worse, if you define methods using MyString as an argument, a malicious user could pass in a subclass of MyString to further cause unexpected and potentially harmful changes to your system.

粗体部分表示该方法依赖于迭代器方法。 AbstractCollection类是为继承而设计的,因此文档清楚地表明扩展类应该考虑重写iterator()。未能记录此行为可能导致客户端不正确地覆盖方法,这可能导致未定义的行为。更糟糕的是,如果您使用MyString定义方法作为参数,恶意用户可以传入MyString的子类,以进一步导致对系统的意外和可能有害的更改。

Mutability is desirable because it makes your program simpler to reason about. Critically immutable objects are inherently thread safe and can be shared easily. They also allow Strings to be cached for performance, but you knew about this.

可变性是可取的,因为它使您的程序更容易推理。严重不可变对象本质上是线程安全的,可以轻松共享。它们还允许为性能缓存字符串,但您知道这一点。

So to answer your question: You can make a mutable, non-final MyString if you wish, but you cannot insure safety. You can only documented inheritance and hope users behave.

所以回答你的问题:如果你愿意,你可以制作一个可变的,非最终的MyString,但是你无法确保安全。您只能记录继承并希望用户行为。

Source: My example was blatantly stolen from Joshua Bloch's Effective Java. Specifically item 15 (minimize mutability) and 17 (design and document for inheritance or else prohibit it) are good sources.

来源:我的例子被Joshua Bloch的Effective Java公然偷走了。特别是项目15(最小化可变性)和17(继承的设计和文件或禁止它)是很好的来源。

#1


1  

You are right. If you create a MyString method and allow inheritance, your program is less safe then if you use the final immutable String class -- this is especially so if you fail to properly document the contract for Overriding methods. If your MyString is mutable, using your class may be even less desirable.

你是对的。如果您创建MyString方法并允许继承,那么如果您使用最终的不可变String类,则您的程序不太安全 - 如果您未能正确记录Overriding方法的合同,则尤其如此。如果您的MyString是可变的,那么使用您的类可能更不可取。

A primary example of an issue with inheritance occurs in the case of self-use of overridable methods. Consider the documentation for java.util.AbstractCollection::remove:

继承问题的主要示例发生在可重写方法的自我使用的情况下。考虑java.util.AbstractCollection :: remove的文档:

Removes a single instance of the specified element from this collection, if it is present (optional operation). More formally, removes an element e such that (o==null ? e==null : o.equals(e)), if this collection contains one or more such elements. Returns true if this collection contained the specified element (or equivalently, if this collection changed as a result of the call). This implementation iterates over the collection looking for the specified element. If it finds the element, it removes the element from the collection using the iterator's remove method.

从此集合中移除指定元素的单个实例(如果存在)(可选操作)。更正式地,如果此集合包含一个或多个此类元素,则删除元素e(o == null?e == null:o.equals(e))。如果此collection包含指定的元素,则返回true(或等效地,如果此集合因调用而更改)。此实现迭代集合以查找指定的元素。如果找到该元素,它将使用迭代器的remove方法从集合中删除该元素。

The bolded section indicates that the method relies on the iterator method. The AbstractCollection class is designed for inheritance, so the documentation makes it clear that extending classes should consider overriding iterator() with care. Failing to document this behavior can lead to clients improperly overriding methods, which can lead to undefined behavior. Worse, if you define methods using MyString as an argument, a malicious user could pass in a subclass of MyString to further cause unexpected and potentially harmful changes to your system.

粗体部分表示该方法依赖于迭代器方法。 AbstractCollection类是为继承而设计的,因此文档清楚地表明扩展类应该考虑重写iterator()。未能记录此行为可能导致客户端不正确地覆盖方法,这可能导致未定义的行为。更糟糕的是,如果您使用MyString定义方法作为参数,恶意用户可以传入MyString的子类,以进一步导致对系统的意外和可能有害的更改。

Mutability is desirable because it makes your program simpler to reason about. Critically immutable objects are inherently thread safe and can be shared easily. They also allow Strings to be cached for performance, but you knew about this.

可变性是可取的,因为它使您的程序更容易推理。严重不可变对象本质上是线程安全的,可以轻松共享。它们还允许为性能缓存字符串,但您知道这一点。

So to answer your question: You can make a mutable, non-final MyString if you wish, but you cannot insure safety. You can only documented inheritance and hope users behave.

所以回答你的问题:如果你愿意,你可以制作一个可变的,非最终的MyString,但是你无法确保安全。您只能记录继承并希望用户行为。

Source: My example was blatantly stolen from Joshua Bloch's Effective Java. Specifically item 15 (minimize mutability) and 17 (design and document for inheritance or else prohibit it) are good sources.

来源:我的例子被Joshua Bloch的Effective Java公然偷走了。特别是项目15(最小化可变性)和17(继承的设计和文件或禁止它)是很好的来源。