Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Можно ли передать String по ссылке


Автор: 3,14 23.8.2007, 12:22
По умолчанию объекты типа String передаются по значению. Можно ли как то исхитрится и передать String по ссылке?
Пока есть только идея передавать массив стрингов, но это не очень удобно :( Так как в методе меняется всего две переменных...

Автор: ekr 23.8.2007, 13:00
Цитата(3 @ 14, 23.8.2007,  12:22 Найти цитируемый пост)
По умолчанию объекты типа String передаются по значению.

по ссылке они передаются, т.к. это объектный тип, а не примитивный

а что сделать-то дальше с ними надо?

Автор: y3u 23.8.2007, 13:30
К тому же есть StringBuilder-ы и StringBuffer-ы... на крайний случай smile
Не хватает информации о решаемой задачи, чтобы что-то предложить...

Автор: 3,14 23.8.2007, 13:51
Цитата(ekr @  23.8.2007,  13:00 Найти цитируемый пост)
по ссылке они передаются, т.к. это объектный тип, а не примитивный

Не всё так просто. Вот код
Код

public class Test
{
    public static void testString(String str) {
        str = "new value";
    }
    public static void main(String[] args) {
        String str = "old value";
        testString(str);
        System.out.println(str);
    }
}

На выходе получаем: old value. Те, по сути происходит передача по значению.
Цитата(y3u @  23.8.2007,  13:30 Найти цитируемый пост)
Не хватает информации о решаемой задачи, чтобы что-то предложить...

Задача такая. Функция должна распарсить передаваемую ей строку, и записать результат в две других строки.

Автор: Shaggie 23.8.2007, 14:10
Код

public class Test
{
    public static String testString(String str) {
        str = "new value";
        return str;
    }
    public static void main(String[] args) {
        String str = "old value";
        str=testString(str);
        System.out.println(str);
    }
}

Автор: nornad 23.8.2007, 14:28
Shaggie, это не поможет:
Цитата(3 @ 14, 23.8.2007,  16:51 Найти цитируемый пост)
Функция должна распарсить передаваемую ей строку, и записать результат в две других строки. 

Приведённый пример проще поставленной задачи.

3,14, а кто мешает сделать свой объект, который будет содержать две строки? И его уже передавать функции. Она в этом случае без проблем изменить содержимое строк.
Ну или тот же массив передавать, но это скорее сишный стиль, чем жабовский.

Кстати, о передаче по ссылке и значению в java уже немало сказано на этом форуме. Поищи и почитай - полезно. Поймёшь, почему у тебя передалось "по значению".  smile 

Автор: goodday1941 23.8.2007, 14:30
Цитата(3 @ 14, 23.8.2007,  13:51 Найти цитируемый пост)
На выходе получаем: old value. Те, по сути происходит передача по значению.

таки так получаеться 

интерестно а что будет если написать так:

Код

public class Test
{
    public static void testString(String str) {
        str.replace(str, "new value");
    }
    public static void main(String[] args) {
        String str = "old value";
        testString(str);
        System.out.println(str);
    }

}


Добавлено через 10 минут и 57 секунд
в общем то результат тот же.. дак почему же не переопределился стринг?

Автор: y3u 23.8.2007, 14:45
Цитата(goodday1941 @  23.8.2007,  15:30 Найти цитируемый пост)
интерестно а что будет если написать так:


ничего не будет smile 

http://java.sun.com/javase/6/docs/api/java/lang/String.html

а вот по поводу иммьютабельности строки, вот показательный пример

http://skipy.developer.juga.ru/technics/strings.html#mutation

но это так, лирика smile

вообще, как ту правильно заметили, лучше сделать для этого POJO и не париться...

Автор: fixxer 23.8.2007, 14:47
Ничего хорошего. String является immutable. str не изменится, а результат возвратится из метода replace.

Автор: 3,14 23.8.2007, 14:50
Цитата(nornad @  23.8.2007,  14:28 Найти цитируемый пост)
3,14, а кто мешает сделать свой объект, который будет содержать две строки?

Цитата(nornad @  23.8.2007,  14:28 Найти цитируемый пост)
Ну или тот же массив передавать, но это скорее сишный стиль, чем жабовский.

потомучто тогда при каждом вызове ф-ии придётся писать 5 строк вместо 1, что очень не приятно

Цитата(nornad @  23.8.2007,  14:28 Найти цитируемый пост)
Кстати, о передаче по ссылке и значению в java уже немало сказано на этом форуме. Поищи и почитай - полезно.

Да я и так знаю, почему это так работает. Я не могу найти решение к-ое меня бы устраивало.



Автор: y3u 23.8.2007, 14:53
Цитата(3 @ 14, 23.8.2007,  15:50 Найти цитируемый пост)
потомучто тогда при каждом вызове ф-ии придётся писать 5 строк вместо 1, что очень не приятно


ну, привыкай smile 

"здесь Вам не С" (с) smile

Автор: goodday1941 23.8.2007, 14:59
Цитата(fixxer @  23.8.2007,  14:47 Найти цитируемый пост)
Ничего хорошего. String является immutable. str не изменится, а результат возвратится из метода replace.

эта строка мне открыла глаза  smile 

а есть где то перечень immutable классов?

Автор: 3,14 23.8.2007, 15:02
Цитата(y3u @  23.8.2007,  14:53 Найти цитируемый пост)
ну, привыкай smile 

Не привык привыкать smile Привык находить более хорошие решения smile

Автор: y3u 23.8.2007, 15:42
по приколу, с ходу не тестируя, т.ч. не пинайте smile Тут, по хорошему, Strategy pattern нужен вместо Factory smile

Код

public interface StringParserResult() {
    String[] getResults();
}

public final class MyStringParserResults() implements StringParserResults {
    private Collection<String> results = new ArrayList<String>();

    public MyStringParserResults() {}

    public MyStringParserResults(String[] results) {
          this.results.addAll(Arrays.asList(results));
    }

    public void addString(String result) {
        results.add(result);  
    }

    public String[] getResults() {
        return results.toArray(new String[results.size()]);
    }
}

public interface StringParser() {
   StringParserResult parse(String src);
}

public final class MyStringParser() {
    private StringParserResult results;

    public StringParserResult parse(String src) {
        return new StringParserResult(src.split("myRegExp"));
    }
}

public final class StringParserFactory() {
    private StringParserFactory(){}

    public static StringParser createStringParser() {
        return new MyStringParser();
    } 
}


использование в одну строчку

Код

    StringParserFactory.createStringParser().parse("asdasdasd");

Автор: nornad 24.8.2007, 03:09
Цитата(3 @ 14, 23.8.2007,  15:22 Найти цитируемый пост)
По умолчанию объекты типа String передаются по значению. Можно ли как то исхитрится и передать String по ссылке?


Цитата(3 @ 14, 23.8.2007,  17:50 Найти цитируемый пост)
Цитата(nornad @  23.8.2007,  14:28 Найти цитируемый пост)
Кстати, о передаче по ссылке и значению в java уже немало сказано на этом форуме. Поищи и почитай - полезно.

Да я и так знаю, почему это так работает. Я не могу найти решение к-ое меня бы устраивало.

Что-то не сходится...


y3u, что-то я не понял, к чему код... Или ты темой ошибся, или я нить рассуждений потерял...

Добавлено через 4 минуты и 22 секунды
Цитата(3 @ 14, 23.8.2007,  17:50 Найти цитируемый пост)
придётся писать 5 строк вместо 1

Мне почему-то кажется, что скорее 3 строки, но в данном случае это не так важно.
Передать "по ссылке" можно лишь, если требуемая переменная лежит внутри другого объекта (передаваемого). Или массива. Другого способа нет.
Хотя... Если через рефлекшн внаглую попробовать "проломить" безопасную ссылку...
Только вот лично я предпочту сделать обёртку. Потому как рефлекшн пользовать не лучшая идея. smile 

Автор: y3u 24.8.2007, 08:23
Цитата(nornad @  24.8.2007,  04:09 Найти цитируемый пост)
Только вот лично я предпочту сделать обёртку. Потому как рефлекшн пользовать не лучшая идея


вот как раз код к этому...

Автор: 3,14 24.8.2007, 10:16
Жесть, меня на сановском форуме все дружно уверяют, что абсолютно все объекты передаются по значению, а не по ссылке. smile 

Автор: fixxer 24.8.2007, 10:38
Цитата(3 @ 14,24.8.2007,  10:16)
Жесть, меня на сановском форуме все дружно уверяют, что абсолютно все объекты передаются по значению, а не по ссылке. smile

Да, это действительно так. В случае ссылочной переменной по значению передается ссылка (копируется во фрейм вызова), поэтому и ее нельзя изменить, чтобы изменения были видны во вне метода.

Автор: ekr 24.8.2007, 11:00
Цитата(3 @ 14, 24.8.2007,  10:16 Найти цитируемый пост)
Жесть, меня на сановском форуме все дружно уверяют, что абсолютно все объекты передаются по значению, а не по ссылке.

разница в контексте.

дело в том, что действительно, 
Цитата(fixxer @  24.8.2007,  10:38 Найти цитируемый пост)
абсолютно все объекты передаются по значению, а не по ссылке

это правда.

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

получается, что технически по значению, а концептуально по ссылке.

во как загнул )

