Project Coin features in Java 7

Post on 17-Jul-2015

143 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

Transcript

Project Coin features i Java 7

Jan Krag

14. Juni 2013

For Udvikling 1

Project Coin

Projekt til forbedring af Java sproget http://openjdk.java.net/projects/coin/

Delt op mod hhv. Java 7 og Java 8

Målsætninger: Gøre java kode mere læsbar

Opfordre til at skrive mere pålidelig kode

velintegreret med både tidligere og fremtidigesprogændringer

Færre tastetryk, renere kode, gladereudviklere

Begrænsninger

INGEN ændringer I JVM’en

Koordineret med kommende Java 8/9 ændringer

Forholdsvis små sprogændringer

Dvs. “små” med henblik på:

ændringer til language spec.

Implementering

Refac af eksisterende libraries

Test

Overblik: the 7-4-7

1. Improved literals

2. Strings in switch

3. Try-with-resources

4. Multicatch

5. Precise rethrow

6. Diamond operator

7. Safe Varargs

1a) Binary literals

Nu kan man også specificere konstanter

I binær form:

byte b = 0b01001101;

1b) Underscores in literals

Den “lille forskel”

Det er nu lovligt at sætte (vilkårligt

mange) underscores mellem “cifre” in

talkonstanter

Kun med formål at gøre koden mere

læsbar.

Ingen konsekvenser efter compile

Eksempel

long creditCardNumber =

1234567890123456L;

long bytes =

0b11010010011010011001010010010010;

Kan nu skrives som:

long creditCardNumber =

1234_5678_9012_3456L;

long bytes =

0b11010010_01101001_10010100_10010010;

long hexWords = 0xCAFE_BABE;

int ok = 5_______2;

Men ikke alt er lovligt:

float pi1 = 3_.1415F;

float pi2 = 3._1415F;

long s = 999_99_9999_L;

int x3 = 52_;

int x6 = 0x_52;

int x5 = 0_x52;

int x1 = _52; // lovligt, men er et variabel navn, ikke en talkostant

// Courtesy Josh Bloch

int bond =

0000_____________0000________0000000000000000__000000000000000000+

00000000_________00000000______000000000000000__0000000000000000000+

000____000_______000____000_____000_______0000__00______0+

000______000_____000______000_____________0000___00______0+

0000______0000___0000______0000___________0000_____0_____0+

0000______0000___0000______0000__________0000___________0+

0000______0000___0000______0000_________000+__0000000000+

0000______0000___0000______0000________0000+

000______000_____000______000________0000+

000____000_______000____000_______00000+

00000000_________00000000_______0000000+

0000_____________0000________000000007;

2) Strings in switch

int monthNameToDays(String s, int year) {

switch(s) {case "April":

case "June":

case "September":

case "November":

return 30;

case "January":

case "March":

case "May":

case "July":

case "August":

case "December":

return 31;

case "February":

return 31;

default: ...

}

Strings in switch

Tilføjet kun 1 ord i JLS!

Implementeret med “desugaring” instedet for JVM ændring!

Dvs. koden reduceres pre-compile til en form der allerede er understøttet

Bruger en switch på String.hashCode (ogequality checks ved hash collision) til at oversætte til int’s, og derefter bare en intswitch.

… perfomer derved klart bedre end en langrække equality checks på strenge

Ulempe???

Risiko: Kan friste udviklere til at

misbruge Strings til kode hvor rigtige

type-stærke datatyper ville være bedre

(ofte Enums)

3) Try with resources

Stort problem med nuværende måde at

sikre lukning af åbne resourcer.

Åbning af resourcer kan smide exceptions,

og skal derfor I try-catch.

Lukning af resourcer kan smide exceptions

og derfor skal der ny try-catch I finally osv.

Går helt galt med de typiske chainede

resourcer (input stream etc.), hvor der er

flere lag der kan smide exceptions

Du tror måske…

… at du kan skrive koden “rigtig” men…

Da man i forbindelse med den nye feature

(tålmodighed please) analyserede de

eksisterende Java standard libraries, fandt

man ud af at koden var “forkert” I 66% af

alle tilfælde, så selv dem der har skrevet

JDK’en har ikke kunnet finde ud af at gøre

koden vandtæt.

