Author Archive Bala Manikandan

ByBala Manikandan

ArrayLists: Dynamic Arrays in Java (Part 2)

Reading Time: 3 minutes

Here is the second post on ArrayLists which is a continuation from part 1 . Here are some points covered in the first part:

  • Main advantage of ArrayLists over arrays
  • Creating an ArrayList
  • Adding elements to ArrayLists
  • Iterating through the elements
  • Modifying and deleting elements

In the next section, we will deal with some methods commonly used to query an ArrayList.

Querying ArrayLists:

The following example demonstrates the usage of some more ArrayList methods:

//Other methods of ArrayList

package codingexamples;

import java.util.*;

 

public class ArrayListExample3 {

     public static void main(String[] args){

        ArrayList<String> list = new ArrayList<>();

        list.add(“Apple”);

        list.add(“Banana”);

        list.add(“Grapes”);

        list.add(1, “Watermelon”);

        list.add(“Apple”);       

        System.out.println(list);       

        String val = list.get(3);     //retrieve element at index 3

        System.out.println(val);

          int sz = list.size();

        System.out.println(sz);

       

        System.out.println(list.contains(“Banana”));

        System.out.println(list.contains(“String”));

        System.out.println(list.indexOf(“Apple”));

        System.out.println(list.indexOf(“String”));

        System.out.println(list.lastIndexOf(“Apple”));

     }

}

The output of the code is:

[Apple, Watermelon, Banana, Grapes, Apple]

Grapes

5

true

false

0

-1

4

The methods get() and size() used above are self-explanatory, which is evident from the first three lines of output (remember that index 3 is the fourth element). The method contains() returns true if the specified item is present in the list and false otherwise. In this case, the list contains “Banana” but does not contain “String”. And last, the indexOf() and lastIndexOf() methods return the indices of the first and the last occurrences of the specified object, respectively, or -1 if the object is not present. This is consistent with the above output.

The next section deals with a slightly more advanced concept related to ArrayLists.

Role of the equals() method in results of ArrayList methods:

The equals() method of class Object is inherited by all the classes in Java. But by default, it only checks whether the references of the invoking object and the method parameter are the same, or in other words, it returns true only if they refer to the same object. However, classes may override this method and define a new “equality” condition, which usually involves comparison of the instance variables of the objects.

Some of the methods in the ArrayList class, such as remove(), contains(), indexOf() and lastIndexOf() use the equals() method to check if an object is present in the list or not. Thus depending on whether the equals() method is overridden or not, the results of these methods may differ. This is demonstrated in the following code:

//Demonstrating effects of overriding equals() in classes used as the

//element type in an ArrayList

package codingexamples;

import java.util.*;

 

class Person1{

    private String name;

    Person1(String nm){name = nm;}

    public String getName(){return name;}

    //no equals() override

}

class Person2{

    private String name;

    Person2(String nm){name = nm;}

    public String getName(){return name;}

   

    //Override equals(), returns true if the names are equal

    public boolean equals(Object obj){

        if(obj instanceof Person2){

            Person2 other = (Person2)obj;

            boolean isEqual = this.name.equals(other.name);

            return isEqual;

        }

        else

            return false;

    }

   

}

public class ArrayListExample4 {

    public static void main(String[] args){

        ArrayList<Person1> list1 = new ArrayList<>();

        Person1 p1 = new Person1(“John”);

        Person1 p2 = new Person1(“Roger”);

        list1.add(p1);

        list1.add(p2);

       

        System.out.println(list1.contains(p2));                     //prints true

        System.out.println(list1.contains(new Person1(“Roger”)));   //prints false!

        list1.remove(new Person1(“John”));                      //doesn’t remove John!

       

        for(Person1 p : list1)

            System.out.print(p.getName() + “:”);

        System.out.println();

       

        ArrayList<Person2> list2 = new ArrayList<>();

        Person2 p3 = new Person2(“John”);

        Person2 p4 = new Person2(“Roger”);

        list2.add(p3);

        list2.add(p4);

       

        System.out.println(list2.contains(p4));                    //prints true

        System.out.println(list2.contains(new Person2(“Roger”)));  //also prints true!

        list2.remove(new Person2(“John”));                         //removes John

       

        for(Person2 p : list2)

            System.out.print(p.getName() + “:”);

        System.out.println();

    }

}

The output of the code, as it turns out, is:

true

false

John:Roger:

true

true

Roger:

The above code defines two almost identical classes, Person1 and Person2, both of which have a single instance variable, name. But Person1 does not override equals(), whereas Person2 does. In case it is tough to understand the code in the equals() override of class Person2, for now just remember that the new definition returns true if the names of the two Person2 objects are the same.

Now an ArrayList of Person1 objects is created and two Person1 objects with names John and Roger are added to it. If the ArrayList is queried whether it contains the object referenced by p2 (that is, ‘Roger’), it results in true. But if instead you pass a new object whose ‘name’ is also Roger to the contains() method, it results in false! Why? Because Person1 did not override equals(), and thus only object references were compared all along! Similarly, the next line demonstrates an unsuccessful (for the very same reason) attempt to remove ‘John’ from the list. This is demonstrated in the third line of output, which displays the ‘names’ of all the elements in the list.

The same things are done for another ArrayList of Person2 objects, and a significant change is observed in the output, only because Person2 overrode equals(), and so names instead of object references were compared! Thus the second call to contains() on the second list also produced true, and this time John was successfully removed from the list.

We have seen how to use ArrayLists in Java in this post – stay tuned for more technical posts!

ByBala Manikandan

ArrayLists: Dynamic Arrays in Java (Part 1)

Reading Time: 3 minutes

Before beginning this post, I would like to state that this post assumes some prior knowledge of Java (particularly arrays, classes and objects, and overriding)

The main limitation with arrays (groups of elements of the same datatype that are referenced by a common name) in Java is that they have a fixed size, and cannot shrink or grow in size. To overcome this, the ArrayList class can be used, which offers the functionality of a dynamic array. This class implements the List interface, which itself defines the methods used to manipulate ArrayLists. Both the class and the interface reside in the java.util package. This post deals with the functionality of various methods in the ArrayList class.

Adding elements to ArrayLists and Iterating through them:

The following example shows how to add elements to an ArrayList and iterate through them.

//Adding elements to an ArrayList and iterating through them

package codingexamples;

import java.util.*;

public class ArrayListExample1 {

    public static void main(String[] args){

        List<String> list = new ArrayList<>();    //works in Java 7 and above

        list.add(“Apple”);

        list.add(“Banana”);

        list.add(“Grapes”);

        list.add(1, “Watermelon”);              //insert “Watermelon” at position 1       

        System.out.println(list);               //prints out names of elements

        System.out.println();

               //iterate through elements using enhanced for loop

        for(String s : list)

            System.out.println(s);

            System.out.println();

            //iterate through elements using ListIterator

        ListIterator<String> itr = list.listIterator();

        while(itr.hasNext())

            System.out.println(itr.next());

        }   

}

The output of the code is:

[Apple, Watermelon, Banana, Grapes]

Apple

Watermelon

Banana

Grapes

Apple

Watermelon

Banana

Grapes

The first line marked in bold shows how to create an ArrayList. Note the use of angle brackets in this line. ArrayList can work with multiple object types (it is a generic collection), and the type to be stored (in this case String) must be specified in the angle brackets, making ArrayLists type safe. Also, as mentioned earlier, ArrayList implements the List interface, and all the methods commonly used with ArrayLists are defined in this interface itself. So, a List reference may be used to store an ArrayList object, as shown in this line. As of Java 7, the angle brackets on the right side of the ‘=’ sign can be left empty. So prior to Java 7, you would have had to write,

List<String> list = new ArrayList<String>();

