2974


Javaの文字列の中で以下のRubyのコードのように式の展開をすることは可能でしょうか？

[code]

    name = "Joel Spolsky"
    p "Hello #{name}"
    
[/code]


CC BY-SA 3.0
2015-01-03T08:40:00.563
2973
2015-01-03T12:15:48.373
556
question
ruby java
Javaの文字列の中でRubyのような式の展開ってできますか？


Java 標準ライブラリにはないです。あえて一番近いのといえば、
[`String.format()`](http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#format-
java.lang.String-java.lang.Object...-) ですね。

[code]

    String name = "Joel Spolsky"
    String result = String.format("Hello %s", name);
    
[/code]

あとは、テンプレートライブラリを使う話になってくると思います。Java にはたくさんあると思うので、 どれを選ぶかは、人それぞれでしょう。

ちょっと冗長ですが、例えば Mushtache
([Handlebars.java](https://github.com/jknack/handlebars.java)) はどうでしょう。

[code]

    String name = "Joel Spolsky"
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compileInline("Hello {{name}}");
    System.out.println(template.apply(name));
    
[/code]


CC BY-SA 3.0
2015-01-03T09:03:46.700
2974
2015-01-03T09:09:25.197
2015-01-03T09:09:25.197
4978
4978
2973
answer


Java言語では残念ながら不可能です。

例えばApache
Commonsの[`StrSubstitutor`クラス](http://commons.apache.org/proper/commons-
lang/javadocs/api-
release/org/apache/commons/lang3/text/StrSubstitutor.html)で似たような処理を実現可能です。（変数名から直接マッピングはできません）

[code]

    Map m = new HashMap();
    m.put("name", "Joel Spolsky");
    System.out.println((new StrSubstitutor(m)).replace("Hello ${name}"));
    
[/code]


CC BY-SA 3.0
2015-01-03T09:10:32.487
2975
2015-01-03T09:15:45.287
2015-01-03T09:15:45.287
49
49
2973
answer


すでに回答されているように、Java 標準ライブラリでは不可能です。

ちょっとした式展開がしたいだけで、テンプレートライブラリを使うほどでも…という場合は、正規表現を使った変換を自前で行ってもいいかもしれません。

[code]

    import java.util.*;
    import java.util.regex.*;
    
    public class TemplateTest {
      public static void main(String[] args) {
        Map<String, String> map = new HashMap<>();
        map.put("name", "Joel Spolsky");
        StringBuilder tmpl = new StringBuilder("Hello #{name}");
        System.out.println(replace(tmpl, map));
      }
      private static Pattern pattern = Pattern.compile("\\#\\{([^\\#\\{\\}]*)\\}");
      private static String replace(StringBuilder tmpl, Map<String, String> map) {
        Matcher m = pattern.matcher(tmpl);
        int i = 0;
        while (i < tmpl.length() && m.find(i)) {
          String key = m.group(1);
          String val = Objects.toString(map.get(key), "null");
          tmpl.replace(m.start(), m.end(), val);
          i = m.start() + val.length();
          m = pattern.matcher(tmpl);
        }
        return tmpl.toString();
      }
    }
    
[/code]


CC BY-SA 3.0
2015-01-03T09:38:30.287
2978
2015-01-03T09:54:01.847
2015-01-03T09:54:01.847
46
46
2973
answer


すでにご存知とは思いますが、Java標準の範囲内で最も一般的な代用法は `+` でつないでゆくことです。

[code]

    String name = "Joel Spolsky";
    System.out.println("Hello " + name);
    
[/code]

Rubyと違って、+で挟まれた式は[文字列以外なら文字列に変換される](http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1)
([日本語訳](http://www.y-adagio.com/public/standards/tr_javalang2/expressions.doc.html#39990))
ので、計算式なども問題なく文字列の間に挟むことができます(文字列の`+`と数値の`+`をコンパイラが混同するので、計算式はカッコで囲むように気をつけてください)。

[code]

    String name = "Joel Spolsky";
    int birthyear = 1965;
    System.out.println("Happy new year " + name + " and your age is " + (2015 - birthyear));
    
[/code]

ただ、`+`はメモリ効率が悪いため、デバッグプリント以外には向いていません。

性能が必要な場合は
[`StringBuilder`](https://docs.oracle.com/javase/jp/8/api/java/lang/StringBuilder.html)
が使われます。こちらも標準ライブラリで、`import`は必要ありません。

[code]

    String name = "Joel Spolsky";
    int birthyear = 1965;
    StringBuilder message = new StringBuilder();
    message.append("Happy new year ").append(name).append(" and your age is ").append(2015 - birthyear);
    System.out.println(message);
    
[/code]


CC BY-SA 3.0
2015-01-03T10:45:12.380
2980
2015-01-03T11:00:06.973
2015-01-03T11:00:06.973
5910
5910
2973
answer


java から ruby の機能をつかいたいなら、jruby を使うという方法も考えられます。

[code]

    // See http://www29.atwiki.jp/red5server/pages/37.html                                                                  
    //     http://dior.ics.muni.cz/~makub/ruby/                                                                             
    // 1. put jaruy.jar を カレントフォルダに置く.                                                                          
    // 2. $ javac -cp ./jruby.jar App.java                                                                                  
    // 3. $ java -cp .:./jruby,jara App                                                                                     
    //    time=2015-01-03 20:45:46 +0900                                                                                    
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineFactory;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import javax.script.ScriptContext;
    
    public class App {
        public static void main(String[] arg) throws ScriptException {
            new App();
        }
    
        public App() throws ScriptException {
            ScriptEngine jruby = new  ScriptEngineManager().getEngineByName("jruby");
    
            String script = "$myval = \"time=#{Time.now}\"";
            jruby.eval(script);
            String myval = (String) jruby.getBindings(ScriptContext.ENGINE_SCOPE).get("myval");
            System.out.println("myval=" + myval);
        }
    }
    
[/code]

これを compile, 実行すると stdout に次の様な文字列が出力されます。 (java 1.8.0_05, jruby 1.7.18 on
MacOSX 10.10.1 で実行)

[code]

    time=2015-01-03 20:45:46 +0900
    
[/code]


CC BY-SA 3.0
2015-01-03T12:15:48.373
2986
2015-01-03T12:15:48.373
2987
2973
answer