0

This answer gives an indication that class String is declared final for thread safety, which does not convince.

This answer does not convince when it says: And so, you make the classes final. There can be no mutable String, because its an immutable class and its final.

Because,

below field with final modifier,

/** The value is used for character storage. */
    private final char value[];

in class String would suffice/indicate that data stored in the created object is suppose to be immutable and thread safe.

So, class String being final has nothing to do with immutability or thread safety.

But it is not clear, why class String is declared final?

Because, as per below class definition, it has final modifier:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{ .... }

So, class String cannot be inherited.

Despite field value[] in class String is declared final, additionaly, What is the necessity for class String also to be final?

Note: Answers to this question will give an idea behind this design decision

overexchange
  • 2,245
  • 2
  • 17
  • 47
  • 2
    That was already discussed on Stack Overflow: http://stackoverflow.com/questions/2068804/why-is-string-class-declared-final-in-java – Kilian Foth Jun 17 '15 at 07:56
  • 1
    see also: [What would truly happen if java.lang.String weren't final?](http://programmers.stackexchange.com/q/97437/31260) – gnat Jun 17 '15 at 07:57
  • 1) I want to make sure that, `class String` being `final` has nothing to do with immutability. But this [answer](http://programmers.stackexchange.com/questions/97437/what-would-truly-happen-if-java-lang-string-werent-final) says here: `Another reason is thread safety: Immutables are always thread safe`. I think thread safety can be ensured by just making the field of `class String` as `final`, but not `class String` as `final`? 2) Similarly this [answer](http://programmers.stackexchange.com/a/256905/131582) does not make sense to me: `And so, you make the ..an immutable class and its final. ` – overexchange Jun 17 '15 at 08:04
  • ["Declaring immutable class final saves programmer from the need to repeat declaring final in each and every method declaration, over and over and over again..."](http://programmers.stackexchange.com/a/214469/31260) – gnat Jun 17 '15 at 08:07
  • @gnat If declaring immutable class as `final` saves programmer from the need to repeat declaring `final` in each and every method declaration, then why required methods are declared `final` in `public final class String{...}`? – overexchange Jun 17 '15 at 08:10
  • to explicitly express an intent I guess. With over 60 methods in this class, it would be way too easy for reader to forget that whole class has been declared final somewhere far away from the point of method declaration. If it had one or two small methods, that could look superfluous... but String is nothing like that – gnat Jun 17 '15 at 08:15
  • ...and if you continue reading the link beyond ellipsis in quote, you'll find out that class level modifier also saves from accidentally omitting final in one of these 60+ methods, which is also important – gnat Jun 17 '15 at 08:21
  • @gnat accidentally? This is not an answer for above question. My question is not duplicate ): I need moderator attention. – overexchange Jun 17 '15 at 08:31
  • I wanna add something: there are reasons to have a final `String`-like class - however, why not just make a `String` interface and then an implementing `ImmutableString` class. So, everyone who cares for immutability e.g. for security or performance reasons can just expect its caller to deliver an `ImmutableString`. Everyone else can just accept a String. Why hasn't it been done this way? – valenterry Jun 17 '15 at 09:14
  • @valenterry After reading my question, when you say: `there are reasons`, please let me know, what are those? – overexchange Jun 17 '15 at 09:55
  • 1
    @overexchange e.g. if someone writes a method that accepts a `String` and he wants to make sure that he knows in before, how its methods are implemented. E.g. he wants to assure that "abc".startsWith("abc") is true and not false because someone has overwritten the method and is not passing a `String` but a `CustomString` class. – valenterry Jun 17 '15 at 10:46
  • @valenterry Every subclass of a class has to pass Liskov test, otherwise such problems would definitely occur. For example, a new subclass to a mutable super class(say) can behave as immutable. – overexchange Jun 17 '15 at 14:47
  • @overexchange Yes, you are totally right. But passing liskov test cannot be guaranteed by the compiler and therefore you want to have some way to make sure that a given type is passing this test for a specific type. The only way I can see to solve this is accepting only the specific type you know (and no subtype) so that you can be sure of the inner workings of that type. I hope we don't missunderstand each other here. – valenterry Jun 18 '15 at 14:34
  • @valenterry **1)** How do we pass the Liskov test? I think like this.. If we consider implementationdetail*PLUS*interface of a super class, the implementation part has to be designed in such a way that, if implementations of super class are changed in next release, it should not affect the public methods overridden in subclass. So, the barrier between interface and implementation should be well designed. **2)** For your point: "liskov test cannot be guaranteed by the compiler" that is not at least my problem, If I have the code in my hand, I would refactor and make it right!!! – overexchange Jun 18 '15 at 14:46
  • @overexchange It's probably not *your* problem, but it's a problem for some people who want to make sure that their method *always* works, no matter what. So they decided to make `String` final to achieve this. Their mistake was probably not to make an interface for `String`. – valenterry Jun 18 '15 at 14:54

2 Answers2

1

You answered your question in your question.

Class String cannot be inherited because it has a final modifier in the class definition. The final modifier does just that in a class definition, declares a class which cannot be inherited from, it has nothing to do with immutability in this case.

The rationale behind this is that a programmer may subclass String therefore have an object which "looks like" a String (i.e. can be passed to methods which take a String argument) however is mutable whereas String is expected to be immutable.

