Collections.emptyList () bir <Object> Listesi döndürür?


269

Genel tür parametrelerini çıkarmak için Java'nın kuralında gezinirken sorun yaşıyorum. İsteğe bağlı bir liste parametresine sahip olan aşağıdaki sınıfı düşünün:

import java.util.Collections;
import java.util.List;

public class Person {
  private String name;
  private List<String> nicknames;

  public Person(String name) {
    this(name,Collections.emptyList());
  }

  public Person(String name,List<String> nicknames) {
    this.name = name;
    this.nicknames = nicknames;
  }
}

Java derleyicim aşağıdaki hatayı veriyor:

Person.java:9: The constructor Person(String, List<Object>) is undefined

Ancak Collections.emptyList()türü döndürür <T> List<T>, döndürmez List<Object>. Oyuncu kadrosu eklemek yardımcı olmaz

public Person(String name) {
  this(name,(List<String>)Collections.emptyList());
}

verim

Person.java:9: inconvertible types

Kullanma EMPTY_LISTyerineemptyList()

public Person(String name) {
  this(name,Collections.EMPTY_LIST);
}

verim

Person.java:9: warning: [unchecked] unchecked conversion

Ancak aşağıdaki değişiklik hatayı ortadan kaldırır:

public Person(String name) {
  this.name = name;
  this.nicknames = Collections.emptyList();
}

Burada hangi tür denetleme kuralını çalıştırdığımı ve bunun üstesinden gelmenin en iyi yolunu açıklayan var mı? Bu örnekte, son kod örneği tatmin edicidir, ancak daha büyük sınıflarla, kodu çoğaltmadan bu "isteğe bağlı parametre" desenini izleyerek yöntemler yazabilmek istiyorum.

Ekstra kredi için: EMPTY_LISTaksine ne zaman kullanılmalı emptyList()?


1
Java Generics ile ilgili tüm sorularınız için Maurice Naftalin, Philip Wadler tarafından yazılan " Java Generics and Collections " ı tavsiye ediyorum.
Julien Chastang

Yanıtlar:


447

Karşılaştığınız sorun, yöntem emptyList()geri dönmesine rağmen, List<T>bunu türle birlikte sağlamadığınızdan, varsayılan olarak döndürülmesidir List<Object>. Type parametresini sağlayabilir ve kodunuzun beklendiği gibi çalışmasını sağlayabilirsiniz:

public Person(String name) {
  this(name,Collections.<String>emptyList());
}

Şimdi düz atama yaparken, derleyici sizin için genel tip parametrelerini bulabilir. Buna tür çıkarımı denir. Örneğin, bunu yaptıysanız:

public Person(String name) {
  List<String> emptyList = Collections.emptyList();
  this(name, emptyList);
}

Daha sonra emptyList()çağrı doğru bir dönecekti List<String>.


12
Anladım. ML dünyasından gelince, Java'nın doğru türü çıkaramadığı garip: resmi parametrenin türü ve emptyList'in dönüş türü açıkça kullanılamaz. Ama sanırım inferencer türü sadece "bebek adımları" atabiliyor.
Chris Conway

5
Bazı basit durumlarda, derleyicinin bu durumda eksik tip parametresini çıkarması mümkün görünebilir - ancak bu tehlikeli olabilir. Yöntemin farklı parametrelerle birden fazla sürümü varsa, yanlış yöntemi çağırmanız gerekebilir. Ve ikincisi henüz var olmayabilir ...
Bill Michell

13
"Koleksiyonlar. <String> emptyList ()" notasyonu gerçekten tuhaf, ama mantıklı. Enum <E'den daha kolay Enum <E>> öğesini genişletir. :)
Thiago Chaves

12
Java 8'de artık bir tür parametresi sağlamak gerekli değildir (olası genel türlerde bir belirsizlik yoksa).
Vitalii Fedorenko

9
İkinci snippet, tür çıkarımını güzel gösteriyor ancak elbette derlenmiyor. To çağrısı thisyapıcıdaki ilk ifade olmalıdır.
Arjan

99

Kullanmak istediğiniz:

Collections.<String>emptyList();

Kaynak için boş listenin ne olduğuna bakarsanız, bunun aslında

return (List<T>)EMPTY_LIST;

26

emptyList yönteminde şu imza bulunur:

public static final <T> List<T> emptyList()

Yani <T>sonucun atanan değişkenin türünden jenerik parametre T'nin değerini çıkarttığı kelime listesi araçlarının önce. Yani bu durumda:

List<String> stringList = Collections.emptyList();

Dönüş değeri daha sonra açıkça bir tür değişkeni tarafından referanslandırılır List<String>, böylece derleyici bunu anlayabilir. Bu durumda:

setList(Collections.emptyList());

Derleyicinin genel türü bulmak için kullanacağı açık bir dönüş değişkeni yoktur, bu nedenle varsayılan değerdir Object.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.