Lambda ifadelerini uygulayabilmek için getirilen arayüzler ile javanın functional programming yetenekleri geliştirilmeye başlandı.
Herhangi bir sınıfa ait olmadan iş yapabilen pratik fonksiyonlar olan Lambda ifadeler ile birlikte Java, funtional programming dünyasına da girmiş oldu.
Metodları, nesneler veya primitive değerlermiş gibi kullanabilmemizi ve bunları başka bir metoda parametre olarak gönderebilmemizi sağlıyor. :: söz dizimi aracılığıyla static methodlar class name ile, static olmayan methodlar ise instance objeleri ile referans verilebilmekte.
Collection’lar üzerinde filter, forEach, map, count, min/max gibi sık kullanılan çeşitli işlemleri yapmayı çok daha kolay hale getiriyor.
File, connection, network vb. açık kaynakları kapatmaya gerek duymadan, AutoClosable interface ile dene-kullan-kapat şeklinde otomatik olarak kapanacak bir kullanım imkan sağlar.
Nesnelerin kullanılmadan önce yapılan NullCheck işlemlerini daha okunabilir ve kontrol edilebilir olmasını sağlayan Optional utility sınıfını sağlıyor.
Tarih ve saat verilerinin daha doğal, net ve anlaşılması kolay şekilde elde edilmesini sağlıyor.
Thread nesneleri oluşturmak ve yönetmek zorunda kalma eşzamanlı concurrent/multitasking işlemlerini daha anlaşılır ve kolay kullanılabilir hale getiriyor.
Java dosyasınını hızlıca derlemeden çalıştırma özelliği gelmiştir.
java MerhabaJava.java
Java 10 ile gelen var ifadesinin kapsamı genişletilerek lambda expressions ile kullanma imkanı gelmiştir.
public class App {
public static void main(String[] args) {
IntStream.of(1, 2, 3, 5, 6, 7)
.filter((var i) -> i % 3 == 0)
.forEach(System.out::println);
}
}
Ayrıca final anahtar kelimesi ile birlikte kullanılabilmektedir.
Sınıf içerisinde yer alan alt sınıfların derlenmesinde değişiklik yapılarak nest olarak adlandırılan bir yapı kurulmuştur.
public class App {
public static void main(String[] args) {
Alt.yazdir();
}
static class Alt {
private static void yazdir() {
System.out.println("Yusuf SEZER");
}
}
}
Yukarıdaki kodlar derlenip javap aracı ile incelendiğinde NestMembers, NestHost alanları görünecektir.
Java 9 ile birlikte gelen HTTP/2 Client Java 11 ile standart olarak java.net.http paketinde gelmektedir.
public class App {
public static void main(String[] args)
throws IOException, InterruptedException {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest httpRequest = HttpRequest
.newBuilder()
.uri(URI.create("https://www.yusufsezer.com/"))
.GET()
.build();
HttpResponse response = httpClient
.send(httpRequest, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
Standart paketi kullanmak için java.net.http; modülünün module-info.java dosyasına eklenmesi gerekir.
Java 9 ile deprecated olarak işaretlenen ve Java SE paketi içerisinde yer alan Java EE ile CORBA modülleri kaldırılmıştır.
Kaldırılan paketler aşağıda yer almaktadır.
java.xml.ws java.xml.bind java.activation java.xml.ws.annotation java.corba java.transaction java.se.ee jdk.xml.ws jdk.xml.bind Java 11 ile birlikte XML işlemleri için JAXB paketinin JAR veya Maven olarak bağımlılık olarak eklenmesi gerekmektedir.
String işlemlerini kolaylaştırmak için yeni metotlar eklenmiştir.
strip, stripLeading, stripTrailing – trim metodundan farkı Unicode desteğinin olmasıdır.
public class App {
public static void main(String[] args) {
var myName = " Yusuf Sefa SEZER ";
System.out.println(myName.strip().length());
var myName2 = " Yusuf Sefa SEZER ";
System.out.println(myName2.stripLeading().length());
System.out.println(myName2.stripTrailing().length());
}
}
isBlank – String ifadesinin boşluk, Unicode boşluk değerine göre kontrol eder.
public class App {
public static void main(String[] args) {
var myName = " \u205F ";
System.out.println(myName.isBlank()); // içeriğe bakar
System.out.println(myName.isEmpty()); // uzunluğa bakar
}
}
lines – String ifadesindeki satır sonlandırıcına göre Stream API değeri verir.
public class App {
public static void main(String[] args) {
var myName = "Yusuf\nSefa\nSEZER\r\n\ry";
System.out.println(myName.lines().count());
}
}
repeat – String ifadesini parametre değeri kadar tekrar eder.
public class App {
public static void main(String[] args) {
var myName = "Yusuf Sefa SEZER\n";
System.out.println(myName.repeat(3));
}
}
Koleksiyonları dizilere çevirmek için toArray(IntFunction) metodu eklenmiştir.
public class App {
public static void main(String[] args) {
String[] myNames = List
.of("Yusuf", "Sefa", "SEZER")
.toArray(String[]::new);
System.out.println(myNames.length);
}
}
Dosya okuma ve yazma işlemlerini hızlıca yapmak için readString, writeString metotları eklenmiştir.
public class App {
public static void main(String[] args) throws IOException {
// writeString
Path tempFile = Files.writeString(
Files.createTempFile("test", ".txt"), "Yusuf Sefa SEZER");
System.out.println(tempFile);
// readString
String fileContent = Files.readString(tempFile);
System.out.println(fileContent);
}
}
Dosya/Dizin yolunu ifade etmek için kullanılan Path arayüzüne of metotları eklenmiştir.
public class App {
public static void main(String[] args) throws IOException {
// of(string)
Path pathString = Path.of("C:", "temp", "test.txt");
System.out.println(pathString);
System.out.println(Files.exists(pathString));
// of(uri)
URI uri = URI.create("file:///C:/temp/test.txt");
System.out.println(uri);
Path pathURI = Path.of(uri);
System.out.println(pathURI);
System.out.println(Files.exists(pathURI));
}
}
Java ile Input/Output işlemlerinde kullanılan java.io paketine yeni nullInputStream, nullOutputStream, nullReader, nullWriter, readNBytes metotları eklenmiştir.
public class App {
public static void main(String[] args) throws IOException {
// nullReader
Reader nullReader = Reader.nullReader();
System.out.println(nullReader.read());
// nullWriter
Writer nullWriter = Writer.nullWriter();
nullWriter.write("Yusuf SEZER");
}
}
public class App {
public static void main(String[] args) throws IOException {
var stream = new ByteArrayInputStream("Yusuf Sefa SEZER".getBytes());
System.out.println(new String(stream.readNBytes(5)));
stream.close();
}
}
FileReader ve FilterWriter sınıflarına yeni kurucu metotlar eklenmiştir.
Nest-based yapısına göre derlenen sınıflar ile ilgili detaylı bilgi almak için Class sınıfına getNestHost, getNestMembers, isNestmateOf metotları eklenmiştir.
public class App {
public static void main(String[] args) {
Class<?> clazz = App.class;
System.out.println(clazz.getNestHost().getSimpleName());
Arrays
.stream(clazz.getNestMembers())
.map(Class::getSimpleName)
.forEach(System.out::println);
}
static class Alt {
private static void yazdir() {
System.out.println("Yusuf SEZER");
}
}
}
Java JIT derleyicisine otomatik vektör özelliği geliştirmesidir. Bu özellik sayesinde Java içerisindeki skalar veya tek işlemin otomatik olarak vektöre dönüştürülmesi ve vektörel işlemlerde elde edilen(SIMD ile) performansın elde edilmesi amaçlanmaktadır. Özellik Java derleyicisinde(JIT) yapılmıştır.
JDK kodlarına C++14 dili desteği eklendi. Özellik sayesinde JDK C++14 ile birlikte gelen özelliklerin kullanımı sağlanmış oldu.
C++ 14 ile gelen özelliklere C++ 14 üzerinden ulaşabilirsiniz.
Java derleyici kaynak kodları Mercurial sürm kontrol sisteminin fazla kaynak kullanımı(dosya boyutu), Mercurial araçlarının yetersiz olması gibi nedenlerden dolayı Git sürüm sistemine geçiş yapılmıştır.
JEP 357 ile Git sürüm sistemine geçiş ile birlikte Git tabanlı Github kullanımına geçiş yapılmıştır.
ZGC çöp toplayıcısında değişiklik yapılarak ZGC çöp toplayıcısının büyük boyutlu verilerle iyi ve kısa sürede çalışmasını sağlar.
İşlemler arasında haberleşme için TCP/IP yerine Unix temelli haberleşme yöntemine(AF_UNIX) geçilmiştir. Özellik Unix temelli MacOS, Linux temelli işletim sistemleri ile birlikte Windows 10 tarafından da desteklenmeye başlanmasıyla kullanılabilir hale gelmiştir.
Bulut tabanlı işletim sistemlerinde sıklıkla kullanılan Alpine işletim sistemi desteği eklenmiştir. Böylece bir çok Java kütüphanesinin Alpine ile birlikte çalışmasını sağlar.
Java uygulamalarına ait kullanılmayan verilerin(metadata) hızlı bir şekilde işletim sistemine iade edilmesini sağlanmıştır.
AArch64 veya ARM64 işlemci desteği eklenmiştir.
C veya C++ kodlarına doğrudan erişim imkanı getirilmiştir. Bu sayede karmaşık JNI işlemleri daha basit hale gelmiştir.
MethodHandle strlen = CLinker.getInstance().downcallHandle(
LibraryLookup.ofDefault().lookup("strlen").get(),
MethodType.methodType(long.class, MemoryAddress.class),
FunctionDescriptor.of(CLinker.C_LONG_LONG, CLinker.C_POINTER)
);
Yukarıdaki kod parçası C dilinde yer alan strlen metoduna erişmektedir.
LibraryLookup ile erişilecek metot belirlenmiştir.
MethodType ile metodun Java’ya döndürülme biçimi belirtilmiştir.
FunctionDescriptor ile ise C dilindeki karşılığı belirtilmiştir.
NOT: İşletim sistemine göre C dili tanımı(FunctionDescriptor kullanımı) farklılık gösterebilir.
Aşağıda örnek kullanım yer almaktadır.
MethodHandle strlen = CLinker.getInstance().downcallHandle(
LibraryLookup.ofDefault().lookup("strlen").get(),
MethodType.methodType(long.class, MemoryAddress.class),
FunctionDescriptor.of(CLinker.C_LONG_LONG, CLinker.C_POINTER)
);
String str = "Yusuf SEZER";
MemorySegment memorySegment = CLinker.toCString(str); // Java String adres bilgisi alınıyor
long result = (long) strlen.invokeExact(memorySegment.address()); // strlen metodu String adres bilgisi ile çalıştırılıyor
System.out.println(result);
memorySegment.close();
CLinker#toCString metodu yardımıyla str değişkeninin adres bilgisi alınarak MethodHandle#invokeExact metoduna parametre olarak gönderilmektedir.
MethodHandle#invokeExact adres bilgisini parametre olarak alarak C komutlarını çalıştırır.
Sonuç istenilen türe çevrilerek kullanılır.
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import jdk.incubator.foreign.CLinker;
import jdk.incubator.foreign.FunctionDescriptor;
import jdk.incubator.foreign.LibraryLookup;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemorySegment;
public class App {
public static void main(String[] args) throws Throwable {
MethodHandle strlen = CLinker.getInstance().downcallHandle(
LibraryLookup.ofDefault().lookup("strlen").get(),
MethodType.methodType(long.class, MemoryAddress.class),
FunctionDescriptor.of(CLinker.C_LONG_LONG, CLinker.C_POINTER)
);
String str = "Yusuf SEZER";
MemorySegment memorySegment = CLinker.toCString(str);
long result = (long) strlen.invokeExact(memorySegment.address());
System.out.println("Uzunluk: " + result);
memorySegment.close();
}
}
Özelliğin kullanımı için jdk.incubator.foreign modülünün proje eklenmesi gerekmektedir.
Modül eklenerek komutlar derlenir.
javac --add-modules jdk.incubator.foreign App.java
Derlendikten sonra çalıştırılır.
java --add-modules jdk.incubator.foreign -Dforeign.restricted=permit App
Değer taşıyan veya @jdk.internal.ValueBased ifadesi ile belirtilen sınıfların senkronizasyonu sırasında uyarı verecektir.
Aşağıdaki komut derlenme aşamasında uyarı verecektir.
Double d = 20.0;
synchronized (d) {}
Java 9 ile birlikte değer taşıyan, sarmalayıcı(wrapper) sınıfların kullanımdan kaldırılan kurucu metotları @Deprecated(since=”9″, forRemoval = true) olarak işaretlenmiştir.
Java 14 sürümüyle birlikte gelen paketleme özelliğinin devamıdır.
Özellik sayesinde ek kütüphaneye ihtiyaç duymadan işletim sistemine göre(deb, rpm, pkg, dmg, msi, exe) kurulum paketi oluşturmayı sağlar.
Swing örneğinde yer alan aşağıdaki kodları kullanarak derleme paketleme işlemini yapalım.
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class App {
public static void main(String[] args) {
JFrame pencere = new JFrame();
pencere.setTitle("Java Swing");
pencere.setSize(300, 200);
JLabel label = new JLabel("www.yusufsezer.com");
label.setBounds(50, 50, 150, 20);
pencere.add(label);
JButton button = new JButton("Tıkla");
button.setBounds(50, 70, 60, 20);
pencere.add(button);
pencere.setLayout(null);
pencere.setLocationRelativeTo(null);
pencere.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pencere.setVisible(true);
}
}
Komutları derleyelim.
javac App.java
Derlenen komutları paketleyelim.
jar cvf app.jar App.class
Paketleme aracını kullanarak işletim sistemine göre kurulum paketi haline getirelim.
jpackage --input . --name App --main-jar app.jar --main-class App
Kurulum dosyası kullanılarak işletim sistemine göre kurulum yapılır.
Kurulum dosyası ayarları ile ilgili detaylı bilgi için araç kullanımına bakmak faydalı olacaktır.
jpackage --help
Java 14 ve 15 sürümlerinde geliştirilmesi devam eden farklı bellek alanına erişim özelliğinin geliştirilmesinin devamıdır.
Java 14 ve 15 sürmlerinde gelen pattern matching özelliği standart hale gelerek Java’ya eklenmiştir.
Java 14 ve 15 sürümlerinde gelen records özelliği standart hale gelerek Java’ya eklenmiştir.
Java 9 ile birlikte JDK içerisinde yer alan sınıflara erişim engellenmiş ancak kullanan sınıfların işleyişi bozulmaması için –illegal-access değeri varsayılan olarak permit değeri ile izin verilmiştir.
Java 16 ile birlikte varsayılan olarak deny olarak değiştirilerek JDK sınıflarının doğrudan kullanımı engellenmiştir.
Java 15 sürümü ile birlikte gelen Sealed Classes özelliğinin devamıdır.