2013-05-05 15 views
16

jenerik türünü kabul eden bir sınıfım var ve ben equals yöntemini uygunsuz bir şekilde geçersiz kılmak istiyorum (örn. Temiz görünen ve çok az miktarda kod içeren, ancak çok genel bir kullanım durumu için)."instanceof" kullanarak jenerikler için "eşittir" yöntemi nasıl uygulanır?

Şu anda böyle bir şey var:

public class SingularNode<T> { 
    private T value; 

    @SuppressWarnings("unchecked") 
    @Override 
    public boolean equals(Object other){ 
     if(other instanceof SingularNode<?>){ 
      if(((SingularNode<T>)other).value.equals(value)){ 
       return true; 
      } 
     } 
     return false; 
    } 
} 

Ki, ben tahmin ediyorum, oldukça kusurludur - Ben potansiyel hata atmak olabilecek şekilde, other nesne üzerinde SingularNode<T> bir döküm yapıyorum.

Başka bir şey - if(other instanceof SingularNode<?>) yaptığımda aslında tam olarak doğru şeyi kontrol etmiyorum. Aslında T türüne karşı kontrol etmek istiyorum ve ? yazmıyor. parametreli tip SingularNode<T> karşı kontrol instanceof yapılamadı

: Ben ?T içine yapmaya zaman, ben bazı hata gibi olsun. ayrıca genel tür bilgileri zamanında bu sorunun üstesinden gelebilirsiniz nasıl

de silinecektir beri yerine formu SingularNode<?> kullanılsın mı? T.class.isInstance(other); yapmanın bir yolu var mı?

@SuppressWarnings("unchecked") 
public boolean isEqualTo(Class<?> c, Object obj){ 
    if(c.isInstance(obj) && c.isInstance(this)){ 
     if(((SingularNode<T>)obj).value.equals(value)){ 
      return true; 
     } 
    } 
    return false; 
} 

Ama bu sadece ekstra yöntem parametresi ile gerçekten garip görünüyor ve equals olduğu gibi aynı zamanda dahili bir fonksiyon değil:

orada böyle bir gerçekten çirkin kesmek çözüm varsayalım.

Jenerikleri anlayan biri lütfen bunu açıklayınız? Ben açıkça görebildiğiniz gibi, Java ile o kadar yetenekli değilim, bu yüzden biraz daha fazla detay ile açıklayınız! Örnekte

+2

Elinizdeki hatanın nedeni, genel türlerin silinmesidir. "T" nin geçilen elemanın –

+0

@MichalBorek mmm sınıfının aynı olup olmadığını kontrol etmesi gerektiğini düşünüyorum. Ben tam anlamıyorum. Yani başka bir sınıfta, eğer yaparsam: 'yeni SingularNode (5) .equals (yeni SingularNode ('k')),' kontrolün nerede olduğunu biliyor musunuz? –

+0

Bir sürü kod koymak için cevabı ekledim. –

cevap

17

Bu sürüm hiçbir uyarı

bir şey yardımcı olmuyor SingularNode<T> için döküm gelince
public boolean equals(Object other){ 
    if (other instanceof SingularNode<?>){ 
     if (((SingularNode<?>)other).value.equals(value)){ 
      return true; 
     } 
    } 
    return false; 
} 

verir, TObject ama herhangi bir şey olabilir kabul edemeyiz.Burada T türü hakkında endişelenmenize gerek yoktur -

jenerik

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

+0

'daki şablonlarla aynı değildir. Yanıt için teşekkürler. Evet, bu kod herhangi bir uyarı vermeyecektir çünkü '('' SingularNode ) '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'yi çeviriyorsunuzAncak, gelecekte "T" türünde kullanmak istediğim durumlarda, "T" türünde yapmak istediğim özel bir şey olduğuna karar vermem gerekiyor. Mantıklı geliyorsa? –

+0

Bunun bir anlamı olduğunu düşünmüyorum çünkü T'nin bir şey olduğunu ama Nesne olduğunu, bir şey olabileceğine inanamıyorum. Muhtemelen T, bir şey –

+0

bir şey uzatır durumda farklı olabilir. Öyleyse aslında '' 'burada' T' ile hemen hemen aynı mıdır? –

