简体   繁体   English

为什么String.length()是一个方法?

[英]Why is String.length() a method?

If a String object is immutable (and thus obviously cannot change its length), why is length() a method, as opposed to simply being public final int length such as there is in an array? 如果一个String对象是不可变的(因此显然不能改变它的长度),为什么length()是一个方法,而不是简单地成为public final int length例如在数组中?

Is it simply a getter method, or does it make some sort of calculation? 它只是一个getter方法,还是进行某种计算?

Just trying to see the logic behind this. 试着看看这背后的逻辑。

Java is a standard, not just an implementation. Java是一种标准,而不仅仅是一种实现。 Different vendors can license and implement Java differently, as long as they adhere to the standard. 不同的供应商可以以不同的方式许可和实施Java,只要它们符合标准即可。 By making the standard call for a field, that limits the implementation quite severely, for no good reason. 通过对字段进行标准调用,可以非常严重地限制实现,这是没有充分理由的。

Also a method is much more flexible in terms of the future of a class. 对于课程的未来而言,方法也更灵活。 It is almost never done, except in some very early Java classes, to expose a final constant as a field that can have a different value with each instance of the class, rather than as a method. 除了在一些非常早期的Java类中,几乎从未完成将最终常量公开为一个字段,该字段可以与类的每个实例具有不同的值,而不是作为方法。

The length() method well predates the CharSequence interface, probably from its first version. length()方法早于 CharSequence接口,可能是它的第一个版本。 Look how well that worked out. 看看效果如何。 Years later, without any loss of backwards compatibility, the CharSequence interface was introduced and fit in nicely. 多年以后,没有任何向后兼容性的损失,CharSequence接口被引入并且非常适合。 This would not have been possible with a field. 对于一个领域来说这是不可能的。

So let's really inverse the question (which is what you should do when you design a class intended to remain unchanged for decades): What does a field gain here, why not simply make it a method? 所以,让我们真正颠倒这个问题(当你设计一个几十年来保持不变的类时,你应该做什么):这里有什么领域,为什么不简单地把它作为一个方法呢?

Perhaps a .length() method was considered more consistent with the corresponding method for a StringBuffer , which would obviously need more than a final member variable. 也许.length()方法被认为与StringBuffer的相应方法更加一致,这显然需要多于final成员变量。

The String class was probably one of the very first classes defined for Java, ever. String类可能是为Java定义的最早的类之一。 It's possible (and this is just speculation) that the implementation used a .length() method before final member variables even existed. 有可能(这只是推测)实现在final成员变量存在之前使用了.length()方法。 It wouldn't take very long before the use of the method was well-embedded into the body of Java code existing at the time. 在将该方法的使用很好地嵌入到当时存在的Java代码体中之前,不需要很长时间。

Perhaps because length() comes from the CharSequence interface . 也许是因为length()来自CharSequence接口 A method is a more sensible abstraction than a variable if its going to have multiple implementations. 如果一个方法有多个实现,那么它是一个比变量更合理的抽象。

This is a fundamental tenet of encapsulation. 这是封装的基本原则。

Part of encapsulation is that the class should hide its implementation from its interface (in the "design by contract" sense of an interface, not in the Java keyword sense). 封装的一部分是类应该从其接口隐藏其实现(在“按合同设计”的接口意义上,而不是在Java关键字意义上)。

What you want is the String's length -- you shouldn't care if this is cached, calculated, delegates to some other field, etc. If the JDK people want to change the implementation down the road, they should be able to do so without you having to recompile. 你想要的是String的长度 - 你不应该关心它是否被缓存,计算,委托给其他领域等等。如果JDK人员希望改变实施方式,他们应该能够这样做你必须重新编译。

You should always use accessor methods in public classes rather than public fields, regardless of whether they are final or not (see Item 14 in Effective Java). 您应该始终在公共类而不是公共字段中使用访问器方法,无论它们是否为final(请参阅Effective Java中的第14项)。

When you allow a field to be accessed directly (ie is public) you lose the benefit of encapsulation, which means you can't change the representation without changing the API (you break peoples code if you do) and you can't perform any action when the field is accessed. 当您允许直接访问字段(即公开)时,您将失去封装的好处,这意味着您无法在不更改API的情况下更改表示(如果您这样做,则会破坏人员代码)并且您无法执行任何操作访问该字段时的操作。

Effective Java provides a really good rule of thumb: 有效的Java提供了一个非常好的经验法则:

If a class is accessible outside its package, provide accessor methods, to preserve the flexibility to change the class's internal representation. 如果类可以在其包外部访问,则提供访问器方法,以保持更改类的内部表示的灵活性。 If a public class exposes its data fields, all hope of changing its representation is lost, as client code can be distributed far and wide. 如果公共类公开其数据字段,则所有更改其表示的希望都将丢失,因为客户端代码可以远程分发。

Basically, it is done this way because it is good design practice to do so. 基本上,它是这样做的,因为这样做是很好的设计实践。 It leaves room to change the implementation of String at a later stage without breaking code for everyone. 它留有空间在稍后阶段更改String的实现,而不会破坏每个人的代码。

String is using encapsulation to hide its internal details from you. String使用封装来隐藏其内部细节。 An immutable object is still free to have mutable internal values as long as its externally visible state doesn't change. 只要外部可见状态不变,不可变对象仍然可以自由地具有可变内部值。 Length could be lazily computed. 长度可以懒惰计算。 I encourage you to take a look as String's source code. 我鼓励你看一下String的源代码。

Checking the source code of String in Open JDK it's only a getter. Open JDK中检查String的源代码,它只是一个getter。

But as @SteveKuo points out this could differ dependent on the implementation. 但正如@SteveKuo指出的那样,这可能因实施而异。

In most current jvm implementations a Substring references the char array of the original String for content and it needs start and length fields to define their own content, so the length() method is used as a getter. 在大多数当前的jvm实现中,Substring引用内容的原始String的char数组,它需要start和length字段来定义自己的内容,因此length()方法用作getter。 However this is not the only possible way to implement String. 但是,这不是实现String的唯一可能方法。

In a different possible implementation each String could have its own char array and since char arrays already have a length field with the correct length it would be redundant to have one for the String object, since String.length() is a method we don't have to do that and can just reference the internal array.length . 在一个不同的可能实现中,每个String都可以有自己的char数组,因为char数组已经有一个长度正确的长度字段,所以String对象有一个冗余字段,因为String.length()是我们不知道的方法。必须这样做,只能引用内部array.length。

These are two possible implementations of String, both with their own good and bad parts and they can replace each other because the length() method hides where the length is stored (internal array or in own field). 这是String的两种可能实现,它们都有自己的好的和坏的部分,并且它们可以互相替换,因为length()方法隐藏了存储长度的位置(内部数组或在自己的字段中)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM