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.

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.

Det kan for eksempel se sådan ud:

var x = new ArrayList<String>();
var y = "Test";
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:

jshell> System.out.println(x.getClass());
class java.util.ArrayList
 
jshell> System.out.println(y.getClass());
class java.lang.String
 
jshell> System.out.println(z.getClass());
|  Error:
|  int cannot be dereferenced
|  System.out.println(z.getClass());
|                     ^--------^

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:
jshell> System.out.println(((Object)z).getClass());
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:

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

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.

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.

Læs også: Værdi-klasser på vej til Java og JVM

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.

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (6)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Matthijs Wensveen

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

Michael Nielsen

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

Baldur Norddahl

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

baldur@jump1:~$ amm  
Loading...  
Welcome to the Ammonite Repl 0.7.8  
(Scala 2.11.8 Java 1.8.0_151)  
   
@ val x = List[String]()   
x: List[String] = List()  
@ val y = "Test"   
y: String = "Test"  
@ val z = 10   
z: Int = 10  
   
@ x.getClass   
res3: Class[?0] = class scala.collection.immutable.Nil$  
@ y.getClass   
res4: Class[?0] = class java.lang.String  
@ z.getClass   
res5: Class[Int] = int  
   
@ val c = () => println("hejsa")   
c: () => Unit = <function0>  
   
@ c.getClass   
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.

Log ind eller Opret konto for at kommentere