$30 off During Our Annual Pro Sale. View Details »

String Templateによる文字列補間

String Templateによる文字列補間

2023-11-11 JJUG CCC セッション資料
String Templateによる文字列補間

Yuichi.Sakuraba

November 10, 2023
Tweet

More Decks by Yuichi.Sakuraba

Other Decks in Technology

Transcript

  1. String Template
    による文字列補間
    櫻庭 祐一
    Java in the Box

    View Slide

  2. Agenda
    Background
    JEP 459 String Templates
    文字列補間の危険性と
    Custom Template Processor
    Advanced Usage

    View Slide

  3. Background

    View Slide

  4. 変数を含んだ文字列連結どうしてる?
    1. 変数が少なければ + 演算子
    多くなったら StringBuilder
    2. String.format or java.util.Formatter
    3. java.text.MessageFormat

    View Slide

  5. を変数で切り替えたい
    “Hello, World!” World
    + 演算子
    “Hello, ” + name + “!”;
    StringBuilder
    new StringBuilder(“Hello, ”)
    .append(name)
    .append(“!”)
    .toString();
    変数が多いとコードを読み書きしにくい ...

    View Slide

  6. を変数で切り替えたい
    “Hello, World!” World
    String.format() or java.util.Formatter
    String.format(“Hello, %s”, name);
    new Formatter().format(“Hello, %s”, name)
    .toString();
    =
    java.text.MessageFormat
    MessageFormat.format(“Hello, {0}”, name);
    変数が多いとフォーマット記述子と変数の対応が ...

    View Slide

  7. もっと簡単に
    まちがいも起こしにくい方法がほしい
    テンプレートを使った文字列補間
    だからといってテンプレートエンジンを使うほどでは ...

    View Slide

  8. もっと簡単に
    まちがいも起こしにくい方法がほしい
    テンプレートを使った文字列補間
    だからといってテンプレートエンジンを使うほどでは ...
    もっと手軽に汎用の文字列補間がほしい
    JEP 459 String Templates

    View Slide

  9. JEP 459 String Templates

    View Slide

  10. String Templates
    文字列に 変数 / 式 を埋め込み
    文字列補間を行う言語仕様
    “Hello, ” + name + “!”;
    STR.”Hello \{name}!”

    View Slide

  11. String Templates の書き方
    STR.”Hello \{name}!”
    テンプレート
    プロセッサ テンプレート引数
    }
    }
    変数 / 式 埋め込み
    テンプレートプロセッサ java.lang.StringTemplate.Processor
    関数型インタフェース processメソッド
    標準で提供 STR, FMT, RAW
    テンプレート引数 文字列リテラル
    テキストブロック

    View Slide

  12. java.lang.StringTemplate.STR
    文字列を生成する最も基本的なテンプレートプロセッサ
    せずとも使用可能
    static import
    WBSYWBSZ
    453za\Y^a\Z^a\YZ^z
    zz
    WBSUPEBZ-PDBM%BUFOPX

    453zzz
    5PEBZJTa\UPEBZ^ a\TXJUDI UPEBZHFU%BZ0G8FFL

    \
    DBTF4"563%": 46/%":l8FFLFOEz
    EFGBVMUl8FFLEBZz
    ^^lzz
    z5PEBZJT 8FFLFOEz

    View Slide

  13. java.util.FormatProcessor.FMT
    形式のフォーマットを使用し、
    Formatter
    文字列を生成するテンプレートプロセッサ
    WBSYWBSZ
    '.5zGa\Y^Ga\Z^Ga\YZ^z
    zz
    '.5z5PEBZJTU%a\-PDBM%BUFOPX
    ^z
    z5PEBZJTz
    ロケールを指定する場合
    WBSGNU'PSNBU1SPDFTTPSDSFBUF -PDBMFPG KB +1


    ʀ
    GNUz5PEBZJTU"a\-PDBM%BUFOPX
    ^z
    z5PEBZJT౔༵೔z

    View Slide

  14. java.lang.StringTemplate.RAW
    未処理の オブジェクトを生成するプロセッサ
    StringTemplate
    WBSYWBSZ
    453za\Y^a\Z^a\YZ^z
    4USJOH5FNQMBUFTU3"8za\Y^a\Z^a\YZ^z
    453QSPDFTT TU

    View Slide

  15. String Templates の動作
    により実行
    invokeDynamic
    453z)FMMP a\OBNF^z
    要素ごとに分解
    z)FMMP l OBNF lz
    z)FMMP l OBNFlz
    -JTU4USJOHGSBHNFOUT -JTU0CKFDUWBMVFT
    文字列と値を別々にまとめる
    WBSTU4USJOH5FNQMBUFPG GSBHNFOUT WBMVFT
    オブジェクト生成
    StringTemplate
    453QSPDFTT TU
    メソッドコール
    Processor.process

    View Slide

  16. Custom Template Processor
    文字列補間の危険性と

    View Slide

  17. Custom Template Processor
    特定用途向け Template Processor
    文字列以外を返すことも可能
    QVCMJDJOUFSGBDF4USJOH5FNQMBUF\
    QVCMJDJOUFSGBDF1SPDFTTPS3 &FYUFOET5ISPXBCMF\
    3QSPDFTT 4USJOH5FNQMBUFTUSJOH5FNQMBUF
    UISPXT&
    TUBUJD51SPDFTTPS5 3VOUJNF&YDFQUJPOPG
    'VODUJPO TVQFS4USJOH5FNQMBUF FYUFOET5QSPDFTT
    \^
    ^

    ^
    例外を扱うのであれば をオーバーライド
    process
    例外を使用しない場合 をコール
    of

    View Slide

  18. of メソッドによるカスタマイズ
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD
    4USJOH5FNQMBUF1SPDFTTPSPG TU\
    GSBHNFOUT
    ͱWBMVFT
    Λ࢖༻ͯ͠هड़
    SFUVSO
    ^

    View Slide

  19. of メソッドによるカスタマイズ
    と同等の
    STR Template Processor
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD
    4USJOH5FNQMBUF1SPDFTTPSPG TU\
    *UFSBUPS4USJOHJUTUGSBHNFOUT
    JUFSBUPS

    WBSTCOFX4USJOH#VJMEFS JUOFYU


    GPS 0CKFDUPCKTUWBMVFT

    \
    TCBQQFOE PCK

    TCBQQFOE JUOFYU


    ^
    SFUVSOTCUP4USJOH

    ^

    View Slide

  20. of メソッドによるカスタマイズ
    と同等の
    STR Template Processor
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD
    4USJOH5FNQMBUF1SPDFTTPSPG 4USJOH5FNQMBUFJOUFSQPMBUF

    View Slide

  21. of メソッドによるカスタマイズ
    値をすべて大文字に変換
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD
    4USJOH5FNQMBUF1SPDFTTPSPG TU\
    WBSWBMVFTTUWBMVFT
    TUSFBN

    NBQ WWUP4USJOH
    UP6QQFS$BTF


    UP-JTU


    SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT
    WBMVFT

    ^

    View Slide

  22. Processor インタフェースをラムダ式で記述
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD
    TU\
    GSBHNFOUT
    ͱWBMVFT
    Λ࢖༻ͯ͠هड़
    ྫ֎Λεϩʔ͢Δ͜ͱ΋Մ
    SFUVSO
    ^

    View Slide

  23. Processor インタフェースをラムダ式で記述
    を許容しない
    null Template Processor
    4USJOH5FNQMBUF1SPDFTTPS4USJOH /VMM1PJOUFS&YDFQUJPOQSPD
    TU\
    JG TUWBMVFT
    DPOUBJOT OVMM

    \
    UISPXOFX/VMM1PJOUFS&YDFQUJPO

    ^

    SFUVSOTUJOUFSQPMBUF

    ^

    View Slide

  24. Processor インタフェースをラムダ式で記述
    を扱う
    JSON
    4USJOH5FNQMBUF1SPDFTTPS+40/0CKFDU 3VOUJNF&YDFQUJPOKTPO1SPD
    TUOFX+40/0CKFDU TUJOUFSQPMBUF


    Template Processor
    WBSOBNFl4BLVSBCBzWBSDJUZl5PLZPz
    WBSKTPOKTPO1SPDzzz
    \
    lOBNFzla\OBNF^z
    lDJUZzla\DJUZ^z
    ^
    lzz

    View Slide

  25. Custom Template Processor のユースケース
    JSON
    SQL
    HTML/CSS/XML
    ログメッセージ/エラーメッセージ
    ...

    View Slide

  26. 文字列補間の危険性
    変数 / 式を埋め込んだ結果が
    不適切な表現になることがある
    SQL インジェクション
    クロスサイトスクリプティング
    4USJOHRVFSZ
    4534&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^
    OBNFl4BLVSBCB03QOBNF4BLVSBCBz
    Custom Template Processor で対応可

    View Slide

  27. Custom Template Processor による対応
    使用できない文字をエスケープ
    4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPO130$TU\
    -JTU4USJOHWBMVFTTUWBMVFT
    TUSFBN

    NBQ WWUP4USJOH
    SFQMBDF aa


    UP-JTU

    SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT
    WBMVFT

    ^
    4USJOHOBNF4BLVSBCB03QOBNF4BLVSBCB
    4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^
    z4&-&$5'30.1FSTPOQ
    8)&3&QOBNF4BLVSBCBa03QOBNFa4BLVSBCBz

    View Slide

  28. Custom Template Processor による対応
    使用できない文字があれば例外
    4USJOH5FNQMBUF1SPDFTTPS4USJOH *MMFHBM"SHVNFOU&YDFQUJPO130$TU\
    TUWBMVFT
    TUSFBN

    NBQ WWUP4USJOH


    pMUFS WWDPOUBJOT


    pOE'JSTU

    JG1SFTFOU T\
    UISPXOFX*MMFHBM"SHVNFOU&YDFQUJPO 453*MMFHBM5FYUa\T^

    ^

    SFUVSOTUJOUFSQPMBUF

    ^

    View Slide

  29. Custom Template Processor による対応
    型による制限 (インスタンス生成時にチェック)
    SFDPSE1FSTPO 4USJOHOBNF
    \ίϯετϥΫλͰ஋νΣοΫ^
    4USJOH5FNQMBUF1SPDFTTPS4USJOH *MMFHBM"SHVNFOU&YDFQUJPO130$TU\
    WBSWBMVFTTUWBMVFT
    TUSFBN

    NBQ W\
    JG WJOTUBODFPG1FSTPO WBSOBNF

    \
    SFUVSOOBNF
    ^FMTF\
    UISPXOFX*MMFHBM"SHVNFOU&YDFQUJPO 453a\WHFU$MBTT
    ^a\W^

    ^^
    UP-JTU

    SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT
    WBMVFT
    ^

    View Slide

  30. Custom Template Processor による対応
    型による制限 (インスタンス生成時にチェック)
    0,
    WBSQFSTPOOFX1FSTPO 4BLVSBCB

    4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\QFSTPO^
    /(
    WBSOBNF4BLVSBCB
    4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^

    View Slide

  31. Advanced Usage

    View Slide

  32. の制限
    String Template
    テンプレート引数 : 文字列リテラル テキストブロック
    or
    453)FMMP a\OBNF^z
    文字列リテラル
    テキストブロック
    }
    テンプレート引数をファイルから読み込みたい
    文字列リテラルを持つクラスを動的生成

    View Slide

  33. 動的テンプレート引数作成
    道具 Compiler API
    Class Loader
    Re ection or MethodHandle
    手順 1. 文字列でクラスのひな型を用意
    2. テンプレート引数にする文字列をひな型に埋め込み
    3. ひな型をコンパイル
    4. コンパイルしたクラスファイルをクラスロード
    5. リフレクションもしくは で実行
    MethodHandle

    View Slide

  34. 動的テンプレート引数作成
    QSJWBUFTUBUJD-JTU FYUFOET+BWB'JMF0CKFDUDSFBUF+BWB'JMF0CKFDUT 4USJOHUFNQMBUF
    \
    +BWBͷιʔεͱͳΔจࣈྻ
    4USJOHUFNQ4SD453
    QVCMJDDMBTT5FNQMBUF\
    QVCMJDTUBUJD4USJOH5FNQMBUFQSPDFTT 4USJOHWBSJBCMF
    \
    SFUVSOKBWBMBOH4USJOH5FNQMBUF3"8aaa
    a\UFNQMBUF^
    aaa
    ^
    ^

    クラスのひな型とテンプレートの埋め込み
    จࣈྻΛιʔεͱ͢Δ+BWB'JMF0CKFDUΛੜ੒͢Δ
    +BWB'JMF0CKFDUpMFPCK
    OFX4USJOH+BWB'JMF0CKFDU 5FNQMBUF UFNQ4SD

    SFUVSO-JTUPG pMFPCK

    ^

    View Slide

  35. 動的テンプレート引数作成
    ίϯύΠϧ͢ΔϑΝΠϧͷ४උ
    WBSpMFPCKTDSFBUF+BWB'JMF0CKFDUT UFNQMBUF


    ίϯύΠϥͷऔಘ
    +BWB$PNQJMFSDPNQJMFS5PPM1SPWJEFSHFU4ZTUFN+BWB$PNQJMFS

    Ծ૝ϑΝΠϧϚωʔδϟͷऔಘ
    WBSpMF.BOBHFSDPNQJMFSHFU4UBOEBSE'JMF.BOBHFS OVMM OVMM OVMM

    ίϯύΠϧλεΫͷੜ੒
    +BWB$PNQJMFS$PNQJMBUJPO5BTLUBTLDPNQJMFSHFU5BTL OVMM pMF.BOBHFS OVMM
    -JTUPG SFMFBTF FOBCMFQSFWJFX
    OVMM pMFPCKT

    ίϯύΠϧ
    UBTLDBMM

    クラスのコンパイル

    View Slide

  36. 動的テンプレート引数作成
    Ϋϥεͷϩʔυ
    WBSMPBEFS$MBTT-PBEFSHFU4ZTUFN$MBTT-PBEFS

    WBSDMTTMPBEFSMPBE$MBTT 5FNQMBUF

    .FUIPEΦϒδΣΫτΛऔಘ͠ɺ
    ϦϑϨΫγϣϯͰ࣮ߦ͢Δ
    WBSNFUIPEDMTTHFU.FUIPE QSPDFTT 4USJOHDMBTT

    4USJOH5FNQMBUFEZOBNJD5FNQMBUF
    4USJOH5FNQMBUF
    NFUIPEJOWPLF OVMM OFX0CKFDU<>\WBSJBCMF^

    クラスのロードと実行

    View Slide

  37. 動的テンプレート引数作成
    ϑΝΠϧ͔ΒςϯϓϨʔτΛಡΈࠐΈ
    4USJOHUFNQMBUFOFX4USJOH 'JMFTSFBE"MM#ZUFT 1BUIPG IFMMPUFNQ



    ಈతςϯϓϨʔτੜ੒
    ୈҾ਺ςϯϓϨʔτୈҾ਺ςϯϓϨʔτʹຒΊࠐΉจࣈྻ
    WBSEZOBNJD5FNQMBUF%ZOBNJD5FNQMBUFQSPDFTT UFNQMBUF #PC%ZMBO

    ೚ҙͷςϯϓϨʔτϓϩηοαͰॲཧ
    WBSSFTVMU453QSPDFTT EZOBNJD5FNQMBUF

    動的テンプレートの使用例

    View Slide

  38. Conclusion
    で簡単、簡潔に文字列補間
    String Template
    で拡張可能
    Custom Template Processor
    文字列補間の危険性も
    Custom Template Processor 対応可能

    View Slide

  39. String Template
    による文字列補間
    櫻庭 祐一
    Java in the Box

    View Slide