As a self-taught java want to be a developer, this was quite a challenge at some point. “To connect pieces of learned knowledge and use it to create something useful” - I remember thinking along those lines and struggling to fulfil such task. At the beginning of my journey with learning how to code, after a couple of first steps on a path to become a software developer, I started learning through platform created for corporate businesses that send their minions to “up” their skills. I wasn’t really aware of it at that time but the way they approached subjects there was very much theory based. I remember learning about system development life cycles and differentiating many different approaches, not going deeply into that knowledge but rather touching it merely and moving on to the next big subject. After some time of that theory loading + basics of practical programming I got to know things like control flow statements, loops, classes, methods, Constructors, this() and super() + what it all means or roughly what it does in a programming language. Despite knowing all that, I felt like my knowledge is scattered around a variety of different concepts that I know and I still couldn’t say I have actually created something that works, like an Application. Since I struggled with it, I thought I can share “one of many ways” to create a super basic app, written in Java, and maybe help someone understand what do you need to do (type/create) in order to make a piece of code work and actually do something.

the goal

I wanted to share with you below source code to the most basic Mobile Phone application. It’s an application that logs contacts; names (+ their numbers) and creates a list of all those contacts. You can think about it as a very basic “address book” on your mobile phone. This app operates through console and you can control it by typing numbers or text into the console. Feel free to download source code from my GitHub repository. I will try to give some basic information about how it works and how it’s structured etc. but if you come across this basic “how to” and it’s not enough for you to grasp + you’d really like to understand fully what’s going on in that code, please comment or get in touch and I’ll try to help you as much as I can.

app objectives (or “clients specifications”)

Create program that implements a simple mobile phone that is able to store, modify, remove and query contact names. You will want to create a separate class for Contacts (name and phone number). Create a master class MobilePhone that holds the ArrayList of Contacts. The MobilePhone class has the functionality to store, modify, remove and query contact names. App should have a menu of options that are available to control it:

  • quit
  • print list of contacts
  • add new contact
  • update existing contact
  • remove existing contact
  • find contact

When adding or updating be sure to check if the contact already exists (use name). Be sure not to expose the inner working of the ArrayList to MobilePhone e.g. no ints, no .get(i) etc MobilePhone should do everything with Contact objects only.

SIDE NOTE: Normally, you probably won’t see objectives telling you want kind of tool to use in order to achieve something your client wants, but I assume I’m talking to a java newbie so it should be helpful to come around first barriers.

the code

Application consist of 3 Classes. Contact.java, MobilePhone.java and Main.java They are encapsulated, meaning all the internals of each class are not exposed to other Classes and there are methods with public access, that allow interaction with Class fields. All 3 classes are packaged inside the same package, so they all “see” each other unless you specify that a field, method or constructor are private.

Contact.java

Let’s start from the end. It’s always easier for me to start from the simplest building blocks that will comprise the whole application and then building further using those pieces. Imagine you’re building a house, in order to do so, you will need bricks and class Contact is exactly this.

Code:
public class Contact {

    // Fields

    public String name;
    public String phoneNumber;

    // Constructors

    public Contact(String name, String phoneNumber) {
        this.name = name;
        this.phoneNumber = phoneNumber;
    }

    // Methods

    public String getName() {
        return name;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public static Contact createContact(String name, String phoneNumber) {
        return new Contact(name, phoneNumber);
    }
}
Comments:
  • Fields name and phoneNumber - they will be holding information that will be typed in by the user. As specified in Clean Code names should describe well the purpose and that’s what I recommend.
  • Contructor - a generic constructor that accepts 2 parameters and assigns the values to fields accordingly.
  • Methods - just getters as after assigning values there won’t be a need to set any values (I told you it’s going to be a simple app, right?) + a special method public static Contact createContact(String name, String phoneNumber). This method is quite tricky, as you can see it takes the same parameters as Constructor does, and it returns Contact object. How tricky! It is essentially a method that when called, can produce Contact object, that has a name and a number. We will use it in our Main.java Class. Note it’s a static method therefore we will be able to use it in Main class.

Ok this should wrap up the first class. Looks very simple, right? But! there might be questions in the head of a Java newbie. Remember, you can spill them out below in comments or contact me to understand and learn how Java code works.

MobilePhone.java

Here we have our MobilePhone class, the purpose is to have code that represents a mobile phone, it can do things for us and in our case, it’s simply create new contacts, edit them, delete and search for in existing “database”. In our case it’s going to be a simple ArrayList. It’s something that already lives in Java code that comes with JDK and you can use it’s functionality. Essentially it’s allowing us to fairly easily manage an array, as there are quite a few limitations with primitive type filled arrays in Java, but to explain this I would need another post, so not diving into details here. Have a brief look at the whole Class code and below, I’ll address each field/method/constructor and explain what it does.

Code
import java.util.ArrayList;

public class MobilePhone {

