Java Application Programming Interfaces (APIs)

First and foremost, we must define an API.  An API is a piece of code that specifies how software should interact with others.

If we go by the definition provided by Wikipedia, it states the following:

“In computer programming, an application programming interface (API) is a set of subroutine definitions, protocols, and tools for building application software. In general terms, it is a set of clearly defined methods of communication between various software components”.

It is correctly defined, but the meaning is not entirely clear. So let’s break it down with the help of a simple example.

image 28 - Java Application Programming Interfaces (APIs)

To gain a better understanding, consider another example that will dispel any remaining doubts.

Have you ever visited a website where you could sign up using Facebook or Google? How do you think you’re able to log in and use the application without ever worrying about how that code was written?! All of your work has been simplified as a result of the API.  All information provided for Google sign up is done via the API.

However, in order to remain good, precautions and measures must be taken. And so do the APIs!

What Are The Libraries In Java?

Libraries in any programming language are the same as any other library.

Suppose you are doing research on a particular topic. You go to a library where you can find books or buy books on that topic. Books have content already written by someone and you simply refer to it to fulfill your purpose, i.e. you do not need to do all the research from scratch. Similarly, libraries are code written for a specific purpose, pre-compiled which assists or helps to complete your task at hand easily without having to write all the code from scratch.

Tip: The best way to learn any OOP language, such as java, is to apply the concepts to real-world scenarios. This is the essence of object-oriented programming. Hundreds of pre-built classes are included with Java. You don’t have to reinvent the wheel if you know where to look in the Java library, also known as the Java API. You’ve got more important things to do. If you’re going to write code, you might as well enjoy yourself. Only write the parts that are truly unique to your application. The Java API is used by all genuine developers. And you will be from now on. The core Java library is a massive collection of classes that you can use as building blocks to create your own program from mostly pre-built code. The Ready-bake Java we use in this course is code that does not have to be written from scratch, but it must still be typed. The Java API is jam-packed with code that you don’t even have to type. All you have to do now is learn how to use it.

In our array introduction, we told you how to create and use an array. But arrays have some limitations.

The limitation of an array is that it has a fixed length, so if it is full, you cannot add any more elements to it; similarly, if a number of elements are removed from it, the memory consumption remains constant because it does not shrink.

Suppose you run a book club. To get books from the club, first one has to be a member of the club. For simplicity, we can use our predefined Member class here. You want to store the members in an array.

Member[] members;

But here comes the first problem. When you want to initialize an array you must determine a size.

Member[] members = new Member[SIZE];

But how many members will be there in the book club? There is no way to know this beforehand. You can make an estimation though. You estimate that there will be 10 members in the book club. So now you can initialize the array:

Member[] members = new Member[10];

The following program demonstrates this concept :

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}


public class BookClub {
    public static void main(String[] args) {

        //An array to hold 10 Member type variables
        Member[] members = new Member[10];
       
        // creating 10 members
        for (int i = 0; i < 10; i++) {
            members[i] = new Member();
        }
       
        // setting members ids and names

        members[0].setMemberId(1);
        members[0].setMemberName("Lucy");

        members[1].setMemberId(2);
        members[1].setMemberName("Aron");

        members[2].setMemberId(3);
        members[2].setMemberName("Monica");

        members[3].setMemberId(4);
        members[3].setMemberName("Rachel");

        members[4].setMemberId(5);
        members[4].setMemberName("Joey");

        members[5].setMemberId(6);
        members[5].setMemberName("Sheldon");

        members[6].setMemberId(7);
        members[6].setMemberName("Amy");

        members[7].setMemberId(8);
        members[7].setMemberName("Sheldon");

        members[8].setMemberId(9);
        members[8].setMemberName("Harry");

        members[9].setMemberId(10);
        members[9].setMemberName("Ron");

        // printing members informations
        for (Member member : members) {
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
        }

    }
}

Output

Member [MemberId=1, MemberName=Lucy]
Member [MemberId=2, MemberName=Aron]
Member [MemberId=3, MemberName=Monica]
Member [MemberId=4, MemberName=Rachel]
Member [MemberId=5, MemberName=Joey]
Member [MemberId=6, MemberName=Sheldon]
Member [MemberId=7, MemberName=Amy]
Member [MemberId=8, MemberName=Sheldon]
Member [MemberId=9, MemberName=Harry]
Member [MemberId=10, MemberName=Ron]

Now a new kid wants to be a member of your club. You thought you could manage at most 10 members for your club. You declared and initialized your array in that way. But now that the new kid wants to join your club you must add him to the array. You will do this by :

        members[10].setMemberId(11);
        members[11].setMemberName("hermione");

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}


public class BookClub {
    public static void main(String[] args) {

        //An array to hold 10 Member type variables
        Member[] members = new Member[10];
       
        // creating 10 members
        for (int i = 0; i < 10; i++) {
            members[i] = new Member();
        }
       
        // setting members ids and names

        members[0].setMemberId(1);
        members[0].setMemberName("Lucy");

        members[1].setMemberId(2);
        members[1].setMemberName("Aron");

        members[2].setMemberId(3);
        members[2].setMemberName("Monica");

        members[3].setMemberId(4);
        members[3].setMemberName("Rachel");

        members[4].setMemberId(5);
        members[4].setMemberName("Joey");

        members[5].setMemberId(6);
        members[5].setMemberName("Sheldon");

        members[6].setMemberId(7);
        members[6].setMemberName("Amy");

        members[7].setMemberId(8);
        members[7].setMemberName("Sheldon");

        members[8].setMemberId(9);
        members[8].setMemberName("Harry");

        members[9].setMemberId(10);
        members[9].setMemberName("Ron");

        members[10].setMemberId(11);
        members[10].setMemberName("hermione");

        // printing members informations
        for (Member member : members) {
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
        }

    }
}

Output:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
        at BookClub.main(BookClub.java:67)

If you now compile the file it compiles just fine. There is no error in the code. But if you run the code you see the above mentioned error.

Let us first see what this error means.

java.lang.ArrayIndexOutOfBoundsException indicates that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array. The size of your array is 10 but you want to shove 11 members there. Of course, this program would give you an error. You had it coming. So now you change the size of the array to hold 11 members. And now it works just fine.

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}


public class BookClub {
    public static void main(String[] args) {

        //An array to hold 11 Member type variables
        Member[] members = new Member[11];
       
        // creating 11 members
        for (int i = 0; i < 11; i++) {
            members[i] = new Member();
        }
       
        // setting members ids and names

        members[0].setMemberId(1);
        members[0].setMemberName("Lucy");

        members[1].setMemberId(2);
        members[1].setMemberName("Aron");

        members[2].setMemberId(3);
        members[2].setMemberName("Monica");

        members[3].setMemberId(4);
        members[3].setMemberName("Rachel");

        members[4].setMemberId(5);
        members[4].setMemberName("Joey");

        members[5].setMemberId(6);
        members[5].setMemberName("Sheldon");

        members[6].setMemberId(7);
        members[6].setMemberName("Amy");

        members[7].setMemberId(8);
        members[7].setMemberName("Sheldon");

        members[8].setMemberId(9);
        members[8].setMemberName("Harry");

        members[9].setMemberId(10);
        members[9].setMemberName("Ron");

        members[10].setMemberId(11);
        members[10].setMemberName("hermione");

        // printing members informations
        for (Member member : members) {
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
        }

    }
}

Output:



Member [MemberId=1, MemberName=Lucy]
Member [MemberId=2, MemberName=Aron]
Member [MemberId=3, MemberName=Monica]
Member [MemberId=4, MemberName=Rachel]
Member [MemberId=5, MemberName=Joey]
Member [MemberId=6, MemberName=Sheldon]
Member [MemberId=7, MemberName=Amy]
Member [MemberId=8, MemberName=Sheldon]
Member [MemberId=9, MemberName=Harry]
Member [MemberId=10, MemberName=Ron]
Member [MemberId=11, MemberName=hermione]

This is fine if you only have to do it once. But suppose in the next five days there are 10 more people that want to join the club. Your club is really getting popular. You would have to make all these changes again and again. One way to solve this is to make a large enough array to hold a large number of members. But if you do not utilize all the spaces in an array they would just lie there harming your memory unnecessarily.

Again, consider this situation. Sheldon is annoying. All the members want him out. So they gather and take a vote. And they decide unanimously to kick Sheldon out of the club and they do. As he is no longer a club member you want to remove him from the member’s array and free up that slot for future use. You want to take him out of the array. How to do that?

You may think of something like this:

Of course, I take something out of the array. I say User sheldon = members[6];

and I get the User object at index 6 out of the array.

Okay, We’ll try to speak slowly so you can keep up. You did not, We repeat, did not remove that User from the array. All you did was duplicate the User reference and assign it to another User variable.

You made the situation worse. Now there are two of them.

We can apply another hack to remove Sheldon from the array. All we just have to do is remove the setters of members[5].

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}