1
Ben kodu koymak için buraya cevap koymak

..

aşağıdaki göre, false olduğunu Integer(5).equals(Char('k')) (sözde kod) sahip java.lang.Integer üzerine uygulanmasını eşittir:

public boolean equals(Object obj) { 
    if (obj instanceof Integer) { 
     return value == ((Integer)obj).intValue(); 
    } 
    return false; 
} 

bu şekilde gidiyor döküm hakkında endişelenmenize gerek yok.

+0

Tamam, şimdi ne demek istediğini görüyorum. teşekkür ederim. Bir nedenden ötürü, Java'nın bir 'InvalidClassCast istisnası' ya da '' Karakter '' bir 'Tamsayı' ile yayınlamaya çalıştığınızda bir şey attığı izlenimi yanlıştı. ancak hata yapmak yerine sadece false döndürür. Şimdi görüyorum –

+0

Genellikle eşittir yöntemini ilk kullandığımız düşünmek diğer nesnenin sınıfıdır ve tüm Java eşittir uygulamaları bu şekilde yapar. –

+0

Bu yüzden '(SingularNode ) obj 'adlı dökümde, aslında gerçekleşen şey,' T 'yerine' obj '' SingularNode '' a dönüştürülmesidir. Yani 'obj.value' aslında 'T' yazıyor, doğru mu? –

2

Evgeniy's solution ve Michal's reasoning de Java derlenmektedir nasıl hakkında daha fazla bilgi doğrudur. Nedeni, equals yönteminin doğru çalışmak için jeneriklere bağlı olmamasıdır. Bunun yerine, Object tarafından bildirilmiş ve bir Object alır. Bir String argümanla Integer.equals çağırarak doğru false dönecektir çünkü Böylece thisSingularNode<String> olması durumda bu.

geçirildi olursa olsun çalışma zamanı türünü denetlemek için sorumlu ve bir SingularNode<Integer> ile karşılaştırın, sonra ((SingularNode<?>)other).value.equals(value) gayet olumlu.

-4

Döküm kullanmanız gerekmez. En ancak daha geneldir, ben de aynı sorun var bu

@Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (!(o instanceof VehicleModel)) return false; 

     VehicleModel that = (VehicleModel) o; 

     if (vehicleName != null ? !vehicleName.equals(that.vehicleName) : that.vehicleName != null) 
      return false; 

     return true; 
    } 
+3

Kafam karıştı. Ben döküm görüyorum. –

0

gibi bakın uygulanmasına eşittir. 3 jenerik türümün olduğu bir dersim var. Bu türlerin herhangi bir değişkenini saklamak zorunda değilim çünkü bu sınıf dönüşüm için kullanılıyor. Ancak 'istek' değişkenleri saklanır ve bu sınıfa dayanarak önbellek kullanırım, bu yüzden bu jeneriklere dayanan equals() yöntemini kullanmam gerekir.

Yansıma olmadan nasıl yapılacağı konusunda herhangi bir yaklaşım varsa biliyor musunuz? Belki bu türün iç değişkeni .. Ancak null.

public class TheClass<I, O, M> { 

    private ClassA param1; 
    private ClassB param2; 
    private ClassC<M> param3; 
    private BiFunction<ClassC<M>, I, Optional<O>> mapping; 

    public ClassD<O, M> doSomething(ClassD<I, M> param) { 
     ... 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) { 
      return true; 
     } 
     if (o == null) { 
      return false; 
     } 
     if (getClass() != o.getClass()) { 
      return false; 
     } 
     TheClass<?, ?, ?> that = (TheClass<?, ?, ?>) o; 

     return Objects.equals(getParam1(), that.getParam1()) && 
       Objects.equals(getParam2(), that.getParam2()) && 
       Objects.equals(getParam3(), that.getParam3()); 
    } 
} 

Daha iyi bir hayal gücü için ... Veritabanından veri almak için DAO nesneleri ayarladım. Öte yandan, farklı formatta (REST, iç sistemler ..) benzer bir veri sağlayan bir dizi API sağlayıcımız var. Bir türden diğerine bir haritalama fonksiyonuna ihtiyacımız var. Daha iyi performans için önbellek kullanırız ve ortadaki tek insan bu sınıftır.

İlgili konular