Why are Wrapper Classes, String,... final ?

Many classes in the Core Java API are final (Wrapper classes, String, Math). Why is it so ?

Wont it be nice if they were extendable ? What if I want to create a class "SpecialString" which will inherit most of the functionality from the String class and have its own version of the equals() method.

And the Math class,it is marked abstract final ?

Am sure these facts would have considered by the API designers before nodding in favour of making the classes final. can someone pls justify this ?

Final, immutable Strings and wrapper objects let you treat them as though they were primitives. You never have to copy them; you can safely give out references to them without worrying about them being changed -- this has both obvious security advantages and also robustness advantages. Their well-understood behaviors make them ideal for use as keys in Maps.

If String wasn't final and immutable, then you'd have to be copying Strings everywhere, which would make your code both uglier and far less efficient.

Consider this. Currently new String("a").equals("a") == true. But what if you could override the equals method to do whatever you wanted! Now suddenly this could happen:

Developing good or bad code is upto the developer. In either case, the developer would be publishing the API doc for the overridden method. Only if ppl find my Class appropriate for them, they'll go ahead and use it.

What if the developer is in a really pressing need to extend String ?

Nathaniel, for sure am missing something...pls clarify

Regards, Arvind

Arvind Sampath
Ranch Hand

Joined: May 11, 2005
Posts: 144

posted Jul 22, 2005 08:16:00

0

If String wasn't final and immutable, then you'd have to be copying Strings everywhere, which would make your code both uglier and far less efficient.

I have no probs reg the immutability of Strings. My concern is the "final" access modifier. Is it possible to make the String object mutable if one were allowed to extend the class?

Is it possible to make the String object mutable if one were allowed to extend the class?

Yes. You could override every method, and have them return whatever you wanted. They could completely ignore the actual methods of String itself, right? So you could make a String whose contents randomly changed every two seconds.

Originally posted by Arvind Sampath: Only if ppl find my Class appropriate for them, they'll go ahead and use it.

Ah, but you're not thinking about what inheritance means. If you write a class that extends String, then you can pass an instance of that class as an argument to any method that accepts a String. Therefore, if String was not final (or equivalently, if every method weren't final,) then the entire Java API (for example) would have to be written to assume nothing about how Strings behave. It would be vastly less efficient, and would not be secure. How could, for example, an Applet container restrict the network connections an Applet could make if you could pass a String address to the URL constructor, then change the address it referred to after the security check was done!

Therefore, if String was not final (or equivalently, if every method weren't final,) then the entire Java API (for example) would have to be written to assume nothing about how Strings behave. It would be vastly less efficient, and would not be secure.

This is what i understood from the above quote. Some of the methods in the Java API (which accept String as a parameter) may invoke its instance methods (say equals()). In such a case, if we had passed an object of our-version-of-String, then the new version of equals() would get invoked which as you pointed out would be deadly dangerous. Is my understanding right ?

I guess am still not getting this right. Will it be possible for us to make a String Mutable , if we were allowed to extend it, Would you mind giving a Layman explanation for this ? I mean, if we pass our-version-of-String to a Java API(as you said to the URL constructor),how would we ever change the passed string after it ? I missing something out here..Pls Clarify...

One word: threads. Remember that Applets, for good reason, are only allowed to open network connections back to the server they came from. Otherwise, a tricky applet could let itself be downloaded behind a firewall, then, for example, connect directly to a database server normally protected by that firewall.

If Strings weren't final, you could, for example, do this in an applet:

1) Define a mutable subclass of String 2) Create a mutable string instance containing the address of the web server 3) Start a new thread ("Thread 2") which starts out sleeping 4) In the main thread, create a Socket object using the string from #2 5) In the main thread, the SecurityManager would check that the String represented a legal address for the Applet to connect to 6) Now Thread 2 wakes up, and changes the String from step 2 to point to the database server 7) The main thread continues using the changed address. The Socket constructor completes, and you get an open connection to the database server!

Getting the timing for this just right would be tricky -- but this sort of attack is very real and has been carried out in other environments. Java is specifically designed to prevent this.

Now, if Strings were mutable, the only way to avoid this would be to copy the String before invoking the security manager. Now you have to always pay the expense of a copy, and if you forget the copy, you've got a potential bug. Billions of lines of existing Java code are written under the assumption that Strings don't need to be copied!

