2012-04-06 22 views
7

Derleme zamanında bir sınıf genişletme yeteneğine sahibim, ancak bu alt sınıfın bir örneğini, hali hazırda başlatılmış olan üst sınıfın bir örneğini kullanarak çalışma zamanında oluşturabilmem gerekir. Teorik olarak bu mümkün olmalıdır, çünkü alt sınıf kurucuları alt sınıf kurucusundan önce çağrılmışlardır.Java: Çalışma Saatinde Sınıfı Genişletme

Anlık sınıfımın alt sınıfını değiştirmek veya orijinal eşgörünümünü kesmek için programa yeterince erişemiyorum.

Kullanım Durumu: X sınıfının mevcut bir örnek dizisi vardır. Kodum sonradan yüklenir. Yüklenen alt sınıf Y X'i genişleterek X örneklerinden birinin yöntemlerinden birini geçersiz kılmam gerekiyor. Üst program, yalnızca bu dizi aracılığıyla nesnelere erişir, bu yüzden bu dizi öğesini Y örneğimle değiştirmek istiyorum, ancak Orijinal olarak bu diziye örneklenmiş gibi davranır. Üst sınıf örneğini ve ileriye dönük çağrıları ekleyemem ve süper sınıfı yeniden yerleştirmekle ilgili zor komplikasyonlar yapıyorum.

Umarım bu daha açıktır.

+3

Lütfen soruyu tekrarlayın. –

+1

Gerçekte neyi başarmaya çalıştığınıza dair bir örnek de verebilir misiniz? Sadece istediğiniz, ama muhtemelen imkansız yerine, bunu yapma yöntemi. – millimoose

+0

Mevcut satırı "public static Foo foo = new Foo();" değiştiremediğim. Ben "public class Bar Foo genişler" var ve ben ilk satır "kamu statik Foo foo = yeni Bar()" olduğu gibi "foo = yeni Bar (...)" yapmak istiyorum. – JAKJ

cevap

5

Yapmaya çalıştığınız şeyi yinelemek için ..

JVM'de bir ClassA örneği vardır. ClassA'nın sınıf heiarchy'sini dinamik olarak değiştirmek istersiniz, böylece ClassA'dan türeyen yeni bir sınıf ClassB olarak adlandırılır. Daha sonra, bir ClassB örneğini örneklemek istersiniz, ancak bunun, sınıf içi uygulaması var olan ClassA örneğinin olması gerekir. Hafıza değişimi gibi bir şey.

http://www.jboss.org/javassist'a bakmak isteyebilirsiniz. Yapmanız gereken şey, ClassLoader'ın yerini almak, sonra ClassA'nın ne zaman yükleneceğini belirlemek, sonra da örneklendirmektir. Daha sonra ClassB kurmanız ve bunun yerine onu iade etmeniz gerekir.

Güncelleme

biraz daha araştırmadan sonra hala istediğini yapabileceği olasılığı vardır. IDE, Eclipse gibi hata ayıklama sırasında HotSwap'ing yöntemi uygulamalarını destekliyor. Enstrümantasyon API'sini kullanıyorlar.

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

Sen yöntem organları yerine ancak eklemek veya yöntemleri kendilerini kaldıramazsınız. Bu nedenle, türü yeni türünüze değiştiremezsiniz, yöntem uygulamanızı yeni uygulamanızla tamamen değiştirebilirsiniz.

+0

Çalışma zamanında devralmayı değiştirmiyorum, ancak yalnızca üst sınıfı zaten oluşturulduğunda bir alt sınıfı başlatıyorum. – JAKJ

+0

@JAKJ Cevap hala aynı. Başka bir nesneye uyarlamak istediğiniz var olan bir nesneye sahipsiniz. Eğer bu yeni nesnenin ilk geri dönüş noktasını kontrol edecekseniz, o zaman Uyarlayabilir ve istediğiniz örneği döndürebilirsiniz. Sorunuzu ne düşündüğünüzü değil, Kullanım Davanızla güncellemenizi öneririz. –

+0

Sınıfım yüklendikten sonra sınıf yükleyiciyi değiştiremiyorum veya üçüncü taraf çalışma zamanlarını kullanamıyorum. Bu Java içinde olmalıdır. – JAKJ

1

Java Proxies'e baktınız mı?

"(aşağıda kısaca bir proxy sınıfı olarak anılacaktır) Dinamik vekil sınıf sınıf oluşturulduğunda zamanında belirtilen arayüzleri listesini uygulayan bir sınıftır": İşte

Javadoc gelen snippet'idir
+0

Proxy'ler arayüzler değil arayüzler içindir. – JAKJ

3

Ben cglib kullanarak öneririm:

CGLIB güçlü, yüksek performanslı ve kaliteli Kod Üretimi Kütüphanesi, Çalışma zamanında arayüzleri JAVA sınıflar için ve uygular edilir

You Burada bazı örnekler bulabilirsin: https://github.com/cglib/cglib/wiki

2

Bu bir aldatmaca olup olmadığını bilmiyorum ama eğer

public static Foo foo = new Foo(); 

ve Foo sizin Bar örneğine foo noktasını izin Foo ve kullanım yansıma için çıtayı bir Sarıcısını yapmak uzanır Bar ile değiştirmek istiyorum.

As

public class Foo extends Bar { 
    private bar; 
    public Foo(Bar oldInstance) { 
    this.bar = oldInstance; 
    } 
} 

ve

// exception handling ommitted 
public static void onStartup() { 
    Class fooRefClass = FooRef.class; 
    Field fooRef = fooRefClass.getDeclaredField("foo"); 

    Foo foo = (Foo)fooRef.get(null); 
    Bar bar = new Bar(foo); 
    fooRef.set(null, bar); 

} Bu durumda mümkün olup olmadığını bilmiyorum anlattı.