Jawaban:
Mungkin contoh yang menunjukkan bagaimana kedua metode digunakan akan membantu Anda untuk memahami hal-hal dengan lebih baik. Jadi, pertimbangkan kelas berikut:
package test;
public class Demo {
public Demo() {
System.out.println("Hi!");
}
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("test.Demo");
Demo demo = (Demo) clazz.newInstance();
}
}
Seperti dijelaskan dalam javadoc-nya, panggilan mengembalikan objek yang terkait dengan kelas atau antarmuka dengan nama string yang diberikan yaitu mengembalikan yang dipengaruhi oleh variabel tipe .Class.forName(String)
Class
test.Demo.class
clazz
Class
Kemudian, panggilan menciptakan instance baru dari kelas yang diwakili oleh objek ini . Kelas dipakai sebagai seolah-olah oleh ekspresi dengan daftar argumen kosong. Dengan kata lain, ini di sini sebenarnya setara dengan dan mengembalikan instance baru .clazz.newInstance()
Class
new
new Demo()
Demo
Dan menjalankan Demo
kelas ini dengan demikian mencetak output berikut:
Hi!
Perbedaan besar dengan tradisional new
adalah yang newInstance
memungkinkan untuk instantiate kelas yang Anda tidak tahu sampai runtime, membuat kode Anda lebih dinamis.
Contoh tipikal adalah JDBC API yang memuat, saat runtime, driver yang dibutuhkan untuk melakukan pekerjaan. Wadah EJB, wadah Servlet adalah contoh bagus lainnya: mereka menggunakan pemuatan runtime dinamis untuk memuat dan membuat komponen yang tidak mereka ketahui sebelum runtime.
Sebenarnya, jika Anda ingin melangkah lebih jauh, lihatlah makalah Ted Neward Understanding Class.forName () yang saya kutip dalam paragraf di atas.
EDIT (menjawab pertanyaan dari OP yang diposting sebagai komentar): Kasus driver JDBC agak istimewa. Seperti yang dijelaskan dalam bab DriverManager tentang Memulai dengan JDBC API :
(...)
Driver
Kelas dimuat, dan karenanya secara otomatis terdaftar denganDriverManager
, dalam salah satu dari dua cara:
dengan memanggil metode
Class.forName
. Ini secara eksplisit memuat kelas driver. Karena tidak tergantung pada pengaturan eksternal apa pun, cara memuat driver ini adalah yang disarankan untuk menggunakanDriverManager
kerangka kerja. Kode berikut memuat kelasacme.db.Driver
:Class.forName("acme.db.Driver");
Jika
acme.db.Driver
telah ditulis sehingga memuatnya menyebabkan instance dibuat dan juga memanggilDriverManager.registerDriver
instance tersebut sebagai parameter (seperti yang seharusnya), maka itu ada dalamDriverManager
daftar driver dan tersedia untuk membuat koneksi.(...)
Dalam kedua kasus ini, adalah tanggung jawab kelas yang baru dimuat
Driver
untuk mendaftar sendiri dengan meneleponDriverManager.registerDriver
. Seperti disebutkan, ini harus dilakukan secara otomatis ketika kelas dimuat.
Untuk mendaftar sendiri selama inisialisasi, driver JDBC biasanya menggunakan blok inisialisasi statis seperti ini:
package acme.db;
public class Driver {
static {
java.sql.DriverManager.registerDriver(new Driver());
}
...
}
Panggilan Class.forName("acme.db.Driver")
menyebabkan inisialisasi acme.db.Driver
kelas dan dengan demikian eksekusi blok inisialisasi statis. Dan Class.forName("acme.db.Driver")
memang akan "membuat" contoh tetapi ini hanya konsekuensi dari bagaimana (baik) Driver JDBC diimplementasikan.
Sebagai catatan, saya akan menyebutkan bahwa semua ini tidak diperlukan lagi dengan JDBC 4.0 (ditambahkan sebagai paket default sejak Java 7) dan fitur auto-loading baru dari driver JDBC 4.0. Lihat peningkatan JDBC 4.0 di Java SE 6 .
DriverManager.registerDriver
. Memanggil Class.forName
driver JDBC menyebabkan inisialisasi dan dengan demikian eksekusi blok statis. Lihat java2s.com/Open-Source/Java-Document/Database-DBMS/… untuk contoh. Jadi ini sebenarnya adalah kasus khusus karena pengemudi internal.
Class.forName () memberi Anda objek kelas, yang berguna untuk refleksi. Metode yang dimiliki objek ini ditentukan oleh Java, bukan oleh programmer yang menulis kelas. Mereka sama untuk setiap kelas. Memanggil newInstance () pada yang memberikan Anda sebuah instance dari kelas itu (yaitu memanggil Class.forName("ExampleClass").newInstance()
itu setara dengan memanggil new ExampleClass()
), di mana Anda dapat memanggil metode yang didefinisikan oleh kelas, mengakses bidang yang terlihat dll.
Di dunia JDBC, praktik normal (menurut JDBC API) adalah yang Anda gunakan Class#forName()
untuk memuat driver JDBC. Driver JDBC harus mendaftar di DriverManager
dalam blok statis:
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class MyDriver implements Driver {
static {
DriverManager.registerDriver(new MyDriver());
}
public MyDriver() {
//
}
}
Memohon Class#forName()
akan menjalankan semua inisialisasi statis . Dengan cara ini DriverManager
dapat menemukan driver terkait di antara driver terdaftar dengan URL koneksi di getConnection()
mana kira-kira terlihat seperti berikut:
public static Connection getConnection(String url) throws SQLException {
for (Driver driver : registeredDrivers) {
if (driver.acceptsURL(url)) {
return driver.connect(url);
}
}
throw new SQLException("No suitable driver");
}
Tapi ada juga kereta driver JDBC, dimulai dengan org.gjt.mm.mysql.Driver
contoh juga dikenal, yang tidak benar mendaftarkan diri dalam Constructor bukan blok statis:
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class BadDriver implements Driver {
public BadDriver() {
DriverManager.registerDriver(this);
}
}
Satu-satunya cara untuk membuatnya bekerja secara dinamis adalah menelepon newInstance()
sesudahnya! Kalau tidak, Anda akan menghadapi pandangan pertama yang tidak dapat dijelaskan "SQLException: no driver yang sesuai". Sekali lagi, ini adalah bug pada driver JDBC, bukan di kode Anda sendiri. Saat ini, tidak ada driver JDBC yang boleh mengandung bug ini. Jadi Anda dapat (dan harus) meninggalkan tempat newInstance()
itu.
1: jika Anda hanya tertarik pada blok statis kelas, pemuatan kelas hanya akan dilakukan, dan akan menjalankan blok statis maka yang Anda butuhkan adalah:
Class.forName("Somthing");
2: jika Anda tertarik untuk memuat kelas, jalankan blok-blok statisnya dan juga ingin mengakses bagian non-statisnya, maka Anda memerlukan sebuah instance dan kemudian Anda perlu:
Class.forName("Somthing").newInstance();
"Class.forName ()" mengembalikan Tipe-Kelas untuk nama yang diberikan. "newInstance ()" mengembalikan instance kelas ini.
Pada tipe yang Anda tidak dapat memanggil langsung metode instance tetapi hanya dapat menggunakan refleksi untuk kelas. Jika Anda ingin bekerja dengan objek kelas Anda harus membuat turunannya (sama dengan memanggil "MyClass baru ()").
Contoh untuk "Class.forName ()"
Class myClass = Class.forName("test.MyClass");
System.out.println("Number of public methods: " + myClass.getMethods().length);
Contoh untuk "Class.forName (). NewInstance ()"
MyClass myClass = (MyClass) Class.forName("test.MyClass").newInstance();
System.out.println("String representation of MyClass instance: " + myClass.toString());
hanya menambahkan jawaban di atas, ketika kita memiliki kode statis (mis. blok kode adalah contoh independen) yang perlu ada dalam memori, kita dapat meminta kelas dikembalikan sehingga kita akan menggunakan Class.forname ("someName") yang lain jika kita jangan punya kode statis, kita bisa menggunakan Class.forname (). newInstance ("someName") karena akan memuat blok kode level objek (non statis) ke memori
Tidak peduli berapa kali Anda memanggil metode Class.forName (), Hanya sekali blok statis dijalankan tidak beberapa kali:
paket untukNameMethodDemo;
MainClass kelas publik {
public static void main(String[] args) throws Exception {
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
Class.forName("forNameMethodDemo.DemoClass");
DemoClass demoClass = (DemoClass)Class.forName("forNameMethodDemo.DemoClass").newInstance();
}
}
DemoClass kelas publik {
static {
System.out.println("in Static block");
}
{
System.out.println("in Instance block");
}
}
output akan menjadi:
in Static block
in Instance block
Ini in Static block
Pernyataan dicetak hanya sekali bukan tiga kali.
Class.forName () -> forName () adalah metode statis kelas Kelas yang dikembalikannya objek kelas Kelas yang digunakan untuk refleksi bukan objek kelas pengguna sehingga Anda hanya dapat memanggil metode kelas Kelas di atasnya seperti getMethods (), getConstructors () dll.
Jika Anda peduli hanya menjalankan blok statis dari kelas Anda (diberikan Runtime) dan hanya mendapatkan informasi tentang metode, konstruktor, Modifier dll dari kelas Anda, Anda dapat melakukannya dengan objek ini yang Anda dapatkan menggunakan Class.forName ()
Tetapi jika Anda ingin mengakses atau memanggil metode kelas Anda (kelas yang telah Anda berikan saat runtime) maka Anda perlu memiliki objeknya sehingga metode Kelas baru melakukannya untuk Anda. Ini membuat instance baru dari kelas dan mengembalikannya kepada Anda Anda hanya perlu mengetikkan gips ke kelas Anda.
mis.: anggaplah Karyawan adalah kelas Anda saat itu
Class a = Class.forName (args [0]);
// args [0] = argumen garis cmd untuk memberikan kelas saat runtime.
Karyawan ob1 = a.newInstance ();
a.newInstance () mirip dengan membuat objek menggunakan Karyawan baru ().
sekarang Anda dapat mengakses semua bidang dan metode yang terlihat kelas Anda.