Archiv der Kategorie: Java 8

Parsen und Formatieren von Datumszeitwerten der Java Date Time API

Alle temporalen Typen überschreiben standardmäßig die toString()-Methode und liefern eine standardisierte Ausgabe. Weiterhin lassen sich die temporalen Typen auch bei String.format(…) und dem java.util.Formatter einsetzen.

format(…)-Methode

Daneben bieten die Typen eine format(…)-Methode, der ein Formatierungsobjekt übergeben wird, sodass individuelle Ausgaben nach einem Muster möglich sind.

Klasse Formatierungsmethode
LocalDateTime format(DateTimeFormatter formatter)
LocalDate format(DateTimeFormatter formatter)
LocalTime format(DateTimeFormatter formatter)
ZonedDateTime format(DateTimeFormatter formatter)
OffsetDateTime format(DateTimeFormatter formatter)

Temporale Klassen nutzen den gleiche Parametertyp DateTimeFormatter

Die format(…)-Methode nimmt einen DateTimeFormatter an, der die Ausgabe beschreibt. Wie kommen wir an einen DateTimeFormatter? Die Klasse hat keinen öffentlichen Konstruktor, sondern Konstanten und statische Fabrikmethoden. Über drei Varianten kommen wir zum konkreten Objekt:

  • Es gibt vordefinierte Konstanten für standardisierte ISO/RFC-Ausgaben,
  • Methoden für vordefinierte lang/kurz-Formate (auch lokalisiert) und
  • Methoden für komplett selbst zusammengestellte Ausgaben.

Die API-Dokumentation zählt die Konstanten mit ihren Formaten aus, Beispiele sind ISO_LOCAL_DATE oder ISO_ZONED_DATE_TIME. Wichtig zu bedenken ist, dass der temporale Typ die Felder auch haben muss! Ein ISO_ZONED_DATE_TIME ist zum Beispiel bei einem LocalDate nicht möglich.

Praktischer sind die statischen ofLocalizedXXX(…)-Methoden, die eine Aufzählung FormatStyle (FULL, LONG, MEDIUM, SHORT) annehmen:

  • DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle)
  • DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle)
  • DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle)
  • DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle)

Einen so aufgebauten DateTimeFormatter lässt sich Zusatzinformation geben mit diversen withXXX(…)-Methoden, etwa withLocale(Locale locale) oder withZone(ZoneId zone).

Beispiel

LocalDateTime now = LocalDateTime.now();

out.println( now.format( BASIC_ISO_DATE ) );

out.println( now.format( ISO_LOCAL_DATE_TIME ) );

out.println( now.format( ofLocalizedDate( SHORT ) ) );

out.println( now.format( ofLocalizedDateTime( MEDIUM ) ) );

out.println( now.format( ofLocalizedDateTime( FULL ).withLocale( FRANCE )

                                                    .withZone( ZoneId.of( "America/Cayenne" ) ) ) );

Die Ausgaben sehen so aus:

20170616

2017-06-16T20:39:11.2114379

16.06.17

16.06.2017, 20:39:11

vendredi 16 juin 2017 à 20:39:11 heure de la Guyane française

Eine völlig flexible Ausgabe ermöglicht ein Muster.

Beispiel

LocalDate now = LocalDate.now();
System.out.println( now );          // 2014-03-21
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( „d. MMMM yyyy“ );
String nowAsString = now.format( formatter );
System.out.println( nowAsString );  // 21. März 2014
LocalDate nowAgain = LocalDate.parse( nowAsString, formatter );
System.out.println( nowAgain );     // 2014-03-21

Die API-Dokumentation zu DateTimeFormatter zeigt einige vordefinierte Formatierungsobjekte und listet alle Formatspezifizierer auf.

parse(…)-Methode

Neben dem Formatieren bieten die Typen auch eine statische parse(…)-Methode, die einmal mit einem String-Parameter das Format erwartet, was toString() liefert, und eine Version mit zwei Parametern, wobei dann ein Formatierungsobjekt erlaubt ist, um genau das Format anzugeben, nach dem geparst werden soll.

