Java 8 Java 8

Java 8 Bize Neler Getirdi?

Java 8, Java diline önemli yenilikler getirerek geliştirmeyi kolaylaştırmıştır. Birçok yeni özelliği ile, Java kodlarının esnekliğini ve güvenliğini önemli ölçüde artırmıştır.
Java giriş

Merhaba arkadaşlar,

Bu yazımda her ne kadar Java 9, Java 10, Java 11 ve Java 12 versiyonları yayınlamış olsa da size mevcut Java projelerinde daha çok kullanılan veya geçiş yapılan Java 8’in bir önceki versiyon olan Java 7 ile arasındaki farklardan bahsedeceğim. Bu farklardan bahsederken başlık, kısa açıklama ve örnek kod şeklinde bir yol ile ilerleyeceğim. Haydi başlayalım.😊

  1. Base64 Sınıfı

Daha önceki versiyonlarda olması gerektiğine inandığım ve ihtiyaç duyulabilen bir sınıf olan Base64 sınıfı bu versiyonda geldi sonunda.Bu sınıf Encoder’lar ve Decoder’lar olan statik yöntemlerden oluşan bir sınıftır.

Java 8 de Basic, URL ve MIME olmak üzere 3 çeşit “Base64” kodlama türü vardır. Decode ve Encode işlemlerinde RFC 4648 ve RFC 2045 yöntemleri kullanılmaktadır.

import java.io.UnsupportedEncodingException;
import java.util.Base64;

public class Base64Ex {

  public static void main(String[] args) {

    try {
      // Basit Encode
      String encodedString = Base64.getEncoder().encodeToString("Hasan".getBytes("utf-8"));
      System.out.println("encodedString: " + encodedString);

      // Basit Decode
      byte[] decodedBytes = Base64.getDecoder().decode(encodedString);
      System.out.println("decodedString: " + new String(decodedBytes, "utf-8"));

      // URL Encode
      String urlEncodedString = Base64.getUrlEncoder()
          .encodeToString("http://www.google.com/xhtml".getBytes("utf-8"));
      System.out.println("urlEncodedString: " + urlEncodedString);

      // Url Decode
      byte[] urlDecodedBytes = Base64.getUrlDecoder().decode(urlEncodedString);
      System.out.println("urlDecodedBytes: " + new String(urlDecodedBytes, "utf-8"));

      // MIME Encode
      String mimeEncodedString = Base64.getMimeEncoder()
          .encodeToString("JSIDAHFAasjhdasdksıdsajdhs".getBytes("utf-8"));
      System.out.println("mimeEncodedString: " + mimeEncodedString);

      // MIME Decode
      byte[] mimeDecodedBytes = Base64.getMimeDecoder().decode(mimeEncodedString);
      System.out.println("mimeDecodedBytes: " + new String(mimeDecodedBytes, "utf-8"));

    } catch (UnsupportedEncodingException e) {
      System.out.println("Error: " + e.getMessage());
    }
  }
}

Output:

encodedString: SGFzYW4=

decodedString: Hasan

urlEncodedString: aHR0cDovL3d3dy5nb29nbGUuY29tL3hodG1s

urlDecodedBytes: http://www.google.com/xhtml

mimeEncodedString: SlNJREFIRkFhc2poZGFzZGtzxLFkc2FqZGhz

mimeDecodedBytes: JSIDAHFAasjhdasdksıdsajdhs

  1. Lambda Projesi

Java 8 için en çok beklenen geliştirmelerden biri olan Lambda Projesi ile Java’nın fonksiyonel programlamaya geçişi ve Java’da geliştirme kolaylığı amaçlanmıştır. Lambda ifadelerini genel olarak tanımlamak gerekirse, herhangi bir sınıfa ait olmadan iş yapabilen fonksiyonlardır. Tek soyut metotlu Interface’leri (arayüzleri) kısa yoldan tanımlamak için kullanılır. Lambda ifadeleri genel olarak aşağıdaki şekillerde ifade edilebilir.

Parametre listesi -> fonksiyon gövdesi

() -> { işlem++; };

param1 -> param1++;

(param1, param2) -> {

param2++;

param1++;

return param1 + param2;

};

Lambda ifadelerinin örnekleri ile beraber genel özellikleri;

  1. Parametre için tür bildiriminin gerekliliği sonlanmıştır.
public class LambdaEx1 {
  public static void main(String[] args) {
    // tur bildirimi yok
    Func fonk = (p1, p2) -> {
      return p1 + p2;
    };

    int sum = fonk.topla(2, 2);
    System.out.println("sum = " + sum);
  }
}

interface Func {
    int topla(int param1, int param2);
}

Output:

sum = 4

  1. İfademizde tek parametre ihtiyacında, parametre tarafında paranteze ihtiyaç yoktur. İfademizde parametre olmaması durumunda veya birden fazla parametre olması durumunda, parametre tarafında parantez ihtiyacı vardır.
public class LambdaEx2 {
  public static void main(String[] args) {
    // iki parametreli lambda
    Fonk fonk = (p1, p2) -> {
      return 2 * p1 + p2;
    };
    // parametresiz lambda	
    Sohbet sohbet = () -> {
      System.out.println("Merhabalar :]");
    };

    sohbet.merhabaDe();
    int sum = fonk.toplam(4, 2);
    System.out.println("sum = " + sum);
  }
}

interface Fonk {
  int toplam(int param1, int param2);
}

interface Sohbet {
  void merhabaDe();
}

Output:

Merhabalar :]

sum = 10

  1. Fonksiyon gövdesinde tek bir işlem varsa süslü parantezlere gerek yoktur. Birden fazla işlem olması durumunda süslü parantez ihtiyacı vardır.
public class LambdaEx3 {

  public static void main(String[] args) {
    // suslu parantezsiz lambda
    Matematik carpma = (a, b) -> a * b;

    System.out.println("3 x 5 = " + carpma.islemYap(3, 5));
    // suslu parantezli lambda
    Matematik mutlakMesafe = (a, b) -> {
      a = a > 0 ? a : -1 * a;
      b = b > 0 ? b : -1 * b;

      return a + b;
    };
    
    System.out.println("-5 ile 9 arasındaki uzaklık: " + mutlakMesafe.islemYap(-5, 9));
  }
}

interface Matematik {
    int islemYap(int a, int b);
}

Output:

3 x 5 = 15

-5 ile 9 arasındaki uzaklık: 14

  1. Eğer Lambda ifademiz bir dönüş değeri olacak ise ve tek işlem ile bu değeri döndürebildiğinizde “return” ifadesini kullanmanıza gerek yoktur.
public class LambdaEx4 {
  public static void main(String[] args) {
    // return gerektirmeyen lambda
    Math cikarma = (a, b) -> a - b;

    System.out.println("4 - 9 = " + cikarma.islemYap(4, 9));
    // return gerektiren lambda
    Math farkinKaresi = (int a, int b) -> {
      int fark = (a - b) > 0 ? (a - b) : (b - a);

      return fark * fark;
    };

    System.out.println("(5 - 1)^2 = " + farkinKaresi.islemYap(5, 1));
  }
}

interface Math {
  int islemYap(int a, int b);
}

Output:

4 – 9 = -5

(5 – 1)^2 = 16

  1. Default ve Static Metot

Java 8 ile Interface’lere default ve static metot özelliği eklenmiştir. Mevcut kodu etkilemeden yeni yöntemlere sahip olma yeteneği için default metot kavramı geliştirilmiştir. Default metot, “override” edilmediği sürece default metot içerisinde belirtilen işlemlerin yapılmasını sağlayan metot tanımıdır. Static metot ise “override” edilmez ve sadece Interface’in adı ile ulaşılabilir.

public class DefaultStaticMethod {
  public static void main(String[] args) {
    //static metot
    double pi = Utils.getPI();

    System.out.println(pi);

    Utils utils = new Utils() {
    };
    //default metodu kullanma
    utils.yazdir("Merhaba !!");

    //default metodu override etme
    Utils utils2 = new Utils() {
      @Override
      public void yazdir(String message) {
        System.out.println("Override Default Method Message: " + message);
      }
    };

    utils2.yazdir("Hello");
  }
}

interface Utils {
  // Default metot
  default void yazdir(String message) {
    System.out.println(message);
  }
  // Static metot
  static double getPI() {
    return 3.14;
  }
}

