Yanıtlar:
Belki her iki yöntemin nasıl kullanıldığını gösteren bir örnek, işleri daha iyi anlamanıza yardımcı olacaktır. Bu nedenle, aşağıdaki sınıfı düşünün:
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();
}
}
De çağrı, kendi javadoc açıklandığı döner belirli bir dize adıyla sınıf veya arayüzü ile ilişkili bir amacı bu döner, yani için etkilenir Çeşidi değişken .Class.forName(String)
Class
test.Demo.class
clazz
Class
Ardından, arama bu nesnenin temsil ettiği sınıfın yeni bir örneğini oluşturur . Sınıf, boş bir bağımsız değişken listesine sahip bir ifade tarafından başlatılır . Başka bir deyişle, bu aslında a ile eşdeğerdir ve yeni bir örneğini döndürür .clazz.newInstance()
Class
new
new Demo()
Demo
Ve bu Demo
sınıfı çalıştırmak aşağıdaki çıktıyı yazdırır:
Hi!
Geleneksel büyük farkı new
DİR newInstance
size kod daha dinamik hale çalışma zamanı kadar bilmiyorum bir sınıf örneğini sağlar.
Tipik bir örnek, çalışma zamanında işi gerçekleştirmek için gereken sürücüyü yükleyen JDBC API'sidir. EJB'ler kapsayıcılar, Servlet kapsayıcılar diğer iyi örneklerdir: çalışma zamanından önce hiçbir şey bilmedikleri bileşenleri yüklemek ve oluşturmak için dinamik çalışma zamanı yüklemesi kullanırlar.
Aslında, daha ileri gitmek isterseniz, yukarıdaki paragrafta anlattığım Ted Neward makalesini Anlamak Class.forName () 'e bir göz atın .
EDIT (yorum olarak yayınlanan OP bir soruya cevap): JDBC sürücüleri durumda biraz özeldir. JDBC API'sine Başlarken'ın DriverManager bölümünde açıklandığı gibi :
(...) Bir
Driver
sınıfDriverManager
iki yoldan biriyle yüklenir ve bu nedenle otomatik olarak kaydedilir :
yöntemi çağırarak
Class.forName
. Bu, sürücü sınıfını açıkça yükler. Herhangi bir harici kuruluma bağlı olmadığından, bu sürücüyü yüklemek için buDriverManager
çerçeveyi kullanmanız önerilir . Aşağıdaki kod sınıfı yükleracme.db.Driver
:Class.forName("acme.db.Driver");
Eğer
acme.db.Driver
bu yükleme bunun oluşturulacak bir örneğini neden olur ve ayrıca çağırır böylece yazılmıştırDriverManager.registerDriver
parametre olarak o örneğe ile (olarak yapmalıdır), sonra içinde bulunduğuDriverManager
sürücülerin 'ın listesi ve bağlantı oluşturmak için kullanılabilir.(...)
Her iki durumda da, yeni yüklenen
Driver
sınıfın kendisini arayarak kayıt yaptırmak kendi sorumluluğundadırDriverManager.registerDriver
. Belirtildiği gibi, bu sınıf yüklendiğinde otomatik olarak yapılmalıdır.
Başlatma sırasında kendilerini kaydettirmek için JDBC sürücüsü genellikle şu gibi statik bir başlatma bloğu kullanır:
package acme.db;
public class Driver {
static {
java.sql.DriverManager.registerDriver(new Driver());
}
...
}
Çağrı Class.forName("acme.db.Driver")
, acme.db.Driver
sınıfın başlatılmasına ve dolayısıyla statik başlatma bloğunun yürütülmesine neden olur . Ve Class.forName("acme.db.Driver")
gerçekten bir örnek "oluşturur" ama bu sadece (iyi) JDBC Sürücüsünün nasıl uygulandığının bir sonucudur.
Bir yan not olarak, tüm bunların artık JDBC 4.0 (Java 7'den beri varsayılan paket olarak eklenmiştir) ve JDBC 4.0 sürücülerinin yeni otomatik yükleme özelliği ile gerekli olmadığını belirtmek isterim. Java SE 6'daki JDBC 4.0 geliştirmelerine bakın .
DriverManager.registerDriver
. Class.forName
JDBC sürücüsünün çağrılması , başlatılmasına ve dolayısıyla statik bloğun yürütülmesine neden olur. Göz at java2s.com/Open-Source/Java-Document/Database-DBMS/... bir örnek için. Yani bu aslında sürücü içlerinden dolayı özel bir durum.
Class.forName () size yansıma için yararlı olan sınıf nesnesini verir. Bu nesnenin sahip olduğu yöntemler, sınıfı yazan programcı tarafından değil Java tarafından tanımlanır. Her sınıf için aynıdır. Bu konuda newInstance () çağrılması sana o sınıfın bir örneğini verir (yani çağırarak Class.forName("ExampleClass").newInstance()
onu çağırmak aynıdır new ExampleClass()
Üzerinde yöntemleri bu sınıf tanımlar, erişim görünür alanları vb çağırabilir,)
JDBC dünyasında, normal uygulama (JDBC API'sine göre) Class#forName()
bir JDBC sürücüsünü yüklemek için kullanmanızdır . JDBC sürücüsü kendisini DriverManager
statik bir blok içine kaydetmelidir :
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class MyDriver implements Driver {
static {
DriverManager.registerDriver(new MyDriver());
}
public MyDriver() {
//
}
}
Çağırma Class#forName()
, tüm statik başlatıcıları yürütür . Bu şekilde, kabaca aşağıdaki gibi görünen DriverManager
bağlantı URL'sine göre, kayıtlı sürücüler arasında ilişkili sürücüyü bulabilirsiniz getConnection()
:
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");
}
Ama aynı zamanda orada arabası ile başlanarak, JDBC sürücüsü org.gjt.mm.mysql.Driver
hatalı içinde kendini kaydeder gibi iyi bilinen, örneğin, Oluşturucu yerine statik bloğun:
package com.dbvendor.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
public class BadDriver implements Driver {
public BadDriver() {
DriverManager.registerDriver(this);
}
}
Dinamik olarak çalışmasını sağlamanın tek yolu newInstance()
daha sonra aramaktır! Aksi takdirde ilk bakışta açıklanamayan "SQLException: uygun sürücü yok" ile karşılaşacaksınız. Bir kez daha, bu kendi kodunuzda değil, JDBC sürücüsünde bir hata . Günümüzde, hiçbir JDBC sürücüsü bu hatayı içermemelidir. Böylece newInstance()
uzaklara gidebilirsin (ve yapmalısın) .
1: yalnızca sınıfın statik bloğuyla ilgileniyorsanız, sınıfın yüklenmesi yalnızca yapacaktır ve statik blokları yürütecekse, ihtiyacınız olan tek şey:
Class.forName("Somthing");
2: sınıfı yüklemekle ilgileniyorsanız, statik bloklarını yürütün ve statik olmayan kısmına da erişmek istiyorsanız, bir örneğe ihtiyacınız var ve sonra ihtiyacınız var:
Class.forName("Somthing").newInstance();
"Class.forName ()", verilen ad için Class-Type değerini döndürür. "newInstance ()" bu sınıfın bir örneğini döndürür.
Türde hiçbir örnek yöntemini doğrudan çağıramazsınız, ancak yalnızca sınıf için yansımayı kullanabilirsiniz. Sınıfın bir nesnesiyle çalışmak istiyorsanız, bunun bir örneğini oluşturmanız gerekir ("yeni Sınıfım ()" olarak adlandırmakla aynı).
"Class.forName ()" için örnek
Class myClass = Class.forName("test.MyClass");
System.out.println("Number of public methods: " + myClass.getMethods().length);
"Class.forName (). NewInstance ()" için örnek
MyClass myClass = (MyClass) Class.forName("test.MyClass").newInstance();
System.out.println("String representation of MyClass instance: " + myClass.toString());
sadece yukarıdaki cevaplara ek olarak, bellekte bulunması gereken bir statik kodumuz olduğunda (örn. kod bloğu bağımsızdır), sınıfın döndürülmesini sağlayabiliriz, böylece eğer Class.forname ("someName") kullanırsak statik kod yok Class.forname (). newInstance ("someName") için gidebilirsiniz çünkü nesne seviyesi kod blokları (statik olmayan) hafızaya yükleyecektir
Class.forName () yöntemini kaç kez çağırırsanız kullanın, yalnızca statik blok birden fazla kez çalıştırılmadığında:
paketNameMethodDemo için;
genel sınıf MainClass {
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();
}
}
herkese açık sınıf DemoClass {
static {
System.out.println("in Static block");
}
{
System.out.println("in Instance block");
}
}
çıktı:
in Static block
in Instance block
Bu in Static block
ifade yalnızca bir kez değil üç kez yazdırılır.
Class.forName () -> forName (), class sınıfının statik yöntemidir ve kullanıcı sınıfı nesnesi değil yansıma için kullanılan Class sınıfı nesnesini döndürür, böylece yalnızca getMethods (), getConstructors () vb. Gibi Class sınıfı yöntemlerini çağırabilirsiniz.
(Runtime given) sınıfınızın yalnızca statik bloğunu çalıştırmayı ve yalnızca sınıfınızın yöntemleri, yapıcıları, Değiştirici vb. Bilgilerini almayı önemsiyorsanız, Class.forName () kullanarak elde ettiğiniz bu nesne ile yapabilirsiniz.
Ancak sınıf yönteminize (çalışma zamanında verdiğiniz sınıf) erişmek veya çağırmak istiyorsanız, nesnenin Class sınıfının newInstance yönteminin sizin için yapmasını sağlamanız gerekir.Sınıfın yeni bir örneğini oluşturun ve size geri gönderin Sınıfınıza yazmanız yeterlidir.
ex-: Diyelim ki Çalışan sizin sınıfınız
Sınıf a = Class.forName (args [0]);
// args [0] = çalışma zamanında sınıf vermek için cmd satırı argümanı.
Çalışan ob1 = a.newInstance ();
a.newInstance () yöntemi, yeni Employee () kullanılarak nesne oluşturmaya benzer.
Artık tüm sınıf görünür alanlarına ve yöntemlerine erişebilirsiniz.