Leaving immuatable aside ... it would seem to be nice to extend String and add new behavior. For example, I'd like it to have all the nifty methods that the REXX language provides. Instead I wrote a class with static methods that mimic those methods.

If you Google for the "Liskov Substitution Principle" you'll find some strong arguments that any method that works with class X should work just as well with any subclass. That's a nice design principle you should try to follow yourself but Sun simply didn't trust you do to it. There is a risk that you might change the behavior of some String method and break a ton of existing code when you start passing in your object instead of String.

A good rule to follow in your own work is never extend a concrete class. It's not a drop dead necessity, but it is an easy way to avoid a lot of trouble.

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi

Ernest, you've made me understand the risks involved in making the String class Extendable. Thanks so much.

One final Clarification Pls. I am very much intersted to know as to how we can make a String mutable by extending it.

6) Now Thread 2 wakes up, and changes the String from step 2 to point to the database server

Let us say, I've extended String and passed the Extended-String-Object to Thread 2. Now how is it going to Change the String. How do i write a method in my Extended Class which makes a modifies the String Object ?

Here's a simple way to imagine it. Take the source code for java.lang.String (the source for all the API classes is freely available.) At the top where it says "public class String", change it to "public class MyString extends String". Now add a method "setStringValue()" which modifies the char[] which is part of MyString. There you go: you've got a mutable String subclass.

Now add a method "setStringValue()" which modifies the char[] which is part of MyString.

Yep, I saw the src code of String.java...hmmm...Now I do understand what all one can do if our dear String class was'nt final

Just when I thought it's all over and I ve got it damn clear, I got this stupid doubt when I went back to your tricky-applet example. "Now that we have access to the src code, what if i remove the 'final' which sits before 'public class String', compile this, add this as part of java/lang and create a Mutable subclass ?"

I know how damn stupid this question may sound ? But no matter how stupid it is, am not able to come with a convincing answer for myself.

I tried to answer it myself...The String class resides inside the ext folder of the jre. So while running the Applet in a remote machine, the JVM would load the String class from the ext folder of that machine. Does this mean that if i gained access to that machine and changed the String class there to be non-final, I can have a mutable subclass which i would pass to the URL constructor and do all kind of malicious activities ?

can u pls clarify this for me, Ernest ?

Ernest, I thank you so much for all your efforts in answering my questions. Now I understand why the core API designers chose to make most of their classes final.

Another way to create your own "flavor" of String is to create a class called MyString that encapsulates a String:

Here's an example of how it would be used:

Produces output:

Of course, because MyString isn't derived from String, we cannot use it directly wherever a String is required -- we'd have to invoke the toString() method that I've provided as shown below:

Nonetheless, encapsulating a standard object within a custom class is a useful design technique; in fact, I'll start a new thread to give an example of how this approach can be used with respect to Collections ... stay tuned!

I tried to answer it myself...The String class resides inside the ext folder of the jre. So while running the Applet in a remote machine, the JVM would load the String class from the ext folder of that machine. Does this mean that if i gained access to that machine and changed the String class there to be non-final, I can have a mutable subclass which i would pass to the URL constructor and do all kind of malicious activities ?

can u pls clarify this for me, Ernest ?

Yes, if you are able to physically copy a modified String.class into the JDK installation, then yes, you could create a modifiable String. But if you can do that, you already have physical access to the machine, and therefore the network; so in our applet/firewall/database scenario, you personally already have access to a machine behind the firewall, and therefore can get to the database, right? The JVM has no more defenses against a human physically modifying it than any other program would.

But an applet container will refuse to download any classes in the java.* namespace, so without physical access to the machine, this can't be done.

Arvind Sampath
Ranch Hand

Joined: May 11, 2005
Posts: 144

posted Jul 25, 2005 08:06:00

0

But if you can do that, you already have physical access to the machine, and therefore the network; so in our applet/firewall/database scenario, you personally already have access to a machine behind the firewall, and therefore can get to the database, right?

Am Convinced now!

This thread has been great learning journey for me. The slope of my learning curve is getting better & better from the day i joined (rather started participating ) in this forum. Thanks Ernest for all your efforts in making me understand this not-found-in-books-i've-ever-read-so-far-topic.

Another way to create your own "flavor" of String is to create a class called MyString that encapsulates a String

Jacquie, Thanks for starting this topic. I though on these lines before, but i had my own reservations following this practice. Anyway, Let us discusss this in the new thread that you said u'll start.

Thanks to all the Ranchers who are helping me in my journey to become a better java developer.