Stream iterate(…)-Methoden

Die zwei statischen iterate(…)-Methoden generieren einen Stream aus einem Startwert und einer Funktion, die das nächste Element produziert.  Bei iterate(T seed,
UnaryOperator<T> f) ist der Strom unendlich, bei der zweiten – in Java 9 hinzugekommenen Methode – iterate(…, Predicate<? super T> hasNext, …)-Methode beendet ein erfülltes Prädikat den Strom und erinnert an eine klassische for-Schleife. Der Abbruch über ein Prädikat ist sehr flexibel, denn bei der ersten iterate(…)-Methode ist das Stoppen immer ein Problem und so folgt oftmals ein limit(…) oder takeWhile(…) zum Limitieren der Elemente.

Beispiele

Produziere Permutationen eines Strings.

UnaryOperator<String> shuffleOp = s -> {

  char[] chars = s.toCharArray();

  for ( int index = chars.length - 1; index > 0; index-- ) {

    int rndIndex = ThreadLocalRandom.current().nextInt( index + 1 );

    if ( index == rndIndex ) continue;

    char c = chars[ rndIndex ];

    chars[ rndIndex ] = chars[ index ];

    chars[ index ] = c;

  }

  return new String( chars );

};

String text = "Sie müssen nur den Nippel durch die Lasche ziehn";

Stream.iterate( text, shuffleOp ).limit( 10 ).forEach( System.out::println );

Erzeuge einen BigInteger-Stream ab 10 Millionen alle Zahlen aus, bis mit hoher Wahrscheinlichkeit eine Zufallszahlen erscheint.

Predicate<BigInteger> isNotPrime = i -> ! i.isProbablePrime( 10 );

UnaryOperator<BigInteger> incBigInt = i -> i.add( BigInteger.ONE );

Stream.iterate( BigInteger.valueOf( 10_000_000 ), isNotPrime, incBigInt )

      .forEach( System.out::println );

java.time.Duration

Eine Klasse Duration repräsentiert Dauern von Zeiten und ist weder mit Zeitzonen verbunden noch mit anderen Zeitleisten. Daher ist auch ein Tag idealisiert exakt 24 Stunden lang, Schaltsekunden kennt die Klasse nicht, und einen Tag zu addieren heißt, 24 Stunden aufzurechnen.

Die interne Berechnungseinheit ist Sekunden bzw. Nanosekunden, auch wenn Hilfsmethoden Zeiteinheiten bis Stunden erlauben. Darüber wird eine Duration auch aufgebaut, über ofXXX()-Methoden wie ofSeconds(long seconds, long nanoAdjustment) oder ofDays(long days). Differenzen bildet wieder Duration between(Temporal startInclusive, Temporal endExclusive), wobei Temporal eine Schnittstelle ist, die etwa von LocalDate, LocalDateTime, LocalTime, OffsetDateTime, OffsetTime, ZonedDateTime, Year, YearMonth, Instant implementiert wird, nicht aber von Period.

Beispiel: Wie viel Zeit vergeht zwischen der Ausführung?

Instant start = Instant.now();
 try {
   Files.walk( Paths.get( System.getProperty( "user.home" ) ) ).count();
 } catch ( Exception e ) { }
 Instant end = Instant.now();
 System.out.println( Duration.between( start, end ).toMillis() + " ms" );

Abgewandelt wird eine Duration wieder über withXXX(…) oder die minusXXX(…)/plusXXX(…)-Methoden. Duration dividedBy(long divisor) teilt die Duration durch eine Zeit. Die neue Java 9-Methode long dividedBy(Duration divisor) sagt, wie oft der divisor in der Duration liegt.

toNanos(), toMillis(), toSeconds() – neu in Java 9 –, toMinutes(), toHours(), toDays() konvertieren in ein long, getNano() und getSeconds() liefern die zwei Bestandteile einer Duration als long. Wichtig ist der Unterschied: Die Getter liefern den Feldwert von Duration, während toXXX() immer konvertiert.