The next few lines add elements to the ArrayList. While the elements “Apple”, “Banana” and “Grapes” are added to the end of the list each time (using the single argument add() method), the element “Watermelon” is inserted at position 1 (so that it is the second element, as the numbering starts from 0), using the two-argument add() method. The remaining elements are shifted ahead by one position when this happens.

In the next line, the list is passed to the println() method, which shows the elements of the ArrayList in order, in agreement with the add() method calls. And finally, the elements of the ArrayList are iterated through, using an enhanced ‘for’ loop and a ListIterator (observe the syntax when using ListIterator).

Modifying and Deleting Elements:

The following example shows how to modify and delete elements from an ArrayList:

//Modifying and deleting elements of an ArrayList

package codingexamples;

import java.util.*;

public class ArrayListExample2 {

    public static void main(String[] args){

        ArrayList<String> list = new ArrayList<>();

        list.add(“Apple”);

        list.add(“Banana”);

        list.add(“Grapes”);

        list.add(1, “Watermelon”);

        list.add(“Apple”);

       System.out.println(list);

     

        list.set(2, “Pomegranate”);      //modify element at index 2

       

        System.out.println(list);

       

        list.remove(2);                 //remove element at index 2

        list.remove(“Apple”);           //remove first occurrence of “Apple”

       

        System.out.println(list);

       

        list.clear();                   //clear the ArrayList

       

        System.out.println(list);

    }

}

The above code outputs:

[Apple, Watermelon, Banana, Grapes, Apple]
[Apple, Watermelon, Pomegranate, Grapes, Apple]
[Watermelon, Grapes, Apple]
[]

The first line of output shows the initial contents of the ArrayList. Then the set() method is used to modify the element at index 2 (that is the third element), which is reflected in the second line of output. After this, the element at index 2 and the element “Apple” are removed using the remove() method. But since the element “Apple” occurs twice in the ArrayList, only the first occurrence of the element is removed. The effect of this is shown in the third line of output. Finally the clear() method is used to clear the ArrayList, which is shown in the fourth line of output.

With this we come to the end of Part 1 of this post. For more information on ArrayLists, please do read Part 2 of this post which will be published on Friday, July 5th, 2019…

ByBala Manikandan

Anonymous Inner Classes and Lambda Expressions in Java

Reading Time: 6 minutes

Before beginning this post, I would like to state that this post assumes some prior knowledge of Java (particularly inheritance, using interfaces and overriding methods)

Most classes we have seen have their own name and exist on their own (outside any other class or method). But anonymous inner classes can exist inside another class/method, and do not have a name (hence the name ‘anonymous’). These classes must either extend another (named) class or implement an interface. When the interface being implemented has only one abstract method, the anonymous inner class can be converted into a special expression called a lambda expression (as of Java 8), which simplifies the code. This post talks about anonymous inner classes and lambda expressions in detail.

Anonymous Inner Classes

As mentioned above, anonymous inner classes do not have a name, can exist within another class/method, and must extend another class or implement an interface.

Let us see the various examples that can be used to work with anonymous inner classes:

  1. The following example uses an anonymous inner class to extend another class and create an object of it on the spot. Observe the syntax carefully:

//Using anonymous inner classes to override methods of an existing class

package codingexamples;

class Sample{

    public void display(){

        System.out.println(“Sample”);

    }

}

public class Example1 {

    public static void main(String[] args){

        Sample s1 = new Sample();

     

        Sample s2 = new Sample() {                //line 1

            public void display(){

                System.out.println(“Sample 2”);

            }

        };                            //this semicolon is very important

       

        useSample(s1);

        useSample(s2);

    }

    static void useSample(Sample s){

        s.display();

    }

}

The output of the above code is:

Sample

Sample 2

Observe the bold section of the code carefully. Note that the first line of code in this region ends in a curly brace, not a semicolon. This line declares a reference variable of type Sample, and initializes it with an object whose type is not Sample, but an anonymous subclass of Sample. The curly brace at the end of the line is the start of the anonymous inner class body.

The next three lines of code, as we can see, are overriding the display() method in the class Sample. This is, of course, the reason behind creating anonymous inner classes. The last line of (bold) code requires some attention. The closing curly brace marks the end of the class, but that’s not all – there is also a semicolon to end the statement started on line 1! As it is unusual to see semicolons after closing braces, this is very easy to miss.

On the whole, the code creates two Sample references, one holding a Sample object, and another holding an object of an anonymous subclass of Sample (which overrides display()). These variables are then passed to the useSample() method which calls their respective display() methods. This leads to the output mentioned above.

 

2. Anonymous inner classes implements an interface in the second example:

//Using anonymous inner classes to implement methods of an interface

package codingexamples;

interface Movable{

    void move();

}

public class Example2 {

    public static void main(String[] args){

      Movable m1 = new Movable(){

            public void move(){

                System.out.println(“m1 is moving”);

            }

        };

       

        useMovable(m1);

    }

    static void useMovable(Movable m){

        m.move();

    }

}

 

The output of the above code is, as expected:

m1 is moving

This code is very similar to the first example. Note that even though the syntax used is ‘new Movable()’, the code is not instantiating the interface (it’s not legal to do so). The variable m1 refers to an anonymous implementer of Movable.

3. Anonymous inner classes can extend/implement classes/interfaces having more than one method as well. They can also be used as method arguments (watch the syntax again). The following example illustrates these two points:

//Another example of anonymous interface

package codingexamples;

interface Bounceable{

    void bounce();

    void jump();

}

public class Example3 {

    public static void main(String[] args){

        /* Create an anonymous implementer of Bounceable in the argument list of useBounceable() */

       useBounceable(new Bounceable(){

            public void bounce(){

                System.out.println(“Anonymous object bouncing”);

            }

            public void jump(){

                System.out.println(“Anonymous object jumping”);

            }

        });

    }

    static void useBounceable(Bounceable b){

        b.bounce();

        b.jump();

    }

}

 

The output of the above code is:

Anonymous object bouncing

Anonymous object jumping

Observe how the object of the anonymous inner class is created right inside the argument. Also note that in this case, the statement ends with a closing curly brace, a closing parenthesis and then a semicolon.

Lambda Expressions

Now we will move onto Lambda expressions. Consider the following scenario. You have a class Student, which stores some details of a student such as name, marks etc. You also have an interface Check, as shown below:

interface Check{

    boolean test(Student s);

}

This is meant to create multiple custom ‘checks’ on the attributes of each student (for example, ‘name’ starts with ‘A’, ‘marks’ >= 95 and so on). For each such test condition, prior to Java 8, it would be necessary to define a class that implements the interface. Of course, it would be inconvenient to define multiple such implementers with names such as ‘CheckName’, ‘CheckMarks’ etc. (as one can see, it is repetitive). Another approach is to use anonymous inner classes as implementers of interface Check (already discussed above), which removes the problem of repetitive names. However, each anonymous implementer, as we have seen already, spans at least five lines of code.

Java 8 allows you to create ‘instances’ of functional interface ‘implementers’ through the use of lambda expressions (a functional interface is one that contains exactly one abstract method). These can, in certain cases, replace anonymous inner classes and simplify the code. The following example defines the class Student, interface Check and makes use of the interface through lambdas:

//Demonstrate the use of lambda expressions

package codingexamples;

class Student{

    private int marks;

    private int grade;

    private String name;

    public Student(String n, int m, int g){

        name = n;

        marks = m;

        grade = g;

    }

    public String getName(){

        return name;

    }

    public int getMarks(){

        return marks;

    }

    public int getGrade(){

        return grade;

    }

}

//Check is a functional interface (one abstract method)

interface Check{

    boolean test(Student s);

}

public class Example4 {

    public static void main(String[] args){

        Student[] students = {

            new Student(“John”, 90, 7),

            new Student(“Roger”, 70, 9),

            new Student(“Fred”, 88, 6),

            new Student(“Robert”, 60, 8)

        };

       //Lambda expressions

        Check seniorsChk = s -> s.getGrade() >= 9;

        Check toppersChk = s -> s.getMarks() >= 85;

       System.out.println(“Senior students:”);

        filterStudents(students, seniorsChk);

       System.out.println();

       System.out.println(“Toppers:”);

        filterStudents(students, toppersChk);

    }

    static void filterStudents(Student[] stu, Check chk){

        for(Student s: stu){

            if(chk.test(s))

                System.out.println(s.getName());

        }

    }

}

The output of the above code is:

Senior students:

Roger

Toppers:

John

Fred

Before going into the working of this code, let us observe the syntax of the lambda expression. The general syntax of a lambda expression is:

<Parameter(s)> <Arrow> <Lambda Body (must be an expression which evaluates to the abstract method’s return type)>

To understand better, keep in mind that the following expression:

s -> s.getGrade() >= 9

Is equivalent to (in this case):

new Check(){

     public boolean test(Student s){

            return s.getGrade() >= 9;

     }

}

Thus a lambda expression essentially just behaves like an anonymous inner class, with fewer lines of code. Now we can understand that the code basically creates two ‘test conditions’ on Student objects, using lambdas, and then filters a list (array) of Student objects using these ‘test conditions’ (implementers of interface Check). Walk through the lines of code to understand better. Here, Roger is considered a senior as he is in a grade higher than or equal to grade 9, and John and Fred are considered toppers as each of them has scored more than or equal to 85 marks each.

Before we end, let us rewrite the code in Example 2 using a lambda expression (interface Movable used in that example is also a functional interface). Old code is commented out:

//Example 2 rewritten using a lambda expression

package codingexamples;

//assuming interface Movable already exists

public class Example5 {

    public static void main(String[] args){

        /* Movable m1 = new Movable(){

            public void move(){

                System.out.println(“m1 is moving”);

            }

        };

        */

        Movable m1 = () -> System.out.println(“m1 is moving”);

        /* note that parentheses are needed when the method

                accepts zero arguments or more than one argument */

        useMovable(m1);

    }

    static void useMovable(Movable m){

        m.move();

    }

}

The output of the code remains the same as before. Note that examples 1 and 3 above cannot be rewritten using lambdas, as example 1 uses a class, and example 3 uses a non-functional interface (two abstract methods).

We have seen different types of anonymous inner classes and Lambda expressions in this post… stay tuned for more technical posts!

 

ByBala Manikandan

Network and System Security

Reading Time: 4 minutes

Network and System Security means protecting your system from different kinds of attacks by unauthorized users. With the development of the Internet and the World Wide Web, it is a field that is gaining a lot of importance. In this post, we will discuss various threats to network security and how to protect our system from such threats.

1.      Worms

A worm is a program which simply creates copies of itself until the entire disk space in your system is filled up.

2.      Trojan Horses

These are harmless-looking applications such as text editors which actually perform malicious functions without your knowledge (for example, deleting/modifying other existing files)

3.      Spyware

This is a kind of software which may get installed on your PC without your consent, tracks your activity and reports this information to people who are willing to pay for it. Spyware mostly finds its way to a PC by getting downloaded along with another file, or from the Internet when you visit a webpage.

4.      Adware

Adware is a software that causes your computer to display unwanted pop-up ads. It reduces the performance of your computer, and is similar to spyware, with the difference that it may be installed with your consent. So it is important to go over the terms and conditions before you install any software on your PC.

5.      Spamming

This is a term used to describe the sending of e-mail in bulk by a known or unknown person. Spamming can also reduce system performance, and can even be used to spread computer viruses.

6.      Phishing and Pharming

These methods of attack rely on tricking users rather than using sophisticated technology.

  1. Phishing: In this attack, an unidentified person uses an authentic-looking e-mail or website to extract sensitive personal information from another user. For example, you may receive an e-mail which seems to be from your bank, asking you to fill up your personal details by clicking on a link. But the link may take you to a fake website where all your details are obtained and later used for malicious purposes.
  2. Pharming: This attack involves redirecting a website’s traffic to another authentic-looking, but bogus, website. The attacker convinces you that the site is real and then obtains all the information you provide to it.

7.      Snooping and Eavesdropping

  1. Snooping: It refers to the unauthorized access of someone else’s information. It may or may not involve using sophisticated snooping software. Examples are monitoring of keystrokes pressed, secretly observing someone else’s computer activity and directly capturing his/her login ID and password.
  2. Eavesdropping: Eavesdropping involves intercepting someone else’s data as it passes from one place to another. For example, intercepting someone else’s credit card number as it passes from the user’s system to the web server that requested it.

8.      Denial of Service (DoS) Attacks

In this kind of attack, the legitimate users are not allowed to use the resources, information or capabilities of the system. This attack, however, generally does not allow the attacker to access or modify data. For example, an attacker may flood the targeted system with a barrage of requests.

9.      Cookies

These are messages (pieces of information) sent by a web server to a web browser so that the web server can track users’ activity on a webpage. They can help webpages load faster, and can customize the page for users who have already visited them. As they are merely text files, they cannot act maliciously on systems. However, any information you provide freely to a website (including sensitive personal information) will most likely be stored in a cookie, unless you disable the cookie feature in your browser. If someone found out the encryption key to your cookies, he/she could get your personal details. Cookies a threat to security this way.

Preventive Measures

Having discussed about various threats to network and system security, the question arises as to how we deal with these threats. There are different methods to deal with different kinds of attacks, some of which are listed below:

General solutions:

  • Be careful when downloading files on the Internet.
  • Use a different way of writing e-mail addresses on the web. (For example, instead of “abc@xyz.com” you could write “abc AT xyz DOT com” or “abc    AT    xyz    DOT    com” with extra spaces.)
  • Instead of clicking links in e-mails, type the URL of the concerned website in your web browser (the link may direct you to a bogus website).
  • Disconnect from the Internet when away from home. Staying on the Internet increases the risk of certain infections and intrusions.

Solutions to Viruses, Adware, Spyware

  1. Use antivirus and anti-spyware software.
  2. Keep your system up-to-date.

   Solutions to Spam

  1. Use anti-spam software.
  2. Keep your e-mail address private.

 Solutions to Phishing and Pharming

  1. Avoid opening e-mails from unknown sources.
  2. Check the security guidelines of websites you often visit (so you can distinguish between legitimate and fake e-mails).

Solutions to Snooping, Eavesdropping and DoS attacks

1.   Protect your system by asking the user for a valid user-ID (authorization) and a valid password (authentication). Keep the passwords strong so that they cannot be easily guessed.

2. Install a firewall on your system. A firewall is a system (hardware or software) designed to prevent unauthorized access to or from a private network.

Solution to threats caused by Cookies:

  1. Turn off the cookie feature in your web browser, to ensure the safety of your personal information when not needed. 

We saw a few ways in which a system may be compromised actively or passively and the way to counter them. Join me as I uncover more topics on yet another post on Information security!

 

 

 

 

ByBala Manikandan

Overloading and Overriding Methods in Java

Reading Time: 2 minutes

Two terms commonly associated with methods in Java are overloading and overriding. These two concepts will be discussed in the following sections.

Method Overloading

Method overloading is the process of defining more than one method having the same name in the same class (or in the same inheritance tree).

Rules to define overloaded methods:

  • The methods must have the same name.
  • The methods must have different argument lists.
  • They may have same or different return types.
  • Their access levels may be same or different.

The correct method to be executed by the system is decided by the Java compiler at compile time, and this is called static polymorphism. The following example demonstrates method overloading:

public class Test {

       public static int add(int a, int b){    //adds 2 numbers

        return a + b;

    }

       public static String add(String a, String b){  //concatenates 2 Strings with a space in between

        return a + ” ” + b;

    }

       public static void main(String[] args){

           System.out.println(“4 + 5 = ” + add(4, 5));

        //calls 1st method

           System.out.println(“Method + Overloading = ” + add(“Method”, “Overloading”));

        //calls 2nd method

    }

   }

The output of the above program is:

4 + 5 = 9

Method + Overloading = Method Overloading

Method Overriding

Method overriding means giving a new definition to an existing method in a class, in one of its subclasses. This is done to redefine the behaviour of objects of the subclass.

Rules to override a method:

  • The overriding method should be present in the subclass of the class in which the overridden method is present.
  • The overriding and overridden methods should have the same name and argument list.
  • The two methods should have the same return type. Or the return type of the overriding method should be a subclass of that of the overridden method.
  • The access modifier of the overriding method must be either the same as or less restrictive than that of the overridden method.

The method to be executed is decided at runtime (not at compile time), and this is called dynamic polymorphism. The following example demonstrates method overriding:

class A {

    public void display(){

        System.out.println(“Executing from class A”);

    }

}

class B extends A {

    public void display(){               //override the method display()

        System.out.println(“Executing from class B”);

   

    }

}

public class Test1 {

    public static void main(String[] args) {

        A objA = new A();

        A objB = new B();              //an A reference, but a B object

        objA.display();

        objB.display();

   

    }

 

}

The above code prints:

Executing from class A

Executing from class B

We have seen the core concepts of ‘Overloading and Overriding’ in Java in this post… Join me as I uncover more Java concepts in subsequent posts…

ByBala Manikandan

Java 8 – Default and Static Methods in Interfaces

Reading Time: 2 minutes

Before beginning this post, I would like state that this post assumes some knowledge of Java.

 

Prior to Java 8, all methods in an interface had to be ‘abstract’. However, in Java 8, default and static methods could also be defined in interfaces. These are discussed in the following sections.

Default Methods:

A default method in an interface is used to define the ‘default’ behaviour of an object of that interface type, in case a class implementing that interface does not override the method. Unlike other interface methods, default methods have a method body. A default method is declared using the keyword ‘default’:

interface TestInterface {
      default void defaultMethod() {  }      //a default method
}

 Flat 20% cashback on Motorola, Vivo and Lenovo Smartphones

Note that the above method uses curly braces, not a semicolon. Just like normal methods, statements can be included between the curly braces. Now consider another piece of code:

package bala;

interface TestInterface{
default void print(){
System.out.println(“Default”);
}
}
class Sample1 implements TestInterface{ //overrides print()

public void print(){
System.out.println(“Not Default”);
}
}
class Sample2 implements TestInterface{} //doesn’t override

public class Test {

public static void main(String[] args) {
TestInterface obj1 = new Sample1();
TestInterface obj2 = new Sample2();
obj1.print();
obj2.print();
}
}

 

 

The above code prints:

Not Default
Default

In the above code, both the classes, Sample1 and Sample2, implement the interface TestInterface, which contains a default method.

class Sample1 overrides the print() method but Sample2 doesn’t.  In the main() method, two objects of object types Sample1 and Sample2 are created, which then invoke the print() method. Since Sample1 has the overridden print() method, the code in the overridden version executes.

But the print() method is not overridden in Sample2,  so the code in the default method of TestInterface executes. This accounts for the above output.

Static Methods:

Recall the definition of static methods – they belong to the class rather to an instance of the class.

As in classes, static methods in interfaces are the methods that can be called using the interface name itself, rather than using an object reference variable. These methods also use curly braces. Their usage is very similar to the usage of static methods in classes, as demonstrated in the following code:

package bala1;

interface TestInterface2{

static void print(){
System.out.println(“Static method inside an interface”);
}
}
public class Test2 {

public static void main(String[] args) {
TestInterface2.print();
}

}

 

As expected, the above code prints:

Static method inside an interface

We have seen the newer features of Java 8(namely – default and static methods in interfaces) in this post! Join me as I uncover some more technical aspects of the world!