Могу ли я добавить новые методы в класс String в Java? - PullRequest
23 голосов
/ 17 сентября 2008

Я хотел бы добавить метод AddDefaultNamespace() в класс String в Java, чтобы я мог набрать "myString".AddDefaultNamespace() вместо DEFAULTNAMESPACE + "myString", чтобы получить что-то вроде "MyDefaultNameSpace.myString". Я не хочу добавлять другой производный класс (например, PrefixedString).

Возможно, такой подход не подходит для вас, но я лично ненавижу использовать +. Но, в любом случае, возможно ли добавить новые методы в класс String в Java?

Спасибо и всего наилучшего.

Ответы [ 15 ]

60 голосов
/ 17 сентября 2008

String - последний класс, который означает, что он не может быть расширен для работы над собственной реализацией.

24 голосов
/ 24 июля 2011

Ну, на самом деле, каждый не может придумать. Мне нужно было написать свою собственную версию метода setsWith, потому что мне нужна была версия без учета регистра

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.

17 голосов
/ 17 сентября 2008

Как и все остальные отметили, вы не можете расширять строку (из-за финала). Однако, если вы чувствуете себя действительно дико, вы можете изменить саму String, поместить его в банку и добавить к загрузочному пути путь -Xbootclasspath / p: myString.jar, чтобы фактически заменить встроенный класс String.

По причинам, в которые я не буду вдаваться, я действительно делал это раньше. Возможно, вам будет интересно узнать, что даже если вы можете заменить класс, внутренняя важность String в каждом аспекте Java означает, что он используется во время запуска JVM, и некоторые изменения просто повредят JVM. Добавление новых методов или конструкторов, кажется, не проблема. Добавление новых полей очень рискованно - в частности, добавление объектов или массивов, кажется, ломает вещи, хотя добавление примитивных полей, кажется, работает.

6 голосов
/ 17 сентября 2008

Это невозможно, поскольку String - последний класс в Java.

Вы можете использовать вспомогательный метод все время, когда хотите что-то добавить к префиксу. Если вам это не нравится, вы можете взглянуть на Groovy или Scala, JRuby или JPython являются языками для JVM, совместимыми с Java, и которые допускают такие расширения.

3 голосов
/ 17 сентября 2008

Объявление класса говорит все это в значительной степени, так как вы не можете наследовать это, потому что оно окончательно. Конечно, вы можете реализовать свой собственный класс строк, но это, вероятно, просто хлопот.

public final class String

C # (.net 3.5) имеет функциональность для использования методов расширения, но, к сожалению, java нет. Существует некоторое расширение Java под названием nice http://nice.sourceforge.net/, хотя, похоже, оно добавляет ту же функциональность в java.

Вот как бы вы написали свой пример на языке Nice (расширение Java):

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

2 голосов
/ 18 мая 2018

ДА!

Исходя из ваших требований (добавить другое пространство имен в строку и не использовать производный класс), вы можете использовать проект Lombok для этого и использовать функциональность в строке следующим образом:

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

Используя идеи Gradle и IntelliJ, выполните следующие действия:

  1. Загрузите плагин lombok из хранилища плагинов intelliJ.
  2. добавить ломбок к зависимостям в 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()); } }

Теперь вы можете использовать метод .appendSize() для любой строки в любом классе, если вы (аннотировали ее), и полученный результат для приведенного выше примера (This is a String!) будет: This is a String! 17

2 голосов
/ 17 сентября 2008

Как и все остальные, нет, вы не можете подкласс 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;
    }

}
2 голосов
/ 17 сентября 2008

Невозможно, и это хорошо. Строка это Строка. Его поведение определено, отклонение от него было бы злом. Кроме того, он помечен как финальный, что означает, что вы не можете создать его подкласс, даже если бы захотели.

1 голос
/ 24 июля 2017

Нет, вы не можете изменить класс String в Java. Потому что это последний класс. и каждый метод, присутствующий в конечном классе по умолчанию, будет финальным.

Абсолютно наиболее важной причиной того, что String является неизменяемой или окончательной, является то, что она используется механизмом загрузки классов и, следовательно, имеет глубокие и фундаментальные аспекты безопасности.

Если бы строка была изменяемой или не финальной, запрос на загрузку "java.io.Writer" мог бы быть изменен для загрузки "mil.vogoon.DiskErasingWriter"

1 голос
/ 24 мая 2016

Люди, которые ищут по ключевым словам «добавить метод в встроенный класс», могут оказаться здесь. Если вы хотите добавить метод в неконечный класс, такой как 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");

EDIT:

В приведенном выше коде для доступа к встроенным методам класса карты вам нужно будет использовать

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");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...