我想在Java中的String类中添加方法AddDefaultNamespace(),以便我可以键入"myString".AddDefaultNamespace()而不是DEFAULTNAMESPACE +"myString"以获得类似"MyDefaultNameSpace.myString"的内容。 我也不想添加另一个派生类(例如PrefixedString)。
也许这种方法对您不利,但我个人讨厌使用+。 但是,无论如何,是否有可能向Java中的String类添加新方法?
谢谢并恭祝安康。
String是最终类,这意味着它不能扩展为在您自己的实现上工作。
好吧,实际上每个人都没有想象力。我需要编写自己的startsWith方法版本,因为我需要一个不区分大小写的版本。
1 2 3 4 5 6 7
| class MyString{
public String str;
public MyString(String str){
this.str = str;
}
// Your methods.
} |
然后,这很简单,您可以将String设置为:
1
| MyString StringOne = new MyString("Stringy stuff"); |
当您需要在String库中调用方法时,可以像这样简单地进行操作:
1
| StringOne.str.equals(""); |
或类似的东西,就在那里...扩展String类。
正如其他所有人都指出的那样,不允许扩展String(由于final)。但是,如果您感觉很疯狂,则可以修改String本身,将其放在jar中,并在bootclasspath之前加上-Xbootclasspath / p:myString.jar以实际替换内置的String类。
由于我不愿讨论的原因,我实际上已经做了。您可能想知道,即使您可以替换该类,但String在Java各个方面的内在重要性意味着它在JVM的整个启动过程中都被使用,并且某些更改只会破坏JVM。添加新方法或构造函数似乎没有问题。添加新字段非常容易-特别是添??加对象或数组似乎会破坏事情,尽管添加原始字段似乎可行。
这是不可能的,因为String是Java中的最终类。
您可以随时使用辅助方法作为前缀。如果您不喜欢,可以考虑使用Groovy或Scala,JRuby或JPython都是与Java兼容的JVM语言,并且允许此类扩展。
类声明几乎说明了所有内容,因为您不能继承它,因为它是最终的。
您当然可以实现自己的字符串类,但这很麻烦。
1
| public final class String |
C#(.net 3.5)具有使用扩展程序方法的功能,但可惜的是Java没有。有一些Java扩展名为nice http://nice.sourceforge.net/,尽管这似乎为Java添加了相同的功能。
这是您使用尼斯语言编写示例的方式(
Java):
1 2 3 4 5 6 7 8 9 10 11 12 13
| private String someMethod(String s)
{
return s.substring(0,1);
}
void main(String[] args)
{
String s1 ="hello";
String s2 = s1.someMethod();
System.out.println(s2);
} |
您可以在http://nice.sf.net上找到有关尼斯的更多信息。
就像其他人都说的那样,不可以将String归类,因为它是最终的。但是,以下内容可能会有所帮助吗?
1 2 3 4 5 6 7 8 9 10 11
| public final class NamespaceUtil {
// private constructor cos this class only has a static method.
private NamespaceUtil() {}
public static String getDefaultNamespacedString(
final String afterDotString) {
return DEFAULT_NAMESPACE +"." + afterDotString;
}
} |
或许:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public final class NamespacedStringFactory {
private final String namespace;
public NamespacedStringFactory(final String namespace) {
this.namespace = namespace;
}
public String getNamespacedString(final String afterDotString) {
return namespace +"." + afterDotString;
}
} |
不可能的,那是一件好事。字符串是字符串。它的行为已定义,偏离它是邪恶的。另外,它被标记为final,这意味着即使您愿意也不能将其子类化。
是!
根据您的要求(将不同的名称空间添加到String而不使用派生类),您可以使用项目Lombok做到这一点,并在String上使用功能,如下所示:
1 2
| String i ="This is my String";
i.numberOfCapitalCharacters(); // = 2 |
使用Gradle和IntelliJ想法请按照以下步骤操作:
从intelliJ插件存储库下载lombok插件。
将lombok添加到gradle中的依赖项中,如下所示:compileOnly 'org.projectlombok:lombok:1.16.20'
转到"Settings > Build > Compiler > Annotation Processors"并启用注释处理
使用扩展功能创建一个类,并添加一个静态方法,如下所示:
1 2 3 4 5
| public class Extension {
public static String appendSize(String i){
return i +"" + i.length();
}
} |
在您想使用方法的地方注释类,如下所示:
1 2 3 4 5 6 7 8 9
| import lombok.experimental.ExtensionMethod;
@ExtensionMethod({Extension.class})
public class Main {
public static void main(String[] args) {
String i ="This is a String!";
System.out.println(i.appendSize());
}
} |
现在,您可以在任何类中的任何字符串上使用方法.appendSize(),只要您已对其进行了注释并为上述示例生成了结果
This is a String!
将会:
This is a String! 17
否,您无法在Java中修改字符串类。因为这是最后一堂课。并且默认情况下,final类中存在的每个方法都是final。
String不可更改或最终更改的绝对最重要的原因是它由类加载机制使用,因此具有深远的基础安全方面。
如果String是可变的或不是最终的,则加载" java.io.Writer"的请求可能已更改为加载" mil.vogoon.DiskErasingWriter"
用关键字"将方法添加到内置类"搜索的人们可能会在这里结束。如果要向非最终类(例如HashMap)添加方法,则可以执行以下操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public class ObjectMap extends HashMap<String, Object> {
public Map<String, Object> map;
public ObjectMap(Map<String, Object> map){
this.map = map;
}
public int getInt(String K) {
return Integer.valueOf(map.get(K).toString());
}
public String getString(String K) {
return String.valueOf(map.get(K));
}
public boolean getBoolean(String K) {
return Boolean.valueOf(map.get(K).toString());
}
@SuppressWarnings("unchecked")
public List<String> getListOfStrings(String K) {
return (List<String>) map.get(K);
}
@SuppressWarnings("unchecked")
public List<Integer> getListOfIntegers(String K) {
return (List<Integer>) map.get(K);
}
@SuppressWarnings("unchecked")
public List<Map<String, String>> getListOfMapString(String K) {
return (List<Map<String, String>>) map.get(K);
}
@SuppressWarnings("unchecked")
public List<Map<String, Object>> getListOfMapObject(String K) {
return (List<Map<String, Object>>) map.get(K);
}
@SuppressWarnings("unchecked")
public Map<String, Object> getMapOfObjects(String K) {
return (Map<String, Object>) map.get(K);
}
@SuppressWarnings("unchecked")
public Map<String, String> getMapOfStrings(String K) {
return (Map<String, String>) map.get(K);
}
} |
现在,将此类的新实例定义为:
1
| ObjectMap objectMap = new ObjectMap(new HashMap<String, Object>(); |
现在,您可以访问内置Map类的所有方法,以及新实现的方法。
1
| objectMap.getInt("KEY"); |
编辑:
在上面的代码中,要访问map类的内置方法,您必须使用
1
| objectMap.map.get("KEY"); |
这是一个更好的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| public class ObjectMap extends HashMap<String, Object> {
public ObjectMap() {
}
public ObjectMap(Map<String, Object> map){
this.putAll(map);
}
public int getInt(String K) {
return Integer.valueOf(this.get(K).toString());
}
public String getString(String K) {
return String.valueOf(this.get(K));
}
public boolean getBoolean(String K) {
return Boolean.valueOf(this.get(K).toString());
}
@SuppressWarnings("unchecked")
public List<String> getListOfStrings(String K) {
return (List<String>) this.get(K);
}
@SuppressWarnings("unchecked")
public List<Integer> getListOfIntegers(String K) {
return (List<Integer>) this.get(K);
}
@SuppressWarnings("unchecked")
public List<Map<String, String>> getListOfMapString(String K) {
return (List<Map<String, String>>) this.get(K);
}
@SuppressWarnings("unchecked")
public List<Map<String, Object>> getListOfMapObject(String K) {
return (List<Map<String, Object>>) this.get(K);
}
@SuppressWarnings("unchecked")
public Map<String, Object> getMapOfObjects(String K) {
return (Map<String, Object>) this.get(K);
}
@SuppressWarnings("unchecked")
public Map<String, String> getMapOfStrings(String K) {
return (Map<String, String>) this.get(K);
}
@SuppressWarnings("unchecked")
public boolean getBooleanForInt(String K) {
return Integer.valueOf(this.get(K).toString()) == 1 ? true : false;
}
} |
现在您不必打电话
1
| objectMap.map.get("KEY"); |
只需致电
最好使用StringBuilder,它具有方法append()并完成所需的工作。 String类是最终的,不能扩展。
之前其他贡献者都说过了。您不能直接扩展String,因为它是最终的。
如果要使用Scala,则可以使用如下隐式转换:
1 2 3 4 5 6 7 8 9 10
| object Snippet {
class MyString(s:String) {
def addDefaultNamespace = println("AddDefaultNamespace called")
}
implicit def wrapIt(s:String) = new MyString(s)
/** test driver */
def main(args:Array[String]):Unit = {
"any java.io.String".addDefaultNamespace // !!! THAT is IT! OR?
} |
Java String类是最终的,使其不可变。这是出于效率方面的考虑,并且很难在逻辑上进行扩展而不会出错。因此,实现者选择将其设为最终类,这意味着无法通过继承对其进行扩展。
根据单职责原则,您希望您的类支持的功能不是String的常规职责的一部分,命名空间是一种不同的抽象,它是更专门的。因此,您应该定义一个新类,其中包括String成员,并支持提供所需名称空间管理所需的方法。
不要害怕添加抽象(类),这些是好的OO设计的本质。
尝试使用类责任协作(CRC)卡来阐明所需的抽象。
实际上,您可以修改String类。如果您编辑src.zip中的String.java文件,然后重建rt.jar,则String类将为您添加更多方法。缺点是该代码仅在您的计算机上可用,或者如果您提供String.class并将其放在默认代码之前的classpath中,则该代码将只在您的计算机上起作用。
您可以创建自己的String类版本并添加方法:-)