Lär dig Java från grunden

Så vill du programmera i Java? Det är fantastiskt, och du har kommit till rätt ställe. Den Java 101-serien ger en egen guidad introduktion till Java-programmering, som börjar med grunderna och omfattar alla de centrala begreppen som du behöver veta för att bli en produktiv Java-utvecklare. Denna serie är teknisk, med många kodexempel som hjälper dig att förstå begreppen när vi går vidare. Jag antar att du redan har en viss programmeringserfarenhet, bara inte i Java.

Denna första artikel introducerar Java-plattformen och förklarar skillnaden mellan dess tre utgåvor: Java SE, Java EE och Java ME. Du lär dig också om den virtuella Java-maskinens (JVM) roll för att distribuera Java-applikationer. Jag hjälper dig att ställa in ett Java Development Kit (JDK) på ditt system så att du kan utveckla och köra Java-program, så kommer jag igång med arkitekturen för en typisk Java-applikation. Slutligen lär du dig hur du kompilerar och kör en enkel Java-app.

Uppdaterad för Java 12 och nya JShell

Denna serie har uppdaterats för Java 12 och innehåller en snabb introduktion till den nya jshell: ett interaktivt verktyg för att lära sig Java och prototypa Java-kod.

ladda ner Skaffa koden Ladda ner källkoden till exempel applikationer i denna handledning. Skapad av Jeff Friesen för JavaWorld.

Vad är Java?

Du kan tänka på Java som ett allmänt, objektorienterat språk som ser mycket ut som C och C ++, men som är lättare att använda och låter dig skapa mer robusta program. Tyvärr ger denna definition dig inte mycket insikt i Java. År 2000 beskrev Sun Microsystems (Java-plattformens upphovsman) Java på detta sätt: 

Java är ett enkelt, objektorienterat, nätverkskunnigt, tolkat, robust, säkert, arkitekturneutralt, bärbart, högpresterande, multitrådat, dynamiskt datorspråk.

Låt oss överväga var och en av dessa definitioner separat.

Java är ett enkelt språk . Java modellerades ursprungligen efter C och C ++, minus några potentiellt förvirrande funktioner. Pekare, flera implementeringsarv och operatörsöverbelastning är några C / C ++ - funktioner som inte ingår i Java. En funktion som inte är obligatorisk i C / C ++, men som är väsentlig för Java, är en sopsamlingsanläggning som automatiskt återfår objekt och matriser.

Java är ett objektorienterat språk . Java: s objektorienterade fokus gör det möjligt för utvecklare att arbeta med att anpassa Java för att lösa ett problem snarare än att tvinga oss att manipulera problemet för att uppfylla språkbegränsningar. Detta skiljer sig från ett strukturerat språk som C. Som ett exempel, medan Java låter dig fokusera på sparkonto föremål kräver C dig att tänka sig om sparkonto tillstånd (en sådan balans) och beteenden (t.ex. insättning och uttag).

Java är ett nätverkskunnigt språk . Javas omfattande nätverksbibliotek gör det enkelt att hantera TCP / IP-nätverksprotokoll (Transmission Control Protocol / Internet Protocol) som HTTP (HyperText Transfer Protocol) och FTP (File Transfer Protocol), och förenklar uppgiften att skapa nätverksanslutningar. Dessutom kan Java-program komma åt objekt i ett TCP / IP-nätverk, via Uniform Resource Locators (URL: er), med samma lätthet som du skulle få tillgång till dem från det lokala filsystemet.

Java är ett tolkat språk . Vid körning körs ett Java-program indirekt på den underliggande plattformen (som Windows eller Linux) via en virtuell maskin (som är en programvarurepresentation av en hypotetisk plattform) och tillhörande exekveringsmiljö. Den virtuella maskinen översätter Java-programmets bytkoder (instruktioner och tillhörande data) till plattformsspecifika instruktioner genom tolkning. Tolkning är att räkna ut vad en bytkodinstruktion betyder och sedan välja motsvarande "konserverade" plattformsspecifika instruktioner att utföra. Den virtuella maskinen kör sedan plattformsspecifika instruktioner.

Tolkning gör det lättare att felsöka felaktiga Java-program eftersom mer information om sammanställningstid är tillgänglig vid körning. Tolkning gör det också möjligt att fördröja länksteget mellan bitarna i ett Java-program till runtime, vilket påskyndar utvecklingen.