public static void main(String[] args) {

BufferedReader br = null;

try {

String line;

br = new BufferedReader(

new FileReader("C:\\testing.txt")

);

while ((line = br.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

if (br != null)br.close();

} catch (IOException ex) {

ex.printStackTrace();

}

}

}

Ny version:

public static void main(String[] args) {

try (

BufferedReader br =

new BufferedReader(

new FileReader("C:\\testing.txt")))

{

String line;

while ((line = br.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

}

try(assignment; assignment; …)

Alle resourcer bliver automatisk lukket eftertry-blokken

Men: der var en del “skjulte” detaljer der skulle håndteres:

Der kan nu genereres flere exceptions I blokken, og vi vil ikke “miste” de underliggende helt

null- håndtering (forsøg på close afresource initialiseret til null)

Try with resources -

implementering

Nyt interface: java.lang.AutoCloseable,

indsat I hieraki over java.io.Closable

Ny feature Throwable.addSuppressed

Taget I brug I den eksisterende JDK

Bl.a. også I JDBC 4.1

Også implementeret med “desugaring”

instedet for JVM ændring!

Desugar

try ResourceSpecification

Block

… bliver til{

final VariableModifiers_minus_final R #resource = Expression;

Throwable #primaryException = null;

try ResourceSpecification

Block

catch (Throwable #t) {

#primaryException = t;

throw #t;

} finally {

if (#resource != null) {

if (#primaryException != null) {

try {

#resource.close();

} catch(Throwable #suppressedException) {

#primaryException.addSuppressed(#suppressedException);

}

} else {

#resource.close();

}

}

}

}

4) Multicatch – kort fortalt

static <T> T instantiate(Class<? extends T> cl) {

try {

return cl.newInstance();

} catch (

IllegalAccessException | InstantiationException leeloo) {

throw new IllegalArgumentException(leeloo);

}

}

Multicatch

Sparer en masse kode-duplikering

(DRY)

Giver faktisk lidt bedre performance, da

det oversættes (af javac) til én entry i

exception tabellen istedet for 4

Multicatch - detaljer

Kræver i princippet at Exception

variablen er final (jvm detaljer), men det

håndteres nu af compileren med ny

“effectively final” analyse

Hvad med:

catch(Foo | SonOfFoo e) {...}

p.t. specifikt forbudt i JDK 7

Men kan sagtens tilføjes senere

5) Precise rethrow

try {

// Reflection operationer som f.eks.

//Class.forName, Class.newInstance,

} catch(

ClassNotFoundException | InstantiationException |

NoSuchMethodException | InvocationTargetException e) {

log(e);

throw e;

}

Eller uden multicatch:

… catch(Exception e) {

log(e);

throw(e);

}

Precise rethrow

… hvad er så typen af den Exception der

kastes i throw(e)?

I JDK <7 er det altid typen af variablen

e, dvs. I praksis “Exception”, og det er jo

problematisk og upraktisk når e ikke kan

være andet end det try-blokken rent

faktisk kan smide.

Rethrow I JDK 7 og frem

Nu kan compileren holde styr på hvilken

type ens Exception rent faktisk kan

have, og derfor smides en “sammensat

type” af de exceptions der er på tale.

Denne sammensatte type kan ikke

“udtrykkes” i kode, (så derfor er der

stadig udfordringer hvis Exc. skal

“gemmes” og smides andetsteds f.eks. i

en anden tråd)

Precise rethrow - konklusion

I praksis en meget brugbar feature med meget få ulemper.

Men: ikke helt bagudkompatibel…try {

throw new DaughterOfFoo();

} catch (Foo e) {

try {

throw e;

// Pre-JDK 7 smides Foo,

// nu smides DaughterOfFoo

} catch (SonOfFoo e2) {

; // Kan denne kode nås?

}

}

6) Diamonds (are a girls coders best

friend)

Vi skriver ofte ting som:Map<Integer, Map<String, String>> usersMaps = new HashMap<Integer, Map<String, String>>();

Aaargh!!!

Nu kan vi “bare” skrive:Map<Integer, Map<String, String>> usersMaps = new HashMap<>();

<> kaldes “Diamond” operatoren

Diamond - fortsat

Laver rigtig “type inference”, ikke bare

streng-substitution

Note: Modsat af mange andre sprog

(f.eks. Scala og .Net)

andre sprog laver inferens på variablen

(venstre side): val a = new String(“asd”)

Java 7 laver inferens på værdi-siden (højre),

dvs. Vi specificerer variablens type, og

gætter typen på det objekt der tildeles.

Diamond - detaljer

Det viste sig at være en relativt

kompleks ændring at indføre, med

mange non-trivielle designbeslutninger

Flere mulige inferens algoritmer blev

overvejet, 2 var “lige gode” (ordnede

hver sine 90%).

problemer med anonyme indre klasser:

Diamond – Et eksempel på problem

Object o;

List<?> arg = ...;

o = new Box<>(arg);

Bliver til:

Object o;

List<?> arg = ...;

o = new Box<List<captureof?>>(arg);

OK, Men hvad så med:

o = new Box<List<captureof ?>>(arg){...};

Laves til en ny klasse:

o = new a$1(arg);

class a$1 extends Box<List<captureof ?>>{...}

Men denne klasses skal indeholde spec af sin superklassestype-descriptor som ikke kan udtrykkes I class-filen.

Derfor ikke lovligt i java 7!

public class Box<T> { private T value;

public Box(T value){ this.value = value;

}

T getValue() { return value;

}

}

7) Safe Varargs

Problem idag (JDK < 7) med “unchecked” warnings ved kald af library metoder der tager varargs.

Skyldes at varargs er impl. som arrays, ogarrays ikke understøtter generics pga. covariant typehierarki (kort: String[] kanassignes til Object[] og resultere I runtime CCE hvis man hiver en forkert type ud)

Warnings kommer på call-site og derforsvære at “fjerne”

Varargs - løsning

@SafeVarargs annotation

Men:

Erklærer kun at koden opfører sig “pænt”

Forhindrer egentlig ikke runtime CCE

Kan kun bruges på static og final metoder

da annotations ikke nedarves.

Fremtidig java-version vil forhåbentligt

få compile-time checks

… mulige Coin forbedringer i JDK 8

Try-with-resources på “effectively final”

variable

Dvs. man ikke behøver at assigne til en ny

variabel i try(…)

Fjerne nogle begrænsninger på

Diamond

Måske @SafeVarargs på private

metoder?

… der var dog mere i JDK 7

NIO.2 – New I/O version 2

Method handles

invokeDynamic (ny bytecode instruktion)

Forbedret concurrency

Forbedret Unicode

Diverse andre småting (f.eks. Objects.deepEquals helper)

Her må være flere gode idéer til fremtidige emner(kom frit frem)

… og så er der jo hele JDK 8 !

top related