JavaのStringクラスはfinal型でスーパクラスにならなようになっている。
これは、書き換え可能になると、セキュリティ上の問題と、メモリの問題、同期の問題などいろいろと考える必要が出てくるからだそうだ。
わりとしっかりとした回答は下記のURLにありました。(英語)
http://javarevisited.blogspot.jp/2010/10/why-string-is-immutable-in-java.html
委譲パターンでそっくりなクラスを作ってみる。
委譲パターンを使うデメリット 文字列だと""でインスタンスを作ることができた。 インスタンスを作ると、newしないといけなくなる。""でnewというシンタックスシューガーを手放すのはちょっと痛い。
拡張性を手に入れるということは、自分のニーズに合わせて進化させることができるということ。
領域は、メモリの消費を気にせず、セキュリティも気にせず、効率重視な作業に特化するとする作業領域はあるはずだ。要は使い分けが必要である。
Stringクラスを委譲パターンで表現してみました。
package base; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.Locale; public class S { private String core; public int length() { return core.length(); } public boolean isEmpty() { return core.isEmpty(); } public char charAt(int index) { return core.charAt(index); } public int codePointAt(int index) { return core.codePointAt(index); } public int codePointBefore(int index) { return core.codePointBefore(index); } public int codePointCount(int beginIndex, int endIndex) { return core.codePointCount(beginIndex, endIndex); } public int offsetByCodePoints(int index, int codePointOffset) { return core.offsetByCodePoints(index, codePointOffset); } public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { core.getChars(srcBegin, srcEnd, dst, dstBegin); } public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) { core.getBytes(srcBegin, srcEnd, dst, dstBegin); } public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { return core.getBytes(charsetName); } public byte[] getBytes(Charset charset) { return core.getBytes(charset); } public byte[] getBytes() { return core.getBytes(); } public boolean equals(Object anObject) { return core.equals(anObject); } public boolean contentEquals(StringBuffer sb) { return core.contentEquals(sb); } public boolean contentEquals(CharSequence cs) { return core.contentEquals(cs); } public boolean equalsIgnoreCase(String anotherString) { return core.equalsIgnoreCase(anotherString); } public int compareTo(String anotherString) { return core.compareTo(anotherString); } public int compareToIgnoreCase(String str) { return core.compareToIgnoreCase(str); } public boolean regionMatches(int toffset, String other, int ooffset, int len) { return core.regionMatches(toffset, other, ooffset, len); } public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) { return core.regionMatches(ignoreCase, toffset, other, ooffset, len); } public boolean startsWith(String prefix, int toffset) { return core.startsWith(prefix, toffset); } public boolean startsWith(String prefix) { return core.startsWith(prefix); } public boolean endsWith(String suffix) { return core.endsWith(suffix); } public int hashCode() { return core.hashCode(); } public int indexOf(int ch) { return core.indexOf(ch); } public int indexOf(int ch, int fromIndex) { return core.indexOf(ch, fromIndex); } public int lastIndexOf(int ch) { return core.lastIndexOf(ch); } public int lastIndexOf(int ch, int fromIndex) { return core.lastIndexOf(ch, fromIndex); } public int indexOf(String str) { return core.indexOf(str); } public int indexOf(String str, int fromIndex) { return core.indexOf(str, fromIndex); } public int lastIndexOf(String str) { return core.lastIndexOf(str); } public int lastIndexOf(String str, int fromIndex) { return core.lastIndexOf(str, fromIndex); } public String substring(int beginIndex) { return core.substring(beginIndex); } public String substring(int beginIndex, int endIndex) { return core.substring(beginIndex, endIndex); } public CharSequence subSequence(int beginIndex, int endIndex) { return core.subSequence(beginIndex, endIndex); } public String concat(String str) { return core.concat(str); } public String replace(char oldChar, char newChar) { return core.replace(oldChar, newChar); } public boolean matches(String regex) { return core.matches(regex); } public boolean contains(CharSequence s) { return core.contains(s); } public String replaceFirst(String regex, String replacement) { return core.replaceFirst(regex, replacement); } public String replaceAll(String regex, String replacement) { return core.replaceAll(regex, replacement); } public String replace(CharSequence target, CharSequence replacement) { return core.replace(target, replacement); } public String[] split(String regex, int limit) { return core.split(regex, limit); } public String[] split(String regex) { return core.split(regex); } public String toLowerCase(Locale locale) { return core.toLowerCase(locale); } public String toLowerCase() { return core.toLowerCase(); } public String toUpperCase(Locale locale) { return core.toUpperCase(locale); } public String toUpperCase() { return core.toUpperCase(); } public String trim() { return core.trim(); } public String toString() { return core.toString(); } public char[] toCharArray() { return core.toCharArray(); } public String intern() { return core.intern(); } }
ほかにも、個人的に思うこと
シングルクォートでくくれない。JavaScript?を使うとそう思う。