Java är ett robust språk . Java-program måste vara pålitliga eftersom de används i både konsument- och uppdragskritiska applikationer, allt från Blu-ray-spelare till fordonsnavigering eller luftkontrollsystem. Språkfunktioner som hjälper till att göra Java-robusta inkluderar deklarationer, dupliceringstypskontroll vid kompileringstid och körtid (för att förhindra problem med att matcha versioner), riktiga matriser med automatisk gränsövervakning och utelämnande av pekare. (Se "Elementära Java-språkfunktioner" för att komma igång med Java-språktyper, bokstäver, variabler och mer.)

En annan aspekt av Java: s robusthet är att loopar måste kontrolleras av booleska uttryck istället för heltaluttryck där 0 är falskt och ett icke-nollvärde är sant. Till exempel tillåter Java inte en C-stil-slinga, till exempel while (x) x++;eftersom slingan kanske inte slutar där förväntat. Istället måste du uttryckligen ange ett booleskt uttryck, till exempel while (x != 10) x++;(vilket innebär att slingan körs till xlika med 10).

Java är ett säkert språk . Java-program används i nätverk / distribuerade miljöer. Eftersom Java-program kan migrera till och utföra på ett nätverks olika plattformar är det viktigt att skydda dessa plattformar från skadlig kod som kan sprida virus, stjäla kreditkortsinformation eller utföra andra skadliga handlingar. Java-språkfunktioner som stöder robusthet (som utelämnande av pekare) fungerar med säkerhetsfunktioner som Java-sandlådans säkerhetsmodell och kryptering med public key. Tillsammans förhindrar dessa funktioner virus och annan farlig kod från att förorsaka förödelse på en intet ont anande plattform.

I teorin är Java säkert. I praktiken har olika säkerhetsproblem upptäckts och utnyttjats. Som ett resultat fortsätter Sun Microsystems då och Oracle nu att släppa säkerhetsuppdateringar.

Java är ett arkitekturneutralt språk . Nätverk kopplar samman plattformar med olika arkitekturer baserade på olika mikroprocessorer och operativsystem. Du kan inte förvänta dig att Java genererar plattformsspecifika instruktioner och att dessa instruktioner "förstås" av alla typer av plattformar som ingår i ett nätverk. Istället genererar Java plattformsoberoende bytekodinstruktioner som är enkla för varje plattform att tolka (via dess implementering av JVM).

Java är ett bärbart språk . Arkitekturnutralitet bidrar till bärbarhet. Det finns dock mer i Java: s portabilitet än plattformsoberoende instruktioner för bytecode. Tänk på att helstorleksstorlekar inte får variera. Till exempel måste 32-bitars heltalstyp alltid signeras och uppta 32 bitar, oavsett var 32-bitars heltal behandlas (t.ex. en plattform med 16-bitarsregister, en plattform med 32-bitarsregister eller en plattform med 64-bitarsregister). Java: s bibliotek bidrar också till bärbarhet. Vid behov tillhandahåller de typer som ansluter Java-kod med plattformsspecifika funktioner på det mest bärbara sättet.

Java är ett högpresterande språk . Tolkning ger en prestandanivå som vanligtvis är mer än tillräcklig. För mycket högpresterande applikationsscenarier använder Java just-in-time kompilering, som analyserar tolkade bytecode-instruktionssekvenser och sammanställer ofta tolkade instruktionssekvenser till plattformsspecifika instruktioner. Efterföljande försök att tolka dessa bytecode-instruktionssekvenser resulterar i exekvering av motsvarande plattformsspecifika instruktioner, vilket resulterar i en prestationsförstärkning.

Java är ett flertrådigt språk . För att förbättra prestanda för program som måste utföra flera uppgifter samtidigt stöder Java begreppet gängad körning . Till exempel använder ett program som hanterar ett grafiskt användargränssnitt (GUI) i väntan på inmatning från en nätverksanslutning en annan tråd för att utföra väntetiden istället för att använda standard-GUI-tråden för båda uppgifterna. Detta håller GUI lyhörd. Java: s synkroniseringsprimitiver tillåter trådar att säkert kommunicera data mellan sig utan att skada data. (Se trådad programmering i Java som diskuteras någon annanstans i Java 101-serien.)

Java är ett dynamiskt språk . Eftersom samtrafik mellan programkod och bibliotek sker dynamiskt vid körning är det inte nödvändigt att uttryckligen länka dem. Som ett resultat, när ett program eller ett av dess bibliotek utvecklas (till exempel för en buggfix eller prestandaförbättring), behöver en utvecklare bara distribuera det uppdaterade programmet eller biblioteket. Även om dynamiskt beteende resulterar i mindre kod att distribuera när en versionändring inträffar, kan denna distributionspolicy också leda till versionskonflikter. Till exempel tar en utvecklare bort en klasstyp från ett bibliotek eller byter namn på den. När ett företag distribuerar det uppdaterade biblioteket misslyckas befintliga program som beror på klasstypen. För att kraftigt minska detta problem stöder Java en gränssnitttyp, vilket är som ett avtal mellan två parter. (Se gränssnitt, typer och andra objektorienterade språkfunktioner som diskuteras någon annanstans i Java 101-serien.)

Att packa upp denna definition lär oss mycket om Java. Viktigast, det avslöjar att Java är både ett språk och en plattform. Du lär dig mer om Java-plattformskomponenter - nämligen den virtuella Java-maskinen och Java-exekveringsmiljön - senare i den här handledningen.

Tre utgåvor av Java: Java SE, Java EE och Java ME

Sun Microsystems släppte Java 1.0-mjukvaruutvecklingssatsen (JDK) i maj 1995. Den första JDK användes för att utveckla stationära applikationer och applets, och Java utvecklades därefter till att omfatta programmering av företagsserver och mobilenheter. Att lagra alla nödvändiga bibliotek i en enda JDK skulle ha gjort JDK för stor för att distribuera, särskilt för att distributionen på 1990-talet var begränsad av små CD-skivor och låga nätverkshastigheter. Eftersom de flesta utvecklare inte behövde alla sista API: er (en applikationsutvecklare på skrivbordet knappast skulle behöva komma åt Java-API: er för företag), delade Sun Java i tre huvudutgåvor. Dessa blev så småningom kända som Java SE, Java EE och Java ME:

  • Java Platform, Standard Edition (Java SE) är Java-plattformen för att utveckla klientapplikationer (som körs på skrivbord) och applets (som körs i webbläsare). Observera att applets av säkerhetsskäl inte längre stöds officiellt.
  • Java Platform, Enterprise Edition (Java EE ) är Java-plattformen byggd ovanpå Java SE, som endast används för att utveckla företagsinriktade serverapplikationer. Server-applikationer inkluderar Java-servlets , som är Java-program som liknar applets men körs på en server snarare än en klient. Servlets överensstämmer med Java Servlet API.
  • Java Platform, Micro Edition (Java ME) är också byggt ovanpå Java SE. Det är Java-plattformen för att utveckla MIDlets , som är Java-program som körs på mobila informationsenheter, och Xlets , som är Java-program som körs på inbäddade enheter.

Java SE är grundplattformen för Java och är fokus för Java 101-serien. Kodexempel kommer att baseras på den senaste versionen av Java i skrivande stund, Java 12.

Java-plattformen och JVM

Java är både ett programmeringsspråk och en plattform för att köra kompilerad Java-kod. Denna plattform består huvudsakligen av JVM, men inkluderar också en exekveringsmiljö som stöder JVM: s körning på den underliggande (native) plattformen. JVM innehåller flera komponenter för att ladda, verifiera och köra Java-kod. Figur 1 visar hur ett Java-program körs på denna plattform. 

Jeff Friesen

Överst i diagrammet finns en serie programklassfiler, varav en betecknas som huvudklassfilen. Ett Java-program består av åtminstone huvudklassfilen, som är den första klassfilen som ska laddas, verifieras och köras.

JVM delegerar klassladdning till sin klassladdarkomponent. Klasslastare laddar klassfiler från olika källor, till exempel filsystem, nätverk och arkivfiler. De isolerar JVM från komplexiteten i klassbelastningen.

En laddad klassfil lagras i minnet och representeras som ett objekt som skapats från Classklassen. När den har laddats verifierar bytecode-verifieraren de olika inställningarna för bytecode för att säkerställa att de är giltiga och inte äventyrar säkerheten.

Om klassfilens bytkoder inte är giltiga avslutas JVM. Annars tolkar dess tolkomponent bytkoden en instruktion i taget. Tolkning identifierar bytkodinstruktioner och utför motsvarande inbyggda instruktioner.

Vissa bytecode-instruktionssekvenser körs oftare än andra. När tolken upptäcker denna situation, kompilerar JVM: s just-in-time (JIT) kompilator bytekodssekvensen till inbyggd kod för snabbare körning.

Under körningen stöter tolkaren vanligtvis på en begäran om att utföra en annan klassfils bytkod (som tillhör programmet eller ett bibliotek). När detta händer laddar klassladdaren klassfilen och bytecode-verifieraren verifierar den laddade klassfilens bytkod innan den körs. Även under körning kan bytkodinstruktioner begära att JVM öppnar en fil, visar något på skärmen, gör ett ljud eller utför en annan uppgift som kräver samarbete med den inbyggda plattformen. JVM svarar genom att använda sin Java Native Interface (JNI) bridge-teknik för att interagera med den inbyggda plattformen för att utföra uppgiften.