導入 データベースに接続するためにJDBCを使用することに慣れている場合は、データベースに接続するためのコードはClass.forNameに基づいている必要があることを知っている必要があります。 ("com.mysql.jdbc.Driver"); パブリック静的Connection getConnection() はClassNotFoundException、SQLExceptionをスローします { if (接続 == null) { クラス.forName("com.mysql.jdbc.Driver"); 接続 = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx"); } 接続を返します。 } これまで、なぜこのようなステートメントが必要なのか考えたことはありませんでした。ドキュメントに従って実行するだけです。この記事では、そうする理由を説明してみたいと思います。 クラスローディングメカニズム その前に、Java のクラスロードメカニズムについて説明しましょう。 Java では、クラスを使用する場合は、そのクラスが JVM にロードされている必要があります。ロード プロセスは、実際には、クラスの完全修飾名を通じてクラスを定義するバイナリ バイト ストリームを取得し、バイト ストリームによって表される静的ストレージ構造をメソッドの動的ランタイム データ構造に変換することです。同時に、メソッド領域内のこのクラスのデータ アクセス エントリとして、java.lang.Class オブジェクトがメモリ内にインスタンス化されます (ここでの使用のため)。 次のような状況では、クラスのロードがトリガーされる可能性があります (<<Java 仮想マシンの詳細な理解>> から引用)。 1. 4 つのバイトコード命令 new、getstatic、putstatic、または invokestatic に遭遇したときに、クラスが初期化されていない場合は、まずその初期化をトリガーする必要があります。これら 4 つの命令を生成する最も一般的な Java コード シナリオは、new キーワードを使用してオブジェクトをインスタンス化する場合、クラスの静的フィールドを読み取ったり設定する場合 (final によって変更され、コンパイル時に結果が定数プールに配置される静的フィールドを除く)、およびクラスの静的メソッドを呼び出す場合です。 2. java.lang.reflect パッケージのメソッドを使用してクラスをリフレクションで呼び出す場合、クラスが初期化されていない場合は、まずその初期化をトリガーする必要があります。 3. クラスを初期化するときに、その親クラスが初期化されていないことが判明した場合は、まずその親クラスの初期化をトリガーする必要があります。 4. 仮想マシンが起動すると、ユーザーは実行するメイン クラス (main() メソッドを含むクラス) を指定する必要があり、仮想マシンは最初にこのメイン クラスを初期化します。 クラス.forName 公式 Java ドキュメントでは、Class.forName は実行時にクラスを動的にロードし、戻り値は生成された Class オブジェクトであると説明されています。 そうすると、jdbc で しかし、Class.forName はクラスをロードするだけであり、返された Class オブジェクトに対して何の操作も行わないことを知っておく必要があります。では、なぜ後でそれを直接使用できるのでしょうか。 まず、Class.forName はネイティブ メソッド forName0(...); を呼び出します。 @発信者センシティブ パブリック スタティック クラス <?> forName(String className) ClassNotFoundException をスローします { クラス<?> 呼び出し元 = Reflection.getCallerClass(); forName0(className, true, ClassLoader.getClassLoader(caller), caller) を返します。 } プライベート静的ネイティブ Class<?> forName0(String name、boolean initialize、ClassLoader loader、Class<?> caller); forName0 には、クラスのロード後に初期化を実行するかどうかを示すために使用される boolean initialize というキー パラメーターがあることに注意してください。コード内で true の場合、初期化操作が実行されることを意味することがわかります。 初期化プロセスは、実際には変数に値を割り当てるプロセスです(初期値を割り当てたり、コンストラクターを呼び出したりすることはありません)。親クラスの初期化を含む、すべてのクラス変数の割り当てと静的コード ステートメント ブロックの実行コードが含まれます。 com.mysql.jdbc.Driver ドライバー クラスを確認します。 パブリッククラスDriverはNonRegisteringDriverを拡張し、java.sql.Driverを実装します。 パブリックDriver()はSQLExceptionをスローします{ } 静的{ 試す { DriverManager.registerDriver(新しいDriver()); } キャッチ (SQLException var1) { throw new RuntimeException("ドライバーを登録できません!"); } } } このクラスには静的コード ブロックが定義されています。静的コード ブロック内にドライバー クラスのインスタンスが作成され、DriverManager に登録されます。静的コード ブロックの内容は初期化プロセス中に実行されるため、 その他のロードクラスメソッド 理解しておく必要があるのは、Java では、クラスを明示的にロードできるのは Class.forName() だけではないということです。では、Class.forName() の代わりに他の読み込みメソッドを使用しないのはなぜでしょうか? クラスは、クラス ローダーを介して JVM にロードすることもできます。ドライバー クラスは しかし、loadClass の実装を詳しく見てみると、 パブリック Class<?> loadClass(String name) は ClassNotFoundException をスローします { loadClass(name, false) を返します。 } 保護された Class<?> loadClass(String name, boolean resolve); オーバーロードされたメソッドが呼び出され、そのメソッドにもブール変数 boolean resolve があり、呼び出されるとデフォルトで false に設定されることがわかります。このパラメータは、ロードされたクラスをリンクするかどうかを識別するために使用されます。リンクしない場合は、初期化操作は行われません。 したがって、このクラスロード方法を使用すると、理論的にはドライバークラスは使用できません。 新しいキーワード また、new キーワードを使用して読み込み操作を実行することもできます。new キーワードを使用すると、クラスが読み込まれているかどうかがチェックされます。読み込まれていない場合は、クラスが読み込まれます。したがって、クラスでは次のように記述することもできます。 パブリック静的Connection getConnection() はClassNotFoundException、SQLExceptionをスローします { if (接続 == null) { new Driver(); //静的コード ブロックは自動的に呼び出されます connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxx"); } 接続を返します。 } しかし実際には、ドライバー クラスの静的コード ブロック内に、オブジェクトをインスタンス化して DriverMananger に登録する操作がすでに存在します。したがって、ここではオブジェクトをインスタンス化するプロセスはまったくありません。最適化プロセスとみなせる Class.forName を使用するだけです。 Class.forName("com.mysql.jdbc.Driver")を使用する必要はありません。 テスト中に、 コードを詳細に追跡した結果、MySQL ドライバー パッケージを導入すると、使用時にドライバー パッケージで提供される構成ファイルに従って、デフォルトでクラスが作成されることがわかりました。 したがって、実際には、ドライバー パッケージが導入されている限り、jdbc を使用して DriverManage を介して直接接続を取得できます。 パブリック静的接続getConnection() SQLException { DriverManager.getConnection("jdbc:mysql://localhost:3306/xxx?serverTimezone=UTC", "root", "xxxxxx"); を返します。 } 要約する 上記は、JDBC を使用して MySQL を操作するときに Class.forName("com.mysql.jdbc.Driver") を追加する必要がある理由についての紹介です。お役に立てれば幸いです。ご質問がある場合は、メッセージを残してください。すぐに返信いたします。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。 以下もご興味があるかもしれません:
|
<<: Vueフロントエンドの効率的な開発のためのレンダリング手順をリストします
>>: Windows に Docker をインストールする詳細なチュートリアル
Nginx によるソケット ポート転送の一般的なシナリオ: オンライン学習アプリケーションでは、通常...
達成される効果多くの場合、入力ボックスの値の変化をリアルタイムで監視し、ブラウザを誘導してウェブサイ...
目次序文1. ルーティングナビゲーションガードを設定する1. グローバルナビゲーションガード2. ロ...
1. コンセプト1. ホットバックアップとバックアップの違いホット バックアップは高可用性 (HA)...
1. まずテーブル作成ステートメントを見てみましょう テーブル学生を作成( sid int 主キー ...
この記事では、CSS で 2 つの固定列と 1 つのアダプティブ列を実装するいくつかの方法を紹介し、...
シナリオ 1:半透明の境界線を実現するには: CSS スタイルのデフォルトの動作により、背景色はコン...
序文この記事は、最も人気のある言語で最も退屈な基礎知識を説明することを目的としていますこのトピックは...
find コマンドは主にディレクトリやファイルを検索するために使用され、一致のために複数のパラメータ...
参考までに、jsを使用して照明スイッチを制御します。具体的な内容は次のとおりです。トピック: js ...
ssh は私が最も頻繁に使用する 2 つのコマンドライン ツールのうちの 1 つです (もう 1 つ...
WeChatアプレット計算機の例、参考までに、具体的な内容は次のとおりです。インデックス.wxml ...
質問Nginx リバース プロキシの後、Tomcat アプリケーションは、クライアント ブラウザーの...
これを見た後、あなたにも手ができて、さまざまな美しい小さなしっぽを作れるようになることを保証します!...
CSS ファイルでは、フォント名が文字化けしていることがよくあります。これは、作成者が中国語フォン...