🔥 Java Explained: Lambdas, Streams, Annotations & Reflection
Since Java 8, the language has evolved with powerful features that simplify code and boost productivity. Modern Java encourages a functional programming style, introduces more expressive APIs, and gives developers more control over metadata and runtime behavior.
In this article, we’ll explore lambda expressions, the Streams API, annotations, and reflection — and see how they make Java development cleaner and more efficient.
1. Lambda Expressions
Before Java 8, creating small functions often required verbose anonymous classes. Lambdas provide a concise way to pass behavior as data.
Example: Without Lambda
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Collections.sort(names, new Comparator<String>() {
public int compare(String a, String b) {
return a.compareTo(b);
}
});
With Lambda
Collections.sort(names, (a, b) -> a.compareTo(b));
👉 Lambdas reduce boilerplate code and make Java closer to functional programming.
2. Streams API
The Streams API (Java 8+) makes it easier to process collections in a declarative style. Instead of loops, you focus on what you want to achieve, not how.
Example: Filtering and Mapping
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
.filter(name -> name.startsWith("A"))
.map(String::toUpperCase)
.forEach(System.out::println);
Output:
ALICE
👉 Streams support operations like filter, map, reduce, collect, making data processing both powerful and readable.
3. Functional Style Programming
Lambdas and streams together encourage functional programming in Java.
Example: Sum of even numbers
Recommended by LinkedIn
int sum = IntStream.range(1, 10)
.filter(n -> n % 2 == 0)
.sum();
System.out.println(sum); // 20
👉 Instead of loops and counters, you express operations as data pipelines.
4. Annotations
Annotations provide metadata about code, influencing how it’s compiled or executed. Java comes with built-in annotations, and you can create custom ones.
Common Annotations
Custom Annotation
@interface Todo {
String value();
}
public class Main {
@Todo("Refactor this method later")
public void process() {
System.out.println("Processing...");
}
}
👉 Frameworks like Spring and JUnit rely heavily on annotations to reduce configuration boilerplate.
5. Reflection
Reflection allows programs to inspect and modify classes, methods, and fields at runtime. It’s widely used in frameworks, ORMs, and dependency injection.
Example: Inspecting Class Info
import java.lang.reflect.*;
public class Main {
public static void main(String[] args) {
Class<?> clazz = String.class;
System.out.println("Class: " + clazz.getName());
for (Method m : clazz.getDeclaredMethods()) {
System.out.println("Method: " + m.getName());
}
}
}
Example: Accessing Private Fields
class Person {
private String name = "Alice";
}
public class Main {
public static void main(String[] args) throws Exception {
Person p = new Person();
Field field = p.getClass().getDeclaredField("name");
field.setAccessible(true);
System.out.println("Name: " + field.get(p));
}
}
👉 Reflection powers libraries like Jackson (JSON parsing) and JUnit (testing).
✅ Wrap-Up
In this article, you explored modern Java features that make your code shorter, cleaner, and smarter:
Together, these features represent the modern Java toolkit — enabling developers to write expressive, maintainable, and powerful applications.
#devbyrohit #java #developer #tutorial #guide