0% found this document useful (0 votes)
5 views9 pages

Java 8 Detailed

Java 8 introduced default and static methods in interfaces, allowing method implementations within interfaces and reducing the need for base implementation classes. Functional interfaces, marked with @FunctionalInterface, enable the use of lambda expressions for cleaner code, while the Stream API provides a way to process collections efficiently. Method references simplify lambda expressions by allowing shorthand syntax for calling existing methods.

Uploaded by

Asha Salantry
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views9 pages

Java 8 Detailed

Java 8 introduced default and static methods in interfaces, allowing method implementations within interfaces and reducing the need for base implementation classes. Functional interfaces, marked with @FunctionalInterface, enable the use of lambda expressions for cleaner code, while the Stream API provides a way to process collections efficiently. Method references simplify lambda expressions by allowing shorthand syntax for calling existing methods.

Uploaded by

Asha Salantry
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Java 8 detailed

Java Interface Default Method

Designing interfaces have always been a tough job because if we


want to add additional methods in the interfaces, it will require
change in all the implementing classes. As interface grows old,
the number of classes implementing it might grow to an extent
that it’s not possible to extend interfaces. That’s why when
designing an application, most of the frameworks provide a base
implementation class and then we extend it and override
methods that are applicable for our application. Java 8 has
brought solution to this issue. Now Interfaces can have method
implementations too.

Let’s look into the default interface methods and static interface
methods and the reasoning of their introduction in Java 8
interface changes.

public interface Interface1 {


void method1(String str);
default void log(String str){
[Link]("Default Method"+str);
}}

public interface Interface2 {


void method1(String str);
default void log(String str){
[Link]("Default Method"+str);
}}
We know that Java doesn’t allow us to extend multiple classes
because it will result in the “Diamond Problem” where compiler
can’t decide which superclass method to use. With the default
methods, the diamond problem would arise for interfaces too.
Because if a class is implementing
both Interface1 and Interface2 and doesn’t implement the
common default method, compiler can’t decide which one to
choose.
So to make sure, this problem won’t occur in interfaces, it’s made
mandatory to provide implementation for common default
methods of interfaces. So if a class is implementing both the
above interfaces, it will have to provide implementation
for log() method otherwise compiler will throw compile time error.

1. Java interface default methods will help us in extending


interfaces without having the fear of breaking
implementation classes.
2. Java interface default methods have bridge down the
differences between interfaces and abstract classes.
3. Java 8 interface default methods will help us in avoiding
utility classes, such as all the Collections class method can
be provided in the interfaces itself.
4. Java interface default methods will help us in removing base
implementation classes, we can provide default
implementation and the implementation classes can choose
which one to override.
5. One of the major reasons for introducing default methods in
interfaces is to enhance the Collections API in Java 8 to
support lambda expressions.
6. If any class in the hierarchy has a method with same
signature, then default methods become irrelevant. A
default method cannot override a method
from [Link]. The reasoning is very simple, it’s
because Object is the base class for all the java classes. So
even if we have Object class methods defined as default
methods in interfaces, it will be useless because Object class
method will always be used. That’s why to avoid confusion,
we can’t have default methods that are overriding Object
class methods.
7. Java interface default methods are also referred to as
Defender Methods or Virtual extension methods.

Static Method:

Java interface static method is similar to default method except


that we can’t override them in the implementation classes. This
feature helps us in avoiding undesired results incase of poor
implementation in implementation classes.

public interface MyData {

default void print(String str) {

if (!isNull(str)) [Link]("MyData Print::" + str); } static boolean


isNull(String str) { [Link]("Interface Null Check"); return str ==
null ? true : "".equals(str) ? true : false; } }

1. Java interface static method is part of interface, we can’t use


it for implementation class objects.
2. Java interface static methods are good for providing utility
methods, for example null check, collection sorting etc.
3. Java interface static method helps us in providing security by
not allowing implementation classes to override them.
4. We can’t define interface static method for Object class
methods, we will get compiler error as “This static method
cannot hide the instance method from Object”. This is
because it’s not allowed in java, since Object is the base
class for all the classes, and we can’t have one class level
static method and another instance method with same
signature.
5. We can use java interface static methods to remove utility
classes such as Collections and move all of it’s static
methods to the corresponding interface, that would be easy
to find and use.

Functional Interfaces and Lambda Expressions


An interface with exactly one abstract method is called Functional
Interface. @FunctionalInterface annotation is added so that we
can mark an interface as functional interface.

It is not mandatory to use it, but it’s best practice to use it with
functional interfaces to avoid addition of extra methods
accidentally. If the interface is annotated
with @FunctionalInterface annotation and we try to have more
than one abstract method, it throws compiler error.

@FunctionalInterface
public interface Functional {

void method2();

default void log(String str){


[Link]("default method"+str);
}

The major benefit of java 8 functional interfaces is that we can


use lambda expressions to instantiate them and avoid using
bulky anonymous class implementation.

The return type of a Lambda function (introduced in JDK 1.8) is also a functional
interface.
Lambda Expression:

In object-oriented programming, each code block is related


to classes and objects. A method cannot exist
independently. For example, when we want to print Hello
world!, we have to create a class and define a method in
this class that performs printing. On the contrary,
functional programming allows us to create and use
independent methods. Lambda expressions are the way
to implement functional programming in the object-
oriented world of Java. It has been added with the Java 8
release.

Lambda Expression are the way through which we can


visualize functional programming in the java object oriented
world. Objects are the base of java programming language and
we can never have a function without an Object, that’s why Java
language provide support for using lambda expressions only with
functional interfaces.

Runnable r = new Runnable(){

@Override
public void run() {
[Link]("My Runnable");

};

Since there is only one abstract function in the functional


interfaces, there is no confusion in applying the lambda
expression to the method. Lambda Expressions syntax
is (argument) -> (body). Now let’s see how we can write above
anonymous Runnable using lambda expression.

Runnable r1 = () -> [Link]("My Runnable");

Let’s try to understand what is happening in the lambda


expression above.

 Runnable is a functional interface, that’s why we can use


lambda expression to create it’s instance.
 Since run() method takes no argument, our lambda
expression also have no argument.
 Just like if-else blocks, we can avoid curly braces ({}) since
we have a single statement in the method body. For multiple
statements, we would have to use curly braces like any
other methods.

Lambda expression in Java doesn’t have a scope of its own, it has the
same scope as its enclosing scope. It results in an error if a variable is
defined with in a lambda expression that has the same name as a variable
in its enclosing scope.
Since lambda expression does not introduce a new level of scoping you
can directly access fields, methods, and local variables of the enclosing
scope. However there is a restriction how variables from enclosing scope
can be used. Like local and anonymous classes, a lambda expression can
only access local variables and parameters of the enclosing scope that are
final or effectively final.
Now the question arises why such restriction for an enclosing scope
variable. A lambda expression that uses the variables from the enclosing
scope captures the values of such variables. Since lambda expression in
Java is an instance of a functional interface so the fields of the enclosing
scope used in such an instance captures the values of those fields and use
it. It is important to maintain the state of such fields so that those are not
modified that’s why this restriction of “effectively final”.
forEach method in Iterable interface
Whenever we need to traverse over a collection, we have to create
an Iterator to iterate over the collection and then we can have our
business logic inside a loop for each of the elements inside the
collection. We might get ConcurrentModificationException if the
iterator is not used properly.
Java 8 has introduced forEach method
in [Link] interface so that while writing code we focus
on business logic. The forEach method takes
[Link] object as an argument, so it helps in
having our business logic at a separate location that we can
reuse.
void forEach(Consumer<? super T> action)
We use forEach to iterate over a collection and perform a certain
action on each element. The action to be performed is contained
in a class that implements the Consumer interface and is passed
to forEach as an argument.
The Consumer interface is a functional interface (an interface with
a single abstract method). It accepts an input and returns no
result.
The number of lines might increase but forEach method helps in
having the logic for iteration and business logic at separate place
resulting in higher separation of concern and cleaner code.

Stream API:

the Stream API is used to process collections of objects. A stream is a


sequence of objects that supports various methods which can be
pipelined to produce the desired result. Before proceeding further let us
discuss out the difference between Collection and Streams in order to
understand why this concept was introduced.

 If we want to represent a group of objects as a single


entity, then we should go for collection.
 But if we want to process objects from the collection then
we should go for streams.

If we want to use the concept of streams then stream() is the method to be


used. Stream is available as an interface.
Stream s = [Link]();
Features of Java stream?
 A stream is not a data structure instead it takes input
from the Collections, Arrays, or I/O channels.
 Streams don’t change the original data structure, they
only provide the result as per the pipelined methods.
 Each intermediate operation is lazily executed and
returns a stream as a result, hence various intermediate
operations can be pipelined. Terminal operations mark
the end of the stream and return the result.
Stream operations are either intermediate or terminal. Intermediate operations
return a stream so we can chain multiple intermediate operations without using
semicolons. Terminal operations are either void or return a non-stream result. In
the above example filter , map and sorted are intermediate operations
whereas forEach is a terminal operation.

Most stream operations accept some kind of lambda expression


parameter, a functional interface specifying the exact behavior of
the operation. Most of those operations must be both non-
interfering and stateless. What does that mean?

A function is non-interfering when it does not modify the


underlying data source of the stream, e.g. in the above example
no lambda expression does modify myList by adding or removing
elements from the collection.

A function is stateless when the execution of the operation is


deterministic, e.g. in the above example no lambda expression
depends on any mutable variables or states from the outer scope
which might change during execution.

Streams can be created from various data sources, especially collections.


Lists and Sets support new methods stream() and parallelStream() to
either create a sequential or a parallel stream. Parallel streams are
capable of operating on multiple threads .

Method References in Java


Method references are a special type of lambda expressions.
They're often used to create simple lambda expressions by
referencing existing methods.
A method reference is the shorthand syntax for a lambda
expression that executes just ONE method. Here's the general
syntax of a method reference:

Object :: methodName

We know that we can use lambda expressions instead of using


an anonymous class. But sometimes, the lambda expression is
really just a call to some method, for example:

Consumer<String> c = s -> [Link](s);

To make the code clearer, you can turn that lambda expression
into a method reference:

Consumer<String> c = [Link]::println;

There are three kinds of method references:

 Static methods
 Instance methods of particular objects.
 Constructor

Q) Difference between abstract class and interface in Java 8


Ans: the main difference between an abstract class and an interface in Java 8 is the fact
that an abstract class is a class and an interface is an interface. A class can have a
state which can be modified by non-abstract methods but an interface cannot have the state
because they can't have instance variables.
Abstract class can have final, non-final, static and non-static variables. The interface has only
static and final variables.

You might also like