Автор: 3,14 24.8.2007, 11:37
Я как то првивык разделять объект и ссылку на объект. Всё таки это разные вещи.
Объект - это, как известно, экземпляр класса. А ссылка - это всего лишь ссылка smile

Автор: nornad 24.8.2007, 13:50
3,14, ну вот, а говорил, что знаешь и понимаешь. smile
В java все объектные переменные - действительно представлены ссылками. Сами ссылки передаются в методы в безопасном виде, что позволяет получить и изменить данные в объекте по ссылке, но не позволяет изменить саму ссылку.

P.S. Блин, на моей памяти уже раз так четвёртый тему мусолим...

Автор: 3,14 24.8.2007, 14:38
nornad, это, знаешь ли, уже вопрос терминилогии. Считать ли пер-ую типа ссылка, передаваемую в метод, объектом. В Java различия между этимми понятиями не делается, но это только в Java.

Автор: nornad 24.8.2007, 14:55
3,14, вот-вот. Ты уже сам ответил на свой вопрос. smile
Если пишешь на Java, надо придерживаться её идеологии. По идеологии Java всё есть объект (ну, за исключением встроенных типов, конечно). Понятие ссылки в Java вообще отсутствует. И не надо его из С/С++ тянуть - там полного аналога для этого не существует.
Нужно просто понять и принять идеологию, а не пытаться притянуть её к другой идеологии, которую ты уже знаешь.