public class BookClub {
    public static void main(String[] args) {

        //An array to hold 10 Member type variables
        Member[] members = new Member[11];
       
        // creating 10 members
        for (int i = 0; i < 11; i++) {
            members[i] = new Member();
        }
       
        // setting members ids and names

        members[0].setMemberId(1);
        members[0].setMemberName("Lucy");

        members[1].setMemberId(2);
        members[1].setMemberName("Aron");

        members[2].setMemberId(3);
        members[2].setMemberName("Monica");

        members[3].setMemberId(4);
        members[3].setMemberName("Rachel");

        members[4].setMemberId(5);
        members[4].setMemberName("Joey");

        members[6].setMemberId(7);
        members[6].setMemberName("Amy");

        members[7].setMemberId(8);
        members[7].setMemberName("Watson");

        members[8].setMemberId(9);
        members[8].setMemberName("Harry");

        members[9].setMemberId(10);
        members[9].setMemberName("Ron");

        members[10].setMemberId(11);
        members[10].setMemberName("hermione");

        // printing members informations
        for (Member member : members) {
           
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
           
        }

    }
}

Output

Member [MemberId=1, MemberName=Lucy]
Member [MemberId=2, MemberName=Aron]
Member [MemberId=3, MemberName=Monica]
Member [MemberId=4, MemberName=Rachel]
Member [MemberId=5, MemberName=Joey]
Member [MemberId=0, MemberName=null]
Member [MemberId=7, MemberName=Amy]
Member [MemberId=8, MemberName=Watson]
Member [MemberId=9, MemberName=Harry]
Member [MemberId=10, MemberName=Ron]
Member [MemberId=11, MemberName=hermione]

This is a very wrong approach. First of all, you should never change your already tested working code. It is not just OO. Once tested working code should not be changed.

Another one is that though we have successfully removed Sheldon from the array, the object we created to hold member[5] data is still there in the heap. It can not be removed from the heap by the Garbage collector as it is referenced by a variable(in this situation member[5]). In real-life array implementation we work with hundreds of thousands of array elements at the same time. So the storage issue becomes a severe one.

Some of you clever fellas already noticed that this is more trouble than it is worth. You can remove sheldon by referencing that element of the array to point null.

member[5] = null;

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}


public class BookClub {
    public static void main(String[] args) {

        //An array to hold 10 Member type variables
        Member[] members = new Member[11];
       
        // creating 10 members
        for (int i = 0; i < 11; i++) {
            members[i] = new Member();
        }
       
        // setting members ids and names

        members[0].setMemberId(1);
        members[0].setMemberName("Lucy");

        members[1].setMemberId(2);
        members[1].setMemberName("Aron");

        members[2].setMemberId(3);
        members[2].setMemberName("Monica");

        members[3].setMemberId(4);
        members[3].setMemberName("Rachel");

        members[4].setMemberId(5);
        members[4].setMemberName("Joey");

        members[5].setMemberId(6);
        members[5].setMemberName("Sheldon");

        members[6].setMemberId(7);
        members[6].setMemberName("Amy");

        members[7].setMemberId(8);
        members[7].setMemberName("Sheldon");

        members[8].setMemberId(9);
        members[8].setMemberName("Harry");

        members[9].setMemberId(10);
        members[9].setMemberName("Ron");

        members[10].setMemberId(11);
        members[10].setMemberName("hermione");

        members[5] = null;

        // printing members informations
        for (Member member : members) {
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
        }

    }
}

Output

Member [MemberId=1, MemberName=Lucy]
Member [MemberId=2, MemberName=Aron]
Member [MemberId=3, MemberName=Monica]
Member [MemberId=4, MemberName=Rachel]
Member [MemberId=5, MemberName=Joey]
Exception in thread "main" java.lang.NullPointerException
        at BookClub.main(BookClub.java:74)

java.lang.NullPointerException: This is where things start to get interesting. Reference variables can be set to null which means “I am referencing nothing”.  A reference variable can have a null value if you explicitly set it that way, or if it is uninitialized and the compiler does not catch it (Java will automatically set the variable to null). When you try to dereference a reference variable that has been set to null, either explicitly or automatically by Java, you get a NullPointerException. The NullPointerException (NPE) typically occurs when you declare a variable but do not create an object and assign it to the variable before attempting to use the variable’s contents. As a result, you have a reference to something that does not exist.

This makes sense right. Your members[5] variable(each element of an array is a variable) is set to refer to nothing so that the sheldon object may be garbage collected by heap. We know in Java memory is managed by Garbage Collector. If an object is not referenced by anything then the object is removed from the heap by GC. Your object is in a sense removed from the array. But when you try to print all the members in the array using an enhanced for loop then it tries to print the member’s information referenced by the members[5] variable.

        for (Member Member : members) {
            System.out.println("Member [MemberId=" + Member.getMemberId()+", MemberName="+Member.getMemberName()+"]");
        }