Output:

3.14

Merhaba !!

Override Default Method Message: Hello

  1. Fonksiyonel Interface (Arayüz)

İçerisinde bir adet soyut metot bulunan Interface’ler için kullanılan isimdir. En bilindik olan Comparable Interface’dir. İçerisinde sadece “compareTo” metodu bulunur. Comparable Interface genellikle nesne içeren koleksiyon ve map’lerin sıralamasında zorunlu koşulan bir interface’dir. Fonksiyonel Interface’ler default ve static metot bulundurabilir ancak en fazla bir adet soyut metot bulundurur. Java 8 içerisinde birçok fonksiyonel arayüz mevcuttur. Fonksiyonel Interface’ler genellikle lambda ifadeleri ile tanımlanırlar. Fonksiyonel Interface’ler tanımlanırken @FunctionalInteface tag’i kullanılmayabilir ama bu tag tanımlanırsa ilgili Interface’de tek soyut metot olmasını sağlar. İkinci soyut metot eklenince hata verir.

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class FunctionalInterfaceEx {

  public static void main(String args[]) {
    List<Integer> list = Arrays.asList(0, 1, -2, 3, 4, 5, 6, 7, 8, 9);
    // Cift sayılari yaz
    eval(list, n -> n % 2 == 0);
  }

  public static void eval(List<Integer> list, TestEt testEt) {
    for (Integer n : list) {
      // Ve sifirdan buyukse yaz
      if (testEt.ve(t -> t > 0).test(n)) {
        System.out.print(n + " ");
      }
    }
  }
}

interface TestEt {
  boolean test(Integer value);

  default TestEt ve(TestEt digerTest) {
    Objects.requireNonNull(digerTest);
    return (t) -> test(t) && digerTest.test(t);
  }
}

Output:

4 6 8

  1. Metot Referansları

Metot referansları, bizi ‘::’ operatörünü ile tanıştırdı. Bu operatör bize metotlara sadece isimleriyle ulaşmamızı sağlar. Buradaki temel mantık, eğer referans edilecek metot, aldığı değerler ve döndüğü değer noktalarında eşleşiyorsa, ‘::’ operatörü kullanılabiliyor. Hangi metotlar referans olarak kullanılabilir dersek;

  • Statik bir metot kullanılabilir,
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

public class MethodReferenceEx1 {

  static List<String> names = Arrays.asList("Hasan", "Cihan", "Dursun");

  public static void main(String[] args){
    // static metod kullanildi
        names.forEach(StringFunc::upper);
    }

}

class StringFunc {
  
  public static void upper(String s) {
    s = s.toUpperCase(Locale.forLanguageTag("tr"));
    System.out.println(s);
  }
}

Output:

HASAN

CİHAN

DURSUN

  • Nesnenin metotları kullanılabilir,
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

public class MethodReferenceEx2 {
  static List<String> names = Arrays.asList("Ümmühan", "Gamze", "Gülzada");

  public static void main(String[] args){
    StringFunct func = new StringFunct();
    // static olmayan metod kullanildi
        	names.forEach(func::lower);
    }
}

class StringFunct {
  public void lower(String s) {
    s = s.toLowerCase(Locale.forLanguageTag("tr"));
    System.out.println(s);
  }
}

Output:

ümmühan

gamze

gülzada

  • Yapıcılar (“Construcor”) new anahtarı sayesinde referans olarak kullanılabilir,
public class MethodReferenceEx3 {
  public static void main(String[] args) {
    Sumable sumable = Sum::new;
    sumable.getSum(-1);
    sumable.getSum(6);
  }
}
//constructor i kullanabilmek icin ayarlanmis fonsiyonel interface
interface Sumable {
  Sum getSum(Integer val);
}
//constructor i kullanilacak sinif
class Sum {
  public Sum(Integer value) {
    if (value > 0)
      System.out.println("Sumable Value: " + value);
    else {
      System.out.println("Not Sumable Value: " + value);
    }
  }
}

Output:

Not Sumable Value: -1

Sumable Value: 6

  1. Optional Sınıfı