Beispiel

Duration aSecond = Duration.of( 1, ChronoUnit.MINUTES );
out.println( aSecond.getSeconds() ); // 60
out.println( aSecond.getNano() ); // 0
out.println( aSecond.toMinutes() ); // 1
out.println( aSecond.toSeconds() ); // 60
out.println( aSecond.toNanos() ); // 60000000000

In Java 9 kommen Methoden hinzu, die die Anteile an Minuten, Sekunden, usw. erfragen, und zwar long toDaysPart(), int toHoursPart(), int toMinutesPart(), int toSecondsPart(), int toMillisPart() und int toNanosPart().

Rock Around the java.time.Clock

Die zeitbezogenen temporalen Typen bekommen ihre Zeit von einer Uhr. Die Uhr kombiniert die aktuelle Zeit mit einer Zeitzone; Java repräsentiert sie durch den Typ java.time.Clock. Der Klasse ist abstrakt und Exemplare sind über statische Fabrikmethoden zu bekommen:

Statische Clock-Mehoden Rückgabe
systemUTC() Uhr mit genauster Zeit in der Greenwich/UTC Zeitzone
systemDefaultZone() Uhr mit genauster Zeit in der aktuellen Systemzeitzone
tickMillis(ZoneId zone) Uhr mit Millisekundenauflösung ohne Nanosekundenanteil in der gegeben Zeitzone (ab Java 9)
tickSeconds(ZoneId zone) Uhr mit Sekundenauflösung ohne Milli- und Nanosekundenanteil in der gegeben Zeitzone
tickMinutes(ZoneId zone) Uhr mit Minutenauflösung ohne Sekunden-, Milli- und Nanosekundenanteil in der gegeben Zeitzone
tick(Clock baseClock, Duration tickDuration) Uhr, die auf der Basis von baseClock in Abständen von tickDuration „tickt“
offset(Clock baseClock, Duration tickDuration) Neue Uhr, die gegenüber der baseClock um tickDuration verschoben ist
fixed(Instant fixedInstant, ZoneId zone) Voreingestellte Uhrzeit, die sie nie ändert

Clock-Exemplare erfragen

Die now()-Methoden der Klassen LocalTime, LocalDate, … nutzen standardmäßig die Uhr in der aktuellen Zeitzone:

public static LocalDate now() {

  return now(Clock.systemDefaultZone());

}

Abzulesen am Beispiel ist, dass die now(…)-Methode überladen ist, sodass ein Programm selbst eine Clock angeben kann. Das ist nützlich zum Testen, wenn zum Beispiel die Zeit immer die gleiche sein soll.

Java SE 8u9[1|2] Update

Alles News unter http://www.oracle.com/technetwork/java/javase/8all-relnotes-2226344.html.

Interessanbt finde ich unter anderem:

New JVM Options added: ExitOnOutOfMemoryError and CrashOnOutOfMemoryError
Two new JVM flags have been added:

  • ExitOnOutOfMemoryError – When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. It can be used if you prefer restarting an instance of the JVM rather than handling out of memory errors.
  • CrashOnOutOfMemoryError – If this option is enabled, when an out-of-memory error occurs, the JVM crashes and produces text and binary crash files (if core files are enabled).

See JDK-8138745.

Und:

Disable MD5withRSA signature algorithm in the JSSE provider
The MD5withRSA signature algorithm is now considered insecure and should no longer be used. Accordingly, MD5withRSA has been deactivated by default in the Oracle JSSE implementation by adding „MD5withRSA“ to the „jdk.tls.disabledAlgorithms“ security property. Now, both TLS handshake messages and X.509 certificates signed with MD5withRSA algorithm are no longer acceptable by default. This change extends the previous MD5-based certificate restriction („jdk.certpath.disabledAlgorithms“) to also include handshake messages in TLS version 1.2. If required, this algorithm can be reactivated by removing „MD5withRSA“ from the „jdk.tls.disabledAlgorithms“ security property.