An addition of conditional statements may solve this problem.

for (Member member : members) {
    if(member != null){
            System.out.println("Member [MemberId=" + member.getMemberId()+", MemberName="+member.getMemberName()+"]");
    }
}

The output will be

Member [MemberId=1, MemberName=Lucy]
Member [MemberId=2, MemberName=Aron]
Member [MemberId=3, MemberName=Monica]
Member [MemberId=4, MemberName=Rachel]
Member [MemberId=5, MemberName=Joey]
Member [MemberId=7, MemberName=Amy]
Member [MemberId=8, MemberName=Watson]
Member [MemberId=9, MemberName=Harry]
Member [MemberId=10, MemberName=Ron]
Member [MemberId=11, MemberName=hermione]

Though this approach is great, we have not really freed up space for the array.

for (int i = 0; i < 11; i++) {
            members[i] = new Member();
        }

We still have 11 variables in the memory though we only need 10. We have removed the reference from member[5] to refer to a Member object but we have not freed up the extra space that is held by member[5].Though from a user perspective the code works just as expected, as a developer we know that this can not be an efficient solution.

Another problem comes if you want to find a member in the list you have to go through all the members in the array. This becomes cumbersome for you. You would be really mad if you had to search a list of 1000 members by yourself just to find one member in the array.

You are wondering “If only I could find an array that shrinks when something is removed. And one in which you don’t have to loop through each element to see if it contains what you’re looking for, but instead simply ask it. And it would allow you to take things out of it without knowing which slot they are in. That would be fantastic. But I know it’s all a dream…”.

image 29 - Java Application Programming Interfaces (APIs)

The Java Standard Edition (which you have) ships with hundreds of pre-built classes similar to our Ready-Bake code except that these pre-built classes have already been compiled.

That means no typing. Just use ‘em.

Some of the methods that the ArrayList class has:

image 30 - Java Application Programming Interfaces (APIs)

This is just a sample of SOME of the methods in ArrayList.

image 31 - Java Application Programming Interfaces (APIs)

class Member {
    private int MemberId;
    private String MemberName;

    public int getMemberId() {
        return MemberId;
    }

    public void setMemberId(int uid) {
        MemberId = uid;
    }

    public String getMemberName() {
        return MemberName;
    }

    public void setMemberName(String name) {
        MemberName = name;
    }

}

public class ArrayListDemo{
    public static void main(String[] args) {
        //Make One
        ArrayList<Member> membersList = new ArrayList<Member>();


        //Put Something in it        
        Member member1 = new Member();
        member1.setMemberId(1);
        member1.setMemberName("Lucy");
        membersList.add(member1);

        //Put another thing in it
        Member member2 = new Member();
        member1.setMemberId(2);
        member1.setMemberName("Aron");
        membersList.add(member2);

        //Find out if it contains something
        boolean isIn = membersList.contains(member1);

        //Find out where something is(i.e. its index)
        int index = membersList.indexOf(member2);

        //Find out if it's empty
        boolean empty = membersList.isEmpty();

        //Remove something from it
        membersList.remove(member1);
    }
}

Try to implement this idea in the BookClub program to solve the problems arising by arrays.

Though arrays and ArrayLists are both defined as objects, arrays lack the functionalities of a proper object. Arrays are also objects. They live on the heap alongside the other objects. Arrays, of course, go on the heap. Objects have states and behaviors. That is unmistakable. Have you ever tried calling a method on an array?

What method would you call, anyway? You are only interested in calling methods on the items you put in the array, not on the array itself. And you can use array syntax to add and remove items from an array. And you can not even properly remove the items from an array if you can at all.  ArraysList is a first-class object. It has methods and can do things like remove the Member’s reference from itself rather than simply setting it to null. And it can change its size on the fly (look it up). Try getting an array to do that!

You’ll notice that while you’re working with an ArrayList object, you’re just invoking regular old methods on a regular old object with the regular old dot operator.

You use special array syntax (like myList[0] = foo) with arrays that you won’t see anywhere else. Even though an array is an object, it exists in its own world and cannot be accessed via methods, though you can access its one and only instance variable, length.

Q: So ArrayList is cool, but how would I know it exists?

The real question is, “How do I know what’s in the API?” This is the key to your success as a Java programmer.

Not to mention your secret to being as lazy as possible while still building software.

You may be surprised at how much time you can save when someone else has done the majority of the heavy lifting and all you have to do is step in and create the fun part.

But we’re getting ahead of ourselves… The short answer is that you spend some time learning what’s in the core API. The long answer can be found at the end of this tutorial.

