UUIDv7をプライマリキーとして使用することで、データベース用の連番キーの生成や管理が不要になり、アプリケーションのロジックを簡素化することが可能です。さらに、UUIDv7は標準UUIDの形式に準拠しているため、従来のUUID向けのコードやライブラリをそのまま活用でき、簡単にバージョンを移行できるとのこと。
UUIDなのにデータベースのプライマリキーに設定してもパフォーマンスの問題を起こさない「UUIDv7」の標準化作業が進行中 - GIGAZINE
⇧「主キー(プライマリキー)」がアルファベットを含みたくない(10進数の数字のみで構成したい)の場合とか、どうなるんだろうか?
Javaでビルド後に生成される.classファイル自体にはpackage文は影響しない?
いままで、気にするような機会が無かったので、今さら感がありますが、
クラス・ファイルの出力先ディレクトリを設定します。そのディレクトリはjavac
によって作成されないため、すでに存在している必要があります。クラスがパッケージに含まれる場合、javac
は、パッケージ名を反映したサブディレクトリにクラス・ファイルを置き、必要に応じてディレクトリを作成します。
-d
C:\myclasses
と指定し、クラスの名前がcom.mypackage.MyClass
である場合、クラス・ファイルはC:\myclasses\com\mypackage\MyClass.class
になります。
-dオプションが指定されていない場合、javac
は各クラス・ファイルを、その生成元のソース・ファイルと同じディレクトリ内に置きます。
注: -dオプションで指定したディレクトリはユーザー・クラス・パスに自動的には追加されません。
https://docs.oracle.com/javase/jp/8/docs/technotes/tools/windows/javac.html
⇧ とあるように、「.java」ファイルで、package文を記述していると、ビルド後に
■package文を記載している場合のビルドで生成されるもの
- 「.class」ファイルに記述したpackage文のサブディレクトリ
- 「.class」ファイル
が生成され、package文を記述していないと、
■package文を記載していない場合のビルドで生成されるもの
- 「.class」ファイル
が生成されますと。
つまり、package文を記述しようが記述しまいが、生成される「.class」ファイル自体には影響しませんと。
と思ってたんだけど、ちょっと分からん...、後述します。
Eclipseを使っていると、クラス(「.java」ファイル)の作成時に、
「デフォルト・パッケージの使用は推奨されません」っていう警告が出てくるから、「デフォルト・パッケージ」は宜しくないっていう刷り込みがされていて、「デフォルト・パッケージ」で運用するJavaアプリケーションを想定していなかったのだけど、package文の記述の無いJavaアプリケーションを扱う機会を得て、曖昧になっていたので調べてみた次第です。
ちなみに、Eclipseの「プロジェクト(P)」>「プロジェクトのビルド(B)」でビルドされると(「自動的にビルド(M)」にチェックが付いていると、「プロジェクトのビルド(B)」は選択できない)、「javac」の「-d」オプションを付けた時と同じ挙動になるっぽい。(つまり、package文が記述されていれば、サブディレクトリが生成される)
⇧「パッケージ・エクスプローラー」だと表示されていないけど、
⇧「プロジェクト・エクスプローラー」で、「.class」ファイルが表示されて、「.classpath」ファイルで指定したパスに「.class」ファイルは生成されてました。
「.java」ファイルが「デフォルト・パッケージ」配下にあるので、サブディレクトリなどは作成されていないようです。
で、package文は、「.class」ファイルにも影響するのかどうかなんだけど、
■package文なしの「.java」ファイルから生成された「.class」ファイル
// 次からコンパイル OOMESample06.java (バージョン 11 : 55.0, スーパー・ビット) public class OOMESample06 { // メソッド記述子 #6 ()V // スタック: 1, ローカル: 1 public OOMESample06(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return 行数: [pc: 0, 行: 4] ローカル変数テーブル: [pc: 0, pc: 5] ローカル: this インデックス: 0 型: OOMESample06 // メソッド記述子 #15 ([Ljava/lang/String;)V // スタック: 4, ローカル: 5 public static void main(java.lang.String[] args) throws java.lang.ClassNotFoundException; 0 new java.util.ArrayList [19] 3 dup 4 invokespecial java.util.ArrayList() [21] 7 astore_1 [classList] 8 iconst_0 9 istore_2 [i] 10 new OOMESample06$MyClassLoader [22] 13 dup 14 invokespecial OOMESample06$MyClassLoader() [24] 17 astore_3 [loader] 18 aload_3 [loader] 19 new java.lang.StringBuilder [25] 22 dup 23 ldc <String "DynamicClass"> [27] 25 invokespecial java.lang.StringBuilder(java.lang.String) [29] 28 iload_2 [i] 29 invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [32] 32 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [36] 35 invokevirtual java.lang.ClassLoader.loadClass(java.lang.String) : java.lang.Class [40] 38 astore 4 [dynamicClass] 40 aload_1 [classList] 41 aload 4 [dynamicClass] 43 invokeinterface java.util.List.add(java.lang.Object) : boolean [46] [nargs: 2] 48 pop 49 iinc 2 1 [i] 52 goto 10 行数: [pc: 0, 行: 6] [pc: 8, 行: 7] [pc: 10, 行: 10] [pc: 18, 行: 11] [pc: 40, 行: 12] [pc: 49, 行: 13] [pc: 52, 行: 9] ローカル変数テーブル: [pc: 0, pc: 55] ローカル: args インデックス: 0 型: java.lang.String[] [pc: 8, pc: 55] ローカル: classList インデックス: 1 型: java.util.List [pc: 10, pc: 55] ローカル: i インデックス: 2 型: int [pc: 18, pc: 52] ローカル: loader インデックス: 3 型: java.lang.ClassLoader [pc: 40, pc: 52] ローカル: dynamicClass インデックス: 4 型: java.lang.Class ローカル変数型テーブル: [pc: 8, pc: 55] ローカル: classList インデックス: 1 型: java.util.List<java.lang.Class<?>> [pc: 40, pc: 52] ローカル: dynamicClass インデックス: 4 型: java.lang.Class<?> スタック・マップ・テーブル: フレーム数 1 [pc: 10, 追加: {java.util.List, int}] メソッド・パラメーター: args インナー・クラス: [インナー・クラス情報: #22 OOMESample06$MyClassLoader, 外部クラス情報: #1 OOMESample06 インナー名: #70 MyClassLoader, アクセス・フラグ: 8 static] Nest Members: #22 OOMESample06$MyClassLoader }
■package文ありの「.java」ファイルから生成された「.class」ファイル
// 次からコンパイル EndpointAppWatchServiceNormal.java (バージョン 1.8 : 52.0, スーパー・ビット) public class apps.EndpointAppWatchServiceNormal { // メソッド記述子 #6 ()V // スタック: 1, ローカル: 1 public EndpointAppWatchServiceNormal(); 0 aload_0 [this] 1 invokespecial java.lang.Object() [8] 4 return 行数: [pc: 0, 行: 10] ローカル変数テーブル: [pc: 0, pc: 5] ローカル: this インデックス: 0 型: apps.EndpointAppWatchServiceNormal // メソッド記述子 #15 ([Ljava/lang/String;)V // スタック: 2, ローカル: 2 public static void main(java.lang.String[] args); 0 new apps.EndpointAppWatchServiceNormal [1] 3 dup 4 invokespecial apps.EndpointAppWatchServiceNormal() [16] 7 astore_1 [endpointAppWatchServiceNormal] 8 aload_1 [endpointAppWatchServiceNormal] 9 aload_0 [args] 10 invokevirtual apps.EndpointAppWatchServiceNormal.startWatchServiceNormal(java.lang.String[]) : void [17] 13 return 行数: [pc: 0, 行: 13] [pc: 8, 行: 14] [pc: 13, 行: 15] ローカル変数テーブル: [pc: 0, pc: 14] ローカル: args インデックス: 0 型: java.lang.String[] [pc: 8, pc: 14] ローカル: endpointAppWatchServiceNormal インデックス: 1 型: apps.EndpointAppWatchServiceNormal メソッド・パラメーター: args // メソッド記述子 #15 ([Ljava/lang/String;)V // スタック: 4, ローカル: 5 public void startWatchServiceNormal(java.lang.String[] args); 0 aload_1 [args] 1 arraylength 2 ifne 8 5 invokestatic apps.service.impl.service_watcher.BaseServiceWatcherRecursive.usage() : void [24] 8 iconst_0 9 istore_2 [recursive] 10 aload_1 [args] 11 iconst_0 12 aaload 13 ldc <String "-r"> [29] 15 invokevirtual java.lang.String.equals(java.lang.Object) : boolean [31] 18 ifeq 23 21 iconst_1 22 istore_2 [recursive] 23 iload_2 [recursive] 24 ifeq 64 27 aload_1 [args] 28 iconst_1 29 aaload 30 iconst_0 31 anewarray java.lang.String [32] 34 invokestatic java.nio.file.Paths.get(java.lang.String, java.lang.String[]) : java.nio.file.Path [37] 37 astore_3 [dirNormal] 38 new apps.service.impl.service_watcher.ServiceWatcherFromNormalImpl [43] 41 dup 42 aload_3 [dirNormal] 43 iload_2 [recursive] 44 invokespecial apps.service.impl.service_watcher.ServiceWatcherFromNormalImpl(java.nio.file.Path, boolean) [45] 47 astore 4 [serviceWatcherFromNormalImpl] 49 aload 4 [serviceWatcherFromNormalImpl] 51 invokevirtual apps.service.impl.service_watcher.ServiceWatcherFromNormalImpl.processEvents() : void [48] 54 goto 64 57 astore 4 [e] 59 aload 4 [e] 61 invokevirtual java.io.IOException.printStackTrace() : void [51] 64 return 例外テーブル: [pc: 38, pc: 54] -> 57 時刻 : java.io.IOException 行数: [pc: 0, 行: 19] [pc: 5, 行: 20] [pc: 8, 行: 23] [pc: 10, 行: 24] [pc: 21, 行: 25] [pc: 23, 行: 28] [pc: 27, 行: 29] [pc: 38, 行: 32] [pc: 49, 行: 34] [pc: 54, 行: 36] [pc: 59, 行: 38] [pc: 64, 行: 41] ローカル変数テーブル: [pc: 0, pc: 65] ローカル: this インデックス: 0 型: apps.EndpointAppWatchServiceNormal [pc: 0, pc: 65] ローカル: args インデックス: 1 型: java.lang.String[] [pc: 10, pc: 65] ローカル: recursive インデックス: 2 型: boolean [pc: 38, pc: 64] ローカル: dirNormal インデックス: 3 型: java.nio.file.Path [pc: 49, pc: 54] ローカル: serviceWatcherFromNormalImpl インデックス: 4 型: apps.service.impl.service_watcher.ServiceWatcherFromNormalImpl [pc: 59, pc: 64] ローカル: e インデックス: 4 型: java.io.IOException スタック・マップ・テーブル: フレーム数 4 [pc: 8, 同じ] [pc: 23, 追加: {int}] [pc: 57, フル, スタック: {java.io.IOException}, ローカル: {apps.EndpointAppWatchServiceNormal, java.lang.String[], int, java.nio.file.Path}] [pc: 64, チョップ 1 ローカル] メソッド・パラメーター: args }
う~ん、コンパイル対象のクラス名には、package文で宣言したパッケージ名が付いているんだけど、コンパイル後(「.class」ファイル)がどういう扱われるのかが分からん...
動作確認してみたら、package文ありの「.java」ファイルでビルドした「.class」ファイルはpackage文で指定したサブディレクトリが作成されている必要があって、そこに配置されていないと「.class」ファイルの実行で、エラーになりましたわ...
「.java」ファイルでpackage文を宣言してるので、
package文の宣言で指定した「apps.jvm.option」の階層のサブディレクトリを作成して、そこに、ビルドした「.class」ファイルを配置したら動作しました。
まじか...
何の気なしに、package文を追加すると、ビルド後の「.class」ファイルが動作しないってことやん...
package文があることが当たり前な感覚になっていたから、あんまり気にしてこなかったけど...
というわけで、
- package文あり
- package文なし
は別物で、「package文」は影響しまくります。
毎度モヤモヤ感が半端ない...
今回はこのへんで。