Passando gli argomenti byte al metodo sovraccaricato


12

Ho preso questo frammento di codice da alcuni quiz, usando IDE l'ho eseguito e ho ottenuto un risultato lungo, lungo ma la risposta corretta è Byte, Byte , perché ho ottenuto risultati diversi? La domanda è correlata a JDK 11

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

MODIFICATO:

Il codice è stato preso qui: Panoramica sulla certificazione Oracle e domande di esempio (Pagina: 13, Domanda: 5)


1
Sei sicuro che non sia Byte b = 5;con la B maiuscola.
Joop Eggen,

4
Vado anche long, longsu Java8 FYI ... Non so perché essere sincero, in attesa di una risposta anche :)
sp00m

Risposte:


6

Quindi, se si passa attraverso la specifica del linguaggio Java per determinare la firma del metodo in fase di compilazione, sarà chiaro:

  1. La prima fase (§15.12.2.2) esegue la risoluzione del sovraccarico senza consentire la conversione boxing o unboxing o l'uso della chiamata al metodo dell'arity variabile. Se durante questa fase non viene trovato alcun metodo applicabile, l'elaborazione continua alla seconda fase.

  2. La seconda fase (§15.12.2.3) esegue la risoluzione del sovraccarico consentendo boxe e unboxing, ma preclude comunque l'uso della chiamata al metodo dell'arity variabile. Se durante questa fase non viene trovato alcun metodo applicabile, l'elaborazione continua alla terza fase.

  3. La terza fase (§15.12.2.4) consente di combinare il sovraccarico con metodi di arity variabile, boxe e unboxing.

Quindi, dai passaggi precedenti, è chiaro che nel tuo caso nella prima fase il compilatore Java troverà un metodo di corrispondenza che lo fa doCalc(long a,long b). Il tuo metodo ha doCalc(Byte s1, Byte s2)bisogno di un box automatico durante la chiamata in modo da ottenere meno preferenze.


1
Per quanto riguarda il motivo per cui longaccetta byte, sembra seguire una conversione primitiva allargata : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Quindi, fondamentalmente, +widening -boxing -varargsquindi +widening +boxing -varargspoi +widening +boxing +varargs.
sp00m,

@kbo Perché pensi che sia la risposta corretta Byte, Byte?
Amit Bera,

3
@kbo Immagino che la risposta corretta sia errata :) Potrebbe valere la pena indirizzare gli autori a questa domanda, se possibile.
sp00m,

3
@ sp00m Ho trovato questa domanda negli esempi di Oracle, per favore dai un'occhiata alla parte modificata
kbo

@kbo Wow ... Non ho idea di come procedere allora!
sp00m,

2

Leggi il capitolo JLS sulle conversioni .

Ciò che sta accadendo nel tuo caso è che durante il runtime, JVM sceglie di eseguire una conversione allargata byte -> long poiché questa è una conversione più sicura perché è garantito che non causi RuntimeException.

La conversione da byteal Bytecosiddetto boxe può comportare OutOfMemoryError poiché la JVM deve allocare nuovi oggetti nell'heap:

Una conversione di boxe può comportare un OutOfMemoryError se è necessario allocare una nuova istanza di una delle classi wrapper (Boolean, Byte, Character, Short, Integer, Long, Float o Double) ed è disponibile memoria insufficiente.

Per questo byte -> long motivo, è preferibile una conversione allargata più sicura .


2
Giusto per nota, boxe da bytea Bytenon provoca mai OutOfMemoryException, dal momento che tutti i valori di Byte(-128 - 127) vengono memorizzati nella cache internamente. Ma potrebbe non essere lo stesso con altri tipi, quindi come regola empirica, l'ampliamento della conversione ha la priorità.
Pavel Smirnov,

1

Per trovare il sovraccarico corretto, l'ordine è:

  1. per numero di parametri
  2. boxing / unboxing
  3. parametri variadici

Così

  • Se bdove Bytesarebbe il risultato Byte, Byte.
  • Se passato sarebbe stato new byte[] { b, b }il risultato sarebbe byte, byte.
  • Se viene passato due byte b, è possibile un ampliamento da byte a int a lungo e il risultato è long, long.
  • Quando viene rimosso il sovraccarico lungo, lungo, si Byte, Byteottiene.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.