“Optional” sınıfı genel olarak yazılımcıların çok muzdarip olduğu “NullPointerException” hatasının kontrolü için yazılan “null” kontrolü metotlarına alternatif olarak sunulmuştur. “Guava” içerisindeki Optional sınıfı ile benzerlik göstermektedir.

import java.util.Optional;

public class OptionalEx {

  public static void main(String args[]) {
    Integer val1 = null;
    Integer val2 = new Integer(10);
    //deger null olabilir
    Optional<Integer> a = Optional.ofNullable(val1);
    //deger null olursa hata firlat
    Optional<Integer> b = Optional.of(val2);
    //kontrol sonuclari yazdir
    System.out.println("a != null : " + a.isPresent());
    System.out.println("b != null : " + b.isPresent());
    //deger null ise -1 ata
    Integer value1 = a.orElse(new Integer(-1));
    //optionaldaki degeri al
    Integer value2 = b.get();

    System.out.println("sum = " + (value1 + value2));
  }
}

Output:

Not Sumable Value: -1

Sumable Value: 6

  1. Nashorn JavaScript

“Nashorn”, mevcut “Rhino” javascript motoru yerine kullanılmak üzere çok daha gelişmiş bir javascript motoru olarak tanıtıldı. Nashorn, kodu doğrudan bellekte derlediği ve bayt kodunu JVM’ye ilettiği için 2 ila 10 kat daha iyi performans sağlar.

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Nashorn {
  public static void main(String args[]) {
    ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
    ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");

    String name = "Murat";
    Integer result = null;

    try {
      nashorn.eval("print('" + name + "')");
      result = (Integer) nashorn.eval("4 * 31");

      System.out.println(result.toString());
    } catch (ScriptException e) {
      System.err.println("Error executing script: " + e.getMessage());
    }
  }
}

Output:

Murat

124

  1. Yeni Date/Time API

Java 8’den önce kullanılan “Date” ve “Time” sınıfına alternatif olarak sunulmuş API’lerdir. “Date” ve “Time” sınıfına alternatif aranmasının temel sebebinin,bu sınıfların daha önce “thread safe” olmamaları idi diyebilirim. Saat dilimi yönetmek ve bazı tarih işlemlerini gerçekleştirmek pek kolay yapılamıyordu.

Java 8 ile gelen “Date” ve “Time” API sınıfları şöyledir;

LocalDate:

LocalDate setDate = LocalDate.of(2017, Month.MARCH, 6);
LocalDate nowDate = LocalDate.now();
System.out.println("setDate: " + setDate);
System.out.println("nowDate: " + nowDate);

Output:

setDate: 2017-03-06

nowDate: 2019-04-07

LocalTime:

LocalTime sampleTime = LocalTime.of(22, 15);
LocalTime nowTime = LocalTime.now();
System.out.println("sampleTime: " + sampleTime);
System.out.println("nowTime: " + nowTime);

Output:

sampleTime: 22:15

nowTime: 14:24:43.514

LocalDateTime:

LocalDateTime currentTime = LocalDateTime.now();
System.out.println("Current DateTime: " + currentTime);

Output:

Current DateTime: 2019-05-06T14:42:24.388

ZonedDateTime:

ZonedDateTime sampleZoneDateTime = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Karachi]");
System.out.println("sampleZoneDateTime: " + sampleZoneDateTime);

ZonedDateTime nowZoneDateTime = ZonedDateTime.now();
System.out.println("nowZoneDateTime: " + nowZoneDateTime);

ZoneId id = ZoneId.of("Europe/Paris");
System.out.println("ZoneId: " + id);

ZoneId currentZone = ZoneId.systemDefault();
System.out.println("CurrentZone: " + currentZone);

Output:

sampleZoneDateTime: 2007-12-03T10:15:30+05:00[Asia/Karachi]

nowZoneDateTime: 2019-04-07T14:28:24.631+03:00[Asia/Istanbul]

ZoneId: Europe/Paris

CurrentZone: Asia/Istanbul

Period:

//suan
LocalDate date1 = LocalDate.now();
//bir ay ileri al ve yaz
LocalDate date2 = date1.plus(1, ChronoUnit.MONTHS);
System.out.println("Next month: " + date2);
//periyodu bul
Period period = Period.between(date2, date1);
System.out.println("Period: " + period);

Output:

Next month: 2019-05-07

