Java

**Java** on Sun Microsystemsin kehittämä teknologiaperhe ja ohjelmistoalusta, johon kuuluu muun muassa laitteistoriippumaton korkean tason, luokkapohjainen, oliopohjainen ohjelmointikieli, joka on suunniteltu siten, että siinä on mahdollisimman vähän toteutusriippuvuutta, sekä ajoaikainen ympäristö virtuaalikoneineen ja luokkakirjastoineen. Java (ohjelmointikieli) on yleiskäyttöinen ohjelmointikieli, jonka avulla ohjelmoijat voivat kirjoittaa koodia, joka kääntäessä toimii kaikilla Javaa tukevilla alustoilla ilman tarvetta kääntää koodia uudelleen.

Java-sovellukset on tyypillisesti käännetty tavukoodiin, joka voi toimia missä tahansa Java-virtuaalikoneessa (JVM) taustalla olevasta tietokoneen arkkitehtuurista riippumatta. Javan syntaksi on samanlainen kuin C:n ja C++:n, mutta siinä on vähemmän matalan tason toimintoja kuin kummallakaan. Java-ajonaika tarjoaa dynaamisia ominaisuuksia (kuten reflektointia ja ajonaikaisen koodin muokkausta), joita ei yleensä ole saatavilla perinteisillä käännetyillä kielillä.

Vuodesta 2019 lähtien Java oli GitHubin mukaan yksi suosituimmista käytössä olevista ohjelmointikielistä, erityisesti asiakas-palvelin-verkkosovelluksissa, ja kehittäjiä on raportoitu 9 miljoonalla. Alun perin kaupallisesti lisensoitu Java on vuodesta 2007 alkaen ollut vapaan GNU GPL -lisenssin alainen. Vuonna 2006 arvioitiin, että Java-alusta on käytössä noin 3,8 miljardissa laitteessa jossakin muodossa.

Javan ollessa yksi suosituimmista ohjelmointikielistä, sen avulla tehty paljon tunnettuja ja menestyneitä sovelluksia.
Lisäksi Javaa on käytetty paljon mm. graafisissa käyttöliittymissä, yrityssovelluksissa, tieteessä ja sulautetuissa järjestelmissä, joista viimeisimmästä esimerkiksi SIM-kortit ja Blu-ray soittimet ovat laajassa käytössä.

## Nimi
Java nimettiin tammikuussa 1995 Yhdysvalloissa *Javaksi* kutsutun kahvilaadun mukaan, jota tuotetaan Jaavalla Indonesiassa. Ennen nimenmuutosta kehittäjät olivat käyttäneet uudesta kielestään nimeä *Oak* ja sitä ennen nimeä *Greentalk*. Nimeä *Oak* ei kuitenkaan voinut enää käyttää, koska Oak Technologies -yhtiöllä oli siihen oikeudet. Uusi nimi valittiin palaverissa kymmenen ehdotuksen joukosta, joista äänestysvaiheeseen pääsivät myös nimet *DNA* ja *Silk*. Nimen *Java* ehdottajasta on nykyisin erilaisia käsityksiä.

Ohjelmointikieli JavaScript nimettiin myöhemmin Javan mukaan, mutta sitä yhdistää Javaan lähinnä vain syntaksi.

## Historia

James Gosling, Mike Sheridan, and Patrick Naughton aloittivat Java-ohjelmointikieliprojektin kesäkuussa vuonna 1991. Java oli alun perin suunniteltu interaktiiviselle televisiolle, mutta se oli liian kehittynyttä sen aikaiselle kaapelitelevisioteollisuudelle. Java sai alkuperäisen nimensä Oak erään Goslingin toimiston ulkopuolella olevan tammipuun mukaan. Myöhemmin projektia kutsuttiin nimellä Green, jonka jälkeen se uudelleennimettiin Javaksi erään indonesialaisen kahvin, Java coffeen, mukaan. Gosling suunnitteli Javan käyttäen C/C++ tyylistä syntaksia, joka olisi jo tunnettu systeemi ja sovellus ohjelmoijille.

Sun Microsystems julkaisivat ensimmäisen julkisen version nimellä Java 1.0 vuonna 1996. Se lupasi 'write once, run anywhere' (WORA)-toiminnallisuuden, tarjoten maksuttomia ajoaikoja suosituilla alustoilla. Kohtuullisen turvallinen ja sisältäen konfiguroitavan tietoturvan, Java sallii verkko- ja tiedostonkäyttörajoituksia. Pian merkittävät verkkoselaimet sisällyttivät mahdollisuuden ajaa Java-sovelmia nettisivuilla, ja Javasta tuli nopeasti suosittu ohjelmointikieli. Arthur van Hoff uudelleenkirjoitti Java-kielellä Java 1.0 kääntäjän noudattamaan tarkasti Java 1.0:n kielispesifikaatioita. Java 2:n tulon myötä (alun perin julkaistu nimellä J2SE 1.2 joulukuussa vuonna 1998-1999) uudet versiot sisälsivät useita kokoonpanoja, jotka oli rakennettu erityyppisille alustoille. J2EE sisälsi teknologioita ja rajapintoja yrityssovelluksiin, jotka tyypillisesti ajettiin palvelinympäristössä, kun taas J2ME sisälsi optimoituja rajapintoja mobiilisovelluksille. Työpöytäversiolle annettiin uusi nimi J2SE. Vuonna 2006, Sun uudelleennimesi uudet J2-versiot Java EE:ksi, Java ME:ksi ja Java SE:ksi markkinointisyistä.

Vuonna 1997 Sun Microsystems otti yhteyttä ISO/ICE JTC 1 Standartia hallinnoivaan elimeen ja myöhemmin Ecna internationaaliin formalisoidakseen Javan, mutta lopetti pian prosessin. Java säilyi standardina, jota ohjataan ja hallitaan Java-yhteisöprosessin kautta. Kerran Sun Microsystems teki suurimman osan sen Java-implemaatioista saatavaksi ilman maksua, vaikka ne olivat heidän omaa ohjelmistoa. Sun Microsystems sai tuloja myymällä lisenssejä erikoistetuille ohjelmistoille, kuten Java Enterprise System ja Java Premium System. 

Marraskuussa 2006 Sun Microsystems julkaisi suuren osan Java-virtuaalikoneestaan (JVM) vapaana ja avoimena lähdekoodina (FOSS) GPL-2.0 -lisenssin ehtojen mukaisesti. Toukokuussa 2007 Sun Microsystems valmisteli prosessin loppuun ja teki JVM:n ytimen koodin saataville ilmaisena avoimen lähdekoodin jakelun ehtojen mukaisesti lukuun ottamatta pientä osaa koodista, josta Sun Microsystems:illä itsellään ei ollut tekijänoikeutta.

Sun Microsystemsin varapuheenjohtaja Rich Green sanoi, että Sunin ihanteellinen rooli Javan suhteen oli evankelista. Oracle Corporationin hankittua Sun Microsystemsin vuosina 2009–2010 Oracle on kuvannut itseään Java-teknologian ylläpitäjänä, jolla on jatkuva sitoutuminen yhteisön osallistumiseen ja avoimuuteen. Tämä ei estänyt Oraclea nostamasta pian sen jälkeen oikeusjuttua Googlen käyttäessä Javaa Android SDK:ssa (ks. Android-kohta).

Javan käyttö Android-pohjaisissa ohjelmissa johti oikeudenkäyntiprosessiin Oraclen ja Googlen välillä vuonna 2012. Toukokuussa vuonna 2012 San Franciscolainen tuomaristo huomasi, että jos tekijänoikeudet koskivat myös ohjelmointirajapintoja, niin Google olisi rikkonut Oraclen tekijänoikeuksia käyttämällä Javaa Android-laitteissa. Käräjäoikeuden William Alsup määräsi 31. toukokuuta 2012 ettei ohjelmointirajapintoja voi suojata tekijänoikeuksilla, mutta tämä laki evättiin myöhemmin U.S. Court of Appeals for the Federal Circuitin puolesta toukokuussa 2014. Google todettiin syyttömäksi toukokuun 26, 2016, vetoamalla Java-ohjelmointirajapintojen reiluun käyttöön Androidissa. Oikeudenkäynti kuitenkin avattiin uudelleen maaliskuussa 2018, tällä kertaa San Franciscon tuomioistuimessa. Google haastoi uudet syytökset vuonna 2019 ja oikeudenkäynti totesi Googlen jälleen syyttömäksi huhtikuussa 2021. Oikeus ei muokannut tekijänoikeuslakeja ohjelmointirajapintojen ympärillä tapahtuman seurauksena, vaan sanoi näiden olevan tapauskohtaisia.

James Gosling erosi Oraclelta 2. huhtikuuta 2010.

### Periaatteet
Kun Java-kieltä luotiin, siinä oli viisi ensisijaista tavoitetta:

1. Kielen on oltava yksinkertainen, objekti-pohjainen ja tutun oloinen.

2. Sen on oltava vahva/tukeva sekä turvallinen.

3. Sen on oltava arkkitehtuurisesti neutraali ja helposti siirrettävä.

Yksi Javan tavoitteista oli siirrettävyys, mikä tarkoittaa, että Java-alustalle kirjoitettujen ohjelmien on toimittava samalla tavalla kaikenlaisilla laitteisto- ja käyttöjärjestelmäyhdistelmällä. Tämä saavutetaan kääntämällä Java-kielinen koodi välimuotoon, jota kutsutaan tavukoodiksi, sen sijaan että se käännettäisiin suoraan arkkitehtuurikohtaiseksi konekoodiksi. Javan tavukoodin ohjeet ovat konekoodin kaltaisia, mutta ne suoritetaan virtuaalikoneella, joka on kirjoitettu erityisesti sille isäntälaitteistolle. Loppukäyttäjät käyttävät yleisesti Java Runtime Environment -ohjelmaa, joka on asennettu heidän laitteeseensa itsenäisiä Java-sovelluksia varten tai web-selainta Java-apletteja varten.

Universaalin tavukoodin käyttö tekee ohjelmien siirrettävyydestä helppoa. Kuitenkin tavukoodin tulkitsemisesta konekoodiksi aiheutuva ylimääräinen suoritusaika tekee tulkittavista ohjelmista lähes aina hitaampia kuin suorat suoritettavat ohjelmat. Itse Java on alustariippumaton ja sopeutuu käyttöalustaan käyttämällä sille tarkoitettua Java Virtual Machine (JVM), joka muuntaa Java-tavukoodin alustan konekielelle.

4. Sen täytyy suorittaa/toimia korkealla suorituskyvyllä.

5. Sen on oltava tulkittu, säikeitetty ja dynaaminen.

**Java ohjelmoinnin neljä periaatetta**

Java-ohjelmointikielessä on neljä keskeistä periaatetta, jotka tunnetaan nimellä "Java-ohjelmoinnin neljä periaatetta" tai "The Four Pillars of Object-Oriented Programming". Nämä periaatteet ovat: 

# Kapselointi (encapsulation)
# Periytyminen (inheritance)
# Polymorfismi (polymorphism)
# Abstraktio (abstraction)

Kapselointi tarkoittaa luokkien käyttämistä ohjelman eri osien eristämiseen toisistaan, mikä helpottaa koodin ylläpidettävyyttä ja selkeyttä. Kapselointi mahdollistaa sen, että ohjelman osat ovat riippumattomia toisistaan, ja muutokset voidaan tehdä vain yhteen luokkaan kerrallaan ilman että tarvitsee huolehtia muista osista.

Periytyminen on periaate, joka mahdollistaa uusien luokkien luomisen jo olemassa olevien luokkien pohjalta. Tämä säästää aikaa ja vaivaa, sillä jo olemassa olevia toimintoja ei tarvitse kirjoittaa uudelleen uutta luokkaa varten.

Polymorfirsmi tarkoittaa eri tyyppisten olioiden käyttämistä yhden ja saman nimen alla, mikä vähentää koodin monimutkaisuutta ja tekee sen ylläpidosta helpompaa. Polymorfismi mahdollistaa ohjelman osien vaihtamisen toisiin, kunhan ne toteuttavat saman rajapinnan.

Abstraktio tarkoittaa oleellisten yksityiskohtien keskittymistä ja epäolennaisten yksityiskohtien poistamista koodista, mikä helpottaa sen ylläpidettävyyttä. Abstraktio mahdollistaa koodin yksinkertaisuuden säilyttämisen ja helpottaa sen ymmärtämistä.

Nämä neljä periaatetta ovat tärkeitä Java-ohjelmoinnissa, sillä ne tekevät koodista jäsennellympää, ymmärrettävämpää ja ylläpidettävämpää.

## Yleistä
Java-ohjelmointikielen kehittivät Bill Joy ja James Gosling kollegoineen Sun Microsystemsillä 1990-luvun alussa. JDK 1.0 (Java Development kit) julkaistiin syksyllä 1995. Se soveltui www-sivulle luotavien applettien tekemiseen, mikä nosti Javan nopeasti ohjelmointimaailman kuumimmaksi puheenaiheeksi. Keväällä 1997 julkaistiin JDK 1.1, jossa oli muuttunut erityisesti käyttöliittymän ohjelmointi oliomaisempaan suuntaan. JDK 1.2 julkaistiin loppuvuonna 1998, ja se sisälsi uuden JFC-luokkakirjaston *([[Java Foundation Classes]])*, jossa mukaan tuli mm. Swing käyttöliittymien luominen ja monipuolisia tietorakenneluokkia.

Java-kielen 1990-luvun lopulla saavuttaman suuren suosion takana ovat laitteistoriippumattomuuden lisäksi kielen C++-kieltä läheisesti muistuttava, mutta helpommin omaksuttavaksi suunniteltu kielioppi, oliopohjaisuus ja virtuaalikoneen mukana tuleva, erittäin kattava standardikirjasto. Myös muistinhallintaa on helpotettu ottamalla käyttöön roskienkeräin (engl. *garbage collector*), joka vapauttaa muistia kun sitä ei enää tarvita. Java kuuluu ohjelmointikieliin, joissa on käytössä ns. vahva tyypitys. Tämä tarkoittaa sitä, että jokaisella muuttujalla on tyyppi ja muuttujat voivat saada ainoastaan tyyppinsä mukaisia arvoja.

Toisin kuin tavanomaisen kielet, Javan lähdekoodia ei käännetä suoraan konekielelle, vaan tavukoodiksi, joka suoritetaan virtuaalikoneessa. Koska Java-ohjelmat ajetaan virtuaalikoneessa, ne eivät normaalisti pysty vaikuttamaan suoraan muihin prosesseihin, eivätkä pääse virtuaalikoneelle määrätyn hiekkalaatikon ulkopuolelle vaan esimerkiksi tiedostoja käsitellessä käskyt kulkevat virtuaalikoneen läpi, joka varmistaa että käsky on turvallisuusasetusten mukainen. Java-ohjelmat ovat mm. näiden rajoitusten vuoksi tavanomaisia konekieliohjelmia turvallisempia, mutta samalla hieman hitaampia.

Javan standardikirjasto sisältää valmiita toteutuksia useille asioille, kuten graafisen käyttöliittymäkirjaston, rinnakkaisuuden hallinnan, verkko-ominaisuudet ja eräät muut rajapinnat, jotka toisissa kielissä ovat käyttöjärjestelmäriippuvaisia tai kolmansien osapuolten kirjastojen varassa.

Javaa markkinoitiin alun perin Web-käyttöön, selaimen sisällä ajettavia sovelmia varten. Se löi kuitenkin varsinaisesti läpi palvelinkäytössä, dynaamisia www-sivuja luotaessa (JSF, JSP, servlet), raskaissa palvelinsovelluksissa (Java EE) ja kännyköissä ja taskutietokoneissa (Java ME). Yleisyytensä ja ilmaisuutensa ansiosta se on myös suosittu opetuskieli.

Java-alustan käyttöä ei ole rajattu Java-ohjelmointikieleen, vaan mm. Python-, Ruby- ja Scheme-kielille on olemassa kääntäjä, joka tuottaa Java-tavukoodia. Sun Microsystemsin lisäksi ainakin IBM ja GNU ovat kehittäneet omat Java-kääntäjänsä ja IBM, Novell, BEA Systems ja Apache omat virtuaalikoneensa lukuisten avoimen lähdekoodin toteutusten (kuten Kaffe, SableVM, JamVM, CACAO, Jikes RVM, VMkit) lisäksi. GNU:n kääntäjäympäristöön GCC:hen kuuluva GCJ osaa kääntää Javaa konekielelle.
GNU ryhtyi myös kehittämään korvaavaa, vapaata luokkakirjastoa GNU Classpath -projektissa.

Sun ilmoitti 13. marraskuuta 2006 julkaisevansa Javan GNU GPL-lisenssillä.

Googlen Android on käyttänyt Apache Harmony -toteutusta Javan kirjastoille, mutta siirtyi käyttämään OpenJDK-toteutusta. Vuodesta 2019 lähtien Kotlin on ollut suositeltu ohjelmointikieli Android-sovelluksille Javan sijaan.

## Sunin/Oraclen kehitysympäristö
Javaan kuuluu ohjelmointikieli, josta on julkaistu eri versioita kehitysympäristön (Java Development Kit; JDK) kehittymisen myötä. Kehitysympäristöön kuuluu kääntäjä (javac) ja muut kehitystyökalut (jar, javadoc, jdb). Kehitysympäristö sisältää myös täydellisen ajoympäristön (Java Runtime Environment; JRE), joka tarvitaan käännettyjen ohjelmien ajamiseen. Ajoympäristö sisältää virtuaalikoneen (Java Virtual Machine; JVM), joka on JRE:n versiosta 1.2 (joulukuu 1998) lähtien sisältänyt ajonaikaisen käännöksen konekielelle (just-in-time compiler; JIT). Ajoympäristöön kuuluvat myös luokkakirjastot, jotka ovat nekin saaneet lisää ominaisuuksia Javan kehittymisen myötä. Java 1.2 brändättiin suurten muutosten vuoksi nimellä Java 2. Java 2 -nimeä ei kuitenkaan käytetty markkinoinnissakaan kovin kauan, sillä jo Java 1.5 brändättiin Java 5:ksi.

Ajoympäristö on nykyisin jaettu kolmeen osaan.
*Java Standard Edition (Java SE) sisältää yleiset ominaisuudet, graafiset käyttöliittymät, tietokanta- (Java Database Connectivity; JDBC) ja perus-XML-rajapinnat.
*Java Enterprise Edition (Java EE) on tarkoitettu palvelinsovellusten kehittämiseen ja ajamiseen ja sisältää mm. nimeämis- ja hakemistopalvelut (Java Naming and Directory Interface; JNDI), komponenttirajapinnan (Enterprise Java Beans; EJB), servlet- ja portlet-määrittelyt, JSP (JavaServer Pages) ja muita web-palvelintekniikoita.
*Java Micro Edition (Java ME) on tarkoitettu teholtaan rajoittuneiden laitteiden ohjelmointiin, kuten matkapuhelimiin ja digibokseihin (Multimedia Home Platform; DVB-MHP). J2ME eroaa merkittävästi muista ympäristöistä ja käyttää rajoitetumpaa virtuaalikonetta (K Virtual Machine; KVM) ja jättää toteuttamatta joitain kielen ominaisuuksia (kuten liukuluvut ja luokkien purkajat). Java ME on edelleen jaettu konfiguraatioihin ja profiileihin laitteiden ominaisuuksien mukaan.

### Versioita
Javan tärkeimmät julkaisuversiot ja niiden julkaisupäivät:
* **JDK [[Ohjelmiston julkaisuelinkaari|Beta]]** esiteltiin 1995.
* **JDK 1.0** esiteltiin 23. tammikuuta 1996.
* **JDK 1.1** esiteltiin 19. helmikuuta 1997.
* **J2SE 1.2** esiteltiin 8. joulukuuta 1998.
* **J2SE 1.3** esiteltiin 8. toukokuuta 2000.
* **J2SE 1.4** esiteltiin 6. helmikuuta 2002.
* **J2SE 5.0** esiteltiin 30. syyskuuta 2004.
* **Java SE 6** (koodinimi "Mustang") esiteltiin 11. joulukuuta 2006.
* **Java SE 7** (koodinimi "Dolphin") esiteltiin 28. heinäkuuta 2011. Viestintävirasto ilmoitti elokuussa 2012, että Java 7 aiheuttaa Windows-ympäristössä vakavan tietoturva-aukon ja kehottaa poistamaan version. Tietoturva-aukkoon tuli korjaava päivitys 30. elokuuta 2012.  (Tuettu heinäkuuhun 2022 asti)
* **Java SE 8** (koodinimi "Spider") esiteltiin 18. maaliskuuta 2014.  (Tuettu joulukuuhun 2030 asti)
* **Java SE 9** esiteltiin 9. syyskuuta 2017.
* **Java SE 10** esiteltiin 20. maaliskuuta 2018.
* **Java SE 11** esiteltiin 25. syyskuuta 2018. (Tuettu syyskuuhun 2026 asti)
* **Java SE 12** esiteltiin 19. maaliskuuta 2019.
* **Java SE 13** esiteltiin 16. syyskuuta 2019.
* **Java SE 14** esiteltiin 17. maaliskuuta 2020.
* **Java SE 15** esiteltiin 15. syyskuuta 2020.
* **Java SE 16** esiteltiin 16. maaliskuuta 2021.
* **Java SE 17** esiteltiin 14. syyskuuta 2021. (Tuettu syyskuuhun 2029 asti)
* **Java SE 18** esiteltiin 22. maaliskuuta 2022.
* **Java SE 19** esiteltiin 20. syyskuuta 2022.
* **Java SE 20** esiteltiin 21. maaliskuuta 2023.
* **Java SE 21** julkaistiin 17. lokakuuta 2023.

Osa Java-versioista kuuluu Oraclen laajennetun tien piiriin. Pidempään tuettuja LTS-versioita (Long-Term-Support) ovat Java SE 7, 8, 11, 17 ja 21.

## Kehitysympäristön asentaminen
Java SE Development Kit on yksityiskäyttäjälle ilmainen, jonka voit ladata Oraclen sivuilta, esim. https://www.oracle.com/in/java/technologies/downloads/ . Se tukee useimpia käyttöjärjestelmiä, kuten, Windowsi, linuxia, Mac OSia.  

**Oracle JDK 20 -sertifioidut järjestelmäkokoonpanot**

Oracle JDK 20 -sertifioidut järjestelmäkokoonpanot Windowsille ovat: Windows Server 2022, Windows Server 2019 Windows Server 2016 Windows Server 2012 R2, Windows 2012, Windows 11 ja Windows 10. 

Linuxin osalta Oracle JDK 20 -sertifioituja järjestelmäkokoonpanoja ovat Oracle Linux:n versiot 6, 7, 7.9+,8 ja 9. Ubuntu Linux:n osalta sertifioituja järjestelmäkokoonpanoja ovat 22.04 LTS, 22.10 ja 23.04, Red Hat Enterprise Linux:n osalta taas versiot 6, 7, 7.9+,8 ja 9 ja Suse Linux Enterprise Server:n sertifioituja järjestelmäkokoonpanoja ovat versiot 12 ja 15. Uudemmat Linuxin eri versiot versiot tukevat X.org-tilaa, mutta Wayland-tilaa ei tueta. 

MacOS alustoista tuettuina ovat versiot macOS 11, macOS 12 ja macOS 13 

Kaikki Oracle:n sivuilla mainitut käyttöjärjestelmät ovat myös sertifioituja, kun niitä käytetään virtuaalisena vierasjärjestelmänä missä tahansa seuraavista hypervisoreista/säilöistä, kunhan kyseinen hypervisori/säilö tukee käyttöjärjestelmää :

* Oracle VM
* Docker
* Microsoft Hyper-V Server

Riippuen haluamastasi versiosta ja käyttöjärjestelmästäsi, tarvitset n. 200Mb tilaa kovalevyllesi, jotta saat ladattua JDK asennustiedoston koneellesi, minkä jälkeen voit asentaa sen itsellesi.

## Turvallisuusarkkitehtuuri
Java-teknologian syntymisen ja käyttöönoton myötä tietoturvallisuus on ollut merkittävä aihe sekä kiinnostuksen kohde. Java-alustan turvallisuus sekä uudet tietoturvaongelmat, joita Java-teknologian käyttöönotto on aiheuttanut, ovat herättäneet yhä kasvavaa huomiota. Teknologian tarjoajan näkökulmasta katsottuna Javan suojaus tarjoaa kaksi näkökulmaa:

* Tarjoaa turvallisen ja valmiin Java-alustan, jolla pystyy ajamaan Java-yhteensopivia sovelluksia turvallisesti
* Tarjoaa Java-ohjelmointikielellä toteutettuja tietoturvatyökaluja ja -palveluita, jotka mahdollistavat laajemman valikoiman turvallisuusherkkiä sovelluksia esimerkiksi yrityksille

### Hiekkalaatikkomalli
Java-alusta tarjoaa oman tietoturva-arkkitehtuurin, jota kutsutaan ”hiekkalaatikoksi”. Hiekkalaatikko on yksi Javan valmiista tietoturvaominaisuuksista ja sen avulla käyttäjät voivat suorittaa rajoitetussa ympäristössä epäluotettavia tai huonosti kirjoitettua koodeja. ”Hiekkalaatikkoympäristössä” voidaan estää koodia pääsemästä tietyille alustan ominaisuuksille ja API-rajapinnoille. Koodia voidaan esimerkiksi estää lukemasta tai kirjoittamasta tiedostoja paikallisessa tiedostojärjestelmässä tai estää sitä suorittamasta mielivaltaisia komentoja sekä estää pääsy verkkoihin. Hiekkalaatikkomalli otettiin käyttöön Java Development Kitin (JDK) kautta, ja se otettiin yleisesti käyttöön JDK 1.0:lla rakennetuissa sovelluksissa, mukaan lukien Java-yhteensopivissa verkkoselaimissa. JDK 1.1 laajensi tätä mallia tuomalla mukaan allekirjoitetun sovelman (signed applet) käsitteen; jos sovelma oli allekirjoituksen perusteella luotetun tahon valmistama, se sai järjestelmään täydet valtuudet. Jos näin ei ollut, sovelma suoritettiin edelleen hiekkalaatikossa. Java SE -ympäristössä hiekkalaatikkomalli on entistä kehittyneempi tuoden mukanaan muun muassa hienostuneemman käyttöoikeuksien hallinnan, helpommin konfiguroitavan turvallisuuspolitiikan ja helpommin laajennettavan käyttöoikeuksien hallintarakenteen sekä turvatarkistusten laajentamisen kaikkiin Java-ohjelmiin, mukaan lukien sovellukset ja appletit. 

## Sovelluskohteet
Javan ensimmäinen kohdeympäristö oli web-selaimet, joissa Java-sovelmia (applet) voitiin ajaa turvallisesti. Appletit olivat osa jo ensimmäistä Java-julkaisua 1995. Tekniikan otti omakseen erityisesti Netscape selainsodissa Microsoftia vastaan. Myös Microsoft kehitti oman virtuaalikoneensa MSJVM:n, jonka toteutuksesta se joutui oikeusjutun kohteeksi Sunin taholta. Microsoft luopui Javan kehityksestä 2001 ja nyttemmin luonut oman lähes samanlaisen kilpailevan tekniikkansa (.NET ja C#). Applettien suosio on jäänyt vähäiseksi ja muut tekniikat, kuten Flash ovat ottaneet paikan yksinkertaisten selainsovellusten luonnissa. Myöskään Java-pohjaiset verkkotietokoneet (JavaStation, JavaOs), joita useat valmistajat esittelivät, eivät yleistyneet.

Verkon yli ladattavien sovellusten luontiin Oraclella on Java Web Start -tekniikka, joka mahdollistaa täydellisten sovellusten suorittamisen verkon yli. Java Web Start esiteltiin maaliskuussa 2001 ja Java versiosta 1.4 lähtien se on ollut osana JRE:tä.

Java Servlet API on dynaamisten websivujen kehittämiseen tarkoitettu rajapinta. Se on osa Java EE -pakettia. Servlet-rajapinnan toteuttaa *servlet container* (joskus käännetty suomeksi termillä *kontti*). Container tarjoaa web-palvelimen, jonka toiminnallisuutta voi laajentaa omilla komponenteilla hyödyntäen Javan rajapintoja. Container tarjoaa suoraan joitain palveluja, kuten istunnonhallinnan. JavaServer Pages (JSP) on Servlet API:a käyttävä tekniikka, joka käyttää yksinkertaista merkkauskieltä HTML:n seassa hyödyntämään palvelimella olevien komponenttien toiminnallisuutta tai sisältää suoraan Java-koodia. JSP muistuttaa lähinnä CGI- tai PHP-skriptausta.

Enterprise JavaBeans (EJB) on Servlet API:n kaltainen tekniikka, mutta on tarkoitettu etupäässä tietokantakäyttöön. EJB-komponentit (pavut) ajetaan sovelluspalvelimessa, joka tukee hajauttamista, transaktioita ja rinnakkaisuuden hallintaa. Sunin määrittelemää rajapintaa hyödyntävien servlet- ja EJB-tekniikoiden hyötynä on se, että periaatteessa sama sovellus on ajettavissa kaikissa rajapinnan toteuttavissa sovelluspalvelimissa. Näitä ovat esim. JBoss, IBM WebSphere Application Server, Oracle GlassFish ja Oracle WebLogic. 

Javaan on saatavilla JavaFX-ohjelmointialusta , jonka ensimmäinen versio julkaistiin vuonna 2008. 
JavaFX:n oli alun perin tarkoitus korvata Swing API kokonaan, mutta myöhemmin aikeesta on luovuttu .  

Apache-säätiö kehitti Javalle avoimen lähdekoodin työkaluja Jakarta-projektissa. Projektin nimi siirtyi Eclipse-säätiön Java-laajennusten paketin nimeksi samassa yhteydessä kun Eclipse otti kehitettäväkseen Apachen J2EE-sovelluspalvelimen. Useat Apachen Java-projektit on eriytetty omiksi ohjelmapaketeikseen, esim. Apache Ant. Apachen yleiset Java-kirjastot tunnetaan nykyisin nimellä Apache Commons.

## Ohjelmointiympäristöt

Javalle on olemassa monia erilaisia ohjelmointiympäristöjä, jotka tarjoavat erilaisia ominaisuuksia ja työkaluja. Ilmaisia ovat esimerkiksi NetBeans ja Eclipse ja BlueJ. Kaupallisia ovat esimerkiksi JetBrainsin IntelliJ IDEA. Googlen Android Studio on virallinen ympäristö Android-kehitykseen ja tukee myös muilla kielillä kehittämistä.

## Ominaisuudet
### Perusominaisuudet
Java tukee tyypillisiä toistorakenteita (`for`, `while`) ja ehtolauserakenteita (`if`, `else`, `switch`).

Javassa osoittimelle voidaan antaa arvoksi *null* eli tyhjä. Kyseistä erikoisarvoa kutsutaan null-osoittimeksi, joka tarkoittaa, että osoitin ei osoita mihinkään. Null ei ole tyyppi tai olio itsessään, vaan viittaus, joka ei osoita mihinkään. Null on oletusarvo minkä tahansa viitetyypin muuttujalle, jota ei ole alustettu ilmoitushetkellä. Tämä koskee kaikenlaisia ​​muuttujia, instanssimuuttujia tai staattisia muuttujia, paitsi että kääntäjä varoittaa, jos käyttää paikallista muuttujaa alustamatta sitä. Null-arvoa käytetään usein osoittamaan, että viitemuuttujaa ei ole alustettu tai että menetelmä ei palauttanut kelvollista objektiviittausta. On tärkeää huomata, että null-arvo voidaan määrittää vain viitetyypeille, minkä myötä sitä ei voi määrittää primitiivisille muuttujille, kuten int, double, float tai boolean. Java:n instanceof -tyyppivertailuoperaattori kokeilee, onko objekti tietyn tyypin esiintymä. Se myös vertaa ilmentymää tyyppiin ja palauttaa joko true(tosi) tai false(epätosi). Jos instanceof-operaattoria käytetään minkä tahansa muuttujan kanssa, jolla on null-arvo, se palauttaa arvon false. 

### Olio-ohjelmointi
Java tukee olio-ohjelmointia. Kielessä voidaan käyttää luokkia, joiden jäsenenä olevia aliohjelmia kutsutaan metodeiksi.

Metodien määrittelyssä kerrotaan paluuarvon tyyppi, nimi ja valinnaisia ominaisuuksia (parametrit, näkyvyys ja niin edelleen). Java tukee poikkeuksia.

Muiden luokkien pääsyä voidaan rajoittaa. Päätasolla näkyvyys voi olla julkinen (`public`) tai pakettikohtainen. Jäsentasolla näkyvyys voi olla `public`, `private` tai `protected`. Jos näkyvyyttä ei määritellä luokalle se näkyy vain sen paketille.

Java rakennettiin lähes yksinomaan oliokieleksi, joten Java-kieliset ohjelmat ovat lähes aina oliopohjaisia ohjelmia. Olio-ohjelmointi onkin nykypäivänä yksi ohjelmointi alan tärkeimmistä työkaluista, jonka avulla voidaan luoda tehokkaampia, joustavampia ja helpommin ylläpidettävissä olevia ohjelmistoja. Java onkin usein käytetty ohjelmointikieli oliopohjaisessa ohjelmoinnissa.

Olio-ohjelmoinnin perusperiaatteisiin kuuluu kapselointi, periytyminen, polymorfismi ja abstraktio. Nämä auttavat ohjelmiston kehittäjiä luomaan modulaarisia ohjelmistoja, joissa eri osat ovat itsenäisiä ja ovat helposti laajennettavissa. Tämän avulla koodia voidaan uudelleenkäyttää ja näin vähentää saman tai samantyylisen koodin toistamista ohjelmistoissa. Olio-ohjelmointi tekee isojen ohjelmien koodista helpommin organisoitavaa. Tämä auttaa ohjelmistojen kehittäjiä työskentelemään tehokkaammin yhdessä ja monimutkaisten ohjelmistojen hallitsemissa. Olio-ohjelmoinnin merkitys tulee tulevaisuudessa vain kasvamaan ohjelmistojen kehittyessä yhä monimutkaisimmiksi.

Kapseloinnilla tarkoitetaan tiedon piilottamista. Eli luokan sisäiset yksityiskohdat voidaan piilottaa ulkopuolisilta.

Periytymisellä tarkoitetaan sitä, että lapsiluokka perii vanhempiensa tiedot ja toiminnallisuudet. Tätä voidaan havainnollistaa esimerkiksi niin, että koira ja kissa ovat kummatkin erilaisia eläimiä, mutta ne molemmat ovat nisäkkäitä. Tällöin he perivät nisäkkään ominaisuudet, mutta niillä on myös omia ominaisuuksia.

Polymorfismilla tarkoitetaan olioiden kykyä ottaa monta muotoa. Esimerkiksi ihminen voi olla jonkun puoliso, lapsi ja työntekijä samaan aikaan, mutta käyttäytyy eri tavalla näissä tilanteissa.

Abstraktio tarkoittaa kokonaisuuksien käsittelyä, jossa tarkennetaan tarvittaessa.

Olio-ohjelmoitaessa pyritään luokilla ja niiden ilmentymillä tyypillisesti mallintamaan jotain todellisen elämän prosessia tai toiminnallisuutta. Olio-ohjelmoinnissa instanssit ovat interaktiivisia ja niiden ominaisuudet, kuten metodit ja muuttujat vastaavat realistista käyttötarkoitusta. Hyvän tyyliohjeen mukaisesti esimerkiksi "Eläin" -luokalla voi olla ainoastaan eri ”eläin” -ilmentymiä, kuten siili tai kissa. Vastaavasti näillä olioilla voi olla vain loogisesti yhteensopivia muuttujia kuten "nimi" tai "ikä", eikä esimerkiksi "teho" tai "polttoainetankin tilavuus".

Javan ja olio-ohjelmoinnin eri ominaisuudet ja perusperiaatteet kuten näkyvyyden rajoittaminen ja periytyminen oikein ja yhdessä käytettynä ohjaavat jäsentelemään koodia siten, että se mallintaisi todellista maailmaa tai vähintäänkin jotain kiinteää systeemiä. Esimerkiksi eläin olion, kuten "kissa", kyky periä kantaluokaltaan kaikille eläimille tyypillisiä piirteitä kuvastaa hyvin olio-ohjelmoinnin reaalimaailman mallintamisen periaatetta. Laadukas oliopohjainen ohjelma näyttää ulospäin ryhmältä olioita, jotka toimivat keskenään omien tarkoitustensa pohjalta ja kommunikoivat niiden toisilleen tarjoamien rajapintojen avulla. 

Jokaisella oliolla on oma tehtävä ja tarkoituksensa eikä muiden olioiden tarvitse välttämättä tietää mistä piilotetuista metodeista ja muuttujista olio tarkalleen muodostuu. Esimerkiksi "kuljettaja" -olion ei tarkalleen tarvitse tietää miten "auto" -olio toimii. Sille riittää, että se voi käyttää "auto" -olion toiminnallisuuksia, kuten ”käynnistä moottori”, ”aja” tai "käänny". Tämä rajapintojen muodostama abstraktio tekee olio-ohjelmoinnista joustavan ja helposti laajennettavissa olevan ohjelmointikielen. Olioiden muodostamien rajapintojen avulla laajennusten yhteensovittaminen on suhteellisen yksinkertaista, kunhan tunnetaan rajapintojen mahdolliset rajoitteet ja oikeat toiminnallisuudet.

### Syntaksi
Javan syntaksi on ottaa suurimman osan pääpiirteistään C++ ja C ohjelmointikielistä. Toisin kuin C++, joka yhdistää syntaksinsa järjesteltyyn, geneeriseen ja oliopohjaiseen ohjelmointiin, Java rakennettiin puhtaaksi olio-ohjelmointikieleksi. Kaikki koodi on kirjoitettu luokkien sisälle, ja jokainen tietokohde on olio, poikkeuksena ovat kuitenkin primitiiviset datatyypit, (kuten esimerkiksi kokonaisluvut ja Boolen arvot), jotka eivät ole oliota suorituskykyyn liittyvien syiden takia. Java uudelleen käyttää joitain suosittuja C++ ominaisuuksia. 

Toisin kuin C++, Java ei tue operaattorin ylirasitusta tai monimuotoista periytymistä luokille, mutta toisaalta monimuotoinen periytyminen on tuettu käyttöliittymille. 

Java käyttää saman tyyppisiä kommentteja kuin C++. On olemassa kolme erilaista tyyliä kommentoida: yhden rivin tyyli merkittynä kahdella kenoviivalla (//), monen linjan tyyli aloitettuna tällä /* ja lopetettuna tällä */, ja Javadoc kommentointi tyyli aloitettuna tällä /** ja lopetettuna tällä */. Javadocin tyyli kommentoida mahdollistaa sen, että käyttäjä voi ajaa Javadoc suoritettavan luodakseen dokumentointia ohjelmalle. Sen dokumentoinnin voi mahdollisesti lukea integroiduilla kehitysympäristöillä (IDE:t) , kuten Eclipsellä antaakseen mahdollisuuden kehittäjille päästä dokumentointiin käsiksi IDE:n sisällä.

**Tunnistin**

Tunnistin on koodissa olevan elementin nimi. On olemassa tiettyjä vakiintuneita nimeämiskäytäntöjä, joita tulee noudattaa elementtien nimien valinnassa. Javassa tunnisteet ovat kirjainkoosta riippuvaisia.

Tunnistin voi sisältää:

-Minkä tahansa Unicode-merkin, joka on kirjain (mukaan lukien numeroa esittävät kirjaimet, kuten roomalaiset numerot) tai numero.

-Valuuttamerkin (kuten ¥).

-Yhdistävän välimerkin (kuten _).

Tunnistin ei voi:

-Aloittaa numerolla.

-Olla yhtä kuin varattu avainsana, null-arvo tai boolean-literal.

**Muuttujat**

Muuttujat ovat tunnisteita, jotka liittyvät arvoihin. Ne julistetaan kirjoittamalla muuttujan tyyppi ja nimi, ja ne voidaan halutessaan alustaa samassa lausekkeessa antamalla sille arvo.

int count;      //Declaring an uninitialized variable called 'count', of type 'int'
count = 35;     //Initializing the variable
int count = 35; //Declaring and initializing the variable at the same time		
```java
int count;      //Declaring an uninitialized variable called 'count', of type 'int'
count = 35;     //Initializing the variable
int count = 35; //Declaring and initializing the variable at the same time
```

Useita saman tyyppisiä muuttujia voidaan julistaa ja alustaa yhdessä lausekkeessa käyttäen pilkkua erotinmerkkinä.
```java
int a, b;         //Declaring multiple variables of the same type
int a = 2, b = 3; //Declaring and initializing multiple variables of the same type
```


### Operaattorit
Operaattorit Javassa ovat samankaltaisia kuin C++:ssa. Kuitenkin Javassa ei ole poisto-operaattoria roskien keräysmekanismien vuoksi, eikä osoittimiin liittyviä toimintoja, koska Java ei perustu osoittimiin, sekä Java suorittaa muistinhallinnan automaattisesti, ilman että ohjelmoijan tarvitsee manuaalisesti allokoida muistia. Toinen ero on, että Javassa on merkitsemätön oikeanpuoleinen siirto-operaattori (`>>>`), kun taas C: n oikeanpuoleinen siirto-operaattorin merkki riippuu tyypistä. Javassa operaattoreita ei voi ylikuormittaa.

### Tunnukset
Javassa ohjelmoija joutuu antamaan nimen eli tunnuksen monille asioille. Esimerkiksi luokat, muuttujat, attribuutit ja metodit tarvitsevat tunnuksen. Javassa tunnus saa sisältää kirjaimia, numeroita ja alaviivan _. Dollarin merkkiä $ ja plussaa + ei kannata käyttää omien luokkien nimissä, koska näitä Java käyttää nimetessään sisäluokkia ja luetellun tietotyypin vakiarvoja. Välilyöntejä tai muita tyhjätilamerkkejä ei saa sisältyä tunnukseen. Tunnuksella ei ole pituusrajoitusta ja sen pitää alkaa kirjaimella. Hyvin kuvaavia nimiä saa käyttää tunnuksen nimeämisessä. Tunnuksista pitää tehdä kuvaavia ja sopivan pituisia. Tunnukset, jotka ovat liian pitkiä, ennemminkin tekevät koodista epäselvää luettavaa kuin auttavat koodin ymmärtämisessä. Tunnus ei saa olla mikään Javan avainsanoista.

Isot ja pienet kirjaimet tarkoittavat tunnuksissa eri asiaa. Monisanaisten tunnusten sanojen alkukirjaimet kirjoitetaan aina isolla kirjaimella, mikä on vakiintunut tapa Javassa. Luokan nimessä ensimmäisen sanan alkukirjain on tapana kirjoittaa isolla kirjaimella. Muuttujien, attribuuttien ja metodien nimissä pientä alkukirjainta käytetään ensimmäisen sanan alkukirjaimena. Esimerkiksi Raketti, RakettiMoottori, RakettiLaukaisualusta ja Alus ovat nimeämissäännön perusteella luokan nimiä. Nimeämissäännön perusteella muuttujien, attribuuttien ja metodien nimiä ovat esimerkiksi raketti, rakettiMoottori, räjäytäAlus ja ajaa.

Erikoiset merkit voivat aiheuttaa ongelmia tiedostojen nimissä, minkä takia luokkien nimeämisessä kannattaa käyttää vain merkkejä a–z. Esimerkiksi Äiti on huono luokan nimi, koska se sisältää ä-kirjaimen.

### Esimerkki

Tyypillinen "Hello, World" -esimerkki:


```java
public class HelloWorld {
    public static void main(String[] args) {
        // Tulostetaan teksti "Hello, world"
        System.out.println("Hello, world!");
    }
}
```
Java-ohjelmoinnissa kaikki lähdetiedostot tulee nimetä niiden sisältävän julkisen luokan mukaan ja lisäksi siihen on liitettävä jälkiliite .java. Yllä esiintyvässä esimerkkitapauksessa tämä tarkoittaa sitä että tämän **public-**class ( julkisen luokan ) nimen ollessa HelloWorld, tulee lähdetiedosto tallentaa seuraavalla nimellä (HelloWorld) ja jälkiliitteellä (.java) HelloWorld.java  Ensin java-kääntäjän on käännettävä tämä tavukoodiksi ja tuotettava .class päätteinen tiedosto. Esimerkkitapauksessa tätä vastaa HelloWorld.class. Vasta tämän jälkeen tuotos voidaan suorittaa tai käynnistää. 

Java-lähdekooditiedosto voi sisältää vain yhden julkisen luokan, mutta siinä voi olla useita luokkia, joilla on ei-julkisen pääsyn määrittävä muuttuja sekä mitä tahansa määrää julkisia sisäluokkia. Kun lähdekooditiedosto sisältää useita luokkia, yhden niistä (joka on määritelty class-avainsanalla) täytyy olla julkinen (jota edeltää public-avainsana) ja lähdekooditiedosto täytyy nimetä kyseisen julkisen luokan nimellä.

Luokka, joka ei ole julkinen, voidaan tallentaa mihin tahansa .java-tiedostoon. Kääntäjä generoi luokkatiedoston jokaiselle lähdekoodissa määritellylle luokalle. Luokkatiedoston nimi on luokan nimi, johon on lisätty .class-pääte. 

Metodi nimi `main` ei ole avainsana Java-ohjelmointikielessä, vaan ns. 'pääohjelmametodi'. Java-ohjelma käynnistetään käynnistämällä luokka, jossa `main`- metodi on. Tätä metodia voidaan käyttää missä tahansa luokassa, joka on osana ohjelmaa. `Main`- metodin sisältävällä luokalla voi olla mikä vain nimi, mutta yleensä näitä luokkia kutsutaan vain `Main` nimellä. 

Avainsanojen merkitystä esitellään alla seuraavasti: 

Avainsana public kertoo, että metodin voi kutsua muista luokista, tai että luokkaa voi käyttää myös luokkahierarkian ulkopuolella olevat luokat. Luokkahierarkia liittyy siihen kansioon, jossa .java-tiedosto sijaitsee, ja tätä kutsutaan pääsyä määrittäväksi muuttujaksi. Muita pääsyä määrittäviä muuttujia ovat private (metodi, johon pääsee vain samassa luokassa) ja protected (joka sallii käyttää koodia samasta paketista). Jos koodi yrittää käyttää yksityisiä tai suojattuja metodeja, JVM antaa SecurityExceptionin. Esimerkki julkisesta ja ei-julkisesta metodista julkisessa luokassa:
```java
public class MainClass {
    
    public void publicMethod() {
        System.out.println("Tämä on julkinen metodi");
    }
    private void nonPublicMethod() {
        System.out.println("Tämä on ei-julkinen metodi");
    }
}
```
Avainsana static metodin edessä tarkoittaa, että kyseessä on staattinen metodi, joka on assosioitu vain luokkaan eikä mihinkään tiettyyn luokan instanssiin. Vain staattisia metodeja voi kutsua ilman viittausta olioon. Staattiset metodit eivät voi käyttää luokan jäseniä, jotka eivät ole staattisia. Metodit, joita ei ole määritelty staattisiksi vaativat tietyn luokan esiintymän toimiakseen.

Avainsana Void osoittaa, että päämenetelmä ei palauta käyttäjälle mitään arvoa. Mikäli Java-ohjelman on tarkoitus poistua ohjelmasta virhekoodilla, sen täytyy kutsua nimenomaisesti metodia System.exit().

### Avainsanat
Javassa on 53 avainsanaa, jotka on luokiteltu useisiin luokkiin, kuten pääsymuuntimet, ohjauskulku, luokat ja tietotyypit. Esimerkkejä käyttöoikeusmäärityksistä ovat "public," "private," ja "protected", jotka määrittelevät luokan tai menetelmän laajuuden. Ohjauskulun avainsanat, kuten "if", "else", "for" ja "while", antavat ohjelmoijille mahdollisuuden määrittää ehdollisen logiikan ja silmukat. Luokkiin ja tietotyyppeihin liittyviä Java-avainsanoja ovat "class," "interface," "enum," "extends" ja "implements". Näiden avainsanojen avulla ohjelmoijat voivat määrittää luokkia, rajapintoja ja enumeja sekä ilmoittaa ja alustaa eri tietotyyppien muuttujia. Java 5 oli ensimmäinen versio, missä oli enum-avainsana.

### Generics
Javassa on geneerisen ohjelmoinnin tuki sen tyyppijärjestelmässä. Generics on lisätty JDK versiossa 5.

Esimerkiksi ArrayList on listarakenne, joka tukee geneeristä ohjelmointia.

ArrayList on dynaaminen lista, joka toimii huomattavasti tehokkaammin kuin perinteiset taulukot. 

Esimerkki ArrayListin käytöstä:

```java
import java.util.ArrayList;

...
// ArrayList, joka hyväksyy String-tyypin
ArrayList<String> hedelmaSalaatti = new ArrayList<>();
hedelmaSalaatti.add("Omena");
hedelmaSalaatti.add("Mango");

for (String hedelma: hedelmaSalaatti)
{
     System.out.println("- " + hedelma);
}
```


Yllä havainnollistettu "import java.util.Arraylist" on ArrayList:n sijaitsema kirjasto ja sen tuominen java-ohjelmaan mahdollistaa ArrayList:n käytön. Listaa pystytään hyödyntämään kätevästi myös luokkien välillä ja siihen liittyvä toiminta voi tapahtua toisen luokan metodeilla.

Tässä esimerkissä ArrayListin käyttö toimii seuraavalla tavalla:

Määritellään lista "ArrayList", mitä tietotyyppiä listaan syötetään  tai alemman esimerkin mukaan , mitä tietoa listaan syötetään "hedelmäSalaatti". Luodaan uusi lista "new Arraylist()". Tyypiksi voidaan määritellä ainoastaan luokkia, eikä primitiivisiä datatyyppejä voida käyttää. Jokaiselle primitiiviselle datatyypille on oma "luokkaversionsa" (wrapper).

Listaan voidaan lisätä tietoja.add menetelmällä, tässä tapauksessa hedelmäSalaatti .add(). Listalta voidaan myös poistaa tietoja metodilla .remove. Tässä tilanteessa hedelmäSalaatti.remove(). Size metodilla voidaan tulkita listan koko, joka toimii seuraavasti yllä olevaa esimerkkiä hyödyntäen: hedelmäSalaatti.size(). Vastaavasti get-metodilla voidaan näyttää tietyllä indeksillä varustettu alkio seuraavasti: hedelmäSalaatti.get(0). Tässä etsimme listan 0:n alkion, mikä vastaa ensimmäistä jäsentä.

Vastaavasti sitä käyttää myös muilla tietotyypeillä:

```java
// ArrayList, joka hyväksyy int-tyypin
ArrayList<Integer> hedelmaSalaatti = new ArrayList<>();
hedelmaSalaatti.add(1);
hedelmaSalaatti.add(2);
```


### Kommentit
Java-ohjelmointikielessä kommentit ovat välttämätön osa koodia, jonka avulla kehittäjät voivat dokumentoida ja selittää ohjelmakoodia. Kommentit ovat tärkeitä, koska ne helpottavat ohjelman ymmärtämistä ja ylläpitoa, auttavat välttämään virheitä sekä mahdollistavat koodin nopean päivittämisen ja muokkaamisen. Java tukee kahta erilaista kommentointityyppiä: yksirivisiä ja monirivisiä kommentteja.

Yksiriviset kommentit aloitetaan kahdella etuliitteellä "//" ja ne päättyvät automaattisesti rivin loppuun. Yksirivisiä kommentteja käytetään yleensä lyhyisiin selityksiin, kuten muuttujien tai metodien nimien selittämiseen.

Moniriviset kommentit aloitetaan "/" merkinnällä ja päättyvät "/" merkinnällä. Monirivisiä kommentteja käytetään yleensä laajempiin selityksiin, kuten ohjelman toimintaa selittämiseen tai koodin osien dokumentointiin. Monirivisiä kommentteja voidaan käyttää myös tilanteissa, joissa koodia ei haluta suorittaa, mutta sitä ei haluta poistaa kokonaan koodista. Tämä on hyödyllistä esimerkiksi testauksen yhteydessä, kun halutaan jättää tiettyjä testilohkoja kommentoituna käyttöön myöhempää käyttöä varten.

Kommentit ovat tärkeitä myös siksi, että ne helpottavat koodin ylläpidettävyyttä ja mahdollistavat koodin ymmärrettävyyden muille kehittäjille. Koodin ymmärrettävyys on erityisen tärkeää, kun useampi kehittäjä työskentelee saman projektin parissa tai kun projektin ylläpitoa siirretään toiselle kehittäjälle. Kommentit helpottavat myös ohjelmakoodin testausta ja vähentävät virheiden riskiä.

On tärkeää käyttää kommentteja harkiten ja järkevästi. Liikaa kommentteja voi tehdä koodista sekavan ja hankalan lukea, kun taas liian vähän kommentteja voi tehdä koodista vaikeasti ymmärrettävää. Hyvä käytäntö on lisätä kommentteja aina silloin, kun koodi ei ole ilmeisen selvää tai se saattaa aiheuttaa epäselvyyksiä muille kehittäjille.

### Periytyminen
Periytyminen (inheritance) on yksi Javan eli olio-ohjelmoinnin perusperiaatteita. Sen avulla voidaan vähentää turhan koodin toistamista. Siinä luokat voivat periä ominaisuusia ylemmiltä luokilta. Tällaista luokkaa, joka perii ylemmän luokan ominaisuuksia, kutsutaan lapsiluokaksi. Vastaavasti luokkaa, jonka ominaisuuksia peritään, kutsutaan lapsiluokan kantajaksi. Lapsiluokan kantaluokassa voidaan määritellä muuttujia ja metodeja, joita lapsiluokka perii ja voi käyttää. Ehtona tälle on kuitenkin se, että lapsiluokan kantaluokassa niiden näkyvyysmääre on määritelty suojattuna eli kyseessä on protected. 

Kantaluokan toteutus metodille perityy lapsiluokalle Javassa. Lapsiluokalle on kuitenkin mahdollista kirjoittaa oma toteutuksensa metodille vanhan tilalle. Korvaavan metodin tulisi silti täyttää sama palvelu kuin alkuperäisen eri toteutuksella samaan rajapintaan. Lapsiluokan ilmentymää kutsuessa tulee kutsua kantaluokan rakentajaa. Javassa lapsiluokka kutsuu kantaluokan oletusrakentajaa automaattisesti. Java käyttää avainsanaa super oletuksen muuttamiseen. Oletuksen muuttamiseksi on kantaluokassa määriteltävä parametritön rakentaja lapsiluokan käyttöön. `super` -avainsanalla päästään käsiksi lapsiluokasta kantaluokan rakentajiin. 

Rajapintaluokkaa käytetään myös jaetun toiminnallisuuden eristämiseen. Luokan tehtävänä on määrittää rajapinta, jota ohjelmiston luokat voivat ilmoittaa käyttävänsä. Rajapintaluokka sisältää vain staattisia ja julkisisa vakiotietokenttiä, ilman mahdollisuutta käyttää itseään kantaluokkana periytymisessä. Mikä tahansa ohjelmisto voi tämän sijasta ilmoittaa toteuttavansa rajapinnan. Määrittely tehdään vaihtamalla normaalin luokan class -avainsana avainsanaksi interface. Luokasta ei voi luoda ilmentymiä eikä määritellä rakentajaa. Ainoat hyväksytyt tietokentät ovat luokkamuuttujavakioita. Rajapintaluokan kaikki metodit ovat abstrakteja metodeja. Metodien tulee myös olla julkisia. Mikäli näkyvyysmääreitä `public`, `static` tai `final` ei olla sisällytetty metodeiden määrittelyyn, ne lisätään määritelmään automaattisesti. 

Ajatellaan periytymistä seuraavan esimerkin avulla. Kaikille moottoriajoneuvoille (lapsiluokan kantaluokka) yhteisiä muuttujia voisi olla valmistaja, polttoaine sekä moottorin kapasiteetti. Vastaavasti yhteisiä metodeja kaikille moottoriajoneuvoille voisi olla moottorin sammutus sekä käynnistys. Moottoriajoneuvojen lapsiluokkia voisi olla auto, lentokone ja vene, jotka perivät siis yllä olevat muuttujat sekä metodit itselleen. Näiden lisäksi jokaisella lapsiluokalla voi olla omia muuttujia sekä metodeja. Auton muuttuja voisi olla väri, metodi voisi olla vaihda vaihdetta. Lentokoneen muuttaja voisi olla siipiväli, metodi voisi olla nosta/laske lentokorkeutta. Veneen muuttuja voisi olla veneen pituus, metodi voisi olla ruorin kääntäminen oikealle ja vasemmalle. Jotta homma ei olisi liian yksinkertaista, voi auto toimia lapsiluokan kantaluokkana erilaisille autotyypeille. Esimerkiksi avo-, lava-, henkilö- ja kuorma-auto perivät kaikki auton sekä moottoriajonevon suojatut muuttujat ja metodit. Avoautolla voisi vielä omana muuttujana olla malli sekä metodina voisi olla katon nostaminen auki kuumana kesäpäivänä.

### Abstraktit luokat ja metodit
Abstrakti luokka on Javassa eräs tapa lisätä ohjelman enkapselointia tarkistamalla, ettei pääluokasta luoda uutta oliota, mutta pääluokan lapsiluokkien olioiden luominen on sallittu. Abstraktia luokkaa ei voida implementoida, mutta abstraktin luokan lapsiluokka voidaan.

Abstraktin luokan rakenteella tehdään määritelmän avulla muottipohja luokasta periytyville lapsiluokille. Näin varmistetaan, että jokainen periytyvä metodi toteuttaa tietyn toiminnallisuuden ilman että kantaluokkaa suoraan kutsutaan. Sen käyttöä edellyttää yleensä jonkin jaetun toiminnallisuuden tarpeen toteamista abstraktia luokkaa varten. Abstrakti luokka luodaan lisäämällä avainsana `abstract` `class` -avainsanan eteen. Ei-abstraktia abstraktin luokan lapsiluokkaa kutsutaan konkreettiseksi luokaksi.

Abstraktin luokan määritys tapahtuu `abstract` -avainsanalla.
```java
public abstract class className {}
```
Jos abstraktista luokasta yritetään luoda uusi olio, Java palauttaa virheviestin. Virheen voi saada kiinni ajon aikana `InstantiationError` luokan avulla jos ja vain jos luokan määritys on yhteensopimattomasti muuttunut. Abstrakti metodi on metodi, joka on määritelty ilman ohjelmakoodia abstraktissa luokassa. Abstrakteja metodeja ei voida määritellä ei-abstraktissa luokassa.

Abstraktin metodin määritys tapahtuu `abstract` -avainsanalla.
```java
public abstract class className {
    abstract void method();
}
```
Abstraktin luokan lapsiluokat voivat käyttää abstrakteja metodeja implementoimalla tai kumoamalla (Override) abstraktin metodin, joka periytynyt pääluokasta.
```java
public abstract class subClassName extends className {
    @Override
    void method();
}
```
Kun abstrakti luokasta on luotu lapsiluokkia, lapsiluokka välittää implementoinnit kaikkiin abstrakteihin metodeihin sen pääluokassa. Jos näin ei ole, niin lapsiluokka pitää myös määritellä abstraktiksi. Abstrakteissa luokissa ja metodeissa voidaan käyttää avainsanaa `static`

### Tiedostonkäsittely Javassa
Javassa tiedostoon kirjoittaminen ja sieltä lukeminen on melko yksinkertaista. Java tarjoaa näitä toimintoja varten käyttäjälleen useita eri kirjastoja ja metodeja, joita Java-ohjelmoijat pääsevät vapaasti käyttämään. FileWriter on yksi java.io kirjaston tarjoama luokka, jota voi hyödyntää tiedoston kirjoittamiseen tai lukemiseen. Tämän jälkeen voidaan käyttää write-metodia tekstin kirjoittamiseen. Esimerkiksi jos halutaan luoda ja kirjoittaa tekstiä tiedostoon "tiedosto.txt", tapahtuu se seuraavanlaisesti.
```java
try (FileWriter kirjoittaja = new FileWriter("tiedosto.txt")) {
    kirjoittaja.write("Kirjoitetaan tekstiä tiedostoon.");
} catch (IOException e) {
    // Poikkeukset tähän
}
```
Java pakottaa käyttäjänsä lisäämään poikkeuksenkäsittelyn, jota esimerkiksi Pythonissa ei tarvitse tehdä. Tällä varmistetaan se, että tiedostojen puuttumiset, käyttöoikeusongelmat sekä muut odottomattomat ongelmat otetaan huomioon. Kuten yllä olevasta koodista huomaa, tapahtuu tiedostoon kirjoittaminen try-lausekkeen sisällä. 

Olion lisääminen tiedostoon tapahtuu Javassa hieman erilailla, kuin esimerkiksi tavallisen tekstin kanssa toimiessa. Tämä johtuu siitä, että oliot usein sisältävät tietoa, joka ei yksinkertaisesti ole kirjoitettavissa tekstinä, vaan se on tallennettava binäärimuodossa. Javassa ohjelmoija joutuu käyttämään ObjectOutputStream - toimintoa, jos haluaa lisätä sen tiedostoon ja vastaavasti sen voi lukea sieltä ObjectInputStream-luokkien avulla. Tässä on yksinkertainen esimerkki siitä, miten olion tallentaminen tiedostoon tapahtuu. 
```java
Henkilo henkilo = new Henkilo("Matti Meikäläinen", 30);
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("tiedosto.txt"))) {
            objectOutputStream.writeObject(henkilo);
        } catch (IOException e) {
            // Poikkeukset tähän
        }
```


### Muistinhallinta
Javan muistinhallinta on automaattista. Java käyttää automaattista roskienkeräintä (eng. *automatic garbage collector*) muistinhallintaan. Sen tarkoitus on hallita objektin muistinkäyttöä sen käyttöiän aikana. 

Tämä poikkeaa esimerkiksi C- ja C++-kielten käytännöistä, joissa ohjelman muistinhallinta on manuaalista ja siten ohjelmoijan vastuulla. Manuaalisen muistinhallinnan ohjelmointikielissä on mahdollista saada aikaan muistivuotoa, eli tilanteen, jossa ohjelma varaa muistia toimintojaan varten, mutta ei vapauta sitä tarpeen ja ohjelman päättyessä. 

Javan roskienkerääjän tarkoitus on ehkäistä muistivuotoa. Vaikka roskienkeräys ei eliminoi muistivuotoja täysin, se vähentää niitä merkittävästi, kuin myös niiden ehkäisemiseen kuluvia resursseja ohjelmistokehittäjiltä.

Roskienkerääjä ajaa jaksollisesti taustalla "roskienkeräyksen" (eng. *garbage collection*), joka pyrkii tunnistamaan muistissa olevat "kuolleet" objektit, joihin ei tulla enää viittaamaan ohjelmassa, vapauttamaan näiden objektien viemä tila muistista ja uudelleenorganisoida "elävät" objektit muistinkäytön ja tulevien roskienkeräysten optimoimiseksi.

Roskienkerääjätyyppejä on useita erilaisia toteutuksia. Käytettävä roskienkerääjä riippuu käytettävissä olevista laitteiston resursseista sekä suorituskykyvaatimuksista. Roskienkerääjätyypit Javassa:

* **Serial Garbage Collector** - Suorittaa kaiken toiminnan yhdellä säikeellä. Omaa suuremmat taukoajat, mutta käyttää vähän resursseja. Sopii parhaiten yhden prosessorin systeemeihin.
* **Parallel Garbage Collector** - Samankaltainen Serial Garbage Collectorin kanssa, mutta käyttää useita säikeitä.
* **Concurrent Mark Sweep (CMS) Garbage Collector** (Hylätty JDK 9:ssä, poistettu JDK 14:ssä) - Vähentää roskienkeräyksen taukoaikoja suorittamalla toimintojaan sovelluksen toimiessa.
* **Garbage First (G1) Garbage Collector** (Oletuksena JDK:n versiosta 9) - Parannus CMS GC:stä, syrjäyttää tämän. G1 sopii parhaiten usean prosessorin laitteisiin suurella muistikapasiteetilla.
* **ZGC** (Kokeellinen JDK 11:ssä, tuotanto JDK 15:ssä) - Erittäin matalan viiveen roskankeräärä, skaalattavissa usean teratavun "keon" (eng. *heap*) sovelluksiin. ZGC:n sisäinen toteutus ja käyttäytyminen poikkeavat merkittävästi muista roskankerääjistä.

### Tyyppimuunnokset
Java on staattisesti tyypitetty kieli. Välillä saattaa tulla eteen tilanne, jossa on tarve tehdä tyyppimuunnos. Tyyppimuunnoksella tarkoitetaan prosessia, jossa muutetaan muuttujan tai arvon tietotyyppi toiseksi tietotyypiksi. Tyyppimuunnos voi tapahtua automaattisesti tai manuaalisesti.

Jos tyyppimuunnoksessa tietotyypit ovat yhteensopivia, ja tavoiteltu tietotyyppi on laajempi kuin alkuperäinen tietotyyppi, tekee Java tyyppimuunnoksen automaattisesti. Esimerkiksi ”int”-tyypin muuttuja  voidaan muuttaa ”long”-tyyppiseksi muuttujaksi, sillä ”long”-tietotyypissä on tarvittava määrä muistia ”int”-tyypin muuttujan säilymiseen. Lisäksi Java muuttaa automaattisesti kokonaislukuarvon ”int” liukulukuarvoksi ”float”, kun laskee näiden kahden jakolaskun.

Jos tyyppimuunnoksessa ei voida taata täydellistä datan säilymistä, ei automaattista tyyppimuunnosta voida tehdä. Kun tyyppimuunnos ei tapahdu automaattisesti, voi tyyppimuunnoksen tehdä manuaalisesti käyttämällä tyyppimuunnosoperaattoria. Operaation nimi on pakotettu tyyppimuunnos. Esimerkiksi, jos haluat muuttaa muuttujan, jonka tietotyyppi on ”float” tietotyypiksi ”int”, voisit käyttää tyyppimuunnosoperaattoria seuraavalla tavalla: (int) float-muuttuja. Haluttu tietotyyppimuuttuja siis sijoitetaan sulkeisiin, jonka jälkeen kirjoitetaan alkuperäinen, muutettava muuttuja. Java pyrkii tekemään tyyppimuunnoksen, vaikkei se olisi kyseisessä tilanteessa mahdollista. Tällainen tilanne voi aiheuttaa ongelmia myöhemmässä vaiheessa, viimeistään ohjelman ajovaiheessa.

Tyyppimuunnos auttaa käsittelemään erilaisia tietotyyppejä ja tehostaa ohjelman suorituskykyä. Tyyppimuunnosta on kuitenkin käytettävä tarkkaavaisuutta vaatien, sillä sen väärinkäyttö voi johtaa virheisiin. Tyyppimuunnoksen yhteydessä esiintyviä yleisimpiä virheitä ovat tyyppimuunnoksen tyyppien yhteensopimattomuus sekä muunnoksen aiheuttamat tietojen menetys tai vääristyminen. Tyyppimuunnoksen käytön tarpeellisuutta onkin tarpeen harkita tapauskohtaisesti.

### Suorituskyky
Javan ohjelmointikieli nähdään laajalti suorituskyvyltään hitaampana kuin muut nopeammat kielet, kuten C ja C++. Ongelma johtuu perustavanlaatuisesta erosta kielien rakenteessa: C ja C++ suorittavat ohjelman suoraan tietokoneen prosessorilta. Java taas avaa virtuaalikoneen (Java virtual machine, JVM) ohjelmaa varten, johtaen merkittävään suorituskyvyn menetykseen.

Java kehittää JVM:n suorituskykyä ja optimointia jatkuvasti uusissa versioissa. Vuonna 1997 Java alkoi käyttämään ajonaikaista kääntöä (Just-in-Time compilation, JIT), joka toi merkittävän parannuksen JVM:n suorituskyvyssä.

Java-ohjelman suorituskyky on siis olennaisesti sidottu paitsi itse ohjelman optimointiin myös käytössä olevaan Javan versioon. Uudemmat versiot Javan virtuaalikoneesta käyttävät tietokoneen prosessointikykyä tehokkaammiin ja ohjelman suorittaminen voi nopeutua merkittävästi vanhemmista versioista. Tämän takia Java-ohjelman suorituskykyä testattaessa on olennaista raportoida käytössä olevan JVM:n versio, myyjä, käyttöjärjestelmä sekä laitearkkitehtuuri.

### Virheidenkäsittely
Java ohjelmointi kielenä tarjoaa laajan virhekontrolli mekanismin. Yksi päätavoista, jolla tämä saavutetaan on poikkeuksen käsittely systeemi (exception). Kun virhe tapahtuu ohjelman aikana, Java voi implementoida poikkeuksen, jossa objekti kuvastaa virhettä. Tämä systeemi mahdollistaa ohjelman käsittelemään virheet jäsennellysti eikä niin, että ohjelma kaatuisi tai tekisi hankalaksi ohjelman ajamista.

Javassa, poikkeukset käsitellään käyttäen *try-catch-finally*-block systeemiä. Try-lause sisältää koodia, joka saattaa poikkeuksen ja Catch-lause sisältää koodin, joka käsittelee poikkeuksen. Finally-lause on näiden jälkeinen toimenpide, joka tekee resurssien putsauksen, kun aiemmat lauseet ovat ajettu.

Java tarjoaa myös mekanismin, jossa *throw* ja *catch* menetelmät toteutetaan eri tavalla, jossa ohjelmoija määrittelee niiden toimenpiteet. Tämä antaa ohjelmoijille hyvän mahdollisuuden tehdä joustavaa virheiden käsittelyä Javan-ohjelmointi kielen normaalien poikkeuskäsittelyn toimenpiteiden lisäksi.

Javan ohjelmointikielellä on myös toinen tapa käsitellä virheitä ja se perustuu *type-safe* mekanismiin. Javan ohjelmointkieli on vahvasti ”näppäilty” kieli mikä tarkoittaa sitä, että muuttujien tyyppi on oltava täysin ilmoitettu siinä ajassa, kun sitä määritellään. Tämä helpottaa virheissä kuten tyyppien yhteensopimattomuudessa sekä *null*-osoittimien poikkeuksissa.

Yleisesti Java-ohjelmointikielen virheidenkäsittely mekaniikat ovat luotettavia ja näiden avulla pystytään ohjelmoimaan vakaata ja helposti käsiteltävää koodia ohjelmistoihin.

### Javan tarjoamia kirjastoja
Java tarjoaa laajan skaalan erilaisia kirjastoja helpottamaan ohjelmoijien työtä. Kirjastoista yleisin ja käytetyin on Javan standardikirjasto (eng. *Java Standard Library*) joka pitää sisällään useita tärkeitä kirjastoja, kuten esimerkiksi java.lang, jo aiemmin mainittu java.util ja java.math. Javan kirjastot saadaan dynaamisesti käyttöön ajon aikana sisällyttämällä kirjastot koodin alkuun komennolla "import" ja kutsumalla kirjastojen sisältämiä komentoja osana koodia. Näin Javassa saadaan käyttöön hyvin laaja skaala komentoja vain parilla lisäsanalla.

#### Esimerkkikirjastoja

* **Javan standardikirjasto** (eng. Java Standard Library) - Javan standardikirjasto on alun perin kehitetty tukemaan Javan sovelluskehitystä. Kirjasto on Oraclen ja sen yhteistyökumppaneiden luoma. Kirjasto sisältää monenlaisia ominaisuuksia, esimerkiksi:
** IO/NIO - ( Package java.io/java.nio ) Kirjasto määrittää ne puskurit, jotka sisältävät dataa sekä antaa yleiskatsauksen muista NIO paketeista.  
** Verkostoituminen - ( Package java.net)  
** Heijastuminen 
** Samanaikaisuus 
** Geneerisyys 
** Skriptaus/kääntäjä 
** Toiminnallinen ohjelmointi 
** Java-kokoelmakehys – Sisältää erilaisia rajapintoja, jotka määrittelevät erilaisia kokoelmia ja luokkia, jotka toteuttavat niitä. Java-kokoelmakehys toimii samalla tavalla kuin kirjastot.  
** Turvallisuus 
** Kirjastot, joiden avulla käyttäjä pystyy kommunikoimaan ulkoisten järjestelmien kanssa 

* **java.util** - Tarjoaa esimerkiksi Arraylist:n jonka avulla voidaan lisätä esimerkiksi string ja int muotoista tekstiä helposti listaan .add-komennon avulla, Scanner:n jonka avulla voidaan esimerkiksi kysyä ajonaikana käytettäviä tietoja käyttäjältä, Date:n jonka avulla voidaan helposti käsitellä aikaa ja päivämääriä, sekä LinkedList:n joka tarjoaa mahdollisuuden luoda linkitetyn listan sekä GregorianCalendar:n eli kalenterin.
* **java.math** - Tarjoaa paljon erilaisia laskemisessa tarvittavia funktioita, kuten Math.abs(), jolla saadaan halutun numeron itseisarvo, Math.round(), jolla saadaan pyöritettyä luku, sekä Math.log(), jolla voidaan laskea halutun luvun luonnollinen logaritmi.
* **java.time** - Tarjoaa esimerkiksi hyödyllisen luokan LocalDate, jolla saadaan käyttöön paikallinen päivämäärä sekä LocalTime, jolla saadaan koodin käyttöön paikallinen aika. Mikäli haluaa molemmat, kannattaa käyttää java.time:n tarjoamaa LocalDateTime:ä, jolla saadaan molemmat käyttöön. Kaikki mainituista sisältää myös mahdolliset talvi- ja kesäajat.
* **java.text** - Tarjoaa muun muassa DecimalFormat:n, jolla voidaan määrittää näytetäänkö käyttäjälle desimaalierottimena oletusarvona olevaa pistettä vai pilkkua sekä SimpleDateFormat:n jonka avulla voidaan määrittää, minkälaisessa muodossa käyttäjälle näytettävät päivämäärät näytetään.
* **java.lang** - sisältää perusluokkia ja rajapintoja, jotka ovat olennaisia ohjelmointikielen suunnittelussa.
* **java.applet** - Sisältää luokat, joita tarvitaan ohjelman luomiseen sekä luokat, joita ohjelma käyttää kommunikoidakseen kontekstinsa kanssa.  
* **java.awt.font** - Sisältää luokkia ja rajapintoja, jotka tarjoavat erilaisia fontteja. 
* **java.awt** - Sisältää luokkia käyttöliittymän luomiseen sekä grafiikan ja kuvien tekemiseen. 
* **java.awt.datatransfer** - Sisältää luokkia ja rajapintoja, jotka mahdollistavat tietojen siirtämisen sovellusten sisällä ja niiden välillä. 
* **java.awt.geom** - Sisältää luokkia kaksiulotteisten geometristen objektien toimintojen määrittämiseen ja suorittamiseen. 
* **java.awt.image** - Sisältää luokkia kuvien luomiseen ja muokkaamiseen. 
* **java.time.format** - Sisältää luokkia päivämäärien ja aikojen jäsentämiseen ja tulostamiseen. 
* **java.util.zip** - Sisältää luokkia ZIP- ja GZIP-tiedostomuotojen lukemiseen ja kirjoittamiseen. 
* **java.swing text** - Sisältää luokkia ja rajapintoja, jotka käsittelevät muokattavia ja ei-muokattavia tekstikompontentteja.  
* **Integraatiokirjastot,** jotka mahdollistavat sovelluksen kehittäjän kommunikoimaan ulkoisten järjestelmien kanssa:
** '''Java Database Connectivity''' **(JDBC)** API, jonka avulla kehittäjä saa yhteyden tietokantntaa
** **[[:en:Java_Naming_and_Directory_Interface|Java Naming and Directory Interface]] (JNDI)** API, jolla kehittäjä voi hakea sekä etsiä tietoa ja resursseja olioina nimen avulla
** **[[:en:Java_remote_method_invocation|RMI]]** ja **[[:en:Common_Object_Request_Broker_Architecture|CORBA]]** hajautettuun sovelluskehitykseen
** **[[:en:Java_Management_Extensions|JMX]]** sovelluksien hallitsemiseen ja valvontaan

* **Käyttöliittymäkirjastot:**
** **[[Abstract Window Toolkit|Abstract Window Toolkit (AWT),]]** joka tarjoaa GUI komponentteja. Kirjasto tarjoaa myös työkaluja asetella kyseisiä komponentteja sekä käsitellä kyseisiin komponentteihin liittyviä tapahtumia
** **[[Swing (Java)|Swing]]** kirjastot, jotka ovat rakennettu AWT:n päälle, mutta tarjoavat ei-natiiveja toteutuksia AWT pienoisohjelmasta
** Ohjelmointirajapintoja äänen tallentamiseen, prosessointiin sekä toistoon
** **[[JavaFX]]**, joka tarjoaa alustan työpöytäsovellusten sekä monipuolisten verkkosovellusten luomiseen

* **[[:en:Java_Web_Start|Java Web Start]]**, joka mahdollistaa Java ohjelmien jakamisen tehokkaasti loppukäyttäjille Internetissä 
* Kirjastoja ohjelmien lisensointiin ja dokumentoimiseen
* Lisäosia, jotka mahdollistavat sovelmien ajamisen selaimessa
* Ohjelmistoalusta riippuvainen toteutus Javan virtuaalikoneesta, jonka avulla Java-kirjastojen ja kolmannen osapuolen sovellusten tavukoodit suoritetaan

* **Kirjastoja data-analytiikkaan, koneoppimiseen ja tekoälyyn:**
** **Deeplearnin4j – DL4J** kirjasto koneoppimiseen ja tekoälyyn, jolla on laaja tuki syväoppimisalgoritmeille. 
** **Java Statistical Analysis Tool – JSAT** kirjasto tilastolliseen laskentaan ja koneoppimiseen
** **Java Machine Learning Library – Java-ML** kirjasto koneoppimiseen ja tiedonlouhintaan. Kirjaston tarjoamia algoritmeja ovat mm. datan klusterointi, klassifiointi sekä datan suodatus algoritmit.

### Ulkoiset Java kirjastot
Java tarjoaa myös mahdollisuuden käyttää ulkoisia kirjastoja. Kirjastot on luotu helpottamaan sovellusten kehitystä tarjoamalla erilaisia työkaluja ja valmiiksi kirjoitettua koodia. Niitä voidaan lisätä omaan ohjelmaan sen toiminnallisuuden laajentamiseksi tai koodin ongelmakohtien ratkaisemiseksi. Kirjastojen tarkoitus on mahdollistaa ohjelmoijan keskittyminen sovelluksen rakenteeseen matalatasoisen toteutuksen sijasta.

Esimerkkikirjastoja:

* Spring on kevyt mutta tehokas Java-sovelluskehityskehys, jota käytetään yleisesti JEE (Java Enterprise Edition) -sovelluksissa. Se tarjoaa erilaisia ​​moduuleja, kuten Spring Security, Spring MVC, Spring Batch, Spring ORM, Spring Boot ja Spring Cloud. Lisäksi Spring tukee Dependency Injection -integraatiota, mikä mahdollistaa riippuvuuksien ratkaisemisen joustavasti. Spring pystyy myös ratkaisemaan riippuvuudet, sillä se tukee Dependency Injection -integraatiota.

* Hibernate helpottaa tietokantaan pääsyä ja hallintaa sekä tarjoaa ominaisuuksia, kuten SQL-kyselyjen käsittelyä, välimuistitusta ja suorituskyvyn optimointia. Hibernate mahdollistaa myös oletusarvoista SQL-tyyppien ohittamista, Java Enumien mappamisen sarakkeisiin sekä yhden ominaisuuden mappamisen useaan sarakkeeseen.

* Grails tarjoaa yhtenäisen kehitysympäristön, joka hyödyntää olemassa olevia Java-teknologioita, kuten Hibernatea ja Springiä, yhden käyttöliittymän alla. Grails tarjoaa myös dokumentaatiota tärkeimmistä osista, kuten pysyvyyskehyksestä, GSP-templaattikielen käytöstä ja dynaamisista tag-kirjastoista. Lisäksi Grails tarjoaa esimerkkisovelluksia, kehysarkkitehtuurin laajennettavuuden sekä tuen Ajaxille.

* Play on nykyaikainen ja kevyt web-kehys, joka keskittyy kehittäjien tuottavuuteen ja tehokkuuteen. Se tukee RESTful-arkkitehtuuria, sisältää yksikkötestauksen tukemisen JUnitin ja Seleniumin avulla, tarjoaa monia sisäänrakennettuja elementtejä ja tukee asynkronista I/O:ta.

### Muita ominaisuuksia
Java tukee myöskin sisäkkäisiä luokkia. Sisäkkäisiä luokkia on erityyppisiä kuten esimerkiksi staattinen sisäinen luokka. Sisäkkäiset luokat parantavat koodin järjestelyä. Lisäksi anonyymit luokat ovat yksi sisäisten luokkien tyyppi.

## Erot muihin kieliin
Ohjelmointikieliä on paljon ja monet niistä jakavatkin samanlaisia ominaisuuksia. C-kieli on rakenteellista ja proseduraalista, kun taas sen jälkeläinen C++ tarjoaa laajemman valikoiman ominaisuuksia ja kielen toiminnallisuus pohjautuu huomattavasti enemmän oliopohjaiseen ohjelmointiin kuten Java. JavaScriptiä taas kuvaillaan enemmän C:n kaltaisena.

Java-ohjelmointi pohjautuu hyvin vahvasti useiden eri luokkien, metodien, olioiden ja niille määritettyjen funktioiden suorittamiseen. Filosofiassaan kieli noudattaa SOLID-periaatetta.

### Java ja JavaScript
Vaikka kielet Java ja JavaScript jakavatkin osittain saman nimen, ovat ne hyvin erilaisia ohjelmointikieliä toimivuudeltaan ja ajatusmaailmaltaan. Java kääntyy Java-bittikoodiksi, jonka takia Javaa suoritetaan useimmiten JVM (Java Virtual Machine) sisällä, kun taas JavaScript suoritetaan selaimen puolella. Muuttamalla koodin Java-biteiksi, Javan oma virtuaalikone mahdollistaa paremman turvallisuuden perustasolla ilman ylimääräistä koodia. JavaScriptiä käytetäänkin usein front end-suunnittelussa ja Javaa back end-suunnittelussa.

Java on kieli, joka tarkistaa static-tietotyyppejä ja JavaScript dynaamisia. Javan kirjoitus voi olla hieman työläämpää, koska siinä voi joutua kirjoittamaan enemmän ja pitämään huolta suunnittelun ohella, että tietotyyppi on määritelty oikein. JavaScript on kielenä nopeampi. Sen scripti tarkastetaan sillä hetkellä, kun sitä suoritetaan. JavaScriptin koodia on helpompi ymmärtää, sillä se kirjoitetaan yksinkertaisena tekstinä. Sitä ei ole käännetty kuten Javassa tehdään.

JavaScriptiä käytetään pääosin nettiselainten suunnitteluun ja toteutukseen ja sen päätehtävä on tehdä sivuista vuorovaikutteisempia kuin perinteisesti koodatut yksinkertaiset sivut.

Javan suunnittelu ja kirjoitus vaatii JDK:n (Java Development Kit), joten sitä voidaan mieltää hieman edistyksellisempänä ohjelmointikielenä.

## Uuden luokan tekeminen ja käyttäminen. Luokan rakentaja ja metodien yksinkertaista käyttöä.
Luokka, eli olio. Tarkoitus on saada koodi selkeämmin hallittavaan pakettiin, että koodi olisi helpommin muokattavissa ja luettavissa.

Ohessa lyhyt esimerkki kahteen tiedostoon rakennetusta ohjelmasta, missä käytetään uutta luokkaa, rakentajaa ja sen metodeita.
### Pää tiedosto
Esimerkki.

```java
package com.example;

public class App 
{
    public static void main( String[] args ){
        Animal siili1 = new Animal();   // Luodaan siili1 niminen olio. Rakentajaa käytetään ilman parametrejä,
                                        // jolloin eläin saa vakio parametrit.
        Animal siili2 = new Animal("Pekka",9);  //Luodaan siili2 niminen olio ja käytetään paramerillistä rakentajaa.
        System.out.println("Siilin1 nimi: " + siili1.getName());//Tulostetaan siili1 nimi
        System.out.println("Siilin2 ikä: " + siili2.getAge());  //Tulostetaan siili2 ikä
        siili1.setName("Maija");                                //Siilin nimeä voidaan myös vaihtaa lennosta. 
        System.out.println(siili1.getName());
        siili1.printAnimalSpecs();                              //Tulostetaan siilin1 tiedot käyttäen metodia.
        siili2.printAnimalSpecs();                              //Tulostetaan siilin2 tiedot käyttäen metodia.
    }
}
```

Olioita voidaan luoda tarpeen mukaan.
### Luokkatiedosto. Luokan ja metodien tekeminen

Esimerkki.

```java
package com.example;

public class Animal {
    public String name = "Heikki";      //Asetettu String tyyppinen nimimuuttuja "Heikki"
    public int age = 15;                //Asetettu int tyyppinen ikämuuttuja 15.

    //Voidaan tehdä useampi rakentaja, kunhan sisään tulevat parametrit eroavat toisistaan.
    public Animal(){        //Rakentaja ilman parametrejä. Nimeksi jää tässätapauksessa nimi "Heikki" ja ikä 15, ellei niitä erikseen muuteta
    }
    public Animal(String name,int ika){ //Rakentaja parametreillä.
        this.name = name;               //Sanaa this.name kertoo kääntäjälle, että käytetään tämän luokan muuttujaa name.
        age = ika;                      //Sama voidaan tehdä myös, jos sisään tulevan parametrin nimeä muutetaan erinimiseksi.
    }
    public String getName(){            //saadaan haettua Animal olion nimi.
        return name;
    }
    public void setName(String name){   //voidaan asettaa Animal olion nimi.
        this.name = name;
        return;
    }
    public int getAge(){                //Voidaan hakea Animal olion ikä.
        return age;
    }
    public void setAge(int age){        //Voidaan asettaaa Animal olion ikä.
        this.age = age;
        return;
    }
    public void printAnimalSpecs(){//Tulostetaan siilin tiedot.
        System.out.println("Nimi: " + name + " ikä: " + age);
    }
}
```

Tuloste:Siilin1 nimi: HeikkiSiilin2 ikä: 9MaijaNimi: Maija ikä: 15Nimi: Pekka ikä: 9Metodeita tehdään sen mukaan, että mitä tietoja halutaan saada luokasta ulos, tai luokkaan sisään.

### Singleton
Singleton on Javassa käytetty suunnittelumalli, jonka avulla voidaan varmistaa, että singelton-luokassa on vain yksi olio (luokan ilmentymä) kerrallaan. Avaintekijöinä singleton-luokan luomisessa toimii yksityinen luokkamuuttuja, yksityinen rakentaja ja julkinen metodi siihen käsiksi pääsemiseen. Luokan rakentaja määritellään yksityiseksi, jotta uusien olioiden luominen luokan ulkopuolella voidaan estää, ja yksityisellä luokkamuuttujalla (määrittelyllä *private static*) päästään käsiksi luotuun olioon. Julkisella luokkametodilla (määrittelyllä *public static*) luodaan pääsy yksityiseksi määriteltyyn olioon. Nimenomaan tämän julkisen luokkametodin sisällä on toiminnallisuus, jolla useampien olioiden luominen luokan ulkopuolella voidaan estää. 

Yksinkertainen esimerkki singleton-luokan luomisesta voi olla esimerkiksi seuraavanlainen:
```java
public class singletonExample{
    
    //yksityinen luokkamuuttuja, jonka arvoksi määritellään aluksi "null"
    private static Storage storage = null;
    
    //yksityinen rakentaja
    private Storage(){
    }
    
    //Luokkametodi, joka tarkistaa onko luokkamuuttuja Storage jo tehty.
    //Jos Storagen arvo on edelleen "null" eli sitä ei ole vielä luotu, luodaan
    //se tässä metodissa ja palautetaan se. Jos Storage on jo olemassa, 
    //palauttaa metodi kyseisen valmiiksi olemassa olevan Storagen.
    public static Storage getInstance(){
        if(storage == null){
            storage == new Storage();
        }
        return storage;
    }
}
```
Singleton-luokan ongelmana on kuitenkin esimerkiksi sen globaalia muuttujaa muistuttava luonne. Kaikilla luokilla on pääsy muuttujaan julkisen instanssin vuoksi, mutta luokkien välisiä riippuvuuksia on vaikea määrittää, koska singelton-luokan yksityisellä rakentajalla ei ole niitä. Luokilla kuitenkin on riippuvuus, jos toinen luokka käyttää toisen instanssia.

Singleton-luokkaa käytetään usein tietokantoja käsittelevissä ohjelmissa. Käytännön näkökulmasta singelton luokka toimii niin, että koko applikaatio, ohjelma tms. käyttää vain yhtä ja samaa tietokannan ilmentymää sen kaikissa toiminnoissa. Tämä ehkäisee virheiden ja poikkeusten esiintymistä, koska aina luotaessa uusi ilmentymä nämä ovat mahdollisia. Lisäksi saman ilmentymän käyttäminen nopeuttaa tiedonhakua ja sen palauttamista tietokannasta.
## Säikeet
Javassa voi käynnistää käyttöjärjestelmän tukemana tavallista ohjelmaprosessia kevyempiä säikeitä. Säikeen käyttämät resurssit kuuluvat säikeen käynnistävälle prosessille. Yksittäinen prosessi voi käynnistää yhden tai suuren määrän säikeitä yhdessä tai useammassa suoritinytimessä käyttöjärjestelmä- ja resurssirajoitteiden puitteissa. Säie on yksi ohjelman suoritusketjuista, joka voi toimia samanaikaisesti muiden säikeiden kanssa. Säikeiden käyttö sallii moniajo-ohjelmoinnin, joka voi parantaa ohjelman suorituskykyä. Javan Thread -luokkaa käytetään säikeiden luomiseen. Kullakin säikeellä on oma suorituskaista, joka voi toimia samanaikaisesti muiden säikeiden kanssa.

Esimerkki.

Oheinen koodiesimerkki luo 5 säiettä ja jokainen niistä tulostaa aloitus- ja lopetusaikansa. Säikeet tallentavat aloitusajan, odottavat satunnaisen ajan ja tallentavat lopetusaikansa. Ohjelma käyttää Thread-luokan sleep -metodia odottamiseen. Taulukkoon tallennetut säikeet käynnistetään for-silmukan avulla. Säikeet käynnistetään samanaikaisesti, mutta niiden suoritusjärjestys ei ole ennalta määrätty. Lopuksi odotetaan, että kaikki säikeet ovat suorittaneet loppuun ennen kuin ohjelma päättyy. Tämä tehdään Thread-luokan join-metodilla, joka pysäyttää nykyisen säikeen suorituksen, kunnes liittyvä säie on suorittanut loppuun. Ilman join-metodia ohjelma saattaisi lopettaa liian aikaisin, kun jotkut säikeet vielä suorittavat.


```java
import java.util.Date;
import java.text.SimpleDateFormat;

public class Saietesti {
    public static void main(String[] args) throws InterruptedException {
        Thread[] saikeet = new Thread[5]; // luodaan taulukko säikeitä varten
        for (int i = 0; i < saikeet.length; i++) {
            final int j = i + 1; // säikeiden numerointi
            saikeet[i] = new Thread(() -> { // luodaan uusi säie
                String aloitettu = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()); // tallennetaan aloitusaika
                System.out.printf("Säie %d aloitettu: %s\n", j, aloitettu); // tulostetaan aloitusaika
                try {
                    int odota = (int) (Math.random() * 9000 + 1000); // arvotaan odotusaika väliltä 1-10 sekuntia
                    Thread.sleep(odota); // nukutetaanaan säiettä odotusajan verran
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                String lopetettu = new SimpleDateFormat("HH:mm:ss.SSS").format(new Date());  // tallennetaan lopetusaika
                System.out.printf("Säie %d lopetettu: %s\n", j, lopetettu); // tulostetaan lopetusaika
            });
            saikeet[i].start(); // käynnistetään säie
        }
        for (Thread saie : saikeet) {
            saie.join(); // odotetaan, että kaikki säikeet ovat suorittaneet loppuun ennen kuin ohjelma päättyy
        }
    }
}
```



```dos
> java Saietesti
Säie 4 aloitettu: 20:38:42.394
Säie 5 aloitettu: 20:38:42.397
Säie 2 aloitettu: 20:38:42.397
Säie 3 aloitettu: 20:38:42.397
Säie 1 aloitettu: 20:38:42.405
Säie 1 lopetettu: 20:38:43.808
Säie 5 lopetettu: 20:38:47.258
Säie 2 lopetettu: 20:38:49.158
Säie 4 lopetettu: 20:38:49.985
Säie 3 lopetettu: 20:38:52.153
```


## Javan käyttö Java-alustan ulkopuolella
### Android
Android OS on suurelta määrin kirjoitettu C ohjelmointikielellä, mutta Android SDK (Androidin ohjelmistokehityspaketti) käyttää kuitenkin Java kieltä sovellusten kehityksen perustana, mutta ei kuitenkaan käytä Javan omia standardeja (GUI, SE, ME) tai muita vakiintuneita Java standardeja. Samalla Android SDK:n tukema tavukoodi ei ole yhteensopiva Javan tavukoodin kanssa sekä Android SDK toimii vain omalla virtuaalikoneellaan, joka on suunniteltu älypuhelimille ja tableteille. Android Studio IDE (Integrated Deveplopment Environment) on Android sovellusten virallinen ohjelmointiympäristö, mutta muitakin ohjelmointiympäristöjä voidaan käyttää vapaasti Android sovelluksien kehittämiseen. Android Studiossa kehittäjä voi luoda emulaattoreita Android OS:ää käyttävistä puhelimista ja testata omia Java-sovelluksiaan näiden emulaattoreiden avulla.

Koko Android OS:n ominaisuusvalikoima on käytettävissä Java ohjelmointikielellä kirjoitettujen ohjelmointirajapintojen (API) kautta käyttäjille. Näitä rajapintoja voidaan pitää Android sovelluksien ns. rakennuspalikoina, joilla voidaan rakentaa sovellusten käyttöliittymä ja ohjata sen toimintoja. Kyseisiä rajapintoja ovat seuraavat:

* **Tarkastelu järjestelmä** (View System), jolla rakennetaan Android sovelluksen käyttöliittymä, käyttäen erilaisia vekottimia (Widgets), kuten esim. nappuloita, listoja, laatikoita ja tekstikenttiä sekä palkkeja.
* **Tehtävienhallitsija** (Resource Manager), jolla voidaan päästä käsiksi paikallisiin teksteihin, grafiikoihin tai asetteluihin.
* **Huomautustenhallitsija** (Notification Manager) mahdollistaa sovellusten esitellä mukautettuja huomautuksia käyttäjille.
* **Toiminnallisuudenhallitsija** (Activity Manager), jolla voidaan hallita sovellusten elinkaarta sekä mahdollistaa navigoinnin sovelluksen eri tehtävien välillä.
* **Sisällön tarjoaja** (Content Provider) mahdollistaa sovellusten datan jakamisen muiden sovellusten välillä, kuten esim. yhteistietojen välittämisen toisesta sovelluksesta toiseen.
**Erimielisyys**

Oraclen ja Googlen välillä käytiin oikeudellista kiistaa Javan API:en (sovellusliittymien) ja lähdekoodin tekijänoikeuksista.

Oracle vaati vahingonkorvauksia Googlelta, joka puolestaan perusteli API:en käytön olleen kohtuuden rajoissa. Kaksi piirituomioistuinta päätti asiasta Googlen eduksi mutta vetoomustuomioistuin kumosi molemmat päätökset. Asiaa käytiin läpi vuodesta 2012 vuoden 2021 kevääseen asti, jolloin lopullisessa ratkaisussa korkein oikeus päätti API:en käytön olleen Googlen osalta kohtuullista. Vaikka se kumosi aiemman päätöksen, lopullinen ratkaisu jätti huomioimatta API:en suojaamisen tekijänoikeuksilla.

Tapaus toimi kiinnostavana esimerkkinä muille alalla toimijoille, sillä monissa tietokoneohjelmissa ja ohjelmistoissa (erityisesti avoimen lähteen) on vastaavasti hyödynnetty API:ja muista tuotteista esimerkiksi ohjelmien yhteensopivuuden helpottamiseksi.

## Kritiikki
Javan kritiikki koskee sen geneerisen ohjelmoinnin toteutusta, nopeutta, etumerkittömien kokonaislukujen käsittelyä, liukulukuaritmetiikkaa sekä tietoturvahaavoittuvuuksia Java-virtuaalikoneen toteutuksissa (HotSpot).

### Etumerkittömät kokonaisluvut
Javassa ei ole luontaisia etumerkittömiä kokonaislukuja. C-kieliset ohjelmat tuottavat yleensä etumerkitöntä dataa, ja tämän tyyppisen datan puute estää suoran tiedon vaihdon Java-kielisten ja C-kielisten ohjelmien välillä. Suuria etumerkittömiä lukuja numeeristen käsittely kenttien numeroina, kuten kryptografiassa, mikä hankaloittaa Javan käyttämistä tällaisissa tehtävissä. Vaikka tämän ongelman kiertäminen on mahdollista käyttäen muunnoskoodia ja suurempia tietotyyppejä, se tekee etumerkittömän datan käsittelystä kömpelöä Javalla. Vaikka 32-bittiseen etumerkillä varustettuun kokonaislukuun on mahdollista tallentaa 16-bittinen etumerkitön kokonaisluku ilman häviöitä, ja 64-bittiseen etumerkillä varustettuun kokonaislukuun voi puolestaan tallentaa 32-bittisen etumerkittömän kokonaisluvun, ei ole kuitenkaan olemassa 64-bittisestä suurempaa tyyppiä etumerkittömän kokonaisluvun tallentamiseen. Kaikissa edellä mainituissa tapauksissa käytetyn muistin määrä voisi kaksinkertaistua, ja kaikki kahden komplementin ylivuotoon turvautuva logiikka pitäisi uudelleen kirjoittaa. Abstrakteissa tapauksissa funktio kutsut olisivat välttämättömiä monissa operaatioissa, jotka ovat monissa muissa kielissä luontaisia. Vaihtoehtoisesti on mahdollista käyttää Javan etumerkillä varustettuja kokonaislukuja jäljittelemään samankokoisia etumerkittömiä kokonaislukuja, mutta tämä vaatii yksityiskohtaista tuntemusta bittikohtaisista operaatioista. JDK 8 tarjosi jonkinlaista tukea etumerkittömille kokonaisluvuille, mutta ei etumerkittömille tavuille eikä myöskään tukea Java kielestä.

### Yhdistetyt arvotyypit
Javassa ei ole yhdistettyjä arvotyyppejä, kuten C:n structeja, joissa on tietopaketteja, joita käsitellään suoraan viittauksien sijaan epäsuorasti. Arvotyypit voivat joskus olla nopeampia ja pienempiä kuin luokat viittauksilla. Esimerkiksi Javan HashMap on toteutettu taulukkona viittauksina HashMap.Entry-olioihin,[16] jotka sisältävät vuorostaan viittauksia avain- ja arvo-olioihin. Tiedon hakeminen vaatii tehotonta kaksoishakemista. Jos Entry olisi arvotyyppi, taulukko voisi tallentaa avain-arvo-parit suoraan, mikä poistaisi ensimmäisen välitystason, lisäisi viittauspaikallisuutta ja vähentäisi muistin käyttöä. Lisäksi, jos Java tukisi geneerisiä primitiivisiä tyyppejä, avaimet ja arvot voitaisiin tallentaa suoraan taulukkoon, poistamalla molemmat välitystasot.

### Perusmuuttujien ja taulukoiden integrointi
Taulukot ja perusmuuttujat ovat jossain määrin erityisiä ja niitä on käsiteltävä eri tavoin kuin luokkia. Tätä on arvosteltu, koska se edellyttää monia funktiovariaatioita yleiskäyttöisten kirjastojen luomisessa.

### Serialisaatio
Javassa on mekanismi objektin serialisoimiseen, jossa objekti voidaan esittää tavujonona, joka sisältää sen tietokentät yhdessä tietonsa ja kenttiensä tyyppitiedon kanssa. Kun objekti on sarjallistettu, sitä voidaan myöhemmin desarjallistaa; eli sen tyyppitiedot ja tietonsa esittävät tavut voidaan käyttää objektin luomiseen muistissa. Tämä aiheuttaa erittäin vakavia teoreettisia ja todellisia turvallisuusriskejä.

Serialisointi prosessi on siitä hyödyllinen, että se on kokonaisuudessaan JVM riippumaton. Tarkoittaen sitä, että objekti voidaan deserialisoida täysin toisella laitteella tai alustalla, kuin se on serialisoitu. 

Luokat ObjectInputStream ja ObjectOutputStream ovat korkeantason virtoja, jotka sisältävät metodit serialisoinnille sekä deserialisoinnille.

Java serialisointi voidaan saavuttaa käyttämällä java.io.Serializable rajapintaa. Objektia serialisoidessa tulee luokan määrittelyssä implementoida tämä rajapinta, joka mahdollistaa tarvittavan tarkistuksen onko objekti serialisoitava. Kun objekti on serialisoitava, se voidaan kirjoittaa ObjectOutputStreamiin, joka konvertoi tämän objektin bittivirraksi. 

Java deserialisointi voidaan saavuttaa lukemalla bitit bittivirrasta ja antamalla bitit ObjectInputStreamille. ObjectInputStream voi konvertoida tämän jälkeen bitit takaisin objektin muotoon ja palauttaa sen takaisin käytettäväksi halutussa muodossa. 

Yksi tärkeä tieto Javan serialisoinnista on se, että siihen liittyy aina turvallisuusriskinsä, jos sen kanssa ei ole varovainen. Serialisoidut objektit voivat sisältää herkkää informaatiota ja jos serialisoitu data päätyy vääriin käsiin, voidaan dataa käyttää esimerkiksi systeemisi hyväksikäyttöön. Tämän seikan takia on hyvä idea käyttää datan salausta (encryption) sekä muita turvallisuuskeinoja työskennellessä serialisoinnin kanssa.

### Suuret taulukot
Javaa on kritisoitu siitä, ettei se tue taulukoita, joiden koko on 231 (noin 2,1 miljardia) alkiota tai enemmän. Tämä rajoittaa Javaa ohjelmointikielenä; *the Java Language Specification*, kohdassa 10.4 sanotaan seuraavaa:

                            Taulukot on indeksoitava konaisluvuilla… Jos yrittää käyttää taulukon arvoa, jonka indeksi on pitkä kokonaisluku, seurauksena on käännösaika-virhe.

Suurten taulukoiden tukeminen vaatisi myös muutoksia Javan virtuaalikoneeseen (JVM). Rajoitus ilmenee osa-alueilla, kuten kokoelmien koon rajoittuminen kahteen miljardiin alkioon ja kyvyttömyys muistikartoittaa jatkuvia tiedostolohkoja, joiden koko on suurempi kuin 2 GB (gigatavua). Javassa ei myöskään ole moniulotteisia taulukoita (vierekkäin varatut yksittäiset muistilohkot, joihin pääsee yhdellä epäsuunnalla), mikä rajoittaa tieteellisen ja teknisen tietojenkäsittelyn suorituskykyä.

Javassa ei ole tehokasta tapaa alustaa taulukoita. Kun taulukko määritetään, Javan virtuaalikone (JVM) kääntää sen tavukoodeiksi ohjeilla, jotka asettavat sen elementit yksitellen ajon aikana. Koska Javan metodit eivät voi olla suurempia kuin 64 KB (kilotavua), jopa vaatimattoman kokoiset taulukot, joiden arvot on asetettu suoraan koodissa, antavat virhe ilmoituksen ”Error: code too large” (Virhe: koodi liian isoa) käännettäessä.

### Hitaus

Koska jokainen koodi on tulkittava konekoodiksi, Java on hitaampi muihin kieliin, kuten esimerkiksi C:hen ja C++:aan. Java on huomattavasti hitaampi kuin kielet, jotka tuottavat käännöskoodia suoraan koneelle, sekä se käyttää paljon muistia.

Javaa on kritisoitu sen nopeudesta sovellusten käynnistyksessä. Javalla tehdyt sovellukset voivat käynnistyä hitaammin kuin muilla ohjelmointikielillä tuotettuihin sovelluksiin, mikä voi tuottaa ongelmia tietynlaisissa sovelluksissa. Javan hitaus sovellusten käynnistämisessä johtuu siitä, että Java-sovellusten on käynnistyessään ladattava suuri määrä luokkia ja kirjastoja, mikä voi johtaa viiveisiin.

Toinen kritiikin kohde Javan nopeuteen liittyen koskee tapaa, jolla Java käsittelee muistin varausta. Vaikka Javan automaattisesta muistin hallinnasta voi olla hyötyä koodaajalle, se voi myös johtaa suorituskyky ongelmiin. Javan käyttämä roskakori voi viedä merkittävän määrän prosessorin resursseista, minkä seurauksena sovellus voi hidastua. Javan muistin varaus voi johtaa myös muistin sirpaloitumiseen, millä on suora vaikutus suorituskykyyn.

Java-ohjelmien sisäiset ominaisuudet ei vaikuta kielen ajonaikaiseen suorituskykyyn yhtä paljon kuin kääntäjän tai virtuaalikoneen laatu. Käännetyn ohjelman ajaminen esimerkiksi virtuaalikoneen avulla on natiivia suoritusta hitaampaa. Virtuaalikoneet voivat tarjota esimerkiksi alustariippumattomuuden ja yksinkertaistetun kehityksen, mutta samalla laskea suorituskykyä.

### Turvallisuus

Java-ohjelmistoja jää myös paljon päivittämättä pelkän tietoisuuden puutteen takia. Yleisin syy tälle on se, ettei käyttäjä yksinkertaisesti ole vain tietoinen uusista ja parantavista päivityksistä, tai toiselta kantilta käyttäjä ei ole tietoinen siitä, kuinka päivitykset tulisi tehdä.

Javan turvallisuutta on kritisoitu paljon. Oraclen toimintaa liittyen siihen, kuinka he informoivat löytyvistä turvallisuusbugeista, on erityisesti nostettu esille. On tullut ilmi, ettei Oraclen puolesta kaikista näistä ei ole laajalti informoitu käyttäjiä. Esimerkiksi kun julkaistiin korjaukset monille vioille Java 7:ssä, poisti se Java 6:n käyttäjien koneista ja erityisesti tämä vaikutti yrityksien sovelluksiin. Oracle oli alun perin vakuuttanut, ettei tämä vaikuttaisi niihin ja ne olisivat turvassa päivityksiltä. Tämä kuitenkin oli vakava turvallisuusriski, sillä Java 6 on laajalti käytössä yrityksien sovelluksissa.

Java-koodiympäristö antaa mahdollisuuden hyödyntää hiekkalaatikko testausta, ja ajaa ohjelmia, joiden koodi ei ole korkealaatuista. Käyttäjä voi siis ajaa ympäristössä koodeja, ja ohjelmia, epäluotettavia tavukoodiohjelmia. Tämä voi antaa haittaohjelmille mahdollisuuden hyödyntää näiden ohjelmien tietoturvaongelmia ja päästä käsiksi esimerkiksi tiedostojärjestelmiin, päästä yhdistämään yksityisiin verkkoihin tai jopa alkaa suorittaa mielivaltaisia komentoja.

## Katso myös

* C#
* C++

### Javan vertailu muihin ohjelmointikieliin

* Java- ja C++-ohjelmointikielten vertailu

## Lähteet
* 
* 
* 
* 
* 
*

### Viitteet

## Aiheesta muualla

* Sunin Java-sivut 
* Javadoc J2SE 1.6 
* Ohjelmoinnin perusteita Java-kielellä
* Aloittelijan Java-opas
* Sopimuspohjainen olio-ohjelmointi Java-kielellä
* Java-kehitysympäristön pystyttäminen ja HelloWorld-ohjelman luominen
* Full Java Tutorial 
* NetBeans, Avoimeen lähdekoodiin perustuva Java-kehitysympäristö