    // Fields

    private ArrayList<Contact> myContacts;

    // Constructors

    public MobilePhone() {
        this.myContacts = new ArrayList<>();
    }

    // Methods

    public void printContacts() {
        System.out.println("You have " + myContacts.size() + " contacts in your Mobile phone.");
        for (int i = 0; i < this.myContacts.size(); i++) {
            System.out.println((i+1) + ". " + this.myContacts.get(i).getName() + " -> " +
                                              this.myContacts.get(i).getPhoneNumber());
        }
    }

    public boolean addNewContact (Contact contact) {
        if (findContact(contact.getName()) >= 0) {
            System.out.println("Contact is already on file");
            return false;
        }

        myContacts.add(contact);
        return true;
    }

    private int findContact(Contact contact) {
        return this.myContacts.indexOf(contact);
    }

    private int findContact(String contactName) {
        for (int i = 0; i < this.myContacts.size(); i++) {
            Contact contact = this.myContacts.get(i);
            if (contact.getName().equals(contactName)) {
                return i;
            }
        }
        return -1;
    }
	
    public Contact queryContact(String name) {
        int position = findContact(name);
        if (position >= 0) {
            return this.myContacts.get(position);
        }
        return null;
    }

    public boolean removeContact (Contact contact) {
        int foundPosition = findContact(contact);
        if (foundPosition < 0) {
            System.out.println(contact.getName() + ", was not found.");
            return false;
        }
        this.myContacts.remove(foundPosition);
        System.out.println(contact.getName() + " , was deleted.");
        return true;
    }