Period: P-1M

Duration:

//suan
LocalTime time1 = LocalTime.now();
//2 saat ileri
LocalTime time2 = time1.plus(2, ChronoUnit.HOURS);
Duration duration = Duration.between(time1, time2);
//sureyi bul
System.out.println("Duration: " + duration);

Output:

Duration: PT2H

Clock:

Clock clock = Clock.systemDefaultZone();

Clock clock1 = Clock.offset(clock, Duration.ofHours(5));
System.out.println("5 saat ileri " + clock1.instant());

Clock clock2 = Clock.offset(clock, Duration.ZERO);
System.out.println("suan " + clock2.instant());

Clock clock3 = Clock.offset(clock, Duration.ofHours(-10));
System.out.println("10 saat geri " + clock3.instant());

Output:

5 saat ileri2019-04-07T16:43:04.865Z

suan 2019-04-07T11:43:04.876Z

10 saat geri 2019-04-07T01:43:04.876Z

TemporalAdjusters:

LocalDate date1 = LocalDate.now();
System.out.println("suan: " + date1);

LocalDate nextTuesday = date1.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println("ilk Sali : " + nextTuesday);
    
LocalDate firstInYear = LocalDate.of(date1.getYear(), date1.getMonth(), 1);
LocalDate secondSaturday = firstInYear.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
System.out.println("ikinci Cumartesi : " + secondSaturday);

Output:

suan: 2019-04-07

ilk Sali : 2019-04-09

ikinci Cumartesi : 2019-04-13

  1. Stream API

Stream API’yi genel olarak, toplu işlemler için kullanılan, bir kaynaktan gelen nesne dizisi olarak tanımlayabiliriz.

Stream API’sinin genel özellikleri olarak şunları diyebiliriz;

  • Yapılan işlem üzerine kaynağı alır ve işlemi yapar. Kaynağı saklamaz.
  • Kaynak olarak diziler, koleksiyonlar ve I/O kaynaklarını destekler.
  • Stream API “foreach”, “limit”, “find”, “filter”, “match” vb. listenin tümünde işlem yapılması gereken işlemleri destekler.
  • Stream API’de çoğu işlem Stream’in kendisini döndürür. Böylece sonuçlar üzerinde tekrar işlem yapılıp aktarılabilir hale gelir. Bu işlemlere ara işlemler de denir. İşlevleri kaynağı almak, işlemek ve sonucu döndürmektir. “collect()” yöntemi, Stream’in çıktısını belirlemek için en sona yazılan işlemdir. Genelde Collectors ile beraber kullanılır.
  • Stream API döngüleri, sağlanan kaynak öğelerin iteratörleri üzerinden dahili olarak gerçekleştirir.

Ardışık (“stream()”) ve paralel (“parallelStream()”) olmak üzere 2 farklı şekilde Stream çevrimi vardır.

Stream API de çok kullanılan fonksiyonlara örnek verecek olursak;

foreach:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class StreamApiEx1 {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.addAll(Arrays.asList("AaD", "BbCd", "intELLIJ", "QweRTy", "EclipSE"));
    //dizideki stringleri kucult
    list.stream().forEach(item -> System.out.print(item.toLowerCase() + " "));
  }
}

Output:

aad bbcd intellij qwerty eclipse

map:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApiEx2 {
  public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.addAll(Arrays.asList(-1, 1, 2, 4, 6, 8));
    //dizideki degerlerin kupunu al ve yaz
    list = list.stream().map(item -> item * item * item).collect(Collectors.toList());
    list.forEach(item -> System.out.print(item + " "));
  }
}

Output:

-1 1 8 64 216 512

filter:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApiEx3 {
  public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    //cift sayilari bul
    list = list.stream().filter(item -> item % 2 == 0).collect(Collectors.toList());
    list.forEach(s -> System.out.print(s + " "));
  }
}

Output:

0 2 4 6 8 10

limit:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApiEx4 {
  public static void main(String[] args) {
    List<Integer> list = new ArrayList<>();
    list.addAll(Arrays.asList(9, 1, 5, 3, 4, 2, 6, 7, 8, 0, 10));
    // ilk 5 eleman icindeki tek sayilari bul
    list = list.stream().limit(5).filter(item -> item % 2 == 1).collect(Collectors.toList());
    list.forEach(System.out::print);
  }
} 

