2011-12-26 22 views
9

Ésta es una pregunta un seguimiento de la discusión:Java 7 Operación Diamante en llamada al método

Why doesn't the diamond operator work within a addAll() call in Java 7?

Desde el Tutorial de Java,

http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html

Tenga en cuenta que la el diamante a menudo funciona en llamadas a métodos; sin embargo, para mayor claridad, se sugiere que use el diamante principalmente para inicializar una variable donde se declare

Por lo tanto, estoy un poco confundido acerca de la primera línea. Cuando hace ¿diamante funciona en llamadas de método?

un poco más explicación sobre cómo funciona el operador de diamantes se pueden encontrar aquí:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20argument%20inference%20for%20constructors?

Y a partir de esto, me han tratado los siguientes, que funciona bien:

Dale que tengo:

private static class Box<T>{ 
    public Box(T t){} 
} 
static void f(Box<Integer> box){} 

una llamada como la siguiente compila bien:

f(new Box<>(new Integer(10))); 

El El parámetro tipo invocando el constructor en la llamada al método de f() anterior se deduce del argumento para el constructor (es decir, Integer).

Así que es esto lo que se quiere decir cuando el tutorial dice

Tenga en cuenta que el diamante a menudo trabaja en método llama

Si no es así, ¿puede alguien tan amable de proporcionar un ejemplo en el diamante obras en la llamada al método?

+0

@gurung es un error tipográfico. Caso grave de cortar y pegar :( –

Respuesta

3

Así que es esto lo que se quiere decir cuando se dice el tutorial

creo que sí, aunque hay un par de aspectos críticos cuando se trata de <> operadores.

En su caso, la instanciación de cuadros no es un problema dado que el tipo puede inferirse trivialmente utilizando el argumento constructor. Intente cambiar el constructor a "no" en un Integer o T y vea cómo falla la invocación.

class BadBox<T> { 

    private T t; 

    public BadBox(){}  

    public void setT(T t) { 
     this.t = t; 
    } 

    static void f(BadBox<Integer> box){} 

    public static void main(final String[] args) { 
     f(new BadBox<>()); //fails, should have worked ideally 
    }  
} 

Del mismo modo, echar un vistazo a esta clase:

class Testi<R> {  
    public void doIt(Set<? extends R> sets) { 
    } 

    public static void main(final String[] args) { 
      // works since type inference is now possible 
     new Testi<CharSequence>().doIt(new HashSet<>(Arrays.asList("a"))); 

      // fails; nothing which can help with type inference 
     new Testi<CharSequence>().doIt(new HashSet<>(); 
    }  
} 

Del mismo modo, el problema en su pregunta vinculada (con respecto addAll) puede ser simplemente resuelto por ayudar a cabo el compilador un poco de la siguiente manera:

List<String> list = new ArrayList<>(); 
list.add("A"); 

// works now! use only if you love diamond operator ;) 
list.addAll(new ArrayList<>(Arrays.asList(new String[0]))); 
// or the old-school way 
list.addAll(new ArrayList<String>())); 

operadores Diamond también parecen romperse cuando se trata de implementar clases anónimas de la siguiente manera:

final String[] strings = { "a", "b", "c" }; 
Arrays.sort(strings, new Comparator<>() { 
    @Override 
    public int compare(String o1, String o2) { 
     return 0; 
    } 
}); 

Afortunadamente, en este caso, el compilador es bastante explícito al mencionar que <> no funciona/no funciona con clases anónimas.

+1

buena respuesta +1. –

0

No se trata realmente de invocación de método. La instrucción independiente

new Box<>(new Integer(10)); 

también compila. Hay suficiente información para inferir T para Box (es decir, desde el argumento entero)

Por otro lado, esto no compila

new ArrayList<>(); 

No hay manera de saber lo que se desea tipo de lista.

Collection<String> strings = new ArrayList<>(); 

Esto funciona porque la inferencia es ayudado por el tipo de destino Collection<String>

+1

'nueva ArrayList <>();' como una declaración independiente * no * compila. – Holger

1

no creo que vale la pena pensar en cuando funciona y cuándo no. El compilador te dirá y, por lo tanto, tienes que volver a escribir lo que no funciona.

No hay una razón real detrás de esto; es más como si los desarrolladores pusieran las limitaciones actuales de la implementación del compilador real en un momento específico en la especificación y nos dijeran: así es como debe ser.

Java 8 elimina muchas de estas limitaciones sin que se congele el infierno. P.ej.

Arrays.asList("foo", "bar").addAll(new ArrayList<>()); 

compila con Java 8 sin ningún error. ¿Y por qué no?

Cuestiones relacionadas