Q: But that is a significant issue. Not only do I need to know that the Java library includes ArrayList, but I also need to know that ArrayList is the thing that can do what I want! So, how do I go from a need-to-do-something to a way-to-do-something?

You’re now right in the heart of it. By the end of this course, you’ll have a good understanding of the language, and the rest of your learning curve will be about knowing how to get from a problem to a solution while writing the least amount of code. If you can wait for a few more pages, we will begin discussing it at the end of this tutorial.

How To Use The Java Library (Java API)?

You made all the way here. And now, as promised, we will teach you how to fool around in the Java library.

In the Java API, classes are grouped into packages.

To use a class in the API, you have to know which package the class is in.

Each class in the Java library is part of a package.

The package has a name, such as javax.swing (which contains some of the Swing GUI classes you’ll learn about soon). ArrayList is part of the java.util package, which contains a large number of utility classes. In a later tutorial, you’ll learn a lot more about packages, including how to include your own classes in your own packages. For the time being, we’re only interested in using some of the Java classes.

It is simple to use a class from the API in your own code. You simply treat the class as if you wrote it yourself… as if you compiled it, and it sits there, waiting for you to use it. One major difference: you must indicate the full name of the library class you want to use somewhere in your code, which means package name + class name.

Even if you weren’t aware of it, you’ve been using classes from a package. The java.lang package includes System (System.out.println), String, and Math (Math.random()).

Q: Why does there have to be a full name? Is that the only purpose of a package?

Packages are significant for three reasons. They first aid in the overall organization of a project or library. Instead of having one massive pile of classes, they’re all organized into packages for specific types of functionality (like GUI, or data structures, or database stuff, etc.) Second, packages provide namescoping, which can help prevent collisions if you and 12 other programmers in your company decide to create a class with the same name. If you have a Set class and someone else (including the Java API) has a Set class, you must tell the JVM which Set class you are attempting to use.

Third, packages provide some level of security because you can restrict the code you write so that it can only be accessed by other classes in the same package. You will learn this in a later tutorial.

Q: OK, back to the name collision thing. How does a full name really help? What’s to prevent two people from giving a class the same package name?

As long as developers follow the naming convention, Java usually prevents this from happening. We’ll go over this in greater detail in a later tutorial.

You have to know the full name of the class you want to use in your code. Unless the class is in the java.lang package.

ArrayList is not ArrayList’s full name, just as ‘Hermione’ is not a full name (unless it’s Madonna or Cher, but we won’t go there). ArrayList’s full name is actually:

java.util.ArrayList

You must specify which ArrayList you want to use. You have two choices:

IMPORT

Put an import statement at the top of your source code file:

import java.util.ArrayList;

public class MyClass {

          Your implementation code go here...

}

TYPE

Type the full name everywhere in your code. Each time you use it. Anywhere you use it.

When you declare and/or instantiate it:

java.util.ArrayList<Member> list = new java.util.ArrayList<Member>();

When you use it as an argument type:

public void go(java.util.ArrayList membersList) {

}

Q: OK, how come I never had to import the String class? Or System?

Remember, you get the java.lang package sort of “pre-imported” for free. Because the classes in java.lang are so fundamental, you don’t have to use the full name. There is only one java.lang.String class, and one java.lang.System class, and Java darn well knows where to find them.

How to play with the API?

Two things you want to know:

What classes are in the library?

Once you find a class, how do you know what it can do?

1. Browse A Book

Flipping through a reference book is the best way to learn about the Java library. Simply browsing pages can lead you to a class that appears to be useful.

2. Use the HTML API docs

The API documentation is the best resource for learning more about a class and its methods.

Assume you were browsing through the reference book and came across a class called Calendar in java.util. The book tells you enough about it to know that this is what you want to use, but you still need to know more about the methods.

The reference book, for example, tells you what arguments the methods accept and what they return. Consider the ArrayList class. The method indexOf(), which we used in the ArrayListDemo class, is documented in the reference book.

But even if you only knew that indexOf() takes an object and returns its index (an int), you still need to know one crucial thing: what happens if the object is not in the ArrayList?

The method signature alone will not tell you how that works. But the API documentation will (most of the time). According to the API documentation, the indexOf() method returns -1 if the object parameter is not in the ArrayList. That’s how we knew we could use it to check if an object is even in the ArrayList, as well as get its index if the object was present. Without the API documentation, we might have assumed that the indexOf() method would blow up if the object was not in the ArrayList.

Share The Tutorial With Your Friends
Twiter
Facebook
LinkedIn
Email
WhatsApp
Skype
Reddit

Check Our Ebook for This Online Course

Advanced topics are covered in this ebook with many practical examples.