Java 11 Features
Java 11 (September 2018) एक LTS (Long-Term Support) release है — मतलब इसे companies production में भरोसे के साथ use करती हैं, क्योंकि Oracle इसे लंबे समय तक support करता है (Java 8 के बाद सबसे popular LTS version)।
इसमें कई छोटी लेकिन useful additions आए: नए String methods (isBlank, strip, lines, repeat), Files.readString()/writeString() से file I/O आसान हुआ, एक नया standard HTTP Client API, और single-file Java programs को बिना compile किए directly run करने की facility।
Interview में Java 11 के features अक्सर "Java 8 के बाद क्या नया आया" जैसी follow-up questions में पूछे जाते हैं — especially var in lambdas, नए String methods, और HTTP Client API।
// Naye String methods
System.out.println(" ".isBlank()); // true
System.out.println("Hi".repeat(3)); // HiHiHi
// Files.readString() — ek line mein file padho
String content = Files.readString(Paths.get("notes.txt"));
// var in lambda parameters
BiFunction<Integer, Integer, Integer> add = (var a, var b) -> a + b;- Java 11 = LTS release (Sept 2018)
- var lambda parameters में use हो सकता है
- isBlank/strip/lines/repeat = नए String methods
- java.net.http = नया standard HTTP Client
- Single-file .java programs बिना compile के run हो सकते हैं
Java 10 में "var" आया था local variables के लिए (var x = 10;), लेकिन lambda parameters में use नहीं कर सकते थे। Java 11 ने यह gap fill किया — अब lambda के parameters में भी var लिख सकते हो, जैसे (var a, var b) -> a + b।
इसका फ़ायदा तब है जब तुम्हें parameter पर annotation लगाना हो (जैसे @NotNull var x) — बिना var के, lambda parameters पर annotation लगाना syntactically possible नहीं था। सिर्फ नाम लिखने से (a, b) -> ... और var लिखने से (var a, var b) -> ... same ही compile होता है — कोई performance फर्क नहीं, सिर्फ annotation support के लिए यह feature आया।
Rule: या तो सारे parameters में var लिखो, या किसी में नहीं — mix नहीं कर सकते, जैसे (var a, b) -> ... गलत है (compile error)।
Interview में पूछा जा सकता है कि var एक "dynamic typing" feature है क्या — नहीं, Java अभी भी statically typed है, var सिर्फ compiler को type infer करने देता है compile-time पर ही, runtime पर कुछ change नहीं होता।
- बिना var: (a, b) -> a + b — छोटा, ज़्यादातर cases के लिए काफी
- var के साथ: (var a, var b) -> a + b — annotation लगाने के काम आता है
- Mix करना गलत: (var a, b) -> ... compile error देगा
// Normal lambda
BiFunction<Integer, Integer, Integer> add1 = (a, b) -> a + b;
// var ke saath (Java 11+)
BiFunction<Integer, Integer, Integer> add2 = (var a, var b) -> a + b;
// Annotation ke saath — sirf var se hi possible
// (var a, @Deprecated var b) -> a + b;isBlank() check करता है String खाली है या सिर्फ whitespace है — isEmpty() सिर्फ length 0 check करता है, लेकिन " " (सिर्फ spaces) के लिए isEmpty() false देगा, जबकि isBlank() true देगा। यह एक common bug source था Java 11 से पहले।
strip()/stripLeading()/stripTrailing() trim() जैसे ही हैं, लेकिन Unicode-aware हैं — trim() सिर्फ ASCII whitespace (space से कम या बराबर character code) समझता है, जबकि strip() Unicode whitespace भी handle करता है (जैसे non-breaking spaces)। Modern code में trim() की जगह strip() prefer किया जाता है।
lines() String को line-by-line एक Stream<String> में तोड़ता है (multi-line text के लिए useful, बिना manually split("\n") किए)। repeat(n) एक String को n बार repeat करके एक नया String बनाता है।
Real-world use-case: form input validation में isBlank() से तुरंत check कर सकते हो कि user ने कुछ meaningful type किया या सिर्फ spaces डाल दिए — पहले यह manual trim().isEmpty() से करना पड़ता था।
- isBlank() — सिर्फ whitespace है क्या, check करता है
- strip()/stripLeading()/stripTrailing() — Unicode-aware trim
- lines() — String को line-by-line Stream में तोड़ता है
- repeat(n) — String को n बार repeat करता है
String s = " ";
System.out.println(s.isEmpty()); // false (length > 0 hai)
System.out.println(s.isBlank()); // true (sirf whitespace hai)
String text = "Line1\nLine2\nLine3";
text.lines().forEach(System.out::println); // 3 lines print
System.out.println("Ab".repeat(3)); // "AbAbAb"Java 11 से पहले पूरी file एक String में पढ़ने के लिए Files.readAllBytes() call करके manually new String(bytes, charset) करना पड़ता था, या Files.lines() से stream collect करना पड़ता था — थोड़ा boilerplate। Files.readString(path) यह सब एक line में कर देता है।
Files.writeString(path, content) similarly एक String को सीधा file में लिख देता है, बिना manually bytes convert किए। दोनों methods UTF-8 default use करते हैं (overload में custom Charset भी दे सकते हो)।
छोटे config files, templates, या test fixtures पढ़ने/लिखने के लिए ये methods perfect हैं — बड़े data files या log processing के लिए NIO के stream-based APIs (जैसे Files.lines()) ज़्यादा suitable रहते हैं।
// Purana tareeka (Java 11 se pehle):
byte[] bytes = Files.readAllBytes(Paths.get("notes.txt"));
String content = new String(bytes, StandardCharsets.UTF_8);
// Java 11+:
String content2 = Files.readString(Paths.get("notes.txt"));
Files.writeString(Paths.get("output.txt"), "Hello Java 11!");Java 9 में incubator (experimental) module के रूप में आया था, Java 11 में यह standard java.net.http package बन गया — पुराने HttpURLConnection (जो Java 1.1 से था, clunky और limited) का modern replacement।
नया client HTTP/2 support करता है (default), synchronous (send()) और asynchronous (sendAsync(), जो CompletableFuture return करता है) दोनों तरीके देता है, और fluent Builder pattern use करता है request बनाने के लिए — third-party libraries (जैसे Apache HttpClient या OkHttp) की ज़रूरत कम हो जाती है simple use-cases के लिए।
Microservices architecture में जहाँ एक service दूसरी service को REST call करती है, यह built-in client third-party dependency add किए बिना काम चला देता है — छोटे projects के लिए especially useful, जहाँ पूरी library add करना overkill लगता है।
- HTTP/2 support by default
- send() — synchronous, जवाब आने तक wait करता है
- sendAsync() — asynchronous, CompletableFuture return करता है
- Fluent Builder pattern से request बनाना
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());Normally Java में पहले javac से compile करके .class file बनानी पड़ती थी, फिर java से run करते थे। Java 11 से एक single .java file को directly java command से run कर सकते हो, बिना explicit compile step के — java Hello.java। JVM खुद background में compile करके memory में ही run कर देता है (कोई .class file disk पर नहीं बनती)।
यह feature सिर्फ single-file programs के लिए है (multi-file projects के लिए नहीं) — quick scripts, prototyping, या सीखने के लिए बहुत useful है, क्योंकि दो commands (javac + java) की जगह एक ही command चलती है।
यह feature especially coding interviews और competitive programming के लिए handy है — किसी भी online judge या quick script के लिए बिना project setup किए सीधा code लिख कर चला सकते हो।
// Hello.java
public class Hello {
public static void main(String[] args) {
System.out.println("Direct run, no compile step!");
}
}
// Terminal mein:
// $ java Hello.java
// Direct run, no compile step!Collection.toArray(IntFunction<T[]> generator) एक नया overload है — पहले toArray(new String[0]) जैसा लिखना पड़ता था, अब toArray(String[]::new) जैसा cleaner method reference use कर सकते हो, जिसमें array size खुद collection decide कर लेता है।
Optional.isEmpty() add हुआ — पहले सिर्फ isPresent() था, और "अगर value नहीं है" check करने के लिए !optional.isPresent() लिखना पड़ता था। isEmpty() ज़्यादा readable है (negation avoid होता है)।
toArray(String[]::new) पुराने toArray(new String[0]) से better है क्योंकि JIT compiler इस pattern को intrinsify कर सकता है, जिससे बड़े collections पर थोड़ा better performance भी मिलता है — एक छोटी सी syntax change का real benefit।
List<String> names = List.of("Riya", "Aman");
String[] arr = names.toArray(String[]::new); // naya, cleaner tareeka
Optional<String> opt = Optional.empty();
if (opt.isEmpty()) {
System.out.println("Koi value nahi hai");
}कभी-कभी एक existing Predicate (जैसे String::isBlank) को negate करना होता है — method reference को directly negate नहीं कर सकते (String::isBlank का negate() call नहीं हो सकता सीधे), इसलिए पहले lambda लिखना पड़ता था: s -> !s.isBlank()।
Predicate.not(predicate) एक static helper है जो इसको clean बना देता है — Predicate.not(String::isBlank) सीधा method reference को negate कर देता है, बिना extra lambda लिखे।
Static import (import static java.util.function.Predicate.not;) के साथ और भी clean हो जाता है — सिर्फ not(String::isBlank) लिख सकते हो, पूरा "Predicate." prefix भी हटा सकते हो।
List<String> words = List.of("Java", "", " ", "Code");
// Java 11 se pehle:
words.stream().filter(s -> !s.isBlank()).forEach(System.out::println);
// Java 11+, Predicate.not() ke saath:
words.stream().filter(Predicate.not(String::isBlank)).forEach(System.out::println);Epsilon GC (JEP 318) एक "no-op" (कुछ नहीं करने वाला) garbage collector है — यह memory allocate तो करता है, लेकिन कभी collect नहीं करता। सुनने में अजीब लगता है, लेकिन performance testing (GC का overhead measure करना) या बहुत short-lived programs (जो खत्म होने से पहले memory खत्म ही नहीं करेंगे) के लिए useful है।
ZGC (JEP 333, इस version में experimental) एक scalable, low-latency garbage collector है जो GB से लेकर multi-TB heaps तक handle कर सकता है, pause times को 10ms से कम रखते हुए — बहुत बड़ी applications (जहाँ थोड़ा सा भी pause noticeable हो) के लिए design किया गया था। Interview में इन दोनों का नाम और एक-line purpose याद रखना काफी होता है — deep internals शायद ही पूछे जाते हैं।
Interview में अगर पूछा जाए "production में Epsilon GC कब use करोगे" — जवाब है: शायद कभी नहीं, यह सिर्फ testing/benchmarking tool है। Production के लिए G1 (default) या specific latency needs के लिए ZGC ज़्यादा practical choices हैं।
| GC | Purpose |
|---|---|
| Epsilon | No-op — सिर्फ allocate करता है, collect कभी नहीं (testing/measurement के लिए) |
| ZGC | बड़े heaps, बहुत कम pause time (experimental in Java 11) |
| G1 (Java 9+ default) | General-purpose, balanced throughput + pause time |