#author("2023-05-01T16:44:16+09:00","default:irrp","irrp")
#author("2024-01-30T15:29:06+09:00","default:irrp","irrp")
→[[Java関連]]

→Javaのリフレクション

→Java文法系Tips

→Eclipse関連

→JavaのWebアプリ開発


#contents


*サブトピック [#ta8966cb]
-Java関連Tipsサンプル集


*Tips集Webサイト [#t58aeb52]
-[[裏Javaメモ>http://www.ne.jp/asahi/hishidama/home/tech/java/strange.html]]
--Javaの微妙なネタ
-[[Java(SE) API逆引き辞典>http://always-pg.com/java/j2se_rd/]]
-[[Javaのとても小さい小技メモ>http://kamakura.cool.ne.jp/oppama/jaco/index.html]]
-[[Java 逆引きリファレンス>http://www.stackasterisk.jp/tech/javaClassref/index.jsp]]
-[[Java Tips index@IT>http://www.atmarkit.co.jp/fjava/javatips/index.html]]
-[[Java Tips集>http://www.masatom.in/pukiwiki/Java/TIPS%BD%B8/]]


*一般 [#q73809c7]
-[[javacの--releaseオプションについて(JEP 247 Compile for Older Platform Versions) - CLOVER🍀>https://kazuhira-r.hatenablog.com/entry/2024/01/01/143407]] 2024.1

-[[Java 21のSequenced Collectionsのreversedの実装について | GMOアドパートナーズ TECH BLOG byGMO>https://techblog.gmo-ap.jp/2023/12/15/java-21-sequenced-collections/]] 2023.12

-[[Java 11で導入されたHTTPクライアント(JEP 321 HTTP Client)を試す - CLOVER🍀>https://kazuhira-r.hatenablog.com/entry/2023/09/03/204511]] 2023.9

-[[Java VMのヒープサイズをパーセンテージで指定する(-XX:InitialRAMPercentage、-XX:MaxRAMPercentage) - CLOVER🍀>https://kazuhira-r.hatenablog.com/entry/2023/07/09/212521]] 2023.7

-[[【ネタ】コメントだけしか書いていないのに「Hello, world!」と表示されるJavaプログラム - Qiita>https://qiita.com/cha84rakanal/items/06477529d48c52f26e2d]] 2023.5

-[[POIを使わずJava標準ライブラリでExcelファイルを生成する - きしだのHatena>https://nowokay.hatenablog.com/entry/2023/03/04/052703]] 2023.3


* Java並行処理 [#q4b64f74]

*C言語との相互運用 [#v1e69598]
-[[java-native-access/jna: Java Native Access>https://github.com/java-native-access/jna]] 2024.1

-[[JavaからCの処理を呼ぶ方法(JNI/JNA/SWIG) #Java - Qiita>https://qiita.com/kiida/items/9d26b850194fa1a02e67]] 2014

-[[JNIより簡単にJavaとC/C++をつなぐ「JNA」とは >http://www.atmarkit.co.jp/fjava/special/jna/jna_1.html]]



* 並行処理 [#q4b64f74]
-[[Virtual Threadsを使ってHTTPサーバー/クライアントを書いて、スレッドまわりの動きを確認してみる(スレッドダンプの取得付き) - CLOVER🍀>https://kazuhira-r.hatenablog.com/entry/2023/12/14/001741]] 2023.12
-[[Java 21で正式版になったJEP 444(Virtual Threads)に関するAPIを試す - CLOVER🍀>https://kazuhira-r.hatenablog.com/entry/2023/12/10/182732]] 2023.12

-[[Java 21仮想スレッドではsynchronizedの代わりにReentrantLockを使用する #Java - Qiita>https://qiita.com/cypher256/items/e7be58ebad6f745a2e21]] 2023.11

-[[Javaの並列/並行処理の基本 - Speaker Deck>https://speakerdeck.com/skrb/bing-xing-chu-li-noji-ben]] 2023.6

-[[Javaで最強 コンカレントプログラミング/concurrent-programming-in-java - Speaker Deck>https://speakerdeck.com/oracle4engineer/concurrent-programming-in-java]] 2023.4

-[[Java並行・並列・非同期処理チートシート - Qiita>https://qiita.com/yohhoy/items/bc119324d2b69570597b#%E4%B8%A6%E8%A1%8C%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A]] 2014

-[[ArrayListをスレッドセーフ化するには? | SYMMETRICソフトウェア開発ブログ>https://www.symmetric.co.jp/blog/archives/29]] 2020
--普通にSynchronizedを使う手とSynchronizedCollection<E> を使う手がある

-[[Concurrency Utilities for Java EE を実装する API タスクの例 - IBM Documentation>https://www.ibm.com/docs/ja/was-liberty/nd?topic=SSAW57_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/rwlp_migrate_to_eeconcurrency.html]] 2022.3



* クラスロード時に実行されるコード [#f0a1dfe2]
 public class testmain {
	
	static {
		try {
			Runtime r = Runtime.getRuntime();
			Process p = r.exec("C:\\WINDOWS\\system32\\notepad.exe");
			System.out.println("実行した");
			p.waitFor();
			System.out.println("メモ帳閉じた");
			p.destroy();
			System.out.println("destroyed");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.out.println("The main function is called.");
	}
 }


* JavaのSerializableを実際にアプリケーションを動かしながら理解する [#qfbd3fb6]
-[[JavaのSerializableを実際にアプリケーションを動かしながら理解する>https://qiita.com/taumax/items/1559439efe0607595465]] 2020.7



*util.Objects [#g06e922b]
-[[クラス java.util.Objectsのおさらいメモ>https://qiita.com/rubytomato@github/items/ba38877ed5a00dd24f16]] 2020.5



*日付/時刻処理いろいろ [#wa075aaa]
-[[Java の DateTimeFormatter の指定方法について>https://zenn.dev/cloud_ace/articles/b398d173e1877d]] 2023.11

-[[DateTimeFormatでは、JSONで受け取った日付をうまく取得できない場合があるという話 - エキサイト TechBlog.>https://tech.excite.co.jp/entry/2022/05/10/170359]] 2022.5

-[[Javaの日付の差分処理はDurationを使おう!!>https://qiita.com/tora_kouno/items/d230f904a2b768ccb319]] 2021.7

-[[Javaバージョン別の改元(新元号)対応まとめ>https://qiita.com/yamadamn/items/56e7370bae2ceaec55d5]] 2019.1

-Timestamp型からDateを経由してCalendarを作る
 java.util.Date = new java.util.Date(ts.getTime());
 Calendar now = Calendar.getInstance();
 now.setTime(date);


-ISO8601形式の日付をDate型に変換して返す  [#r37f066f]
 public static Date Iso8601toDate(String isoDate) 
 throws java.text.ParseException{
  try {
   Calendar cal =DatatypeConverter.parseDateTime(isoDate);
	return cal.getTime();
  } catch (ParseException e) {
 	e.printStackTrace();
	return null;
  }
 }

-カレント月(YYYYMM)取得
 java.util.Date dtNow = new java.util.Date();
 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMM"); 
 String ymNow = formatter.format(dtNow);

-1月進めて月を取得
 Date dt = new Date();
 Calendar calendar = Calendar.getInstance();
 calendar.setTime(dt);
 calendar.add(Calendar.MONTH, 1);
 dt = calendar.getTime();
 SimpleDateFormat formatter = new SimpleDateFormat ("yyyyMM"); 
 String ymNow = formatter.format(dt);




*Runtime#addShutdownHookで JVM 終了時に処理を実行する [#g1cf1f8e]
-http://www.smallstyle.com/20070215.html


*Velocity [#nca80fcf]
-[[汎用テンプレートエンジンVelocity>http://www.stackasterisk.jp/tech/java/velocity01_01.jsp]]
--http://velocity.apache.org/


*マルチスレッド [#z0afd4c1]
-[[Java: Threadおさらい - Qiita>https://qiita.com/e99h2121/items/8eb3e031529083901485]] 2021.11

-[[マルチスレッドプログラミングの入門>http://programming-10000.hatenadiary.jp/entry/20140530/1401450268]] 2014.5.30

-チュートリアル
--http://java.sun.com/docs/books/tutorial/essential/concurrency/index.html



*強制ガベージコレクション [#m2465ffe]
-System.gc() もしくは Runtime.getRuntime().gc()


*テキストファイルの読み込み [#l0820c18]
-http://www.tohoho-web.com/java/file.htm
 import java.io.*;
 
 class BufferedReaderTest {
    public static void main(String[] args) {
        try {
            FileReader in = new FileReader("file.txt");
            BufferedReader br = new BufferedReader(in);
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
            in.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }
 }


* イメージをpngファイルに出力 [#ua836eae]
  /**
   * pngファイルに出力
   * @param im 出力したいイメージ
   * @param fname 出力ファイル名
   * @throws FileNotFoundException
   * @throws IOException
   */
  public static void savePng(BufferedImage im, String fname)
      throws FileNotFoundException, IOException {
    // Open output file.
    OutputStream out = new FileOutputStream(fname);
    
    ImageOutputStream ios =
            ImageIO.createImageOutputStream(out);
    ImageWriter iw = (ImageWriter)ImageIO.
            getImageWritersByFormatName("png").next();
    iw.setOutput(ios);
    iw.write(im);
    
    // Close output file.
    out.close();
  }


*イメージ⇔バイト列の変換 [#hb7b4c52]
  /**
   * イメージをバイト列に変換する
   * @param im イメージ
   * @param formatName フォーマット名 png, bmp, jpeg など
   * @return バイト列
   * @throws IOException
   */
  public static byte[] getBytesFromImage(BufferedImage im, String formatName) 
    throws IOException{
    
    if(formatName == null)
      formatName = "png";
    
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(im, formatName, bos);
    return bos.toByteArray();
  }
  
  /**
   * バイト列からイメージを作成する
   * @param bytes
   * @return イメージ
   * @throws IOException
   */
  public static BufferedImage getImageFromBytes(byte[] bytes) 
          throws IOException{
    
    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    BufferedImage im = ImageIO.read(bis);
    return im;
  }


*フォントにアンチエイリアスをかける [#f73a05c7]
-参考ページ:http://itpro.nikkeibp.co.jp/article/COLUMN/20070205/260649/
  private void testDrawAnti(Graphics2D g) {
    String text = "Limousine";
    // HRGB
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
  
 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
    g.drawString("HRGB:" + text, 10, 140);
    // HBGR
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    
 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR);
    g.drawString("HBGR:" + text, 10, 180);
  
    // VRGB
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    
 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB);
    g.drawString("VRGB:" + text, 10, 220);
  
    // VBGR
    g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
    
 RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR);
    g.drawString("VBGR:" + text, 10, 260);
  }


*BigDecimalの丸め方 [#p8673458]
-http://always-pg.com/java/j2se_rd/number/setscale.html


* 指定のバイト長さになるようにスペースを詰める [#ba6ea65c]
   * @param s 対象の文字列
   * @param length つめた結果の長さ(バイト長)
   * @param leftPad trueなら左に詰める(文字は右詰になる)
   * @return 詰めた文字列
   * @throws UnsupportedEncodingException 
   */
  public static String padSpaceHankaku(String s, int length, booleanleftPad) 
            throwsUnsupportedEncodingException{
    if(isEmpty(s)){
      return repeatChar(' ', length);
    }
    else {
      //シフトJISでバイトにしたときの長さを得て、足りない分を補う
      byte[] bytes = s.getBytes("SJIS");
      int spaceLen = length - bytes.length; 
      if(spaceLen <= 0)
        return s;
      else {
        if(leftPad)
          return repeatChar(' ',spaceLen) + s;
        else
          return s + repeatChar(' ',spaceLen);
      }
    }
  }


*バイト列の16進文字列化 [#tfd6e3a0]
 private String toHex(byte buffer[]) {
     StringBuffer sb = new StringBuffer(buffer.length * 2);
     for (int i = 0; i < buffer.length; i++) {
          sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
          sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
     }
     return sb.toString();
 }


*jar内のクラスファイルの一覧を得るバッチファイル [#kceae917]
-http://cjasmin.fc2web.com/tips/search_class.html
 @echo off
 
 REM pluginsディレクトリを指定
 set PLUGIN_PATH=C:\eclipse-2.1.3\plugins
 
 REM pluginsのパスが存在しなければエラーを返して終了
 if not exist %PLUGIN_PATH% goto PLUGIN_PATH_ERROR
 
 REM 出力先ファイル名が指定されていなければUsageを表示して終了
 if x%1==x goto USAGE
 set OUTPUT_FILE=%1
 
 REM すでに出力先ファイルが存在する場合は消去
 if exist %OUTPUT_FILE% del %OUPUT_FILE%
 
 REM plugins以下のディレクトリにあるjarファイル、それぞれに含まれるファイルの一覧を
 REM OUTPUT_FILEに書き出す。
 for /F "usebackq" %%f IN (`dir /s/b %PLUGIN_PATH%\*.jar`) do (
         jar tvf %%f > tmp_class_list.txt
         for /F "tokens=8" %%i in (tmp_class_list.txt) do echo [%%f] %%i >> %OUTPUT_FILE%
 )
 del tmp_class_list.txt
 
 goto END
 
 :USAGE
 echo Usage: makelist.bat output_file
 goto END
 
 :PLUGIN_PATH_ERROR
 echo プラグインのパスが存在しません: %PLUGIN_PATH%
 goto END
 
 :END


*前ゼロつける [#h1d74b71]
-文字列に前ゼロ:素朴なやり方
 private String padLeadingZero(String value, int width) {
    String wrkValue = value;
    if(wrkValue != null){
        if(wrkValue.length() < width) {
            StringBuffer sb = new StringBuffer();
            int zeroLen = width - wrkValue.length();
            for( int i = 0; i < zeroLen ; i++) {
                sb.append("0");
            }
            wrkValue = sb.append(wrkValue).toString();
        }
    }
    return wrkValue;
 }
-左側にn桁のゼロ文字列をつけた上で右n桁のsubstringを使う方法もある

-数値に前ゼロ
 String.format("%07d", n)
または
 DecimalFormat df = new DecimalFormat();
 df.applyPattern("0000000");
 String max_str = df.format(n);


*ファイル一覧取得 [#fa0747de]
-http://sattontanabe.blog86.fc2.com/blog-entry-56.html


*Java のスタンドアロンプログラムで終了コードを設定するには [#td9a655b]
 System.exit(-1);


*PDFを生成する [#tc59c185]
-http://www.atmarkit.co.jp/fjava/javatips/121jspservlet41.html


*XMLに対応したProperties [#z37787f0]
-http://www.javainthebox.net/laboratory/J2SE1.5/TinyTips/Properties/Properties.html


*プロパティファイル読み込み [#zea80fc5]
-下のようにgetPath()でパスを取得する方法ではjarファイルにしたときFileNotFoundになる。jarファイルになっても読めるやり方は
 ClassLoader loader = Thread.currentThread().getContextClassLoader();
 URL url = loader.getResource("config.properties");
 prop.load(url.openStream());

-参考:[[jarファイルをエクスポートしたときファイルを開けなくなる>http://d.hatena.ne.jp/g-wong/20080710/1215695631]]

-リソースフォルダにあるプロパティファイルを読み込む
 ClassLoader loader = Thread.currentThread().getContextClassLoader();
 URL url = loader.getResource("config.properties");
 //パスにスペースなどがあるとURLエンコードされる点に注意
 String path = url.getPath(); 
 String path2 = URLDecoder.decode(path, "UTF-16");
 prop.load(new FileInputStream(path2));

-http://d.hatena.ne.jp/mikeda/20090325/1238017508
    String configFile = "prop.conf";
    Properties prop = new Properties();
 
    try {
      prop.load(new FileInputStream(configFile));
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
 
    String name = prop.getProperty("name");
    String addr = prop.getProperty("addr");


*スタンドアロンアプリで二重起動防止 [#qd1f8983]
-ファイルのロックを使う
-http://oshiete1.goo.ne.jp/qa2030088.html
 import java.io.File;
 import java.io.FileOutputStream;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 
 public class Sample {
   
   public static void main(String[] args) {
     
     //起動チェック
     final FileOutputStream fos = new FileOutputStream(new File("lock"));
     final FileChannel fc = fos.getChannel();
     final FileLock lock = fc.tryLock();
     if (lock == null) {
       //既に起動されているので終了する
       return;
     }
     
     //ロック開放処理を登録
     Runtime.getRuntime().addShutdownHook(
       new Thread() {
         public void run() {
           if (lock != null && lock.isValid()) {
             lock.release();
           }
           fc.close();
           fos.close();
         }
       }
     );
     
     //処理を続行
   }
 }


*ImageI/O関連 [#fc0337dc]
-[[ImageI/O APIガイド>http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/guide/imageio/index.html]]
--http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/guide/imageio/spec/imageio_guideTOC.fm.html

-[[ImageI/O 説明>http://www.javainthebox.net/laboratory/JDK1.4/Graphics/ImageIO/ImageIO.html]]

-[[ImageI/Oファイルで画像ファイルを読み書きする>http://www.javadrive.jp/java2d/bufferedImage/index2.html]]

-[[Graphics2Dによる描画>http://codezine.jp/article/detail/1021?p=1]]


**Graphics2D+ImageI/Oを使って画像に別の画像を挿入したファイルを作成する [#k86aad8b]
-参考:http://www.javadrive.jp/java2d/bufferedImage/index2.html
 import java.awt.Color;
 
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream; 
 
 import java.awt.*;
 import java.awt.geom.*;
 import javax.imageio.*;
 import javax.imageio.stream.ImageOutputStream; 
 
 static void outByImageIO() throws Exception{
  // イメージの作成
  //   BufferedImage im = new BufferedImage(600,800,
  //                                BufferedImage.TYPE_INT_RGB);
      BufferedImage im = ImageIO.read(new File("sample.png")); //挿入される画像
      BufferedImage im2 = ImageIO.read(new File("test2.jpg")); //挿入する画像
  
        Graphics2D g = im.createGraphics();
        g.drawImage(im2, 20,10, null);
       g.dispose();
 
   // Open output file.
       OutputStream out = new FileOutputStream("test.jpg");
       
       ImageOutputStream ios =
               ImageIO.createImageOutputStream(out);
       ImageWriter iw = (ImageWriter)ImageIO.
               getImageWritersByFormatName("jpeg").next();
       iw.setOutput(ios);
       iw.write(im);
       
       // Close output file.
       out.close();
 }

*正規表現によるマッチング [#t445ef73]
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 ...
 public boolean isHogeNumFormat(String arg) {
   String regexp = <正規表現の文字列>;
   Pattern pat = Pattern.compile(regexp);
   return pat.matcher(arg).matches();
 }


*シリアルバージョンUIDの生成 [#if425795]
-シリアライズを実装するクラスにはUIDをつける必要がある
-解説:http://www.javaroad.jp/faq/faq_os_eclipse1.htm
-Eclipseではワーニングの出た位置にカーソルを合わせてCtrl+1を押すと生成できる


*実行時の対応ソース行取得 [#o969aba2]
 int line = (new Throwable().getStackTrace()[0]).getLineNumber();


*Javaオブジェクトのハッシュコードのルール [#w3ff9fa1]
-The hashCode( ) method is supposed to return an int that should uniquely identify different objects.
-A properly written hashCode( ) method will follow these rules:
--It is repeatable: hashCode(x) must return the same int when called repeatedly, unless set methods have been called.
--It is consistent with equality: if x.equals(y), then x.hashCode( ) must == y.hashCode( ).
--If !x.equals(y), it is not required that x.hashCode( ) != y.hashCode( ), but doing so may improve performance of hash tables; i.e., hashes may call hashCode( ) before equals( ).
-The default hashCode( ) on Sun's JDK returns a machine address, which conforms to Rule 1. Conformance to Rules 2 and 3 depends, in part, upon your equals( ) method. Here is a program that prints the hashcodes of a small handful of objects:


*コンパイラの警告抑制 [#u5033083]
-↓のアノテーションをメソッドにつけるとキャストのときに出る警告を抑制できる
  @SuppressWarnings("unchecked")
あまり推奨はできないが…


*バイト配列から文字列への変換 [#g90835e2]
-[[Javaで整数型やbyte配列と16進表記の文字列との間の変換を行なう - エキサイト TechBlog.>https://tech.excite.co.jp/entry/2023/12/19/063000]] 2023.12

 result = new String(bytes, offset, length, charsetName);
-charsetName は "shift-jis"とか


*JNDIのlookupをだましてとりあえず動かす [#bd15b3d3]
  public class DummyNamingContext implements InitialContextFactoryBuilder, InitialContextFactory, Context {
	public static DummyNamingContext setup() throws Exception {
	  if (!NamingManager.hasInitialContextFactoryBuilder()) {
	    final DummyNamingContext instance = new DummyNamingContext();
	    NamingManager.setInitialContextFactoryBuilder(instance);
	    return instance;
	  }
	  final Context con = NamingManager.getInitialContext(null);
	  if (con instanceof DummyNamingContext) {
	    return (DummyNamingContext) con;
	  }
	  throw new IllegalStateException("No DummyNamingContext");
	}
    private final Map<Name, Object> nameMap;
    private final Map<String, Object> strMap;
  
	@Override
    public void bind(final String name, final Object obj) throws NamingException {
      this.strMap.put(name, obj);
    }
	
	@Override
	public Object lookup(final String name) throws NamingException {
		return this.strMap.get(name)
	}
  
	...
  }

-[[JNDIとは?JDBCとの違いやメリット・デメリットについてもご紹介 &#8211; Rainbow Engine>https://rainbow-engine.com/jndi-jdbc-difference/]] 2021

-JNDIとはJava Naming and Directory Interfaceの頭文字を取ったもので、Javaから
 ネーミング・サービス
 ディレクトリー・サービス
を扱うためのインターフェイスを規定した仕様です。現在の最新バージョンはJNDI 1.2で、最新のWebSphere Application Server V5.1で採用しているJ2SE 1.4でもこのバージョンがサポートされています。
-「インターフェイス」ですので、JNDIではネーミング・サービスやディレクトリー・サービスそのものは提供しません。あくまでも、他の実装で提供されるサービスをJavaから利用するためのしくみがJNDIです。



*Javaのソース解析/AST(Abstract Syntax Tree) [#o15fd42f]
-[[ASTを活用してコードの自動修正に挑戦してみよう - Cybozu Inside Out | サイボウズエンジニアのブログ>https://blog.cybozu.io/entry/2018/09/07/080000]] 2018

-[[JavaParser 使い方メモ>https://qiita.com/opengl-8080/items/50ddee7d635c7baee0ab]] 2017
-[[JDTでJavaのソースコード解析を行う>https://qiita.com/esplo/items/fa93ab6136e7697ed1d9]] 2015
-[[Eclipse JDT AST>http://www.ne.jp/asahi/hishidama/home/tech/eclipse/plugin/develop/jdt/ast.html]]


* その他 [#ha61b806]
-[[Java New String Methods - From Java 8 To Java 17>https://javaconceptoftheday.com/java-new-string-methods-with-examples/]] 2022.7


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS