Ah var-behar? Her er nyhederne i Java 10

9. januar 2018 kl. 05:126
Ah var-behar? Her er nyhederne i Java 10
Illustration: mkabakov/Bigstock.
Så fik Java endelig typeinferens i version 10 med faciliteten ‘var’. Udgaven indvarsler en ny tid med halvårlige Java-opdateringer.
Artiklen er ældre end 30 dage
Manglende links i teksten kan sandsynligvis findes i bunden af artiklen.

Kun tre måneder efter, at Java 9 kom på gaden, står næste version på spring. Den vanskelige og svært forsinkede fødsel af nieren gjorde, at Javas chefarkitekt, Mark Reinhold fra Oracle, slog på tromme for en mere agil proces med halvårlige udgaver af miljøet, som det passer sig i en tid, hvor kontinuerlig udgivelse i små skridt er dagens orden.

»Udviklere, som foretrækker hastig innovation og ønsker at anvende nye funktioner i produktion så hurtigt som muligt, kan bruge den nyeste udgave eller en opdatering og gå videre til den næste, når den frigives,« skrev han sidste år i et blogindlæg.

Den nye stil indebærer, at Java 10 allerede er færdig i forhold til, hvilke funktioner der skal med i udgivelsen. De hyppige udgivelser betyder også, at nyhederne er knap så mange og opsigtsvækkende.

Kompileren finder typen

Den store nyskabelse i nummer 10 er typeinferens for lokale variabler. Det findes i snart sagt alle andre moderne sprog og betyder i alt sin enkelthed, at programmøren ved initialisering ikke længere skal angive en type foran variablen, så længe det foregår lokalt, altså indenfor et sæt tuborg-parenteser.

Artiklen fortsætter efter annoncen

Det kan for eksempel se sådan ud:

  1. var x = new ArrayList<String>();
  2. var y = "Test";
  3. var z = 10;

Hvis vi spørger variablerne om, hvilken type kompileren har fundet til dem inde i Java-shell’en Jshell, får vi de her svar:

  1. jshell> System.out.println(x.getClass());
  2. class java.util.ArrayList
  3.  
  4. jshell> System.out.println(y.getClass());
  5. class java.lang.String
  6.  
  7. jshell> System.out.println(z.getClass());
  8. | Error:
  9. | int cannot be dereferenced
  10. | System.out.println(z.getClass());
  11. | ^--------^

Her er z en int, som er en primitiv type, der ikke har en getClass-metode. Det sidste går bedre, hvis vi først typekonverterer (caster) z til Object:

  1. jshell> System.out.println(((Object)z).getClass());
  2. class java.lang.Integer

Det skal i parentes bemærkes, at grunden til, at vores x har typen ArrayList og ikke ArrayList<String> er, at Java benytter ‘erasure’ i forbindelse med parametrisering af typer, hvor typeparameteren kun benyttes ved kompilering og smides væk under kørsel.

Det er dog ikke alle udtryk, der kan bruges på højre side af tildelingstegnet. Hvis vi prøver med en closure, går det galt:

  1. jshell> var c = () -> { System.out.println("hejsa"); };
  2. | Error:
  3. | cannot infer type for local variable c
  4. | (lambda expression needs an explicit target-type)
  5. | var c = () -> { System.out.println("hejsa"); };
  6. | ^---------------------------------------------^

Det skyldes, at det samme lambda-udtryk kan passe til flere typer, nemlig alle ‘funktionelle interfaces’ med samme signatur. Det samme gælder visse andre slags såkaldte ‘poly-udtryk’, hvor der skal en typeangivelse til for at fastslå typen over for kompileren.

Fakta om Java

Java består af mange dele. Den, der behandles i denne artikel, er Java SE. Hele familien ser sådan ud:

  • Java Card - Java til smartcards. Indbygget i mange SIM-kort og betalingskort.
  • Java ME - Mobile edition. Til gammeldags mobiltelefoner og indlejrede enheder.
  • Android - Ikke officielt en del af Java. Klassebibliotek består af dele af Java SE samt egne Android-klasser.
  • Java SE - Standard edition eller desktop-udgaven af Java.
  • Java EE - Enterprise edition - Java til serverprogrammering.

Den nye facilitet kan heller ikke bruges i forbindelse med felter, parametre og metoders returværdier.

‘Var’ er ikke et egentligt nøgleord, men et såkaldt reserveret typenavn, så ældre kode, der benytter ‘var' som identifier, bliver ikke påvirket.

Hurtigere opstart med serverless i skyen

De øvrige nyheder i Java 10 har ikke så meget at gøre med almindelige programmørers hverdag.

Application Class-Data Sharing gør det muligt at gennemtygge en applikations klasser, så opstartstiden nedsættes. Specielt i forbindelse med ‘serverless’ sky-systemer skulle dette nedsætte opstartstider og give en reduktion af hukommelsesforbrug på op til hundredvis af megabytes pr. JVM-proces.

Blandt andre nyheder i Java 10 kan nævnes oprydning i JVM’ens kode, så det bliver nemmere at skifte garbage collectors, parallelisering af garbage collectoren G1 samt optimering af tråde.

Java 10 er sat til at udkomme den 20. marts. Næste udgave kommer til oktober, hvor værdi-klasser måske bliver højdepunktet.

Den endnu ufærdige version af Java 10 kan hentes på projektets hjemmeside. Eksemplerne her i artiklen er lavet med build 37. Eksemplerne kan downloades her.

6 kommentarer.  Hop til debatten
Denne artikel er gratis...

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.

Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.

Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.

Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.

Debatten
Log ind eller opret en bruger for at deltage i debatten.
settingsDebatindstillinger
6
11. januar 2018 kl. 02:52

Sig mig har vi ikke været her før? Scala lavede dette for mere end 10 år siden og gør det bedre:

  1. baldur@jump1:~$ amm
  2. Loading...
  3. Welcome to the Ammonite Repl 0.7.8
  4. (Scala 2.11.8 Java 1.8.0_151)
  5.  
  6. @ val x = List<a href="">String</a>
  7. x: List[String] = List()
  8. @ val y = "Test"
  9. y: String = "Test"
  10. @ val z = 10
  11. z: Int = 10
  12.  
  13. @ x.getClass
  14. res3: Class[?0] = class scala.collection.immutable.Nil$
  15. @ y.getClass
  16. res4: Class[?0] = class java.lang.String
  17. @ z.getClass
  18. res5: Class[Int] = int
  19.  
  20. @ val c = () => println("hejsa")
  21. c: () => Unit = <function0>
  22.  
  23. @ c.getClass
  24. res7: Class[?0] = class $sess.cmd6$$anonfun$1

Den største forskel er at begrænsningerne ikke er der. Du kan uden problemer kalde .getClass på int typen og du kan også bruge type inferens på anonyme funktioner.

4
10. januar 2018 kl. 12:04

Hvor har jeg ofte skulle hjælpe programmører fordi de ikke har styr på deres typer og hvordan de bruger dem. Nu får de endnu et værktøj til at totalt tabe kontrol af hvordan deres kode virker. Samt 100% afhængig af compileren til at finde bare den mindste fejl.

Suk bekvemmelighed, og dovenskab længe leve..

3
9. januar 2018 kl. 23:26

Men ville det så stadig være Java?

Jo, autoboxing blev introduceret i Java 1.5, men afhænger af variablens deklarerede type. Og det er lige det, det mangler i 'var' deklarationer.

Man plejer ikke at vælge C# eller Java på grund af sproget (jeg er fuldstændig lige meget), men på grund af infrastruktur, platform eller strategi. Eller en bestikkelse fra Microsoft :)

2
9. januar 2018 kl. 16:19

Men ville det så stadig være Java? Ville det bære essensen af Java hvis det ikke var omstændigt at have med at gøre? Hvis du tager omstændigheden ud af Java kan du jo ligeså godt skrive C#.

1
9. januar 2018 kl. 11:26

Har ikke brugt Java i mange år, men det under mig, at 'z' i 'z.getClass()' ikke bliver autoboxet.