我可以在Java中向String类添加新方法吗?

时间:2008-09-17 10:23:40

标签: java string

我想在Java中的String类中添加方法AddDefaultNamespace(),以便我可以键入"myString".AddDefaultNamespace()而不是DEFAULTNAMESPACE + "myString",以获得类似"MyDefaultNameSpace.myString"的内容。我不想添加另一个派生类(例如PrefixedString)。

也许这种做法对你不利,但我个人讨厌使用+。但是,无论如何,是否可以在Java中向String类添加新方法?

谢谢和问候。

15 个答案:

答案 0 :(得分:60)

String是一个最终类,这意味着它无法扩展到您自己的实现。

答案 1 :(得分:24)

嗯,实际上每个人都缺乏想象力。我需要编写自己的startsWith方法版本,因为我需要一个不区分大小写的方法。

class MyString{
    public String str;
    public MyString(String str){
        this.str = str;
    }
    // Your methods.
}

然后很简单,你就这样制作你的字符串:

MyString StringOne = new MyString("Stringy stuff");

当你需要在String库中调用一个方法时,这样做很简单:

StringOne.str.equals("");

或类似的东西,你有它...扩展String类。

答案 2 :(得分:17)

正如其他人都注意到的那样,你不允许扩展String(由于最终)。但是,如果您感觉非常疯狂,可以修改String本身,将其放在jar中,并在-cbootclasspath / p:myString.jar之前添加bootclasspath以实际替换内置的String类。

由于我不会进入的原因,我实际上已经这样做了。您可能有兴趣知道即使您可以替换该类,但在Java的每个方面,String的内在重要性意味着它在整个JVM启动过程中使用,并且一些更改将简单地破坏JVM。添加新方法或构造函数似乎没有问题。添加新字段非常冒险 - 特别是添加对象或数组似乎会破坏事情,尽管添加原始字段似乎有效。

答案 3 :(得分:6)

这是不可能的,因为String是Java中的最终类。

您可以随时使用辅助方法为前缀添加前缀。如果您不喜欢它,您可以查看Groovy或Scala,JRuby或JPython都是与Java兼容的JVM语言,并允许这样的扩展。

答案 4 :(得分:3)

班级宣言几乎都说明了,因为你不能继承它,因为它是最后的。 你可以在当前实现自己的字符串类,但这只是一个麻烦。

public final class String

C#(。net 3.5)具有使用扩展器metods的功能,但遗憾的是java没有。有一些名为nice http://nice.sourceforge.net/的java扩展,虽然它似乎为java添加了相同的功能。

以下是用Nice语言编写示例的方法(扩展名为 爪哇):

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

找到有关尼斯的更多信息

答案 5 :(得分:2)

不可能,这是件好事。 String是一个String。它的行为被定义,偏离它将是邪恶的。此外,它标记为final,意味着即使您想要也不能将其子类化。

答案 6 :(得分:2)

正如其他人所说,不,你不能将String子类化,因为它是最终的。但是可能会有以下帮助吗?

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

}

或者也许:

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

}

答案 7 :(得分:2)

是<!/强>

基于您的需求(向String添加不同的命名空间而不使用派生类)您可以使用项目Lombok来实现这一点,并在String上使用函数,如下所示:

String i = “This is my String”;
i.numberOfCapitalCharacters(); // = 2

使用Gradle和IntelliJ构思请按照以下步骤操作:

  1. 从intelliJ plugins repository下载lombok插件。
  2. 将lombok添加到gradle中的依赖项,如:compileOnly 'org.projectlombok:lombok:1.16.20'
  3. 转到"Settings > Build > Compiler > Annotation Processors"并启用注释处理
  4. 使用扩展函数创建一个类,并添加如下静态方法:

    public class Extension { public static String appendSize(String i){ return i + " " + i.length(); } }

  5. 注释要使用方法的类,如下所示:

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

  6. 现在你可以在任何类中的任何字符串上使用.appendSize()方法,只要你有(注释它),上面例子(This is a String!)的生成结果就是:This is a String! 17

答案 8 :(得分:1)

最好使用StringBuilder,它有方法append()并完成你想要的工作。 String类是final,无法扩展。

答案 9 :(得分:1)

使用关键字“将方法添加到内置类中”的人可能会在这里结束。如果您要将方法添加到非最终类(如HashMap),则可以执行此类操作。

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

现在将此类的新实例定义为:

ObjectMap objectMap = new ObjectMap(new HashMap<String, Object>();

现在,您可以访问内置Map类的所有方法,以及新实现的方法。

objectMap.getInt("KEY");

修改

在上面的代码中,为了访问map类的内置方法,你必须使用

objectMap.map.get("KEY");

这是一个更好的解决方案:

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

现在您不必致电

objectMap.map.get("KEY");

只需致电

objectMap.get("KEY");

答案 10 :(得分:1)

不能在java中修改字符串类。因为它是最后一堂课。默认情况下,最终班级中的每个方法都是最终的。

String是不可变的或最终的绝对最重要的原因是它被类加载机制使用,因此具有深刻和基本的安全方面。

如果String是可变的或不是最终的,请求加载&#34; java.io.Writer&#34;可能已被改为加载&#34; mil.vogoon.DiskErasingWriter&#34;

答案 11 :(得分:0)

Java String类是final,使其不可变。这是出于效率的原因,并且在没有错误的情况下逻辑扩展是非常困难的;因此,实施者选择将其作为最终类,这意味着它不能通过继承来扩展。

根据single responsibility principle,您希望您的类支持的功能不是String的常规职责的正确部分,命名空间是一个不同的抽象,它更专业。因此,您应该定义一个新类,其中包括String成员并支持您提供所需命名空间管理所需的方法。

不要害怕添加抽象(类)这些是良好的OO设计的本质。

尝试使用class responsibility collaboration (CRC) card来阐明您需要的抽象。

答案 12 :(得分:0)

以前其他贡献者都说过。你不能直接扩展String,因为它是最终的。

如果您使用Scala,则可以使用这样的隐式转换:

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

答案 13 :(得分:-2)

您可以创建自己的String类版本并添加方法: - )

答案 14 :(得分:-2)

实际上,您可以修改String类。如果编辑位于src.zip中的String.java文件,然后重建rt.jar,则String类将添加更多方法。缺点是该代码只能在您的计算机上运行,​​或者如果您提供String.class,并将其放在默认的类路径之前。