ALXGTV
  • 1,475
  • 1
  • 12
  • 10
  • I understand that `class String` being `final` has nothing to do with immutability. But why `class String` is declared `final`? Of course classes that are final cannot be inherited. But what is the necessity for `class String` to be `final`? – overexchange Jun 17 '15 at 08:20
  • Edited my response – ALXGTV Jun 17 '15 at 08:35
  • Can you be more precise on, how subclass designer would treat as mutable? I am not clear with your updated response. – overexchange Jun 17 '15 at 08:39
  • @overexchange If String would not be final, I could subclass it and use another mutable (!!) field to store the raw `char[]`, overriding all methods to use that value, which makes it possible to pass an object which is both recognised by the type checker as a String and mutable. – 11684 Jun 17 '15 at 10:44
  • Just to give an example the String contains a replace(oldChar, newChar) method. String.replace returns a NEW string with each occurrence of oldChar replaced with newChar. If String were not final, it would be possible to subclass String and override the replace method to mutate the string in place instead of returning a copy. – ALXGTV Jun 17 '15 at 12:47
  • Any method which takes a String will now also be able to take the new subclass of String as an argument, However the method may rely on the String to be immutable (and thus thread safe). – ALXGTV Jun 17 '15 at 12:49
  • 1
    Consider the nefarious String subclasses too: `class AlwaysTrueString extends String { public boolean equals(Object o) { return 1; }}` and then pass it into a method somewhere that looks like `boolean passwordMatch(String password)` This would be **bad**. Being able to reason how String works is important. Having to worry if each String that you dealt with to or from other sources might be designed nefariously makes it much harder for me to write simple code and reason about how that code works. –  Jun 17 '15 at 13:26
  • @ALXGTV For you point: "it would be possible to subclass String and override the `replace` method to mutate the string", I would say, a class can be introduced as subclass, if it passes Liskov test. If subclass does not pass Liskov test, then there is a chance to tamper at any level. I am still not clear, why `class String` is `final`? – overexchange Jun 17 '15 at 14:45
  • @overexchange The Liskov test is a test to see whether you need inheritance or composition. Any object inherited from String is a String. Anyway it's part of Java's philosophy to enforce safety i.e. to minimize the chance of shooting yourself in the foot which is probably the reason why String is final. – ALXGTV Jun 17 '15 at 17:04
  • @ALXGTV LSP says: if `S`is a subtype of `T`, then objects of type `T` may be replaced with objects of type `S` (i.e., objects of type `S` may substitute objects of type `T`) without altering any of the desirable properties of that program (correctness, task performed, etc.). – overexchange Jun 17 '15 at 18:06
  • Yes but the LSP is not a semantic guarantee, it is a merely a test on the programmers part, i.e. it is the programmers responsibility to uphold this principle, if there was no final keyword on String, there would be nothing stopping me from subclassing string and violating this principle, like I said earlier Java's philosophy is to enforce safety. – ALXGTV Jun 17 '15 at 18:24
  • @ALXGTV For your point: "it is a merely a test on the programmers part". So, forget about `class String`, any class class I write has to be non-final because other programmer may not hold responsibility to uphold this principle, while subclassing. What are we talking here? – overexchange Jun 18 '15 at 04:24
  • @overexchange You mean has to be final not "non-final"? Anyway it depends on your judgement, if you believe there is no need for any class to inherit from your class and believe inheriting from that class can cause issues in the future, then declare it final, if you believe that you may need to inherit from it in the future, then don't declare it final. When it comes to String the Java developers obviously decided that there is no need for any class to inherit from String hence it is final. – ALXGTV Jun 18 '15 at 07:18
  • @overexchange Yes this is actually right (I think you meant "final" and not "non-final"). See also this post (#7) which explains it quite good: http://www.yegor256.com/2014/11/20/seven-virtues-of-good-object.html – valenterry Jun 18 '15 at 14:38
  • @valenterry I am trying to say that, it is practically impossible to have every concrete `class` as `final` to just ensure that sub classing does not break the rules. I am not sure, if this point is practically possible: `A good object comes from either a final or abstract class`. Instead one would think to create good barrier between implementation and interface within super class. If you make the `class` as `final`, with the fear that, subclass would break the rules, then that mean, you did not create the barrier within your class well. – overexchange Jun 18 '15 at 15:01
  • @overexchange No that's wrong. Making a class final so one can assert certain behaviour and working out an abstract interface with different possible implementations is no contradiction. You can do both at the same time. Even though you have one interface with 10 final classes, the "barrier" between the 10 implementations and the contract is still there and it's good to have it. – valenterry Jun 18 '15 at 15:05
  • @valenterry Wrt post #7, Using `final`, "You can never break me; I'm a black box for you". I would say, breaking responsibility of my class(after subclassing) is completely dependent on quality of designing abstraction, but not on the programmer who is sub classing. Root cause is, my class is bad data abstraction. – overexchange Jun 18 '15 at 15:17
  • @overexchange what do you mean "dependent on me"? Everyone who can subclass it can break it. You can't prevent it unless you are using only your own code - which in real world is rarely the case. – valenterry Jun 18 '15 at 15:19
0

It doesn't matter that value[] is final when none of the methods on String are not. If string class were not final, I could derive and override all the methods and in effect have a mutable string.

Esben Skov Pedersen
  • 5,098
  • 2
  • 21
  • 24