Output:

9153

sorted:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamApiEx5 {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.addAll(Arrays.asList("za-", "az-", "dz+", "yp+"));
    //sirala
    list = list.stream().sorted().collect(Collectors.toList());
    list.forEach(System.out::print);
  }
}

Output:

az-dz+yp+za-

match:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class StreamApiEx6 {
  public static void main(String[] args) {
    Predicate<String> p1 = s -> s.startsWith("S");
    Predicate<String> p2 = s -> s.length() < 4;
    Predicate<String> p3 = s -> s.endsWith("z");
    List<String> list = Arrays.asList("Logan", "Magneto", "Rogue", "Storm");
    // herhangi biri S ile baslıyor mu?
    boolean b3 = list.stream().anyMatch(p1);
    System.out.println(b3);
    // hepsinin uzunlugu 4 ten kucuk mu?
    boolean b4 = list.stream().allMatch(p2);
    System.out.println(b4);
    // hicbiride z ile bitmez dogru mu?
    boolean b5 = list.stream().noneMatch(p3);
    System.out.println(b5);
  }
}

Output:

true

false

true

**** Not: Predicate java.util.function paketi altındaki bir fonksiyonel Interface’dir ve tek soyut metodu testtir.

find:

import java.util.Arrays;
import java.util.List;

public class StreamApiEx7 {
  public static void main(String[] args) {
    List<String> list = Arrays.asList("Rogue", "Magneto", "Logan", "Storme");
    //herhangi e ile biten deger
    String f1 = list.stream().filter(s -> s.endsWith("e")).findAny().get();
    System.out.println(f1);
    // ilk a iceren deger
    String f2 = list.stream().filter(s -> s.contains("a")).findFirst().get();
    System.out.println(f2);
  }
}

Output:

Rogue

Magneto

  1. Java Ondalık Gösterimi ve Exception Handling

Java 8’de “try” – “catch” – “finally” kullanımında yeni bir düzenleme yapıldı. Finally’de socket veya scanner gibi kapatma işlemi gerektiren işlemlerde Java 8 bunu kendi otomatik olarak halledilebiliyor.

Örnek:

/*Java 7*/
Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

/*Java 8*/
try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

Java 8’de büyük rakam tanımlamalarında gösterim açısından kolaylık olması için ‘_’ işareti ile ayrım yapabiliyoruz. Bu işaretin sayının değeri ile ilgili bir müdahalesi olmuyor sadece daha anlaşılır gösterimi sağlıyor. Örnek:

Integer sayi = 3_536_456;
Double değer = 3.149_58_98_00;

Evet arkadaşlar maalesef yazımızın sonuna geldik.☹ Sizin için elimden geldiğince her konuya değinmeye çalıştım. Eğer Java 8’e henüz geçmediyseniz, mutlaka geçmenizi öneririm. Geçtiyseniz, çevrenizi de yönlendireceğinize eminim. 😊

Yazımı, naçizane tavsiyelerimi paylaşarak sonlandırmak isterim.

  • Öncelike java.util.function paketi altındaki fonksiyonel interface’lere bakmanızı tavsiye ederim.
  • “new Date()”i yavaş yavaş elinizden bırakın ve “LocalDatetime” veya “LocalDate” sınıflarına teslim olun. 😊
  • Java’dan asla vazgeçmeyin.

İyi çalışmalar arkadaşlar..

Hasan Dayan

Yazılım Geliştirme Uzmanı

Github linki:

https://github.com/egem-github/egemsoftBlog/tree/master/Java8Features/src/com/egemsoft

Kaynaklar:

https://en.wikipedia.org/wiki/Java_version_history

https://github.com/AlicanAkkus/java8

https://www.tutorialspoint.com/java8/java8_overview.htm

https://www.javatpoint.com/java-8-method-reference

http://devnot.com/2017/java-8-hakkinda-bilmeniz-gerekenler/

https://github.com/sinanselimoglu/streamsamples
https://medium.com/@sinanselimoglu/java-8-stream-yap%C4%B1s%C4%B1na-nazik-bir-giri%C5%9F-f2a5977215c6