    public boolean updateContact (Contact oldContact, Contact newContact) {
        int foundPosition = findContact(oldContact);
        if (foundPosition < 0) {
            System.out.println(oldContact.getName() + ", was not found.");
            return false;
        } else if(findContact(newContact.getName()) != -1) {
            System.out.println("Contact with name " + newContact.getName() + " already exists. Update not successful.");
            return false;
        }

        this.myContacts.set(foundPosition, newContact);
        System.out.println(oldContact.getName() + " was replaced with " + newContact.getName());
        return true;
    }

}
Comments:

Ok, there’s a little bit to explain. So let’s do it piece by piece.

private ArrayList<Contact> myContacts;

Only one field, ArrayList, we create it to store all the contacts. It returns Contact and its name is myContacts. Simple so far. We are utilising created class Contact.

public MobilePhone() {
        this.myContacts = new ArrayList<>();
    }

We don’t have any other fields in our MobilePhone apart from ArrayList. All we need to do when MobileClass will be initiated, will be to also initiate our myContacts ArrayList, so that’s all we do in our Constructor code.

public void printContacts() {
        System.out.println("You have " + myContacts.size() + " contacts in your Mobile phone.");
        for (int i = 0; i < this.myContacts.size(); i++) {
            System.out.println((i+1) + ". " + this.myContacts.get(i).getName() + " -> " +
                                              this.myContacts.get(i).getPhoneNumber());
        }
    }

Next piece is a method called printContacts. We want to have an option to print all of our contacts to console and we deal with it here. Firstly we display message about how many contacts are in our ArrayList and if there’s 0 our for loop will start and stop as 0 is not less than 0. If we have at least one contact, for loop will iterate once printing contacts name and phone number. Notice we use .get(i) method to access each element of ArrayList and then we use getters from Contact class we created already.

public boolean addNewContact (Contact contact) {
        if (findContact(contact.getName()) >= 0) {
            System.out.println("Contact is already on file");
            return false;
        }

        myContacts.add(contact);
        return true;
    }

Next we have to create a way to add new contacts. We create method addNewContact. We return boolean primitive value and accept Contact instance as a parameter. In the code above we first check if contact we try to add already exists. It’s certainly a job for internal method, we call it findContact. If you’re curious how it works, scroll down. I explain it further. Now that we know that contact already exists in our ArrayList, we display message to user and return value false. If findContact() returns false we go ahead and add new item to myContacts using .add(contact) method with parameter supplied and return true value.

private int findContact(Contact contact) {
        return this.myContacts.indexOf(contact);
    }

Now we create method we used already in method above. The idea is to find out if we already have contact in our list. As you probably guessed already it’s a method that is being used only internally in MobilePhone class, so we hide it from other classes and make it a private method. This method has to return and int as we are utilising .indexOf method that returns int value. It’s a method that’s supplied within ArrayList we import from Java JDK. The way it workds is it checks if supplied object already is on ArrayList and if yes, it returns value -1 if not, it returns it’s index number on the list. If you go back to previous method, you will see our if() is checking if value returned is <= to 0. How smart, eh?

private int findContact(String contactName) {
    for (int i = 0; i < this.myContacts.size(); i++) {
        Contact contact = this.myContacts.get(i);
        if (contact.getName().equals(contactName)) {
            return i;
        }
    }
    return -1;
}
	
public Contact queryContact(String name) {
    int position = findContact(name);
    if (position >= 0) {
        return this.myContacts.get(position);
    }
    return null;
}

If you remember well, we also wanted to have option to search our Address Book, therefore we have to Overload our method findContact as user probably won’t remember each person number in the Address book, rather a name. Therefore we create private int finContact (String contactName) method. That we will be used in public Contact queryContact (String name). Notice first method is private as it will be used internally only. Second method will be used in our Main.java application starting Class. The way queryContact works is it assigns index number to position. If number is less than 0, it will return null if not, it returns object using position to point to it.

The overloaded method findContact loops over the whole ArrayList and looks for a match. For loop goes as many times as the .size() of current list is. Inside the loop we create contact object and assign with each record iterating with i iterator each time loop goes around. Next, we compare current contact name with our supplied parameter contactName if it .equals we return i number (which will become position in our queryContact method), if none fits, we will return value -1. So our method works very similarly to .indexOf we already used. This time we wrote it ourselves.

Phew, this takes time, no? Maybe that’s why they pay developers such good money these days, me thinks now. Onto the next part.

public boolean removeContact (Contact contact) {
        int foundPosition = findContact(contact);
        if (foundPosition < 0) {
            System.out.println(contact.getName() + ", was not found.");
            return false;
        }
        this.myContacts.remove(foundPosition);
        System.out.println(contact.getName() + " , was deleted.");
        return true;
    }

Here we create next method to remove record from our list. We return boolean value and accept Contact object. Again we use method we already used to find out if we have record we want to remove. If not, we notify user with a message about contact that isn’t on the list, otherwise we go on and use .remove method that comes with ArrayList and we supply it with foundPosition we already established with help of findContact method. We print “success” message and return true. Record deleted. Hurray!

Next

public boolean updateContact (Contact oldContact, Contact newContact) {
        int foundPosition = findContact(oldContact);
        if (foundPosition < 0) {
            System.out.println(oldContact.getName() + ", was not found.");
            return false;
        } else if(findContact(newContact.getName()) != -1) {
            System.out.println("Contact with name " + newContact.getName() + " already exists. Update not successful.");
            return false;
        }

        this.myContacts.set(foundPosition, newContact);
        System.out.println(oldContact.getName() + " was replaced with " + newContact.getName());
        return true;
    }

Here we implement method to deal with updating existing contact. This method accepts old contact and new contact as a parameter and swaps them if old contact exists in the ArrayList -> myContacts. We first utilise our findContact method to check if oldContact exists in our array list. If yes we then check if our new contact name exists in address book. If not we succesfully swap contacts. Every step returns message to console to inform user about what is happening.

Ok! We’ve done our MobilePhone.java class. Now’s the time to create some code in Main.java class and start using our app.

Main.java

It’s where the code that creates the app resides. All the functionality behind is done, now we have to use main method and type in some helper methods to start up the class. We will also use Scanner class from java libraries to scan user input from console and feed our code with it. This class will implement and use all methods we created in previous classes. Let’s dive in:

Code
import java.util.Scanner;

public class Main {

    // Fields