Автор: 3,14 24.8.2007, 15:18
nornad,  я на Java пишу гораздо дольше, чем некогда писал на C++. Просто такая идеология куда как удобней когда нужно копатся, напрмер, с байт кодом.

Автор: AntonSaburov 24.8.2007, 15:34
Чего-то тут много словов всяких smile

Да вернуть массив строк и всех делов

Вот для примера - разбиавем строку на массив строк - разделителем является символ двоеточия ":"
Код

public String[] parseMyOldValue(String s)
{
   String[] p = s.split(":");
   return p;
}


Автор: nornad 24.8.2007, 22:29
Цитата(AntonSaburov @  24.8.2007,  18:34 Найти цитируемый пост)
Чего-то тут много словов всяких 

Ниасилил? smile
А пример, кстати, хорош - коротко и ясно. Если хочется большего - меняем String на Object и радуемся резко возросшим возможностям.
Жаль только, что камраду такой вариант не нравится - не лаконичен, видите ли... Ну, кому что, как говорится.

Автор: math64 26.8.2007, 01:09
Если не нравится возвращать массив, то проще этого не придумаешь:
Код

interface StringSetter {
   void set(String value);
}

public class Parser {
   private String string1;
   private String string2;
   StringSetter setter1 = new StringSetter() {
      void set(String value) { string1 = value; }
   }
   StringSetter setter2 = new StringSetter() {
      void set(String value) { string2 = value; }
   }

   public static void main(String[] args) {
      Parser parser = new Parser();
      parse(args[0], parser.setter1, parser.setter2);
   }

   static void parse(String s, StringSetter setter1, StringSetter setter2) {
      int index = s.indexOf(',');
      if (index < 0) {
        setter1.set(s);
        setter2.set(null);
      } else {
        setter1.set(s.substring(0,index));
        setter2.set(s.substring(index));
      }
   }
};


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)