java.lang.String is declared as final, however are there any mechanisms available legitimate or otherwise to extend it and replace the equals(String other) method?
6 Answers
No, absolutely not. If you want some "other" kind of string, create another type which might contain a string:
public final class OtherString {
private final String underlyingString;
public OtherString(String underlyingString) {
this.underlyingString = underlyingString;
}
// Override equals however you want here
}
14 Comments
OtherString s = new OtherString("hi");String is final.I guess the closest you can come is making some class that implements CharSequence. Most JDK string manipulation methods accept a CharSequence. StringBuilder for example. Combined with a good implementation of toString(), the various methods of String and valueOf(), you can come pretty close to a natural substitute.
2 Comments
.length() == 0 checks in my code!Now, there is a way. With manifold it's possible to extend every Java Class. Here is an example for String:
package extensions.java.lang.String;
import manifold.ext.api.*;
@Extension
public class MyStringExtension {
public static void print(@This String thiz) {
System.out.println(thiz);
}
@Extension
public static String lineSeparator() {
return System.lineSeparator();
}
}
Can than be used as follow:
String name = "Manifold";
name.print();
String.lineSeparator();
Another example can be found here: https://jaxenter.com/manifold-code-generator-part-2-151762.html
Notice, that manifold is still alpha.
1 Comment
It is not possible to directly inherit String class as it is final. Also wrapper classes java.lang.Integer, java.lang.Float, etc... are final.
1 Comment
I wrote a simple Strings class that mimics java.lang.String and can be extended. This is just to demonstrate the core implementation requirements behind String are not "mysterious" or "complicated". And, you can use it to do things like create a password extension and manage strings more effectively.
Needs:
- native call to big-endian. (see private static native boolean isBigEndian();)
- other String methods.
package com.paintedintel.util; import java.nio.charset.StandardCharsets; /** * * @author David Urry * @date 2/8/2020 * * Strings is a light weight string implementation based on StringUTF16. * It's sole purpose is to create a system where strings can be extended * so that the type of string can be extended without the weight of carrying * extra object references. * * Strings extension is important for 2 reasons: * 1) The extra object reference slows the code down by a factor of 50% making * a 10X speed improvement only 5X. As the object of looking at/comparing and * otherwise managing strings is expensive. * 2) The code understanding benefits greatly from understanding the type of string * you are working with (Name, Value, Field, InitValue, Comment...). The constant * evaluation of List<String> for example is greatly simplified when observing * List<Field> instead. * * This problem was also greatly simplified by working with Type, Domain, Datum, * StreamDomain, StreamCase and other objects as complex objects. */ public class Strings { final byte[] value; /** Cache the hash code for the string */ private int hash; // Default to 0 protected Strings(String value){ if (value != null) { this.value = value.getBytes(); this.hash = value.hashCode(); } else { this.value = new byte[0]; this.hash = 0; } } Strings(byte[] value){ this.value = value; this.hash = Strings.hashCode(value); } @Override public String toString() { return new String(value, StandardCharsets.UTF_8); } public String str() { return toString(); } public boolean equals(String str) { return (str == null)?((value == null || this.length() == 0)?true:false):str.hashCode() == value.hashCode(); } public boolean eq(String str) { return equals(str); } byte[] getBytes() { return value; } int getHash() { return hash; } public int length() { return value.length >> 1; } /** * this is based on StringUTF16 * @param value * @return */ synchronized public static int hashCode(byte[] value) { int h = 0; int length = value.length >> 1; for (int i = 0; i < length; i++) { h = 31 * h + getChar(value, i); } return h; } // intrinsic performs no bounds checks synchronized static char getChar(byte[] val, int index) { assert index >= 0 && index < length(val) : "Trusted caller missed bounds check"; index <<= 1; return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) | ((val[index] & 0xff) << LO_BYTE_SHIFT)); } //private static native boolean isBigEndian(); // private static boolean isBigEndian() { // //as of 2018 there are no major BigEndian systems left. // // This is because it's less processing to convert & work with // // Little-Endian. // return false; // } static final int HI_BYTE_SHIFT = 0; static final int LO_BYTE_SHIFT = 8; // static { // if (isBigEndian()) { // HI_BYTE_SHIFT = 8; // LO_BYTE_SHIFT = 0; // } else { // HI_BYTE_SHIFT = 0; // LO_BYTE_SHIFT = 8; // } // } synchronized public static int length(byte[] value) { return value.length >> 1; } }
If programmers were free to extend the String class, civilization - as we know it - could collapse.MyClassand then be able to doMyClass = 'My String'. Also there are languages that do allow you to override / create your own String classes... C++ springs to mind. I'm not saying I like C++ string handling (au contraire), but it's not like civilization has collapsed due to it.