    private static Scanner scanner = new Scanner(System.in);

    private static MobilePhone mobilePhone = new MobilePhone();

    // Methods

    public static void main(String[] args) {
        boolean quit = false;
        startPhone();
        printActions();
        while (!quit) {
                System.out.println("\nEnter action: (6 for menu)\n");
                int action = scanner.nextInt();
                scanner.nextLine();

            switch (action) {
                case 0:
                    System.out.println("\nShutting down..");
                    quit = true;
                    break;
                case 1:
                    mobilePhone.printContacts();
                    break;
                case 2:
                    addNewContact();
                    break;
                case 3:
                    updateContact();
                    break;
                case 4:
                    removeContact();
                    break;
                case 5:
                    queryContact();
                    break;
                case 6:
                    printActions();
                    break;
            }
        }
    }

    private static void startPhone() {
        System.out.println("Starting Phone...");
    }

    private static void printActions() {
        System.out.println("\nAvailable actions:\npress");
        System.out.println("0 - to shutdown\n" +
                "1 - to print contacts\n" +
                "2 - to add a new contact\n" +
                "3 - to update an existing contact\n" +
                "4 - to remove an existing contact\n" +
                "5 - query if an existing contact exists\n" +
                "6 - to print a list of available actions\n");
        System.out.println("Choose your action: ");

    }

    private static void addNewContact() {
        System.out.println("Enter new contact name: ");
        String name = scanner.nextLine();
        System.out.println("Enter phone number: ");
        String phone = scanner.nextLine();

        Contact newContact = Contact.createContact(name,phone);
        if (mobilePhone.addNewContact(newContact)) {
            System.out.println("New contact added: " + name + ", number: " + phone);
        } else {
            System.out.println("Cannot add, " + name + " already in file");
        }

    }

    private static void updateContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if(existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }

        System.out.println("Enter new contact name: ");
        String newName = scanner.nextLine();
        System.out.println("Enter new contact phone number: ");
        String newNumber = scanner.nextLine();

        Contact newContact = Contact.createContact(newName,newNumber);
        if(mobilePhone.updateContact(existingContactRecord,newContact)) {
            System.out.println("Successfully updated record");
        } else {
            System.out.println("Error updating record");
        }

    }

    private static void removeContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if (existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }

        if (mobilePhone.removeContact(existingContactRecord)) {
            System.out.println("Successfully removed contact");
        } else {
            System.out.println("Error while removing record");
        }
    }

    private static void queryContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if (existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }
        System.out.println("Name: "+ existingContactRecord.getName() +
                " phone number is " + existingContactRecord.getPhoneNumber());
    }

}
Comments

Notice: All our Main class methods are private (apart from main method obviously). Can you guess why? Yes! It’s because we don’t need to expose them to any other class. It’s like “the end” class, no other class will ever use those methods other than our Main class.

Ok, Let’s cut this code and do it piece by piece again.

We create two static fields:

	private static Scanner scanner = new Scanner(System.in);

    private static MobilePhone mobilePhone = new MobilePhone();

Firstly, we create an instance of a Scanner as we will need it to scan user input (System.in), as mentioned above. Secondly we will need an instance of our MobilePhone.java class to get access to all the code we typed in that class. Both fields are static so it means they have access to static methods that are waiting to be dissected by us.

public static void main(String[] args) {
        boolean quit = false;
        startPhone();
        printActions();
        while (!quit) {
            System.out.println("\nEnter action: (6 for menu)\n");
            int action = scanner.nextInt();
            scanner.nextLine();

            switch (action) {
                case 0:
                    System.out.println("\nShutting down..");
                    quit = true;
                    break;
                case 1:
                    mobilePhone.printContacts();
                    break;
                case 2:
                    addNewContact();
                    break;
                case 3:
                    updateContact();
                    break;
                case 4:
                    removeContact();
                    break;
                case 5:
                    queryContact();
                    break;
                case 6:
                    printActions();
                    break;
            }
        }
    }

This is our main method. It is the backbone of our app. Very simple code but it gave me perspective on how an app actually runs constantly. As you can see it’s got a switch statement which is enclosed inside a never ending while loop. The loop ends only if user selects option 0. This means our boolean quit field becomes true and effectively our loop doesn’t go for another spin. At the beginning of our main method we see information that prompts us to choose the number and then our scanner is trying to catch and store users input inside action field. When that happens our switch takes it as a parameter and runs matching case. There is no try/catch implemented here, so if user types any text value, app crashes. (I think I’ve said it’s a very simple app, twice, no? ;) As you can see there are methods underneath each “button” and we will dive into each one of them below.