JDK-8144773 (not public)

 

Das Ende vom Java-Plugin für Web-Browser

Oracle hat angekündigt, dass das Java-Plugin für Web-Browser mit dem Erscheinen von Java 9 im nächsten Jahr nicht mehr weiterentwickelt wird.

Nachdem Mozilla Firefox und auch Google Chrome ankündigten, das Java-Plugin nicht mehr weiter unterstützen zu wollen, sind das offenbar u. a. Gründe für den Abschied vom Browser-Plugin.

Der Anteil von Java-Applets ist ohnehin kaum noch „messbar“, spätestens mit dem Java 7 Update 51, mit dem die Sicherheitsmechanismen für Java-Applets noch einmal deutlich überarbeitet wurden, sind Java-Applets in „freier Wildbahn“ kaum noch zu finden.

Oracle empfiehlt als Ersatz Java WebStart, das ohne das Plugin auskommt.

JDK 8u40 freigegeben

http://www.oracle.com/technetwork/java/javase/8u40-relnotes-2389089.html.

Und es sind interessante Neuerungen dabei.

The endorsed-standards override mechanism and the extension mechanism are deprecated and may be removed in a future release. There are no runtime changes. Existing applications using the ‚endorsed-standards override‘ or ‚extension‘ mechanisms are recommended to migrate away from using these mechanisms. To help identify any existing uses of these mechanisms, the -XX:+CheckEndorsedAndExtDirs command-line option is available.

Grund dafür ist das neue Modulsystem,was in Java 9 kommt.

Und:

Starting with JDK 8u40 release, JavaFX controls are enhanced to support assistive technologies, meaning that JavaFX controls are now accessible. In addition, a public API is provided to allow developers to write their own accessible controls.

JDK 8u40 release includes new JavaFX UI controls; a spinner control, formatted-text support, and a standard set of alert dialogs.

Viele Bugs wurden gefixt: http://www.oracle.com/technetwork/java/javase/2col/8u40-bugfixes-2423829.html

Java Interfaces mit main-Methode

Statische Schnittstellenmethoden erlauben eine neue Möglichkeit zur Deklaration der main(…)-Methode:

interface HelloWorldInInterfaces {

  static void main( String[] args ) {

    System.out.println( „Hallo Welt einmal anders!“ );

}

}

Das Schlüsselwort interface ist vier Zeichen länger als class, doch mit der Einsparung von public und einem Trenner ergibt sich eine Kürzung von drei Zeichen – wieder eine neue Möglichkeit zum Längefeilschen.

null coalescing operator in Java nachbilden

Da null viel zu oft vorkommt, null-Referenzierungen aber vermieden werden müssen, gibt es viel Code der Art: o != null ? o : non_null_o.

Diverse Programmiersprachen bieten für dieses Konstrukt eine Abkürzung über den sogenannten null coalescing operator (Coalescing, zu Deutsch verschmelzend), der geschrieben wird mal als ?? oder als ?:, für unser Beispiel: o ?? non_null_o. Besonders hübsch ist dass bei sequenziellen Tests der Art o ?? p ?? q ?? r, wo es dann sinngemäß lautete: Liefere die erste Referenz ungleich null.

Java-Programmierer kommen nicht zu diesem Glück, können aber tricksen (http://stackoverflow.com/a/28306286/388317):

If there are only two references to test and you are using Java 8, you could use

Object o = null;
Object p = "p";
Object r = Optional.ofNullable( o ).orElse( p );
System.out.println( r );   // p

If you import static Optional the expression is not too bad.

Unfortunately your case with „several variables“ is not possible with an Optional-method. Instead you could use:

Object o = null; Object p = null; Object q = "p"; Optional<Object> r = Stream.of( o, p, q ).filter( Objects::nonNull ).findFirst(); System.out.println( r.get() ); // p