Sök…


Introduktion

Operatörer på Java-programmeringsspråk är speciella symboler som utför specifika operationer på en, två eller tre operander och sedan returnerar ett resultat.

Anmärkningar

En operatör är en symbol (eller symboler) som ber ett Java-program att utföra en operation på en, två eller tre operander . En operatör och dess operander bildar ett uttryck (se uttrycket ämne). Operandernas operander är själva uttryck.

Detta ämne beskriver de 40 eller så distinkta operatörer som definierats av Java. Det separata ämnet för uttryck förklarar:

  • hur operatörer, operander och andra saker kombineras till uttryck,
  • hur uttryck utvärderas, och
  • hur uttryckstypning, konverteringar och uttrycksutvärdering fungerar.

String Concatenation Operator (+)

Symbolen + kan betyda tre distinkta operatörer i Java:

  • Om det inte finns någon operand före + , är det den unary Plus-operatören.
  • Om det finns två operander, och de är båda numeriska. då är det den binära tilläggsoperatören.
  • Om det finns två operander, och åtminstone en av dem är en String , är det den binära Concatenation-operatören.

I det enkla fallet sammanfogar Concatenation-operatören två strängar för att ge en tredje sträng. Till exempel:

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

När en av de två operanderna inte är en sträng konverteras den till en String enligt följande:

  • En operand vars typ är en primitiv typ konverteras som om man ringer toString() på det boxade värdet.

  • En operand vars typ är en referenstyp konverteras genom att kalla operandens toString() -metod. Om operanden är null , eller om toString() returnerar null , används istället strängens bokstavliga "null" .

Till exempel:

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"

Förklaringen till s5 exemplet är att toString() på arraytyper ärvs från java.lang.Object , och beteendet är att producera en sträng som består av typnamnet och objektets identitet hashcode.

Concatenation-operatören anges för att skapa ett nytt String , utom i det fall där uttrycket är ett konstant uttryck. I det senare fallet utvärderas uttrycket vid kompileringstyp, och dess körningsvärde motsvarar en strängbokstav. Detta innebär att det inte finns några driftskostnader för att dela en lång sträng bokstavlig som denna:

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

Optimering och effektivitet

Som nämnts ovan, med undantag för konstant uttryck, skapar varje strängkoncatenationsuttryck ett nytt String . Tänk på den här koden:

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

I metoden ovan skapar varje iteration av slingan en ny String som är ett tecken längre än föregående iteration. Varje sammankoppling kopierar alla tecken i operandsträngarna för att bilda den nya String . Således kommer stars(N) att:

  • skapa N nya String och kasta bort alla utom det sista,
  • kopiera N * (N + 1) / 2 tecken och
  • generera O(N^2) byte av skräp.

Detta är mycket dyrt för stora N Faktum är att varje kod som sammanlänker strängar i en slinga kan ha detta problem. Ett bättre sätt att skriva detta skulle vara följande:

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();
}

Helst bör du ställa in StringBuilder , men om detta inte är praktiskt kommer klassen automatiskt att växa upp stödmaterialet som byggaren använder för att hålla tecken. (Obs! Implementeringen utvidgar stödmaterialet exponentiellt. Denna strategi håller den mängden karaktärskopiering till en O(N) snarare än O(N^2) .)

Vissa människor tillämpar detta mönster på alla strängkoncentrationer. Detta är emellertid onödigt eftersom JLS tillåter en Java-kompilator att optimera strängkopplingar inom ett enda uttryck. Till exempel:

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

kommer vanligtvis att optimeras av bytekodkompilatorn till något liknande;

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();

(JIT-kompilatorn kan optimera det ytterligare om den kan dra slutsatsen att s1 eller s2 inte kan vara null .) Men observera att denna optimering endast är tillåten inom ett enda uttryck.

Kort sagt, om du är bekymrad över effektiviteten i strängkopplingar:

  • Gör handoptimering om du gör upprepade sammanlänkningar i en slinga (eller liknande).
  • Optimera inte ett enda sammanlänkningsuttryck.

Aritmetiska operatörer (+, -, *, /,%)

