دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
در اکثر مثال هایی که برای اتصال به دیتابیس دیدم از متد
Class.forName("...")
بدون هیچ گونه assign ای استفاده میشه. دلیل اینکار رو متوجه نشدم!
خود متد خب آبجکت کلاس رو در حین اجرای برنامه بهمون میده. خب این که هیچی. و مستقیم هم میتونیم از کلاسش استفاده کنیم ولی اونوقت کلاس ثابت بود و در حین اجرای برنامه نمیشد کلاس رو تغییر داد. حالا فرض کنیم این به خاطر انعطاف پذیر بودنش.
اما نکته دیگه اینه که این متد یک آبجکت کلاس برمیگردونه. ولی در اکثر مثال هایی که من دیدم به متغیری تخصیص داده نمیشه. از طرفی وقتی این خط رو ننویسیم هم جواب میده!
دلیل استفادش چیه؟
نقل قول: دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
میشه یه قسمت از اون کد را من هم ببینم؟
------------------------------------------------------
فکر کنم به خاطر اینه که مطمئن بشن اون کلاس وجود داره.
نقل قول: دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
این کد شروعی ترین نقطه استفاده از Reflection یا تشخیص/استفاده از نوع در زمان اجرا هستش.
زمانی که شما اسم یک کلاس رو که میخوای ازش شی درست کنی در زمان کامپایل نمیدونی! و در زمان اجرا برات مشخص میشه چطوری میخوای بنویسی new XYZ !? (زمانی که جاوا به اسامی کلاس ها میرسه ClassLoader داخل JVM اتوماتیک میره اونا رو با اولین برخورد به اسمشون از تو فایل .class شون میخونه و بارگذاری میکنه تا بشه باهاشون کار کرد و ازشون new کرد و...)
فرض کن اسم اون کلاس توی یه متغیر String قرار ست بشه (مثلن از ورودی خونده بشه... یا....) خوب حالا این بارگذاری چطور باید انجام بشه!؟ یعنی JVM از کجا باید بفهمه همچون کلاسی هم هست!؟
خوب! اون یک خط جواب این سواله.
حالا زمانی که شما به اون شی کلاس برگشتی از اون متد احتیاج داری واسه کارهای Reflection خب نگه میداری ازش یه Reference اما تو این مثال ها که مربوط به JDBC میشه خب نیازی نیست... چون ما فقط می خوایم اسم کلاس درایورمون رو بدیم و اون رو بارگذاری کنیم و بعد به خود لایببری میگیم بهمون یه Connection با اون Driver بده.
نقل قول: دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
نقل قول:
این کد شروعی ترین نقطه استفاده از Reflection یا تشخیص/استفاده از نوع در زمان اجرا هستش.
زمانی که شما اسم یک کلاس رو که میخوای ازش شی درست کنی در زمان کامپایل نمیدونی! و در زمان اجرا برات مشخص میشه چطوری میخوای بنویسی new XYZ !? (زمانی که جاوا به اسامی کلاس ها میرسه ClassLoader داخل JVM اتوماتیک میره اونا رو با اولین برخورد به اسمشون از تو فایل .class شون میخونه و بارگذاری میکنه تا بشه باهاشون کار کرد و ازشون new کرد و...)
فرض کن اسم اون کلاس توی یه متغیر String قرار ست بشه (مثلن از ورودی خونده بشه... یا....) خوب حالا این بارگذاری چطور باید انجام بشه!؟ یعنی JVM از کجا باید بفهمه همچون کلاسی هم هست!؟
خوب! اون یک خط جواب این سواله.
تا اینجاشو متوجهم و خب به گفته شما گاهی اوقات حین برنامه معلوم میشه چه آبجکتی میخوایم. سوالم دقیقا این بود که این چرا به هیچ متغیری Assign نشده. در اصل به نظر کار بیهوده ای میاد مگر اینکه نکته دیگه ای داشته باشه.
نقل قول:
حالا زمانی که شما به اون شی کلاس برگشتی از اون متد احتیاج داری واسه کارهای Reflection خب نگه میداری ازش یه Reference اما تو این مثال ها که مربوط به JDBC میشه خب نیازی نیست... چون ما فقط می خوایم اسم کلاس درایورمون رو بدیم و اون رو بارگذاری کنیم و بعد به خود لایببری میگیم بهمون یه Connection با اون Driver بده.
همینطوره. برای دیتابیس کم پیش میاد که از اول مشخص نباشه دیتابیسمون چیه.
کد زیر رو ببینید :
// this will load the MySQL driver, each DB has its own driver
Class.forName("com.mysql.jdbc.Driver");
// setup the connection with the DB.
connect = DriverManager
.getConnection("jdbc:mysql://localhost/feedback?"
+ "user=sqluser&password=sqluserpw");
همانطور که میبینید میگه این MySQL Driver رو لود میکنه. خب من یه بار حذف کردم، بازم اجرا میشد. مگر اینکه پای هوشمندی JVM بذاریم. در صورتی که در بخش بعدی که نوشته getConnection ما فقط اسم mysql رو آوردیم خودش چجوری درایورش رو پیدا کرده؟
نقل قول: دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
به جز اینکه وقتی اون قسمت Class.forName رو حذف کنیم و هنوز جوابی ندارم براش، اما برای متد بدون تخصیص به متغیر فکر میکنم به جواب رسیدم. فقط دوستان تصحیح کنند اگر اشتباه بود:
از اونجایی که متد DriverManger.getConnection استاتیک است، پس فیلدهای استاتیکی استفاده کرده. که از هر جایی با تغییر این فیلد ها بدون ساخت آبجکت، میتونیم در طول اجرای برنامه به مقادیر دسترسی داشته باشیم.
حالا کد com.mysql.jdbc.Driver رو ببینید :
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
// ~ Static fields/initializers
// ---------------------------------------------
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
// ~ Constructors
// -----------------------------------------------------------
/**
* Construct a new driver and register it with DriverManager
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
خب تو خط
java.sql.DriverManager.registerDriver(new Driver());
میبینیم مستقیم از متد استاتیک registerDriver کلاس DriverManager استفاده کرده ( بیرون از کانستراکتور هم نوشته تا نیازی به new کردن نباشه و با forName اجرا بشه ) و آبجکتی از خودش ( مثلا اینجا درایور mysql بوده پس یکی از خودش new کرده ) به عنوان پارامتر داده. متد registerDriver هم میگه :
public static synchronized void registerDriver(java.sql.Driver driver) throws SQLException {
...
registeredDrivers.addIfAbsent(new DriverInfo(driver));
درایور جدید رو به لیست اضافه کن.
فکر میکنم واضح شد. حداقل برای من تا اینجاش واضح بود.
فقط سوالی که میمونه اینه که بدون Class.forName چطور DriverManager.getConnection باز هم تشخیص میده؟!!!
نقل قول: دلیل استفاده متد Class.forName بدون تخصیص به متغیر؟! ( در استفاده از دیتابیس )
آفرین! تو که کلن جواب هر دو سوال رو پیدا کردی! هون طور که گفتم از Class.forName فقط برای لود کردن کلاس توی JVM استفاده میشه... با لود شدن بلاک های استاتیک کلاس ها یک بار اجرا میشن.
جواب سوال آخرتم همینه:
java.sql.DriverManager.registerDriver(newDriver());
بعدشم میگی:
DriverManager.getConnection
کاملن روشنه دیگه!