Perché l'autoboxing Java non si estende alle invocazioni di metodi dei tipi autoboxed?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

Domanda

Voglio convertire una primitiva in una stringa e ho provato:

myInt.toString();

Questo fallisce con l'errore:

int cannot be dereferenced

Ora, capisco che le primitive non sono tipi di riferimento (cioè non un oggetto) e quindi non possono avere metodi.Tuttavia, Java 5 ha introdotto l'autoboxing e l'unboxing (alla C#...che non mi è mai piaciuto in C#, ma non è questo il punto).Quindi con l'autoboxing, mi aspetto che quanto sopra converta myInt in un numero intero e quindi chiami toString() su quello.

Inoltre, credo che C# consenta tale chiamata, a meno che non ricordi male.Si tratta solo di uno sfortunato difetto delle specifiche di autoboxing/unboxing di Java o c'è una buona ragione per questo?

È stato utile?

Soluzione

L'autoboxing/unboxing Java non arriva al punto di consentirti di dereferenziare una primitiva, quindi il tuo compilatore lo impedisce.Il tuo compilatore lo sa ancora myInt come primitivo.C'è un articolo su questo problema su jcp.org.

L'autoboxing è utile principalmente durante l'assegnazione o il passaggio di parametri, consentendo di passare una primitiva come oggetto (o viceversa) o assegnare una primitiva a un oggetto (o viceversa).

Quindi sfortunatamente dovresti farlo in questo modo:(complimenti Patrick, sono passato alla tua strada)

Integer.toString(myInt);

Altri suggerimenti

Idem per quello che ha detto Justin, ma dovresti fare questo invece:

Integer.toString(myInt);

Salva un'allocazione o due ed è più leggibile.

Un altro modo per farlo è usare:

String.valueOf(myInt);

Questo metodo viene sovraccaricato per ogni tipo primitivo e Object.In questo modo non devi nemmeno pensare al tipo che stai utilizzando.Le implementazioni del metodo chiameranno per te il metodo appropriato del tipo specificato, ad es. Integer.toString(myInt).

Vedere http://java.sun.com/javase/6/docs/api/java/lang/String.html.

Mi sembra un difetto della specifica

Ci sono più carenze e questo è un argomento delicato.Controllo Questo fuori:

public class methodOverloading{
   public static void hello(Integer x){
      System.out.println("Integer");
   }

   public static void hello(long x){
      System.out.println("long");
   }

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

Qui verrebbe stampato "long" (non l'ho controllato personalmente), perché il compilatore sceglie l'ampliamento rispetto all'autoboxing.Fai attenzione quando usi l'autoboxing o non usarlo affatto!

La sintassi valida più vicina al tuo esempio è

((Integer) myInt).toString();

Al termine del compilatore, equivale a

Integer.valueOf(myInt).toString();

Tuttavia, questo non ha le stesse prestazioni dell'uso convenzionale, String.valueOf(myInt), perché, tranne in casi speciali, crea una nuova istanza di Integer, quindi la butta via immediatamente, risultando in altra spazzatura non necessaria.(Un piccolo intervallo di numeri interi viene memorizzato nella cache e l'accesso avviene tramite un accesso ad array.) Forse i progettisti del linguaggio volevano scoraggiare questo utilizzo per motivi di prestazioni.

Modificare:Apprezzerei se i downvoter commentassero il motivo per cui questo non è utile.

In C#, gli interi non sono né tipi di riferimento né devono essere racchiusi in un box per poterli utilizzare Accordare() da chiamare.Essi Sono considerati oggetti nel Framework (come ValueType, quindi hanno una semantica di valore), tuttavia.Nel CLR, i metodi sulle primitive vengono chiamati caricandoli "indirettamente" nello stack (ldind).

Come tutti hanno sottolineato, l'autoboxing ti consente di semplificare parte del codice, ma non puoi fingere che le primitive siano tipi complessi.

Interessante anche: "l'autoboxing è un hack a livello di compilatore" a Giava.L'autoboxing è fondamentalmente uno strano kludge aggiunto a Java.Guardare questo post per maggiori dettagli su quanto sia strano.

Sarebbe utile se Java definisse alcuni metodi statici per operare su tipi primitivi e incorporasse nel compilatore un po' di zucchero sintattico in modo che

5.asInteger

sarebbe equivalente a

some.magic.stuff.Integer.asInteger(5);

Non penso che una funzionalità del genere causerebbe incompatibilità con qualsiasi codice compilato secondo le regole attuali e in molti casi aiuterebbe a ridurre la confusione sintattica.Se Java dovesse eseguire l'autoboxing delle primitive a cui è stato effettuato il dereferenziamento, le persone potrebbero presumere che stia mappando la sintassi di dereferenziazione alle chiamate di metodi statici (che è effettivamente ciò che accade in .NET), e quindi che le operazioni scritte in quella forma non sarebbero più costose di quanto sarebbero le invocazioni di metodi statici equivalenti.Aggiunta di una nuova funzionalità linguistica che incoraggi le persone a scrivere codice errato (ad es.primitive dereferenziate con auto-boxing) non sembra una buona idea, anche se consentire metodi in stile dereferenziazione potrebbe esserlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top