Java-språket tillhandahåller 7 operatörer som utför aritmetik på heltal och flytande punktvärden.

  • Det finns två + operatörer:
    • Den binära tilläggsoperatören lägger till ett nummer till ett annat. (Det finns också en binär + operatör som utför strängtillkoppling. Det beskrivs i ett separat exempel.)
    • Unary plus-operatören gör inget annat än att utlösa numerisk marknadsföring (se nedan)
  • Det finns två - operatörer:
    • Den binära subtraheringsoperatören drar ett nummer från ett annat.
    • Operatören unary minus motsvarar att subtrahera operand från noll.
  • Den binära multiplikationsoperatören (*) multiplicerar ett nummer med ett annat.
  • Den binära divideringsoperatören (/) delar ett nummer med ett annat.
  • Den binära återstoden 1- operatören (%) beräknar återstoden när ett nummer delas av ett annat.

1. Detta kallas ofta felaktigt som "modulus" -operatören. "Rest" är termen som används av JLS. "Modulus" och "rest" är inte samma sak.

Operand- och resultattyper och numerisk marknadsföring

Operatörerna kräver numeriska operander och ger numeriska resultat. Operandtyperna kan vara vilken primitiv numerisk typ som helst (dvs. byte , short , char , int , long , float eller double ) eller vilken numerisk omslagstyp som definieras i java.lang ; dvs ( Byte , Character , Short , Integer , Long , Float eller Double .

Resultattypen bestäms baserat på operandens eller operandstyperna enligt följande:

  • Om någon av operandema är en double eller Double , är resultattypen double .
  • Annars, om någon av operanderna är en float eller Float , då resultatet typ är float .
  • Annars, om någon av operanderna är long eller Long , är resultattypen long .
  • Annars är resultattypen int . Detta täcker byte , short och char operander samt `int.

Resultattypen för operationen avgör hur den aritmetiska operationen utförs och hur operanderna hanteras

  • Om resultattypen är double , befordras operandema till double , och operationen utförs med 64-bitars (dubbel precision binär) IEE 754 flytande punkt aritmetik.
  • Om resultattypen är float , befordras operandema till att float , och operationen utförs med 32-bitars (enstaka precision binär) IEE 754 flytande punkt aritmetik.
  • Om resultattypen är long , befordras operandema till long , och operationen utförs med 64-bitars signerade två-komplement-binär heltal-aritmetik.
  • Om resultattypen är int , befrämjas operandema till int , och operationen utförs med 32-bitars signerad två-komplement binär heltal-aritmetik.

Kampanj genomförs i två steg:

  • Om operandtypen är en omslagstyp, är operandvärdet oboxat till ett värde av motsvarande primitivtyp.
  • Vid behov befordras den primitiva typen till den önskade typen:
    • Främjande av heltal till int eller long är förlustfri.
    • Främjande av float till double är förlustfri.
    • Främjande av ett heltal till ett flytande punktvärde kan leda till förlust av precision. Konverteringen utförs med användning av IEE 768 "rund-till-närmaste" semantik.

Betydelsen av delning

Operatören delar upp den vänstra handen n ( utdelningen ) och den högra operanden d ( delaren ) och producerar resultatet q ( kvoten ).

Java-heltalsavdelningen avrundar mot noll. JLS Avsnitt 15.17.2 specificerar beteendet för Java-heltalsdelning enligt följande:

Kvoten som produceras för operanderna n och d är ett heltal q vars storlek är så stor som möjligt samtidigt som |d ⋅ q| ≤ |n| . Dessutom är q positiv när |n| ≥ |d| och n och d har samma tecken, men q är negativt när |n| ≥ |d| och n och d har motsatta tecken.

Det finns ett par specialfall:

  • Om n är MIN_VALUE , och delaren är -1, inträffar MIN_VALUE och resultatet är MIN_VALUE . Inget undantag kastas i detta fall.
  • Om d är 0, kastas `AritmeticException.

Java flyttalsdelning har fler kanter att tänka på. Grundidén är dock att resultatet q är det värde som är närmast tillfredsställande d . q = n .

Flytande punktdelning kommer aldrig att resultera i ett undantag. Istället resulterar operationer som divideras med noll i INF- och NaN-värden; se nedan.

Betydelsen av resten

Till skillnad från C och C ++ fungerar resten av operatören i Java med både heltal och flytande punktoperationer.

För heltalfall definieras resultatet av a % b som antalet r så att (a / b) * b + r är lika med a , där / , * och + är lämpliga Java-heltaloperatörer. Detta gäller i alla fall utom när b är noll. I så fall resulterar resten i en ArithmeticException .

Av ovanstående definition följer att a % b kan vara negativt om a är negativt och att det är positivt endast om a är positivt. Dessutom är storleken på a % b alltid mindre än storleken på b .

Återstående drift av flytande punkter är en generalisering av heltalets fall. Resultatet av a % b är resten r definieras av den matematiska relationen r = a - (b ⋅ q) där:

  • q är ett heltal,
  • det är negativt bara om a / b är negativt en positivt endast om a / b är positivt, och
  • dess storlek är så stor som möjligt utan att överskrida storleken på den verkliga matematiska kvoten på a och b .

Återstående flytande punkt kan producera INF och NaN värden i kantfall såsom när b är noll; se nedan. Det kommer inte att kasta ett undantag.

Viktig notering:

Resultatet av en flytande punktoperation som beräknas med % är inte detsamma som den som produceras av återstående operation definierad av IEEE 754. IEEE 754-återstoden kan beräknas med hjälp av Math.IEEEremainder bibliotek.

Heltals överflöde

Java 32- och 64-bitars heltal är signerade och använder två-komplementär binär representation. Till exempel är antalet intervall som kan representeras som (32 bitar) int -2 31 till +2 31 - 1.

När du lägger till, subtraherar eller flera två N-bitars heltal (N == 32 eller 64) kan resultatet av operationen vara för stort för att representera som ett N-bitars heltal. I detta fall leder operationen till heltalöverskridning , och resultatet kan beräknas enligt följande:

  • Den matematiska operationen utförs för att ge en mellanliggande två-komplement-representation av hela antalet. Denna representation kommer att vara större än N-bitar.
  • De nedre 32 eller 64 bitarna i mellanrepresentationen används som resultat.

Det bör noteras att heltalsöverskridning inte under några omständigheter leder till undantag.

Flytande INF- och NAN-värden

Java använder IEE 754 flytpunktsrepresentationer för float och double . Dessa representationer har några specialvärden för att representera värden som faller utanför domänen för verkliga nummer:

  • Värdena "oändligt" eller INF anger för stora siffror. +INF värdet anger siffror som är för stora och positiva. -INF värdet anger siffror som är för stora och negativa.
  • "Obestämd" / "inte ett tal" eller NaN anger värden som härrör från meningslösa operationer.

INF-värdena produceras genom flytande operationer som orsakar överflöde eller genom att divideras med noll.

NaN-värdena produceras genom att dividera noll med noll eller genom att beräkna noll återstående noll.

Överraskande är det möjligt att utföra aritmetik med INF- och NaN-operander utan att utlösa undantag. Till exempel:

  • Att lägga till + INF och ett ändligt värde ger + INF.
  • Lägga till + INF och + INF ger + INF.
  • Att lägga till + INF och -INF ger NaN.
  • Att dela med INF ger antingen +0,0 eller -0,0.
  • Alla operationer med en eller flera NaN-operander ger NaN.

För fullständig information hänvisas till relevanta underavsnitt i JLS 15 . Observera att detta till stor del är "akademiskt". För typiska beräkningar betyder en INF eller NaN att något har gått fel; t.ex. har du ofullständiga eller felaktiga inmatningsdata, eller beräkningen har programmerats fel.

Jämställdhetsoperatörerna (==,! =)

Operatörerna == och != Är binära operatörer som utvärderar till true eller false beroende på om operanderna är lika. Den == operatör ger true om operanderna är lika och false annars. Operatören != Anger false om operandema är lika och true annars.

Dessa operatörer kan användas operander med primitiva och referenstyper, men beteendet är betydligt annorlunda. Enligt JLS finns det faktiskt tre distinkta uppsättningar av dessa operatörer:

  • Boolean == och != Operatörer.
  • Numeriska == och != Operatörer.
  • Referens == och != Operatörer.

I alla fall är dock resultattypen för operatörerna == och != boolean .

Numeriska == och != Operatörer

När en (eller båda) av operandema hos en == eller != Operatör är en primitiv numerisk typ ( byte , short , char , int, long , float eller double ), är operatören en numerisk jämförelse. Den andra operanden måste vara antingen av en primitiv numerisk typ eller av en ruta numerisk typ.

De andra numeriska operatörernas beteende är som följer:

  1. Om en av operanderna är av en boxad typ är den oboxad.
  2. Om någon av operanderna nu är en byte , short eller char , befordras den till en int .
  3. Om operandtyperna inte är desamma, befordras operand med typen "mindre" till den "större" typen.
  4. Jämförelsen genomförs sedan enligt följande:
    • Om de promoterade operandema är int eller long testas värdena för att se om de är identiska.
    • Om de befordrade operandema är float eller double så:
      • de två versionerna av noll ( +0.0 och -0.0 ) behandlas som lika
      • ett NaN värde behandlas som inte lika med något, och
      • andra värden är lika om deras IEEE 754-representationer är identiska.

Obs! Du måste vara försiktig när du använder == och != För att jämföra värden för flytande punkter.

Boolean == och != Operatörer

Om båda operanderna är boolean , eller den ena är boolean och den andra är Boolean , dessa operatörer Boolean == och != Operatörer. Beteendet är som följer:

  1. Om en av operanderna är en Boolean , är den oboxad.
  2. De oboxade operandema testas och det booleska resultatet beräknas enligt följande sanningstabell
EN B A == B A! = B
falsk falsk Sann falsk
falsk Sann falsk Sann
Sann falsk falsk Sann
Sann Sann Sann falsk

Det finns två "fallgropar" som gör det tillrådligt att använda == och != Sparsamt med sanningsvärden:

Referens == och != Operatörer

Om båda operanderna är objektreferenser testar operatörerna == och != Om de två operanderna refererar till samma objekt . Det är ofta inte det du vill ha. För att testa om två objekt är lika med värde .equals() metoden. .equals() användas istället.

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

Varning: att använda == och != För att jämföra String är felaktigt i de flesta fall; se http://www.riptutorial.com/java/example/16290/pitfall--using----to-compare-strings . Ett liknande problem gäller primitiva omslagstyper; se http://www.riptutorial.com/java/example/8996/pitfall--using----to-compare-primitive-wrappers-objects-such-as-integer .

Om NaN-kanterna

JLS 15.21.1 anger följande:

Om endera operand är NaN , är resultatet av == false men resultatet av != Är true . Faktum är att testet x != x är true om och bara om värdet på x är NaN .

Detta beteende är (för de flesta programmerare) oväntat. Om du testar om ett NaN värde är lika med sig själv är svaret "Nej det är det inte!". Med andra ord == är inte reflexiv för NaN värden.

Detta är emellertid inte en "konstighet" i Java, detta beteende anges i IEEE 754 flytpunktsstandarder, och du kommer att upptäcka att det implementeras av de flesta moderna programmeringsspråk. (För mer information, se http://stackoverflow.com/a/1573715/139985 ... att notera att detta är skrivet av någon som var "i rummet när besluten fattades"!)

Inkrement / Decrement Operators (++ / -)

Variabler kan ökas eller dekrementeras med 1 med hjälp av ++ respektive -- .

När ++ och -- operatörer följer variabler, kallas de efterhandsökning och efterhandsminskning respektive.

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

När ++ och -- operatörerna föregår variablerna kallas operationerna pre-increment respektive pre-decrement .

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

Om operatören föregår variabeln är uttryckets värde värdet på variabeln efter att den har ökats eller minskats. Om operatören följer variabeln är uttryckets värde värdet på variabeln innan den ökas eller minskas.

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

Var noga med att inte överskriva efterintervaller eller minskningar. Detta händer om du använder en post-in / decrement-operatör i slutet av ett uttryck som tilldelas till själva in / decremented-variabeln. In / decrement kommer inte att påverka. Även om variabeln på vänster sida ökas korrekt kommer dess värde omedelbart att skrivas över med det tidigare utvärderade resultatet från höger sida av uttrycket:

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!) 

Korrekt:

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

Den villkorade operatören (? :)

Syntax

{villkor att utvärdera} ? {uttalande-utfört-on-true} : {uttalande-utfört-på-falskt}

Som visas i syntaxen använder den villkorade operatören (även känd som den ternära operatören 1 ) ? (frågetecken) och : (kolon) tecken för att möjliggöra ett villkorat uttryck av två möjliga resultat. Det kan användas för att ersätta längre if-else block för att returnera ett av två värden baserat på villkor.

result = testCondition ? value1 : value2

Är ekvivalent med

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

Det kan läsas som ”Om testCondition är sant, ställ in resultatet till värde1; annars, ställ in resultatet på värde2 ”.

Till exempel:

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

Är ekvivalent med

// 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"

Vanlig användning

Du kan använda den villkorade operatören för villkorade tilldelningar (som nollkontroll).

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

Detta exempel motsvarar:

String x = "";

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

Eftersom den villkorade operatören har den näst lägsta prioriteten, ovanför tilldelningsoperatörerna , finns det sällan ett behov av användning av parenteser kring villkoret , men parentes krävs runt hela villkorade operatörskonstruktionen i kombination med andra operatörer:

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

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

Betingade operatörer som häckar kan också göras i den tredje delen, där det fungerar mer som kedja eller som ett switch-uttalande.

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))

Fotnot:

1 - Både Java Language Specification och Java Tutorial kallar operatören ( ? : :) För villkorad operatör . Instruktionen säger att den är "också känd som den ternära operatören" eftersom den (för närvarande) är den enda ternära operatören definierad av Java. Termen "Villkorlig operatör" överensstämmer med C och C ++ och andra språk med en motsvarande operatör.

Bitvisa och logiska operatörer (~, &, |, ^)

Java-språket tillhandahåller fyra operatörer som utför bitvisa eller logiska operationer på heltal eller booleska operander.

  • Operatören för komplement ( ~ ) är en unär operatör som utför en bitvis eller logisk inversion av bitarna i en operand; se JLS 15.15.5. .
  • Operatören AND ( & ) är en binär operatör som utför en bitvis eller logisk "och" av två operander; se JLS 15.22.2. .
  • Operatören OR ( | ) är en binär operatör som utför en bitvis eller logisk "inklusive eller" av två operander; se JLS 15.22.2. .
  • Operatören XOR ( ^ ) är en binär operatör som utför en bitvis eller logisk "exklusiv eller" av två operander; se JLS 15.22.2. .

De logiska operationerna som utförs av dessa operatörer när operanderna är booleaner kan sammanfattas enligt följande:

EN 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

Observera att ovanstående tabeller beskriver vad som händer för enskilda bitar. Operatörerna fungerar faktiskt på alla 32 eller 64 bitar av operand eller operander parallellt.

Operandtyper och resultattyper.

De vanliga aritmetiska omvandlingarna gäller när operanderna är heltal. Vanliga användningsfall för bitvisa operatörer


Operatören ~ används för att vända ett booleskt värde eller ändra alla bitar i en heltaloperand.

Operatören & används för att "maskera ut" några av bitarna i ett heltalsoperand. Till exempel:

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

Den | operator används för att kombinera sanningsvärdena för två operander. Till exempel:

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

^ -Operatören används för att växla eller "vända" bitar:

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

För mer exempel på användning av bitvisa operatörer, se Bitmanipulation

Instansenof operatören

Denna operatör kontrollerar om objektet är av en viss typ av klass / gränssnitt. instans av operatören är skriven som:

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

Exempel:

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 );
   }
}

Detta skulle ge följande resultat:

true

Den här operatören kommer fortfarande att återge sanningen om objektet som jämförs är tilldelningen kompatibel med typen till höger.

Exempel:

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 );
   }
}

Detta skulle ge följande resultat:

true

Uppdragsoperatörerna (=, + =, - =, * =, / =,% =, << =, >> =, >>> =, & =, | = och ^ =)

Den vänstra handen för dessa operatörer måste vara antingen en icke-slutlig variabel eller ett element i en matris. Högeroperand måste vara uppdragskompatibel med vänsteroperand. Detta innebär att antingen typerna måste vara desamma, eller att den högra operandtypen måste vara konvertibel till den vänstra operandtypen genom en kombination av boxning, unboxing eller breddning. (För fullständig information se JLS 5.2 .)

Den exakta betydelsen av operatörerna "operation och tilldela" specificeras av JLS 15.26.2 som:

Ett sammansatt tilldelningsuttryck av formen E1 op= E2 är ekvivalent med E1 = (T) ((E1) op (E2)) , där T är typen av E1 , förutom att E1 endast utvärderas en gång.

Observera att det finns en implicit typbesättning före den slutliga tilldelningen.

1. =

Den enkla tilldelningsoperatören: tilldelar värdet på den högra handen till den vänstra handen.

Exempel: c = a + b lägger till värdet på a + b till värdet på c och tilldelar det till c

2. +=

Operatören "lägg till och tilldela": lägger till värdet på höger operand till värdet på den vänstra handen och tilldelar resultatet till vänsteroperand. Om den vänstra operand har typen String , är detta en "sammankoppling och tilldela" operatör.

Exempel: c += a är ungefär samma som c = c + a

3. -=

Operatören "subtrahera och tilldela": subtraherar värdet på höger operand från värdet på vänsteroperand och tilldelar resultatet till vänsteroperand.

Exempel: c -= a är ungefär samma som c = c - a

4. *=

Operatören "multiplicera och tilldela": multiplicerar värdet på den högra operand med värdet på den vänstra handen och tilldelar resultatet till vänsteroperand. .

Exempel: c *= a är ungefär samma som c = c * a

5. /=

Operatören "dela och tilldela": delar värdet på den högra operand med värdet på den vänstra handen och tilldela resultatet till vänsteroperand.

Exempel: c /*= a är ungefär samma som c = c / a

6. %=

Operatören "modulus och tilldela": beräknar modulen för värdet på högeroperand med värdet på den vänstra operand och tilldelar resultatet till vänsteroperand.

Exempel: c %*= a är ungefär samma som c = c % a

7. <<=

Operatören "vänster skift och tilldela".

Exempel: c <<= 2 är ungefär samma som c = c << 2

8. >>=

Operatören "aritmetisk högerväxling och tilldelning".

Exempel: c >>= 2 är ungefär samma som c = c >> 2

9. >>>=

Operatören "logiskt höger skift och tilldela".

Exempel: c >>>= 2 är ungefär samma som c = c >>> 2

10. &=

Operatören "bitvis och och tilldela".

Exempel: c &= 2 är ungefär samma som c = c & 2

11. |=

Operatören "bitvis eller tilldela".

Exempel: c |= 2 är ungefär samma som c = c | 2

12. ^=

Operatören "bitvis exklusiv eller tilldela".

Exempel: c ^= 2 är ungefär samma som c = c ^ 2

De villkorade och villkorade eller operatörerna (&& och ||)

Java tillhandahåller en villkorlig och en villkorlig eller operatör, som båda tar en eller två operander av typen boolean och ger ett boolean resultat. Dessa är:

  • && - operatören med villkorad OCH

  • || - de villkorade OR-operatörerna. Utvärderingen av <left-expr> && <right-expr> motsvarar följande pseudokod:

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

Utvärderingen av <left-expr> || <right-expr> motsvarar följande pseudokod:

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

Som pseudokoden ovan illustrerar, är kortslutningsoperatörernas beteende likvärdiga med att använda if / else uttalanden.

Exempel - att använda && som en vakt i ett uttryck

Följande exempel visar det vanligaste användningsmönstret för && operatören. Jämför dessa två versioner av en metod för att testa om ett levererat Integer är noll.

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

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

Den första versionen fungerar i de flesta fall, men om value argument är null , sedan en NullPointerException kommer att kastas.

I den andra versionen har vi lagt till ett "vakt" -test. value != null && value == 0 uttrycket utvärderas genom att först utföra value != null . Om null lyckas (dvs. det utvärderas till true ) utvärderas uttrycket value == 0 . Om null misslyckas, hoppas utvärderingen av value == 0 (kortslutas), och vi får ingen NullPointerException .

Exempel - att använda && för att undvika en kostsam beräkning

Följande exempel visar hur && kan användas för att undvika en relativt kostsam beräkning:

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

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

I den första versionen är båda operanderna på | kommer alltid att utvärderas, så metoden (dyra) isPrime kommer att kallas onödigt. Den andra versionen undviker det onödiga samtalet genom att använda || istället för | .

Skiftoperatörerna (<<, >> och >>>)

Java-språket tillhandahåller tre operatörer för att utföra bitvis växling på 32- och 64-bitars heltal. Dessa är alla binära operatörer med den första operanden som är värdet som ska flyttas, och den andra operand som säger hur långt man ska skifta.

  • Operatören << eller vänster skift flyttar värdet som ges av den första operanden åt vänster med antalet bitpositioner som ges av den andra operanden. De tomma positionerna i höger ände är fyllda med nollor.

  • Operatören ">>" eller aritmetisk skift förskjuter värdet som ges av den första operanden åt höger med antalet bitpositioner som ges av den andra operanden. De tomma positionerna i vänster slut fylls genom att kopiera den vänstra biten. Den här processen kallas teckenförlängning .

  • Operatören ">>>" eller logisk högerväxling förskjuter värdet som ges av den första operanden åt höger med antalet bitpositioner som ges av den andra operanden. De tomma positionerna i vänstra änden är fyllda med nollor.

Anmärkningar:

  1. Dessa operatörer kräver ett int eller long värde som den första operanden och producerar ett värde med samma typ som den första operand. (Du måste använda en uttrycklig typbesättning när du tilldelar resultatet av en växling till en byte , short eller char .)

  2. Om du använder en skiftoperatör med en första operand som är en byte , char eller short , befordras den till en int och operationen producerar en int .)

  3. Den andra operanden reduceras modulo antalet bitar av operationen för att ge skiftmängden. Mer information om modet matematiskt , se Modulus-exempel .

  4. De bitar som flyttas från vänster eller höger ände av operationen kastas. (Java tillhandahåller inte en primitiv "roterande" operatör.)

  5. Den aritmetiska skiftoperatören motsvarar ett (två komplement) nummer med en effekt på 2.

  6. Den vänstra skiftoperatören motsvarar ett (två komplement) nummer med en effekt på 2.

Följande tabell hjälper dig att se effekterna av de tre skiftoperatörerna. (Siffrorna har uttryckts i binär notation för att stödja vizualisering.)

operand1 operand2 << >> >>>
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

Det finns exempel på användaren av skiftoperatörer i Bitmanipulation

Lambda-operatören (->)

Från Java 8 och framåt är Lambda-operatören ( -> ) den operatör som används för att introducera ett Lambda-uttryck. Det finns två vanliga syntaxer, som illustreras av dessa exempel:

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

Ett lambda-uttryck definierar en anonym funktion, eller mer korrekt en instans av en anonym klass som implementerar ett funktionellt gränssnitt .

(Detta exempel ingår här för fullständighet. Se Lambda Expressions ämnet för fullständig behandling.)

Relationsoperatörerna (<, <=,>,> =)

Operatörerna < , <= , > och >= är binära operatörer för att jämföra siffror. Betydelsen av operatörerna är som du kan förvänta dig. Om till exempel a och b deklareras som någon av byte , short , char , int , long , float , double eller motsvarande rutor:

- `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`. 

Resultattypen för dessa operatörer är boolean i alla fall.

Relationsoperatörer kan användas för att jämföra siffror med olika typer. Till exempel:

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

Relationsoperatörer kan användas när endera eller båda siffrorna är fall av siffror i rutor. Till exempel:

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");
}

Det exakta beteendet sammanfattas enligt följande:

  1. Om en av operanderna är av en boxad typ är den oboxad.
  2. Om någon av operanderna nu är en byte , short eller char , befordras den till en int .
  3. Om operandtyperna inte är desamma, befordras operand med typen "mindre" till den "större" typen.
  4. Jämförelsen utförs på de resulterande int , long , float eller double värdena.

Du måste vara försiktig med relationella jämförelser som involverar flytande punktnummer:

  • Uttryck som beräknar flytande punktsnummer orsakar ofta rundningsfel på grund av att datorns flytpunktsrepresentationer har begränsad precision.
  • När man jämför en heltalstyp och en flytande punkttyp kan omvandlingen av heltalet till flyttpunkten också leda till rundningsfel.

Slutligen stöder Java användningen av relationella operatörer med andra typer än de som anges ovan. Du kan till exempel inte använda dessa operatörer för att jämföra strängar, matriser med siffror och så vidare.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow