Java 8 is a major release in Java history with lots of new features. With the direct support of Java 8 features in Android, Â we can now utilise those features into our Android Project which can help write code more efficient and less error prone.
This tutorial is all about a brief overview of how to set up our Android Project to support Java 8 and how to use Java 8 features in our Android Project. Lets get started.
Jack Toolchain is Deprecated
[adinserter block=”3″]
3 Simple steps to Setup Project to support # Android Java 8 features:
[adinserter block=”3″]
1. Install Android Studio Preview:
Download and install the latest preview version of Android Studio from the following link.
2. Modify Project’s build.gradle file:
We need to modify our Android’s Plugin Version from our Project’s build.gradle file as follows:
buildscript { ... dependencies { classpath 'com.android.tools.build:gradle:2.3.3' } ... }
3. Modify Apps build.gradle:
Now modify app module’s build.gradle file as follows:
android { ... // Configure only for each module that uses Java 8 // language features (either in its source code or // through dependencies). compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
Related Articles:
Supported Android Java 8 Features as of now:
[adinserter block=”3″]
- Lambda Expressions,
- Method References,
- Default and Static interface methods
- Type Annotations, (Only at compile time as of now, not runtime)
- Repeating Annotations,
In this article, we will briefly go through the above features. In later articles, we’ll address each of the above features in depth.
1. Lambda Expressions
Lambda Expressions are one of the most powerful features introduced into Java 8. Its reshaping the language in a similar way how Generics reshaped Java when they were introduced in Java 5.
Uses:
- Reduces boilerplate code.
- Eliminates unnecessary creation of objects which reduces garbage collection work
- Pass functions as method arguments, which can be executed on demand.
Limitations:
- It can be used with functional interfaces which should consist of only one abstract method.
Usage Example:
[adinserter block=”3″]
Here is the demonstration of a simple example from Android on Button’s click event listener. The following is the code where we use Anonymous inner class to perform action after listening to click event:
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(MainActivity.this, "Button Clicked!", Toast.LENGTH_SHORT).show(); } });
Notice that we implemented anonymous inner class by calling new keyword where we’ve implemented View class’s OnclickListener interface which consists of only one method which is perfectly suitable to replace with Lambda Expression.
So the above code can be reduced to the following code below:
button.setOnClickListener(v -> Toast.makeText(MainActivity.this, "Button Clicked!", Toast.LENGTH_SHORT).show());
This explains the beauty of Lambda expressions where boilerplate code is simply reduced to one-liner and Java 8 takes care of the rest of the things such as Type Inference etc.
[adinserter block=”3″]
2. Method References
Method references are used to further reduce the coding and lambda expressions if the arguments are simply a passthrough.
Simple Example:
Suppose let us take a list of items for which we need to print them one by one. Here is the example code:
List<String> shoppingList = Arrays.asList("Brush", "Paste", "Shampoo", "Comb", "Conditioner", "Soap", "Hand Wash" ); shoppingList.forEach(s -> System.out.println(s));
If we take a look at the above example, here forEach() method takes Consumer’s object as a parameter (Consumer is a functional interface, functional interfaces will soon be explained in next tutorial in depth along with Lambda Expressions).
We can observe that each item is directly being passed as an argument for lambda expression we are simply printing the list. We can observe that the variable is directly a passthrough which is a perfect match where we can use Method Reference.
The above code can be further simplified using Method references as follows:
List<String> shoppingList = Arrays.asList("Brush", "Paste", "Shampoo", "Comb", "Conditioner", "Soap", "Hand Wash" ); shoppingList.forEach(System.out::println);
The last line demonstrates the usage of Method reference. We will cover the method reference types and usages in further depth in our future tutorials.
[adinserter block=”3″]
3. Default and Static interface methods
Prior to Java 8 only abstract methods, i.e., only methods without a body are allowed inside interface. But then default and static methods were introduced.
Both default and static methods contains bodies where they can be used to implement methods. Both are used for specific purposes:
Default methods can be overridden by the class implementing the interface containing that default method. It means a specific default statements can be added which will be performed when an overriding class doesnot have its own implementation.
Static methods cannot be overridden by the class implementing the interface. Static methods can only be called by Interface class reference variable but not by the implementing class variable.
Consider the following example below::
public class MyClass { public interface MyInterface { default void defaultMethod() { System.out.println("Default"); } static void staticMethod() { System.out.println("Static from My Interface"); } } public static void main(String[] args) { MyClass.staticMethod(); MyInterface.staticMethod(); //valid } static void staticMethod() { System.out.println("Static from My Class"); } }
If we observe carefully, both interface and class contains same method named staticMethod(). One doesnot override other. If we consider main method, both will be printed successfully and the output would be:
Static from My Class Static from My Interface
4. Type Annotations
[adinserter block=”3″]
Prior to Java 8, annotations could only be applied to declarations. After Java 8 release, annotations can be applied to anywhere where we use a type.
Annotations make sure that compiler will check for errors in before hand. For example, we can check null pointer exceptions for a variable by using @NonNull annotation for it as follows:
@NonNull String myStr;
By using type annotations we can write code that is stronger and less prone to error.
5. Repeating Annotations
If we want to apply same annotation more than once to a declaration or data type, we would use Repeating annotations.
Here is an Example:
@Schedule(dayOfMonth="last") @Schedule(dayOfWeek="Fri", hour="23") public void performRequiredTask() { ... }
Java compiler automatically generates the container annotation to store the repeating annotations for compatibility issues. In order for compiler to do this, we require to perform two steps in our code:
[adinserter block=”3″]
- Repeatable annotation type declaration
- We need to mark the annotation type with @Repeatable meta-annotation
import java.lang.annotation.Repeatable; @Repeatable(Schedules.class) public @interface Schedule { String dayOfMonth() default "first"; String dayOfWeek() default "Mon"; int hour() default 12; }
- The value of theÂ
@Repeatable
 meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations. In this example, the containing annotation type isÂSchedules
, so repeatingÂ@Schedule
 annotations is stored in anÂ@Schedules
 annotation. - Applying the same annotation to a declaration without first declaring it to be repeatable results in a compile-time error.
- We need to mark the annotation type with @Repeatable meta-annotation
- Containing Annotation type declaration
- The containing annotation type must have aÂ
value
 element with an array type. The component type of the array type must be the repeatable annotation type. The following is the declaration for theÂSchedules
 containing annotation type:public @interface Schedules { Schedule[] value(); }
- The containing annotation type must have aÂ
This completes our brief overview of Java 8 features and how to use them in our Android project. In upcoming tutorials, we will discuss in depth about lambda expressions, method references.
[adinserter block=”3″]