private static void startPhone() {
        System.out.println("Starting Phone...");
    }

    private static void printActions() {
        System.out.println("\nAvailable actions:\npress");
        System.out.println("0 - to shutdown\n" +
                "1 - to print contacts\n" +
                "2 - to add a new contact\n" +
                "3 - to update an existing contact\n" +
                "4 - to remove an existing contact\n" +
                "5 - query if an existing contact exists\n" +
                "6 - to print a list of available actions\n");
        System.out.println("Choose your action: ");

    }

Ok, I believe there’s nothing to add when it comes to startPhone and printActions methods. They are pretty straightforward. Next.

private static void addNewContact() {
        System.out.println("Enter new contact name: ");
        String name = scanner.nextLine();
        System.out.println("Enter phone number: ");
        String phone = scanner.nextLine();

        Contact newContact = Contact.createContact(name,phone);
        if (mobilePhone.addNewContact(newContact)) {
            System.out.println("New contact added: " + name + ", number: " + phone);
        } else {
            System.out.println("Cannot add, " + name + " already in file");
        }

    }

Method addNewContact is utilising our addNewContact method from MobilePhone Class to check if we already have same contact in ArrayList. I guess you noticed those methods are named the same. It might be confusing at the beginning. The reason for this is, we wouldn’t like to have that many lines of code inside our switch statement and here it fits perfectly. Don’t be deceived by same name because those two methods are doing different things.

First part of code records name and phone from user input and stores that in according fields. Then we create new Contact object by calling our “sassy” method from Contact Class called createContact. As you remember this method, returns new Contact object utilising Contact classes Constructor. Next we check if contact supplied by user already is in list.

private static void updateContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if(existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }

        System.out.println("Enter new contact name: ");
        String newName = scanner.nextLine();
        System.out.println("Enter new contact phone number: ");
        String newNumber = scanner.nextLine();

        Contact newContact = Contact.createContact(newName,newNumber);
        if(mobilePhone.updateContact(existingContactRecord,newContact)) {
            System.out.println("Successfully updated record");
        } else {
            System.out.println("Error updating record");
        }

    }

Let’s dissect updateContact method. Name as always explains purpose of our private method. We start by asking user and then registering input in local field name. Next we use queryContact supply it with freshly captured name and assign return to local object existingContactRecord. Now we have a record, if it’s null we know it could not been found and therefore we can return “not found” to user and stop the function. Otherwise if found, we need to find out newName and newNumber to then go ahead and create newContact that will be supplied to updateContact method from our MobilePhone class. This method will effectively change records and return true which will invoke message “Successfully updated record” voila! records updated.

private static void removeContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if (existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }

        if (mobilePhone.removeContact(existingContactRecord)) {
            System.out.println("Successfully removed contact");
        } else {
            System.out.println("Error while removing record");
        }
    }

Here we start by capturing name from user input again. Then we go and create Contact object that should hold value null if mobilePhone.queryContact can’t find name supplied by user. If it happens, message “Contact not found.” gets displayed and return effectively ends whole process. If not, we go on to use removeContact (supplying it with existingContactRecord object) method from our previous MobilePhone class which returns boolean value. As you can see the structure is pretty similar to previous method.

On to the last bit..

private static void queryContact () {
        System.out.println("Enter existing contact name: ");
        String name = scanner.nextLine();
        Contact existingContactRecord = mobilePhone.queryContact(name);
        if (existingContactRecord == null) {
            System.out.println("Contact not found.");
            return;
        }
        System.out.println("Name: "+ existingContactRecord.getName() +
                " phone number is " + existingContactRecord.getPhoneNumber());
    }

Method queryContact from Main utilises queryContact from MobilePhone to create existingContactRecord. If it exists it Prints records name and phone. Easy.

Sum up

I hope you’ve been able to download, run and see how the app is actually working. I remember feeling extremely good after using it as it felt like I have created a first useful “thing”. If you’re struggling, use communication channels and I will teach you how to make it all work if needed.