简体   繁体   中英

Extend java.lang.String

java.lang.String 被声明为 final,但是是否有任何可用的合法或其他机制来扩展它并替换 equals(String other) 方法?

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
}

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.

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.

You cannot extend a class that is marked as final. You can use composition to either put a String object inside or you can hand roll your own version. This can be accomplished via character arrays and the other magic that goes into creating String classes.

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.

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; } }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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