Ricerca…


introduzione

Gli operatori nel linguaggio di programmazione Java sono simboli speciali che eseguono operazioni specifiche su uno, due o tre operandi e quindi restituiscono un risultato.

Osservazioni

Un operatore è un simbolo (o simboli) che indica a un programma Java di eseguire un'operazione su uno, due o tre operandi . Un operatore e i suoi operandi formano un'espressione (vedere l'argomento Espressioni). Gli operandi di un operatore sono essi stessi espressioni.

Questo argomento descrive i 40 operatori distinti definiti da Java. L'argomento delle espressioni separate spiega:

  • in che modo operatori, operandi e altre cose sono combinati in espressioni,
  • come vengono valutate le espressioni e
  • come funzionano le espressioni di battitura, le conversioni e le espressioni.

The String Concatenation Operator (+)

Il simbolo + può significare tre operatori distinti in Java:

  • Se non c'è un operando prima del + , allora è l'operatore unario Plus.
  • Se ci sono due operandi e sono entrambi numerici. quindi è l'operatore di aggiunta binaria.
  • Se ci sono due operandi e almeno uno di essi è una String , allora è l'operatore di concatenazione binaria.

Nel caso semplice, l'operatore Concatenazione unisce due stringhe per dare una terza stringa. Per esempio:

String s1 = "a String";
String s2 = "This is " + s1;    // s2 contains "This is a String"

Quando uno dei due operandi non è una stringa, viene convertito in una String come segue:

  • Un operando il cui tipo è di tipo primitivo viene convertito come se chiamasse toString() sul valore box.

  • Un operando il cui tipo è un tipo di riferimento viene convertito chiamando il metodo toString() dell'operando. Se l'operando è null o se il metodo toString() restituisce null , viene utilizzata la stringa letterale "null" .

Per esempio:

int one = 1;
String s3 = "One is "  + one;         // s3 contains "One is 1"
String s4 = null + " is null";        // s4 contains "null is null"
String s5 = "{1} is " + new int[]{1}; // s5 contains something like
                                      // "{} is [I@xxxxxxxx"

La spiegazione per l'esempio s5 è che il metodo toString() sui tipi di array è ereditato da java.lang.Object e il comportamento è quello di produrre una stringa che comprende il nome del tipo e l'hashcode dell'identità dell'oggetto.

L'operatore Concatenazione viene specificato per creare un nuovo oggetto String , tranne nel caso in cui l'espressione sia un'espressione costante. In quest'ultimo caso, l'espressione viene valutata al tipo di compilazione e il suo valore di runtime è equivalente a un valore letterale stringa. Ciò significa che non c'è nessun sovraccarico di runtime nel dividere un lungo letterale come questo:

String typing = "The quick brown fox " +
                "jumped over the " +
                "lazy dog";           // constant expression

Ottimizzazione ed efficienza

Come notato sopra, con l'eccezione delle espressioni costanti, ogni espressione di concatenazione di stringhe crea un nuovo oggetto String . Considera questo codice:

public String stars(int count) {
    String res = "";
    for (int i = 0; i < count; i++) {
        res = res + "*";
    }
    return res;
}

Nel metodo sopra, ogni iterazione del ciclo creerà una nuova String che è un carattere più lungo rispetto alla precedente iterazione. Ogni concatenazione copia tutti i caratteri nelle stringhe degli operandi per formare la nuova String . Quindi, le stars(N) :

  • crea N nuovi oggetti String , e butta via tutto tranne l'ultimo,
  • copia N * (N + 1) / 2 caratteri e
  • genera O(N^2) byte di spazzatura.

Questo è molto costoso per il grande N In effetti, qualsiasi codice che concatena stringhe in un ciclo è suscettibile di avere questo problema. Un modo migliore per scrivere questo sarebbe il seguente:

public String stars(int count) {
    // Create a string builder with capacity 'count' 
    StringBuilder sb = new StringBuilder(count);
    for (int i = 0; i < count; i++) {
        sb.append("*");
    }
    return sb.toString();
}

Idealmente, si dovrebbe impostare la capacità della StringBuilder , ma se questo non è pratico, la classe crescerà automaticamente la matrice supporto che il costruttore utilizza per tenere caratteri. (Nota: l'implementazione espande l'array di supporto in modo esponenziale. Questa strategia mantiene quella quantità di copia del personaggio su un O(N) piuttosto che su O(N^2) .)

Alcune persone applicano questo modello a tutte le concatenazioni di stringhe. Tuttavia, questo non è necessario perché il JLS consente a un compilatore Java di ottimizzare le concatenazioni di stringhe all'interno di una singola espressione. Per esempio:

String s1 = ...;
String s2 = ...;    
String test = "Hello " + s1 + ". Welcome to " + s2 + "\n";

sarà tipicamente ottimizzato dal compilatore bytecode per qualcosa di simile;

StringBuilder tmp = new StringBuilder();
tmp.append("Hello ")
tmp.append(s1 == null ? "null" + s1);
tmp.append("Welcome to ");
tmp.append(s2 == null ? "null" + s2);
tmp.append("\n");
String test = tmp.toString();

(Il compilatore JIT può ottimizzarlo ulteriormente se può dedurre che s1 o s2 non può essere null .) Ma si noti che questa ottimizzazione è consentita solo all'interno di una singola espressione.

In breve, se sei preoccupato dell'efficienza delle concatenazioni di stringhe:

  • Ottimizza a mano se esegui una concatenazione ripetuta in un ciclo (o simile).
  • Non ottimizzare a mano una singola espressione di concatenazione.

Gli operatori aritmetici (+, -, *, /,%)

Il linguaggio Java fornisce 7 operatori che eseguono l'aritmetica su valori interi e in virgola mobile.

  • Ci sono due operatori + :
    • L'operatore di aggiunta binaria aggiunge un numero a un altro. (Esiste anche un operatore binario + che esegue la concatenazione di stringhe, come descritto in un esempio separato).
    • L'operatore unario plus non fa nulla oltre all'attivazione della promozione numerica (vedi sotto)
  • Ci sono due - operatori:
    • L'operatore di sottrazione binaria sottrae un numero da un altro.
    • L'operatore unario meno equivale a sottrarre il suo operando da zero.
  • L'operatore di moltiplicazione binario (*) moltiplica un numero per un altro.
  • L'operatore di divisione binaria (/) divide un numero per un altro.
  • L'operatore del resto 1 binario (%) calcola il resto quando un numero viene diviso per un altro.

1. Questo è spesso erroneamente definito come l'operatore "modulo". "Remainder" è il termine utilizzato da JLS. "Modulo" e "resto" non sono la stessa cosa.

Operand e tipi di risultato e promozione numerica

Gli operatori richiedono operandi numerici e producono risultati numerici. I tipi di operando possono essere qualsiasi tipo di carattere numerico primitivo (es. byte , short , char , int , long , float o double ) o qualsiasi tipo di wrapper numerico definito in java.lang ; es. ( Byte , Character , Short , Integer , Long , Float o Double .

Il tipo di risultato è determinato in base ai tipi dell'operando o degli operandi, come segue:

  • Se uno degli operandi è double o Double , il tipo di risultato è double .
  • Altrimenti, se uno degli operandi è float o Float , il tipo di risultato è float .
  • Altrimenti, se uno degli operandi è long o Long , il tipo di risultato è long .
  • Altrimenti, il tipo di risultato è int . Questo copre byte , short e char operandi così come `int.

Il tipo di risultato dell'operazione determina come viene eseguita l'operazione aritmetica e come vengono gestiti gli operandi

  • Se il tipo di risultato è double , gli operandi vengono promossi a double e l'operazione viene eseguita utilizzando l'aritmetica in virgola mobile IEE 754 a 64 bit (binario a precisione doppia).
  • Se il tipo di risultato è float , gli operandi vengono promossi in float e l'operazione viene eseguita utilizzando l'aritmetica in virgola mobile IEE 754 a 32 bit (binario a precisione singola).
  • Se il tipo di risultato è long , gli operandi vengono promossi a long e l'operazione viene eseguita utilizzando l'aritmetica di numeri interi binari a due complementi con segno a 64 bit.
  • Se il tipo di risultato è int , gli operandi vengono promossi a int e l'operazione viene eseguita utilizzando l'aritmetica di numeri interi binari a due complementi con segno a 32 bit.

La promozione viene eseguita in due fasi:

  • Se il tipo di operando è un tipo di wrapper, il valore dell'operando è non inserito in un valore del tipo primitivo corrispondente.
  • Se necessario, il tipo primitivo viene promosso al tipo richiesto:
    • La promozione di interi per int o long è senza perdite.
    • La promozione del float da double è senza perdite.
    • La promozione di un intero con un valore in virgola mobile può portare a una perdita di precisione. La conversione viene eseguita utilizzando la semantica IEE 768 "round-to-nearest".

Il significato della divisione

L'operatore / divide l'operando di sinistra n (il dividendo ) e l'operando di destra d (il divisore ) e produce il risultato q (il quoziente ).

La divisione intera Java si arrotonda verso lo zero. La sezione 15.17.2 di JLS specifica il comportamento della divisione in intero Java come segue:

Il quoziente prodotto per gli operatori n e d è un valore intero q cui grandezza è la più grande possibile mentre soddisfa |d ⋅ q| ≤ |n| . Inoltre, q è positivo quando |n| ≥ |d| e n e d hanno lo stesso segno, ma q è negativo quando |n| ≥ |d| e n e d hanno segni opposti.

Ci sono un paio di casi speciali:

  • Se n è MIN_VALUE e il divisore è -1, si verifica un overflow di numero intero e il risultato è MIN_VALUE . Nessuna eccezione è lanciata in questo caso.
  • Se d è 0, viene lanciata l'opzione ArithmeticException.

La divisione Java floating point ha altri casi da considerare. Tuttavia l'idea di base è che il risultato q è il valore più vicino alla soddisfazione d . q = n .

La divisione in virgola mobile non genererà mai un'eccezione. Invece, le operazioni che dividono per zero risultano in valori INF e NaN; vedi sotto.

Il significato di resto

A differenza di C e C ++, l'operatore rimanente in Java funziona con operazioni sia a interi che a virgola mobile.

Per i casi interi, il risultato di a % b è definito come il numero r tale che (a / b) * b + r è uguale a a , dove / , * e + sono gli operatori di numero intero Java appropriati. Questo vale in tutti i casi tranne quando b è zero. In quel caso, il resto risulta in ArithmeticException .

Dalla definizione sopra riportata risulta che a % b può essere negativa solo se a è negativa, ed è positiva solo se a è positiva. Inoltre, la grandezza di a % b è sempre inferiore alla grandezza di b .

L'operazione di resto del punto mobile è una generalizzazione del caso intero. Il risultato di a % b è il resto r è definito dalla relazione matematica r = a - (b ⋅ q) dove:

  • q è un numero intero,
  • è negativo solo se a / b è negativo e solo se a / b è positivo, e
  • la sua grandezza è la più ampia possibile senza superare la grandezza del vero quoziente matematico di a e b .

Il resto in virgola mobile può produrre valori INF e NaN in casi limite come quando b è zero; vedi sotto. Non genererà un'eccezione.

Nota importante:

Il risultato di un'operazione remainder a virgola mobile come calcolata da % non è uguale a quella prodotta dall'operazione resto definita da IEEE 754. Il resto IEEE 754 può essere calcolato utilizzando il metodo di libreria Math.IEEEremainder .

Overflow intero

I valori interi Java 32 e 64 bit sono firmati e utilizzano la rappresentazione binaria a due complementi. Ad esempio, l'intervallo di numeri rappresentabili come (32 bit) int -2 31 a +2 31 - 1.

Quando si aggiunge, si sottraggono o più due numeri interi a N bit (N == 32 o 64), il risultato dell'operazione potrebbe essere troppo grande per rappresentare un numero intero N bit. In questo caso, l'operazione porta a un overflow di numeri interi e il risultato può essere calcolato come segue:

  • L'operazione matematica viene eseguita per fornire una rappresentazione intermedia del complemento a due dell'intero numero. Questa rappresentazione sarà più grande di N bit.
  • Come risultato, vengono utilizzati i 32 o 64 bit inferiori della rappresentazione intermedia.

È necessario notare che l'overflow dei numeri interi non comporta eccezioni in nessuna circostanza.

Valori INF e NAN a virgola mobile

Java utilizza le rappresentazioni in virgola mobile IEE 754 per float e double . Queste rappresentazioni hanno alcuni valori speciali per rappresentare valori che non rientrano nel dominio dei numeri reali:

  • I valori "infinito" o INF indicano numeri troppo grandi. Il valore +INF indica numeri troppo grandi e positivi. Il valore -INF denota numeri troppo grandi e negativi.
  • Il "indefinito" / "non un numero" o NaN denotano valori derivanti da operazioni prive di significato.

I valori INF sono generati da operazioni mobili che causano un overflow, o dalla divisione per zero.

I valori NaN vengono prodotti dividendo zero per zero o calcolando zero resto zero.

Sorprendentemente, è possibile eseguire operazioni aritmetiche utilizzando gli operandi INF e NaN senza attivare eccezioni. Per esempio:

  • Aggiungere + INF e un valore finito dà + INF.
  • Aggiungere + INF e + INF dà + INF.
  • Aggiungere + INF e -INF dà NaN.
  • Dividere per INF fornisce +0.0 o -0.0.
  • Tutte le operazioni con uno o più operandi NaN danno NaN.

Per i dettagli completi, fare riferimento alle sottosezioni rilevanti di JLS 15 . Si noti che questo è in gran parte "accademico". Per i calcoli tipici, un INF o NaN significa che qualcosa è andato storto; ad esempio, hai dati di input incompleti o errati o il calcolo è stato programmato in modo errato.

The Equality Operators (==,! =)

Gli operatori == e != Sono operatori binari che valutano true o false seconda che gli operandi siano uguali. L'operatore == restituisce true se gli operandi sono uguali e false altrimenti. L'operatore !=false se gli operandi sono uguali e true altrimenti.

Questi operatori possono essere utilizzati operandi con tipi primitivi e di riferimento, ma il comportamento è significativamente diverso. Secondo JLS, ci sono in realtà tre serie distinte di questi operatori:

  • Gli operatori booleani == e != .
  • Gli operatori numerici == e != .
  • Gli operatori di riferimento == e != .

Tuttavia, in tutti i casi, il tipo di risultato degli operatori == e != È boolean .

Gli operatori numerici == e !=

Quando uno (o entrambi) degli operandi di un operatore == o != È un tipo numerico primitivo ( byte , short , char , int, long , float o double ), l'operatore è un confronto numerico. Il secondo operando deve essere un tipo numerico primitivo o un tipo numerico in scatola.

Il comportamento di altri operatori numerici è il seguente:

  1. Se uno degli operandi è di tipo boxed, è unbox.
  2. Se uno degli operandi ora è un byte , short o char , viene promosso a un int .
  3. Se i tipi di operandi non sono gli stessi, l'operando con il tipo "più piccolo" viene promosso al tipo "più grande".
  4. Il confronto viene quindi eseguito come segue:
    • Se gli operandi promossi sono int o long i valori vengono testati per vedere se sono identici.
    • Se gli operandi promossi sono float o double allora:
      • le due versioni di zero ( +0.0 e -0.0 ) sono considerate uguali
      • un valore NaN viene trattato come non uguale a nulla, e
      • altri valori sono uguali se le loro rappresentazioni IEEE 754 sono identiche.

Nota: è necessario fare attenzione quando si utilizza == e != Per confrontare i valori in virgola mobile.

Gli operatori booleani == e !=

Se entrambi gli operandi sono boolean , o uno è boolean e l'altro è Boolean , questi operatori sono gli operatori booleani == e != . Il comportamento è il seguente:

  1. Se uno degli operandi è un Boolean , è unbox.
  2. Gli operandi unbox vengono testati e il risultato booleano viene calcolato in base alla seguente tabella di verità
UN B A == B A! = B
falso falso vero falso
falso vero falso vero
vero falso falso vero
vero vero vero falso

Ci sono due "trappole" che rendono consigliabile usare == e != parsimonia con valori di verità:

Gli operatori di riferimento == e !=

Se entrambi gli operandi sono riferimenti a oggetti, gli operatori == e != Testano se i due operandi si riferiscono allo stesso oggetto . Questo spesso non è quello che vuoi. Per verificare se due oggetti sono uguali per valore , dovrebbe essere usato il metodo .equals() .

String s1 = "We are equal";
String s2 = new String("We are equal");

s1.equals(s2); // true

// WARNING - don't use == or != with String values
s1 == s2;      // false

Avvertenza: l'uso di == e != Per confrontare i valori di String non è corretto nella maggior parte dei casi; vedere http://www.Scriptutorial.com/java/example/16290/pitfall--using- to- compare- strings . Un problema simile si applica ai tipi di wrapper primitivi; vedi http://www.Scriptutorial.com/java/example/8996/pitfall--using- a- compare- primitive-wrappers- objects- such- as- integer .

Informazioni sui casi limite di NaN

JLS 15.21.1 afferma quanto segue:

Se uno degli operandi è NaN , il risultato di == è false ma il risultato di != È true . In effetti, il test x != x è true se e solo se il valore di x è NaN .

Questo comportamento è (per la maggior parte dei programmatori) inaspettato. Se si verifica se un valore NaN è uguale a se stesso, la risposta è "No non lo è!". In altre parole, == non è riflessivo per i valori NaN .

Tuttavia, questa non è una "stranezza" di Java, questo comportamento è specificato negli standard IEEE 754 a virgola mobile, e scoprirete che è implementato dalla maggior parte dei moderni linguaggi di programmazione. (Per ulteriori informazioni, consultare http://stackoverflow.com/a/1573715/139985 ... notando che questo è scritto da qualcuno che era "nella stanza quando sono state prese le decisioni"!)

Gli operatori di incremento / decremento (++ / -)

Le variabili possono essere incrementate o decrementate di 1 usando rispettivamente gli operatori ++ e -- .

Quando gli operatori ++ e -- seguono le variabili, sono chiamati rispettivamente post-incremento e post-decremento .

int a = 10;
a++; // a now equals 11
a--; // a now equals 10 again

Quando gli operatori ++ e -- precedono le variabili, le operazioni sono chiamate rispettivamente pre-incremento e pre-decremento .

int x = 10;
--x; // x now equals 9
++x; // x now equals 10

Se l'operatore precede la variabile, il valore dell'espressione è il valore della variabile dopo essere stato incrementato o decrementato. Se l'operatore segue la variabile, il valore dell'espressione è il valore della variabile prima di essere incrementato o decrementato.

int x=10;

System.out.println("x=" + x + " x=" + x++ + " x=" + x); // outputs x=10 x=10 x=11
System.out.println("x=" + x + " x=" + ++x + " x=" + x); // outputs x=11 x=12 x=12
System.out.println("x=" + x + " x=" + x-- + " x=" + x); // outputs x=12 x=12 x=11
System.out.println("x=" + x + " x=" + --x + " x=" + x); // outputs x=11 x=10 x=10

Fare attenzione a non sovrascrivere post-incrementi o decrementi. Ciò accade se si utilizza un operatore post-in / decrement alla fine di un'espressione che viene riassegnato alla variabile in / decrementata stessa. L'in / decremento non avrà effetto. Anche se la variabile sul lato sinistro viene incrementata correttamente, il suo valore verrà immediatamente sovrascritto con il risultato valutato in precedenza dal lato destro dell'espressione:

int x = 0; 
x = x++ + 1 + x++;      // x = 0 + 1 + 1 
                        // do not do this - the last increment has no effect (bug!) 
System.out.println(x);  // prints 2 (not 3!) 

Corretta:

int x = 0;
x = x++ + 1 + x;        // evaluates to x = 0 + 1 + 1
x++;                    // adds 1
System.out.println(x);  // prints 3 

L'operatore condizionale (? :)

Sintassi

{condition-to-valutare} ? {statement-execution-on-true} : {istruzione-eseguito-su-falso}

Come mostrato nella sintassi, l'Operatore Condizionale (noto anche come Operatore Ternario 1 ) usa il ? (punto interrogativo) e : (due punti) caratteri per abilitare un'espressione condizionale di due possibili risultati. Può essere usato per sostituire i blocchi if-else più lunghi per restituire uno dei due valori in base alla condizione.

result = testCondition ? value1 : value2

È equivalente a

if (testCondition) { 
    result = value1; 
} else { 
    result = value2; 
}

Può essere letto come "Se testCondition è vero, imposta il risultato su value1; altrimenti, imposta il risultato su value2 ".

Per esempio:

// get absolute value using conditional operator 
a = -10;
int absValue = a < 0 ? -a : a;
System.out.println("abs = " + absValue); // prints "abs = 10"

È equivalente a

// get absolute value using if/else loop
a = -10;
int absValue;
if (a < 0) {
    absValue = -a;
} else {
    absValue = a;
}
System.out.println("abs = " + absValue); // prints "abs = 10"

Uso comune

È possibile utilizzare l'operatore condizionale per assegnazioni condizionali (come il controllo nullo).

String x = y != null ? y.toString() : ""; //where y is an object

Questo esempio è equivalente a:

String x = "";

if (y != null) {
    x = y.toString();
}

Poiché l'operatore condizionale ha la seconda precedenza più bassa, al di sopra degli operatori di assegnazione , raramente è necessario utilizzare la parentesi intorno alla condizione , ma è necessaria una parentesi attorno all'intero costrutto dell'operatore condizionale quando combinato con altri operatori:

// no parenthesis needed for expressions in the 3 parts
10 <= a && a < 19 ? b * 5 : b * 7

// parenthesis required
7 * (a > 0 ? 2 : 5)

La nidificazione degli operatori condizionali può essere eseguita anche nella terza parte, dove funziona più come concatenare o come un'istruzione switch.

a ? "a is true" :
b ? "a is false, b is true" :
c ? "a and b are false, c is true" :
    "a, b, and c are false"

//Operator precedence can be illustrated with parenthesis:

a ? x : (b ? y : (c ? z : w))

Nota:

1 - Sia Java Language Specification che Java Tutorial chiamano l'operatore ( ? : :) L'operatore condizionale . Il Tutorial dice che è "noto anche come Operatore Ternario" poiché è (attualmente) l'unico operatore ternario definito da Java. La terminologia "Operatore condizionale" è coerente con C e C ++ e altre lingue con un operatore equivalente.

Gli operatori bitwise e logici (~, &, |, ^)

Il linguaggio Java fornisce 4 operatori che eseguono operazioni bit a bit o logiche su operandi interi o booleani.

  • L'operatore complementare ( ~ ) è un operatore unario che esegue un'inversione bit per bit o logica dei bit di un operando; vedi JLS 15.15.5. .
  • L'operatore AND ( & ) è un operatore binario che esegue un "e" logico o bit a bit di due operandi; vedi JLS 15.22.2. .
  • L'operatore OR ( | ) è un operatore binario che esegue un "inclusivo" o "logico" di bit di due operandi; vedi JLS 15.22.2. .
  • L'operatore XOR ( ^ ) è un operatore binario che esegue un "esclusivo o" bitwise o logico di due operandi; vedi JLS 15.22.2. .

Le operazioni logiche eseguite da questi operatori quando gli operandi sono booleani possono essere riassunte come segue:

UN B ~ A A & B A | B A ^ B
0 0 1 0 0 0
0 1 1 0 1 1
1 0 0 0 1 1
1 1 0 1 1 0

Nota che per gli operandi interi, la tabella sopra descrive cosa succede per i singoli bit. Gli operatori operano effettivamente su tutti i 32 o 64 bit dell'operando o degli operandi in parallelo.

Tipi di operandi e tipi di risultato.

Le normali conversioni aritmetiche si applicano quando gli operandi sono numeri interi. Casi d'uso comuni per gli operatori bit a bit


L'operatore ~ viene utilizzato per invertire un valore booleano o modificare tutti i bit in un operando intero.

L'operatore & viene usato per "mascherare" alcuni dei bit in un operando intero. Per esempio:

int word = 0b00101010;
int mask = 0b00000011;   // Mask for masking out all but the bottom 
                         // two bits of a word
int lowBits = word & mask;            // -> 0b00000010
int highBits = word & ~mask;          // -> 0b00101000

Il | l'operatore è usato per combinare i valori di verità di due operandi. Per esempio:

int word2 = 0b01011111; 
// Combine the bottom 2 bits of word1 with the top 30 bits of word2
int combined = (word & mask) | (word2 & ~mask);   // -> 0b01011110

L'operatore ^ viene utilizzato per alternare o "sfogliare" i bit:

int word3 = 0b00101010;
int word4 = word3 ^ mask;             // -> 0b00101001

Per ulteriori esempi sull'uso degli operatori bit a bit, vedere Manipolazione bit

L'istanza di operatore

Questo operatore controlla se l'oggetto è di un particolare tipo di classe / interfaccia. L' operatore instanceof è scritto come:

( Object reference variable ) instanceof  (class/interface type)

Esempio:

public class Test {

   public static void main(String args[]){
      String name = "Buyya";
      // following will return true since name is type of String
      boolean result = name instanceof String;  
      System.out.println( result );
   }
}

Ciò produrrebbe il seguente risultato:

true

Questo operatore restituirà comunque true se l'oggetto da confrontare è l'assegnazione compatibile con il tipo sulla destra.

Esempio:

class Vehicle {}

public class Car extends Vehicle {
   public static void main(String args[]){
      Vehicle a = new Car();
      boolean result =  a instanceof Car;
      System.out.println( result );
   }
}

Ciò produrrebbe il seguente risultato:

true

The Assignment Operators (=, + =, - =, * =, / =,% =, << =, >> =, >>> =, & =, | = e ^ =)

L'operando di sinistra per questi operatori deve essere una variabile non finale o un elemento di una matrice. L'operando destro deve essere compatibile con l'operando di sinistra. Ciò significa che i tipi devono essere uguali oppure che il tipo di operando destro deve essere convertibile nel tipo di operandi di sinistra mediante una combinazione di boxing, unboxing o widening. (Per i dettagli completi, fare riferimento a JLS 5.2 .)

Il significato preciso degli operatori "operazione e assegnazione" è specificato da JLS 15.26.2 come:

Un'espressione di assegnazione composta della forma E1 op= E2 è equivalente a E1 = (T) ((E1) op (E2)) , dove T è il tipo di E1 , tranne che E1 viene valutato solo una volta.

Nota che c'è un cast implicito del tipo prima dell'assegnazione finale.

1. =

L'operatore di assegnazione semplice: assegna il valore dell'operando di destra all'operando di sinistra.

Esempio: c = a + b aggiungerà il valore di a + b al valore di c e assegnarlo a c

2. +=

L'operatore "aggiungi e assegna": aggiunge il valore dell'operando di destra al valore dell'operando di sinistra e assegna il risultato all'operando di sinistra. Se l'operando di sinistra ha tipo String , allora questo è un operatore "concatena e assegna".

Esempio: c += a è all'incirca uguale a c = c + a

3. -=

L'operatore "sottrazione e assegnazione": sottrae il valore dell'operando di destra dal valore dell'operando della mano sinistra e assegna il risultato all'operando della mano sinistra.

Esempio: c -= a è all'incirca uguale a c = c - a

4. *=

L'operatore "moltiplica e assegna": moltiplica il valore dell'operando di destra per il valore dell'operando di sinistra e assegna il risultato all'operando di sinistra. .

Esempio: c *= a è all'incirca uguale a c = c * a

5. /=

L'operatore "divide e assegna": divide il valore dell'operando di destra per il valore dell'operando di sinistra e assegna il risultato all'operando di sinistra.

Esempio: c /*= a è approssimativamente uguale a c = c / a

6. %=

L'operatore "modulus and assign": calcola il modulo del valore dell'operando di destra per il valore dell'operando di sinistra e assegna il risultato all'operando di sinistra.

Esempio: c %*= a è approssimativamente uguale a c = c % a

7. <<=

L'operatore "spostamento a sinistra e assegnazione".

Esempio: c <<= 2 equivale all'incirca a c = c << 2

8. >>=

L'operatore "aritmetico destro cambia e assegna".

Esempio: c >>= 2 equivale all'incirca a c = c >> 2

9. >>>=

L'operatore "spostamento logico destro e assegnazione".

Esempio: c >>>= 2 equivale all'incirca a c = c >>> 2

10. &=

L'operatore "bit a bit e assegnazione".

Esempio: c &= 2 è approssimativamente uguale a c = c & 2

11. |=

L'operatore "bit a bit o assign".

Esempio: c |= 2 equivale all'incirca a c = c | 2

12. ^=

L'operatore "bitwise exclusive or and assign".

Esempio: c ^= 2 equivale all'incirca a c = c ^ 2

Gli operatori condizionali e condizionali o (&& e ||)

Java fornisce un operatore condizionale e / o condizionale, che entrambi accettano uno o due operandi di tipo boolean e producono un risultato boolean . Questi sono:

  • && - l'operatore AND condizionale,

  • || - gli operatori OR condizionali. La valutazione di <left-expr> && <right-expr> è equivalente al seguente pseudo-codice:

    {
       boolean L = evaluate(<left-expr>);
       if (L) {
           return evaluate(<right-expr>);
       } else {
           // short-circuit the evaluation of the 2nd operand expression
           return false;
       }
    }
    

La valutazione di <left-expr> || <right-expr> è equivalente al seguente pseudo-codice:

    {
       boolean L = evaluate(<left-expr>);
       if (!L) {
           return evaluate(<right-expr>);
       } else {
           // short-circuit the evaluation of the 2nd operand expression
           return true;
       }
    }

Come illustrato dallo pseudo-codice sopra, il comportamento degli operatori di cortocircuito è equivalente all'utilizzo delle istruzioni if / else .

Esempio: uso di && come guardia in un'espressione

L'esempio seguente mostra il modello di utilizzo più comune per l'operatore && . Confrontare queste due versioni di un metodo per verificare se un Integer fornito è zero.

public boolean isZero(Integer value) {
    return value == 0;
}

public boolean isZero(Integer value) {
    return value != null && value == 0;
}

La prima versione funziona nella maggior parte dei casi, ma se l'argomento value è null , verrà NullPointerException una NullPointerException .

Nella seconda versione abbiamo aggiunto un test di "guardia". Il value != null && value == 0 espressione viene valutata eseguendo prima il value != null test. Se il test null esito positivo (vale a dire vale true ), viene valutato il value == 0 espressione. Se il test null fallisce, allora la valutazione del value == 0 viene saltata (cortocircuitata) e non si ottiene NullPointerException .

Esempio: usare && per evitare un calcolo costoso

L'esempio seguente mostra come && può essere usato per evitare un calcolo relativamente costoso:

public boolean verify(int value, boolean needPrime) {
    return !needPrime | isPrime(value);
}

public boolean verify(int value, boolean needPrime) {
    return !needPrime || isPrime(value);
}

Nella prima versione, entrambi gli operandi del | sarà sempre valutato, quindi il metodo (costoso) isPrime verrà chiamato inutilmente. La seconda versione evita la chiamata non necessaria utilizzando || invece di | .

The Shift Operators (<<, >> e >>>)

Il linguaggio Java fornisce tre operatori per eseguire lo spostamento bit per bit su valori interi a 32 e 64 bit. Questi sono tutti operatori binari con il primo operando come valore da spostare, e il secondo operando che dice quanto lontano spostare.

  • L'operatore << o spostamento a sinistra sposta il valore dato dal primo operando verso sinistra per il numero di posizioni di bit date dal secondo operando. Le posizioni vuote all'estremità destra sono piene di zeri.

  • L'operatore '>>' o spostamento aritmetico sposta il valore dato dal primo operando a destra del numero di posizioni di bit date dal secondo operando. Le posizioni vuote all'estremità sinistra vengono riempite copiando il bit più a sinistra. Questo processo è noto come estensione del segno .

  • L'operatore ">>>" o spostamento logico destro sposta il valore dato dal primo operando a destra del numero di posizioni di bit fornite dal secondo operando. Le posizioni vuote all'estremità sinistra sono piene di zeri.

Gli appunti:

  1. Questi operatori richiedono un valore int o long come primo operando e producono un valore con lo stesso tipo del primo operando. (Sarà necessario utilizzare un cast di tipo esplicito quando si assegna il risultato di uno spostamento a una variabile byte , short o char .)

  2. Se si utilizza un operatore di spostamento con un primo operando che è un byte , char o short , viene promosso a un int e l'operazione produce un int .)

  3. Il secondo operando viene ridotto modulo il numero di bit dell'operazione per dare l'ammontare dello spostamento. Per ulteriori informazioni sul concetto matematico mod , vedere Esempi di moduli .

  4. I bit che vengono spostati dalla fine sinistra o destra dall'operazione vengono scartati. (Java non fornisce un operatore di "rotazione" primitivo).

  5. L'operatore di spostamento aritmetico equivale a dividere un numero (a complemento di due) per una potenza di 2.

  6. L'operatore di spostamento a sinistra equivale a moltiplicare un numero (a complemento di due) per una potenza di 2.

La seguente tabella ti aiuterà a vedere gli effetti dei tre operatori di turno. (I numeri sono stati espressi in notazione binaria per aiutare la visualizzazione).

operand1 operando2 << >> >>>
0b0000000000001011 0 0b0000000000001011 0b0000000000001011 0b0000000000001011
0b0000000000001011 1 0b0000000000010110 0b0000000000000101 0b0000000000000101
0b0000000000001011 2 0b0000000000101100 0b0000000000000010 0b0000000000000010
0b0000000000001011 28 0b1011000000000000 0b0000000000000000 0b0000000000000000
0b0000000000001011 31 0b1000000000000000 0b0000000000000000 0b0000000000000000
0b0000000000001011 32 0b0000000000001011 0b0000000000001011 0b0000000000001011
... ... ... ... ...
0b1000000000001011 0 0b1000000000001011 0b1000000000001011 0b1000000000001011
0b1000000000001011 1 0b0000000000010110 0b1100000000000101 0b0100000000000101
0b1000000000001011 2 0b0000000000101100 0b1110000000000010 0b00100000000000100
0b1000000000001011 31 0b1000000000000000 0b1111111111111111 0b0000000000000001

Ci sono esempi di utenti di operatori di shift nella manipolazione di Bit

L'operatore Lambda (->)

Da Java 8 in poi, l'operatore Lambda ( -> ) è l'operatore utilizzato per introdurre un'espressione Lambda. Esistono due sintassi comuni, come illustrato da questi esempi:

Java SE 8
  a -> a + 1              // a lambda that adds one to its argument
  a -> { return a + 1; }  // an equivalent lambda using a block.

Un'espressione lambda definisce una funzione anonima, o più correttamente un'istanza di una classe anonima che implementa un'interfaccia funzionale .

(Questo esempio è incluso qui per completezza. Fare riferimento all'argomento Lambda Expressions per il trattamento completo.)

The Relational Operators (<, <=,>,> =)

Gli operatori < , <= , > e >= sono operatori binari per il confronto di tipi numerici. Il significato degli operatori è come ci si aspetterebbe. Ad esempio, se a e b sono dichiarati come byte , short , char , int , long , float , double o i corrispondenti tipi di box:

- `a < b` tests if the value of `a` is less than the value of `b`. 
- `a <= b` tests if the value of `a` is less than or equal to the value of `b`. 
- `a > b` tests if the value of `a` is greater than the value of `b`. 
- `a >= b` tests if the value of `a` is greater than or equal to the value of `b`. 

Il tipo di risultato per questi operatori è boolean in tutti i casi.

Gli operatori relazionali possono essere utilizzati per confrontare i numeri con tipi diversi. Per esempio:

int i = 1;
long l = 2;
if (i < l) {
    System.out.println("i is smaller");
}

Gli operatori relazionali possono essere utilizzati quando uno o entrambi i numeri sono esempi di tipi numerici in scatola. Per esempio:

Integer i = 1;   // 1 is autoboxed to an Integer
Integer j = 2;   // 2 is autoboxed to an Integer
if (i < j) {
    System.out.println("i is smaller");
}

Il comportamento preciso è riassunto come segue:

  1. Se uno degli operandi è di tipo boxed, è unbox.
  2. Se uno degli operandi ora è un byte , short o char , viene promosso a un int .
  3. Se i tipi di operandi non sono gli stessi, l'operando con il tipo "più piccolo" viene promosso al tipo "più grande".
  4. Il confronto viene eseguito sui valori int , long , float o double risultanti.

Devi stare attento con i confronti relazionali che coinvolgono numeri in virgola mobile:

  • Le espressioni che calcolano i numeri in virgola mobile spesso causano errori di arrotondamento dovuti al fatto che le rappresentazioni in virgola mobile del computer hanno una precisione limitata.
  • Quando si confronta un tipo intero e un tipo a virgola mobile, anche la conversione del numero intero in virgola mobile può portare a errori di arrotondamento.

Infine, Java supporta bit l'uso di operatori relazionali con tipi diversi da quelli sopra elencati. Ad esempio, non è possibile utilizzare questi operatori per confrontare stringhe, matrici di numeri e così via.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow