Java Language
operatörer
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 ärnull
, eller omtoString()
returnerarnull
, 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
nyaString
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)
- Den binära tilläggsoperatören lägger till ett nummer till ett annat. (Det finns också en binär
- 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
ellerDouble
, är resultattypendouble
. - Annars, om någon av operanderna är en
float
ellerFloat
, då resultatet typ ärfloat
. - Annars, om någon av operanderna är
long
ellerLong
, är resultattypenlong
. - Annars är resultattypen
int
. Detta täckerbyte
,short
ochchar
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 tilldouble
, och operationen utförs med 64-bitars (dubbel precision binär) IEE 754 flytande punkt aritmetik. - Om resultattypen är
float
, befordras operandema till attfloat
, och operationen utförs med 32-bitars (enstaka precision binär) IEE 754 flytande punkt aritmetik. - Om resultattypen är
long
, befordras operandema tilllong
, och operationen utförs med 64-bitars signerade två-komplement-binär heltal-aritmetik. - Om resultattypen är
int
, befrämjas operandema tillint
, 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
ellerlong
är förlustfri. - Främjande av
float
tilldouble
ä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.
- Främjande av heltal till
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
ochd
är ett heltalq
vars storlek är så stor som möjligt samtidigt som|d ⋅ q| ≤ |n|
. Dessutom ärq
positiv när|n| ≥ |d|
ochn
ochd
har samma tecken, menq
är negativt när|n| ≥ |d|
ochn
ochd
har motsatta tecken.
Det finns ett par specialfall:
- Om
n
ärMIN_VALUE
, och delaren är -1, inträffarMIN_VALUE
och resultatet ärMIN_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 oma / b
är positivt, och - dess storlek är så stor som möjligt utan att överskrida storleken på den verkliga matematiska kvoten på
a
ochb
.
Å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 avMath.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:
- Om en av operanderna är av en boxad typ är den oboxad.
- Om någon av operanderna nu är en
byte
,short
ellerchar
, befordras den till enint
. - Om operandtyperna inte är desamma, befordras operand med typen "mindre" till den "större" typen.
- Jämförelsen genomförs sedan enligt följande:
- Om de promoterade operandema är
int
ellerlong
testas värdena för att se om de är identiska. - Om de befordrade operandema är
float
ellerdouble
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.
- de två versionerna av noll (
- Om de promoterade operandema är
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:
- Om en av operanderna är en
Boolean
, är den oboxad. - 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:
Om du använder
==
eller!=
För att jämföra tvåBoolean
objekt används referensoperatörerna. Detta kan ge ett oväntat resultat; se Fallgrop: använder == för att jämföra primitiva omslagobjekt som heltalOperatören
==
kan enkelt skrivas in som=
. För de flesta operandtyper leder detta misstag till ett sammanställningsfel. Förboolean
ochBoolean
operander leder emellertid misstaget till felaktigt körbeteende; se Fallgrop - Använda '==' för att testa en boolean
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!=
Ärtrue
. Faktum är att testetx != x
ärtrue
om och bara om värdet påx
ärNaN
.
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 medE1 = (T) ((E1) op (E2))
, därT
är typen avE1
, förutom attE1
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 tillc
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 somc = 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 somc = 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 somc = 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 somc = 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 somc = c % a
7. <<=
Operatören "vänster skift och tilldela".
Exempel:
c <<= 2
är ungefär samma somc = c << 2
8. >>=
Operatören "aritmetisk högerväxling och tilldelning".
Exempel:
c >>= 2
är ungefär samma somc = c >> 2
9. >>>=
Operatören "logiskt höger skift och tilldela".
Exempel:
c >>>= 2
är ungefär samma somc = c >>> 2
10. &=
Operatören "bitvis och och tilldela".
Exempel:
c &= 2
är ungefär samma somc = c & 2
11. |=
Operatören "bitvis eller tilldela".
Exempel:
c |= 2
är ungefär samma somc = c | 2
12. ^=
Operatören "bitvis exklusiv eller tilldela".
Exempel:
c ^= 2
är ungefär samma somc = 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:
Dessa operatörer kräver ett
int
ellerlong
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 enbyte
,short
ellerchar
.)Om du använder en skiftoperatör med en första operand som är en
byte
,char
ellershort
, befordras den till enint
och operationen producerar enint
.)Den andra operanden reduceras modulo antalet bitar av operationen för att ge skiftmängden. Mer information om modet matematiskt , se Modulus-exempel .
De bitar som flyttas från vänster eller höger ände av operationen kastas. (Java tillhandahåller inte en primitiv "roterande" operatör.)
Den aritmetiska skiftoperatören motsvarar ett (två komplement) nummer med en effekt på 2.
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:
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:
- Om en av operanderna är av en boxad typ är den oboxad.
- Om någon av operanderna nu är en
byte
,short
ellerchar
, befordras den till enint
. - Om operandtyperna inte är desamma, befordras operand med typen "mindre" till den "större" typen.
- Jämförelsen utförs på de resulterande
int
,long
,float
ellerdouble
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.