Test a REST API with Java | Baeldung

<br>

Table of Contents
  • 1. Overview
  • 2. Testing the Status Code
  • 3. Testing the Media Type
  • 4. Testing the JSON Payload
  • 5. Utilities for Testing
  • 6. Dependencies
  • 7. Conclusion


1. Overview

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

The main goal is to provide an introduction to testing the basic correctness of the API – and we’re going to be using the latest version of the GitHub REST API for the examples.

For an internal application, this kind of testing will usually run as a late step in a Continuous Integration process, consuming the REST API after it has already been deployed.

When testing a REST resource, there are usually a few orthogonal responsibilities the tests should focus on:

  • the HTTP response code
  • other HTTP headers in the response
  • the payload (JSON, XML)

Each test should only focus on a single responsibility and include a single assertion. Focusing on a clear separation always has benefits, but when doing this kind of black box testing it’s even more important, as the general tendency is to write complex test scenarios in the very beginning.

Another important aspect of the integration tests is adherence to the Single Level of Abstraction Principle – the logic within a test should be written at a high level. Details such as creating the request, sending the HTTP request to the server, dealing with IO, etc should not be done inline but via utility methods.


2. Testing the Status Code


@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {
  
   // Given
   String name = RandomStringUtils.randomAlphabetic( 8 );
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
 
   // When
   HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );
 
   // Then
   assertThat(
     httpResponse.getStatusLine().getStatusCode(),
     equalTo(HttpStatus.SC_NOT_FOUND));
}


This is a rather simple test – it verifies that a basic happy path is working, without adding too much complexity to the test suite.

If for whatever reason, it fails, then there is no need to look at any other test for this URL until this is fixed.


3. Testing the Media Type


@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {
  
   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}


4. Testing the JSON Payload
@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {
  
    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}


In this case, I know the default representation of GitHub resources is JSON, but usually, the Content-Type header of the response should be tested alongside the Accept header of the request – the client asks for a particular type of representation via Accept, which the server should honor.


5. Utilities for Testing

We’re going to use Jackson 2 to unmarshall the raw JSON String into a type-safe Java Entity:

public class GitHubUser {
 
    private String login;
 
    // standard getters and setters
}


We’re only using a simple utility to keep the tests clean, readable and at a high level of abstraction:

public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz) 
  throws IOException {
  
    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}


Notice that Jackson is ignoring unknown properties that the GitHub API is sending our way – that’s simply because the Representation of a User Resource on GitHub gets pretty complex – and we don’t need any of that information here.

6. Dependencies

The utilities and tests make use of the following libraries, all available in Maven central:

  • HttpClient
  • Jackson 2
  • Hamcrest (optional)

7. Conclusion

This is only one part of what the complete integration testing suite should be. The tests focus on ensuring basic correctness for the REST API, without going into more complex scenarios,

For example, the following are not covered: Discoverability of the API, consumption of different representations for the same Resource, etc.



Introduction programming Models for Servers in Java

Introduction programming Models for Servers in Java

Very often, our applications don't need to handle thousands of users in parallel or process hundreds of thousands of messages in one second. We just need to cope with tens or hundreds of concurrently connected users, let's say in our internal application or some microservice application that's not supposed to be under such a big load.

In this case, we can use some high-level frameworks/libraries that are not as optimized in terms of the threading model/used memory, and still, we can withstand that load with some reasonable resources and pretty quick delivery time.

However, from time to time, we encounter situations where a piece of our system needs to be scaled better than the rest of the applications. Writing this part of our system by the traditional way or frameworks could lead to huge resource consumption, and a lot of instances of the same service would need to be started to handle the load. The algorithms and approaches that lead to the ability to handle tens of thousands of connections are also called the** C10K problem.**

In this article, I'm going to focus mainly on optimizations that can be done in terms of TCP Connections/Traffic to tune your (micro)service instance to waste as few resources as possible, go deeper into how the OS works with TCP and Sockets, and, last but not least, how to gain an insight into all of these things. Let's get started.

I/O Programming Strategies

Let's describes what kind of I/O programming models we currently have and from what options we need to choose when we design our application. First of all, there is no Good or Bad approach, just approaches that fit better into our current use case. Choosing the wrong approach can have very inconvenient consequences in the future. It can result in wasted resources or even re-writing your application from scratch.

Blocking I/O With Blocking Processing

Thread-per-Connection Server

The idea behind this approach is that the Socket Connection is not accepted (we will show later what does it mean) without any dedicated/free thread. Blocking, in this case, means that the particular thread is tied to the connection and blocks always when it reads from, or writes to, the connection.

public static void main(String[] args) throws IOException {
    try (ServerSocket serverSocket = new ServerSocket(5050)) {
        while (true) {
            Socket clientSocket = serverSocket.accept();
            var dis = new DataInputStream(clientSocket.getInputStream());
            var dos = new DataOutputStream(clientSocket.getOutputStream());
            new Thread(new ClientHandler(dis, dos)).start();
        }
    }
}

The simplest version of a Socket Server that starts on a port 5050 and reads from InputStream and writes to OutputStream in a blocking way. Useful when we need to transfer a small number of objects via a single connection then close it start a new when whenever it's needed.

  • It can be implemented even without any high-level library.

  • Reading/writing using blocking streams (waiting on blocking InputStream read operation that fills a provided byte array by bytes that are available in TCP Receive Buffer at that time and returns the number of bytes or -1 - the end of the stream) and consuming bytes until we have enough data to construct a request.

  • A big problem and inefficiency can come when we start creating threads for incoming connections unbounded way. We will pay a price for very expensive thread creation and memory impact that comes hand in hand with mapping one Java Thread to one Kernel Thread.

  • It's not suitable for "real" production unless we really need an application with a low-memory footprint and don't want to load a lot of classes belonging to some frameworks.

Non-Blocking I/O With Blocking Processing

Thread-Pool Based Servers

This is a category that the majority of well-known enterprise HTTP Servers belong to. In general, this model uses several Thread-Pools to make processing more efficient in the multi-CPUs environment and more suitable for enterprise applications. There are several ways how thread-pools can be configured but the basic idea is absolutely the same in all HTTP servers. Please, see HTTP Grizzly I/O Strategies for all possible strategies that can be usually configured in terms of Thread-Pool based non-blocking servers.

  • The first thread-pool for accepting new connections. It can be even a single-threaded pool if one thread is able to manage the speed of incoming connections. There are usually two backlogs that can be filled up and next incoming connections rejected. Check if you properly use persistent connections if it's possible.

  • The second thread pool for reading/writing from/to the socket by the non-blocking way (selector threads or IO threads). Every selector thread handles multiple clients (channels).

  • The third thread pool that separates the non-blocking and blocking parts of the request processing (usually called worker threads). The Selector thread cannot be blocked by some blocking operation because all other channels wouldn't be able to make any progress (there is only one thread for the group of channels and this thread would be blocked).

  • Non-blocking reading/writing is implemented using buffers, selector threads read new bytes from the socket and write into dedicated buffers (pooled buffers) as long as particular threads handling the request are not satisfied (because they don't have enough data to construct e.g. HTTP request).

  • We need to clarify the term NON-BLOCKING:

  • If we talk in the context of Socket Servers, then non-blocking means that threads are not tied to opened connections and don't wait for incoming data (or even writing data if TCP Send Buffers are full), just try to read and if there are no bytes then no bytes are added into buffers for further processing (constructing the request) and the given selector thread proceeds with reading from another opened connection.

  • However, in terms of processing the request, the code is in most cases BLOCKING, which means that we execute some piece of code that blocks the current thread and this thread waits for completion of I/O-bound processing (database query, HTTP invocation, reading from disk, ..) or some long-lasting CPU-bound processing (computing hashes/factorial, crypto mining, ..). If the execution is completed then the thread is woken up and proceeds in some business logic.

  • The BLOCKING nature of our business logic is the main reason why worker-pools are so huge, we just need to get plenty of threads into play to increase throughput. Otherwise, in case of higher load (e.g. more HTTP Requests), we could end up with all threads in blocked state and with no available thread for request processing (there are no threads in Runnable State to be ready for an execution on CPU).

Advantages

  • Even if the number of requests is pretty high and a lot of our worker threads are blocked on some blocking operation, we are able to accept new connections, even if we are probably not able to handle their request immediately and data must wait in TCP Receive Buffers.

  • This programming model is used by many frameworks/libraries (Spring Controllers, Jersey, ..) and HTTP Servers (Jetty, Tomcat, Grizzly ..) under the hood because it's very easy to write business code and let the threads block if it's really needed.

Disadvantages

  • Parallelism is not usually determined by the number of CPUs but is very limited by the nature of blocking operations and the number of worker threads. In general, it means that if the time ratio of a blocking operation (I/O) and further execution (during the request process) is too high, then we can end up with:

    • A lot of blocked threads on a blocking operation (database query, ..) and

    • A lot of request waiting for a worker thread to be processed and

  • CPU that is very unutilized because of no thread can proceed further in its execution
  • Bigger thread pools lead to context-switching and inefficient use of CPU caches
How to Set Up Your Thread Pools

Ok, we have one or multiple Thread-pools for handling blocking business operations. However, what is the optimal size of the thread-pool? We can encounter two problems:

  • The thread-pool is too small and we don't have enough threads to cover the time when all threads are blocked, let's say waiting for I/O operations, and your CPUs are not effectively used.

  • The thread-pool is too big and we pay a price for a lot of threads that are actually idle (see below what is the price when we run a lot of threads).

I would refer to a great book **Java Concurrency in Practice **from Brian Goetz that says that sizing thread pools is not the exact science, it's more about understanding your environment and the nature of your tasks.

  • How many CPUs and how much memory your environment have?

  • Do tasks perform mostly computation, I/O, or some combination?

  • Do they require a scarce resource (JDBC connection)? Thread pool and connection pool would influence each other and probably does not make sense to increase the thread pool to get better throughput when we fully utilize the connection pool.

If our program contains I/O or other blocking operations, you need a larger pool because your threads are not allowed to be placed on CPU all the time. You need to estimate the ratio of waiting time to compute time for your tasks using some profilers or benchmarks and observe CPU utilization in different phases of your production workload (peak time vs. off-peak).

Non-Blocking I/O With Non-Blocking Processing

Servers Based on the Same Number of Threads as CPU Cores

This strategy is the most efficient if we are able to manage the majority of our workload in a non-blocking way. That means that handling our socket (accepting connections, reading, writing) is implemented using a non-blocking algorithm but even business processing does not contain any blocking operations.

The typical representative for this strategy is Netty Framework, therefore let's dive into the architectural basics of how this framework is implemented to be able to see why it's the best fit for solving the C10K problem. If you want to dive into details how it really works then I can recommend the resources below:

  • Netty in Action - written by the author of Netty Framework Norman Mauer. It's a great resource to get know how to implement clients or servers based on Netty using handlers with various protocols.

  • User Guide for 4.x - a sample application in Netty that shows all basic principles.

I/O Library With an Asynchronous Programming Model

Netty is an I/O library and framework that simplified non-blocking IO programming and provide an asynchronous programming model for events that will happen during the lifecycle of the server and incoming connections. We just need to hook up to the callbacks with our lambdas and we get everything for free.

A lot of protocols are ready to use without having a dependency on some huge library

It's very discouraging to start building an application with pure JDK NIO but Netty contains features that keep programmers on a lower level and provide a possibility to make a lot of things much more efficient. Netty already contains the majority of well-known protocols which means we can work with them much more efficiently than in higher-level libraries (e.g. Jersey/Spring MVC for HTTP/REST) with a lot of boilerplate.

Identify the right non-blocking use-cases to fully utilize the power of Netty

I/O processing, protocol's implementation, and all other handlers are supposed to use non-blocking operations to never stop the current thread. We can always use an additional thread pool for blocking operations. However, if we need to switch processing of our every request to the dedicated thread pool for blocking operations then we barely utilize the power of Netty because we very likely end up in the same situation as with Non-Blocking IO with Blocking Processing - one big thread-pool just in a different part of our application.

On the picture above, we can see the main components that are parts of Netty Architecture

  • EventLoopGroup — gathers event loops and provides channels to be registered to one of the event loops.

  • EventLoop — handles all I/O operations for the registered Channels for the given event loop. EventLoop runs only on one thread. Therefore, the optimal number of event loops for one EventLoopGroup is the number of CPUs (some frameworks use a number of CPUs + 1 to have additional thread when Page Fault occurs).

  • Pipeline —keeps an execution order of handlers (components that are ordered and executed when some input or output event occurs, contains the actual business logic). Pipeline and handlers are executed on the thread belonging to EventLoop, therefore, the blocking operation in handlers blocks all other processing/channels on the given EventLoop.

Thank you for reading

Learn Java Programming - Java Tutorial For Beginners

Learn Java Programming - Java Tutorial For Beginners

Learn Java Programming in simple and easy steps starting from basic to advanced

Now, let us move ahead in this Java Tutorial, where we will understand each aspect of Java in the following sequence:
Hello World ProgramMember variables in JavaData types and operatorsControl StatementsClasses & ObjectsStructure of a programArraysOOPs concept – Inheritance, Encapsulation, Polymorphism, Abstraction
Let’s get started

Hello World Program

First of all, I will give you a simple overview of how a Java program looks like. In the below code, I have created a class – MyFirstJavaProgram and printed “Hello World”. Go ahead and try to execute the below example in your Eclipse IDE. Do not worry, we will discuss about Java class in a while.

public class MyFirstJavaProgram {
       public static void main(String[] args)
   {
    System.out.println("Hello World");
   }
} 

Next, let us understand different member variables in Java.

Java Tutorial: Member Variables

A member variable plays a major role in a class as it is used to store a data value. When we define a class, we can declare a member variable. These variables are members of a class.

Member variables are further classified into three types:
Local variableInstance variableClass/Static variable
Let me discuss about each one of them:

Local variable: These are the variables which are declared within the method of a class. Let’s understand this with a programmatic example:

public class Car {
      public void display(int m){  // Method
           int model=m;                 // Created a local variable model
           System.out.println("Model of the car is" +model);
     }

In the above code, my local variable is ‘model’ which I have declared inside a method ‘display’ which has a parameter ‘m’.

Instance variable: Instance variable is declared in a class but outside a method, constructor or any block. Let’s understand this with a programmatic example.

public class Car {
      public String color;     // Created an instance variable color
     
Car(String c)
   {
    color=c;
   }
 
public void display() {  // Method
      System.out.println("color of the car is"+color);
   }
 
public static void main(String args[]){
              Car obj=new Car("black");
                obj.display();
       }
}

In the above code, ‘color’ is my instance variable which has a value “black” associated to it.

Class variable: Class variables are also called as static variables. These variables have only one copy that is shared by all the different objects in a class. Let’s understand this with a programmatic example.

public class Car {
      public static int tyres;   // Created a class variable tyres
        public static void main(String args[]){
           tyres=4;
           System.out.println("Number of tyres are"+tyres);
        }
}

All cars must be having 4 tyres, right? So in my above code, I have declared a static variable as ‘tyre’ whose value remains same throughout the class.

Let’s move ahead in this Java Tutorial blog and look at our next topic i.e data types and operators in Java.

**Java Tutorial: Data types **

A data type is used to represent different values which are stored in a variable. They are mainly classified into 4 different aspects – Integer, Float, Character and Boolean. You can refer to the below image to understand the different data types with respect to the memory allocated to them.

As you can see in the above image, data types are of 4 major types.
The first data type is an Integer which stores a numerical value.Now, if a numerical value contains decimal part, it will be referred as float.Next, if you wish to store a character, then the third data type i.e char is used. In char, you can store any alphabetical character as well as a special character.The last data type is Boolean which stores only ‘true’ or ‘false’ value.
Let’s move forward and look at the various data operations which you can perform in Java.

Java Tutorial: Data Operators

There are mainly 4 different types of operators, which are listed below:

  • Arithmetic Operator: Perform arithmetic operations such as addition, subtraction, multiplication, division and modulus.
  • Unary Operator: Unary operators are used to increment or decrement a particular value. For example: ++ stands for increment, – – stands for decrement.
  • Relational Operator: It defines some kind of relation between two entities. For example: <, >, <=, >=, !=, ==.
  • Logical Operator: Logical operators are typically used with boolean (logical) values.

Next, let us move forward in Java Tutorial blog and understand the concept of control statements.

Java Tutorial: Control statements

Control statements are the statements that define the flow of your program. There are 3 types of control statements in Java: Selection, iteration and jump statements.

Lets see these control statements one by one.

**Selection Statements: **Selection statements allow you to control the flow of the program during run time on the basis of the outcome of an expression or state of a variable. For example: you want to eat pizza, but then where can you get that pizza in best price. You can select between various popular options like Domino’s, Pizza Hut or any other outlet. So here you are following a selection process from the various options available.

Now these statements can be further classified into the following:
If-else StatementsSwitch Statements
Refer to the following flowchart to get a better understanding of if-else statements:

In this flowchart, the code will respond in the following way:
First of all, it will enter the loop where it checks the condition.If the condition is true, the set of statements in ‘if’ part will be executed.If the condition is false, the set of statements in the ‘else’ part will be executed.
Here you must have got an idea of how these if-else statements work. Now, how can we use these statements in Eclipse IDE? Let’s have a look at the code:

public class Compare {
     int a=10,
     int b=5;
  
if(a>b)
      {  // if condition
     System.out.println(" A is greater than B");
      }
else
      {     // else condition
      System.out.println(" B is greater");
      }
}

In the above code, I have created a class Compare where I have compared two numbers ‘a’ and ‘b’. First of all, it will go in ‘if’ condition where it checks whether the value of ‘a’ is greater than ‘b’ or not. If the condition is true, it will print “A is greater than B” else it will execute “B is greater”.

Moving on, we have Switch case statement. The switch statement defines multiple paths for execution of a set of statements. It is a better alternative than using a large set of if-else statements as it is a multi-way branch statement.

Refer to the following flowchart to get a better understanding of switch statements:

In this Switch case flowchart, the code will respond in the following steps:
First of all it will enter the switch case which has an expression.Next it will go to Case 1 condition, checks the value passed to the condition. If it is true, Statement block will execute. After that, it will break from that switch case.In case it is false, then it will switch to the next case. If Case 2 condition is true, it will execute the statement and break from that case, else it will again jump to the next case.Now let’s say you have not specified any case or there is some wrong input from the user, then it will go to the default case where it will print your default statement.
Again, if we look at the code for switch statements in IDE, here it is:

public class SwitchExample {
     int week=7;
     String weeknumber;
 
switch(week){    // switch case
case 1:
          weeknumber="Monday";
       break;
     
case2:
          weeknumber="tuesday";
       break;
 
case3:
          weeknumber="wednesday";
       break;
 
default:        // default case
          weeknumber="invalid week";
       break;
     }
  System.out.println(weeknumber);
     }
}

In the above code, I have created a class SwitchExample which has 3 cases that print days of a week. It also has a default case which is executed whenever a user doesn’t specify a case.

Concluding both of the selection statements, we understood that if we are comparing two statements, we are using if-else, but let’s say if you are checking a specific value against a particular statement, then we are going for the Switch statement.

Next, there is another set of control statements, i.e Iteration Statements.

**Iteration Statements: **In Java, these statements are commonly called as loops, as they are used to iterate through small pieces of code. Iteration statements provide the following types of loop to handle looping requirements.

Let’s understand each one of them in detail:
While statement: Repeat a group of statements while a given condition is true. It tests the condition before executing the loop body. Let’s understand this better with a flow chart:

In this flowchart, the code will respond in the following steps:

  1. First of all, it will enter the loop where it checks the condition.
  2. If it’s true, it will execute the set of code and repeat the process.
  3. If it’s False, it will directly exit the loop.

Now, let us see how you can implement the code in IDE.

public class WhileExample {
      public static void main(String args[]) {
         int a=5;
   while(a<10)   //while condition
         {
         System.out.println("value of a" +a);
         a++;
   System.out.println("
");
         }
    }
}

In the above code, it first checks the condition whether the value of a is less than 10 or not. Here, the value of a is 5 which in turn satisfy the condition, and thus perform functions.
Do-while statement: It is like a while statement, but it tests the condition at the end of the loop body. Also, it will executes the program at least once. Let’s understand this better with a flow chart:

In this do-while flowchart, the code will respond in the following steps:
First of all, it will execute a set of statements that is mentioned in your ‘do’ block.After that, it will come to ‘while’ part where it checks the condition.If the condition is true, it will go back and execute the statements.If the condition is false, it will directly exit the loop.
Let’s see how you can implement the code in IDE.

public class DoWhileExample {
      public static void main(string args[]){
          int count=1;
do {                        // do statement
     System.out.println("count is:"+count);
     count++;
   }
 while (count<10)            // while condition
       }
  }

In the above code, it will first execute the ‘do’ statements and then jump to the while part. In this program, the output would be : 1 2 3 4 5 6 7 8 9.
For statement: For statement execute a sequence of statements multiple time where you can manage the loop variable. You basically have 3 operations here: initialization, condition and iteration. Let’s understand this better with a flow chart:

In this flowchart, the code will respond in the following steps:

  1. First of all, it will enter the loop where it checks the condition.
  2. Next, if the condition is true, the statements will be executed.
  3. If the condition is false, it directly exits the loop.

Let’s see how you can implement the code in IDE.

public class ForExample {
      public static void main(String args[]) {
          for(int i=0; i<=10; i++)  // for condition 
          {
          System.out.println(i);
          }
     }
}

In the above code, it will directly print the numbers from 1 to 10.

The last type of control statement we will be discussing is Jump Statement.

Jump statement: Jump statement are used to transfer the control to another part of your program. These are further classified into – break and continue.

Let’s learn about them in detail:

  1. Break statement: Whenever a break statement is used, the loop is terminated and the program control is resumed to the next statement following the loop. Let’s understand this better with a flow chart:

In this flowchart, the code will respond in the following steps:

  • First of all, it will enter the loop where it checks the condition.
  • If the loop condition is false, it directly exits the loop.
  • If the condition is true, it will then check the break condition.
  • If break condition is true, it exists from the loop.
  • If the break condition is false, then it will execute the statements that are remaining in the loop and then repeat the same steps.

The syntax for this statement is just the ‘break’ keyword followed by a semicolon.

**2. Continue statement: **Continue statement is another type of control statements. The continue keyword causes the loop to immediately jump to the next iteration of the loop. Let’s understand this better with a flow chart:

In this flowchart, the code will respond in the following steps:
First of all, it will enter the loop where it checks the condition.If the loop condition is false, it directly exits the loop.If the loop condition is true, it will execute block 1 statements.After that it will check for ‘continue’ statement. If it is present, then the statements after that will not be executed in the same iteration of the loop.If ‘continue’ statement is not present, then all the statements after that will be executed.
The syntax is just the ‘continue’ keyword followed by a semicolon.

Next, let us see what are classes and objects in Java.

Java Tutorial: Classes and Objects

A class in Java is a blueprint which includes all your data. A class contain fields(variables) and methods to describe the behavior of an object. Let’s have a look at the syntax of a class.

class Abc {
      member variables // class body
        methods
 }

But how can you access these member variables and methods? Here comes the concept of Object.

An object is a major element in a class which has a state and behavior. It is an instance of a class which can access your data. Let’s see the syntax to create an object in Java:

Here, Student is your class name followed by the name of the object. Then there is a “new” keyword which is used to allocate memory. Finally, there is a call to constructor. This call initializes the new object.

Now let’s see how can you call a method using an object in Java:

class Student()
      void display(); {            // Method
     ------                           // logic of method
}
public static void main(String args[]){
      Student obj=new Student();   // Created an object
      obj.display();               // Method called
} 

Want to know more about them? I would suggest you to see this Java class video which will take you through in-depth details of Java classes and the different key-components in Java. Go ahead, enjoy the video and tell me what you think.

Next, let us move ahead in our Java Tutorial blog where we’ll be discussing about another key concept i.e. Arrays.

Java Tutorial: Arrays

Arrays in Java is similar to that of C++ or any other programming langauage. An array is a data structure which holds the sequential elements of the same type.

Let’s say you want to store 50 numbers. Instead of declaring individual variables, such as number0, number1, … and so on. You can declare one array variable – “numbers” and use number[0], number[1] to represent individual variables. This will ease your task and minimizes the redundancy.

Each array has two components: index and value. Refer to the below image for better understanding:

Here the indexing starts from zero and goes till (n-1) where n= size of the array. Let’s say you want to store 10 numbers, then the indexing starts from zero and goes till 9.

There are two types of arrays in Java:
Single-dimension ArrayMulti-dimension Array
Single-dimension Array: In a single-dimension array, a list of variables of the same type can be accessed by a common name. You can initialize the array using the following syntax:

int a[] = new int[12];

You can refer to the below image where I have stored data with respect to the given index.

**Multi–dimension Array: **In a multi-dimension array, your data is stored in a matrix form. Here, you can initialize the array using the following syntax:

int table[][]= new int[4][5];

It is quite similar to the matrix that we use in mathematics. Refer to the below image where I have stored data with respect to different dimensions.

Thus, arrays help you in optimizing the code where you can insert the data at any location.

Let’s see the below code to understand the concept of array in Java.

import java.util.*;
public class ArrayExample {
      public static void main( String args[])
     {
     double invoice[][]= new double[10][2];  // Initializing array
          Scanner obj= new Scanner(System.in);    // creating a scanner object to take input from user
          for(i=0;i<10;i++){                       // nested for loops
              for(j=0;j<2;j++);
               {
               System.out.println("Enter the value");
               invoice[i][j]=obj.nextDouble();         // store values to array   
          for(i=0;i<10;i++){
              for(j=0;j<2;j++)
               {
                System.out.println(invoice[i][j]);
               }
         }
     }
}

In the above code, I have explained how you can take input for the array and print the same.

I hope you guys are clear with how an array looks like and how do you initialize one. Now, let’s summarize the above topics and see the entire structure of a Java program.

Java Tutorial: Structure of a Program

Till now, we have learned about member variables, data types, control statements, classes and objects. Let’s see how all of them are structured together in a class in Java.

public class Car{                    // Class creation
       String color;                        // Member variables  
       String model;
       public void SpeedCheck(int s)        // Method
         {
         int speed=s;
           if(speed>100)                        // Control statement
           {
           System.out.println(" You are driving very fast");
           }
           else
           {
            System.out.println("You are driving at normal speed");
           }
public static void main ( String args[])
         {
         Car obj= new Car();                  // Object creation
         obj.speed(60);
         }

Finally, we come to our last topic in Java Tutorial blog i.e Object Oriented programming concepts.

Java Tutorial: OOPs Concept

We have already discussed about classes and objects in Java. Let’s discuss the 4 main concepts of object oriented programming – Inheritance, Encapsulation, Polymorphism and Abstraction.

Let’s begin with the first concept i.e. Inheritance.

Inheritance: Most of you must be familiar with inheritance. Inheritance is a process where one class acquires the properties of another. But whose properties are inherited? Here we have two classes, a child class which inherits the properties of a base class.

A Class which inherits the properties are known as **Child class. **It is also referred as derived class or a subclass. Next, the class whose properties are inherited are known as **Parent class **or a base class.

Let’s understand these classes by looking at this real-life example of animals.

In the above image, Animal is the superclass whereas amphibians, reptiles, mammals and birds are your child classes which are inheriting the properties from ‘Animal’ class.

In Java, inheritance is used to avoid code redundancy. Also, inheritance has many types, don’t worry, we will be going into more depth in my next blog on object oriented programming.

**Encapsulation: **Encapsulation in Java is a mechanism of wrapping up the data and code together as a single unit. Refer to the below image where all your methods, variables are binded together in a single class.

In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class.

**Polymorphism: **Polymorphism is the ability of a variable, function or object to take multiple forms. The most common use of polymorphism in OOPs occur when a parent class is used to refer a child class object. Polymorphism is also achieved through function overloading. Don’t worry! I will be explaining the whole concept in my next blog. For now, let’s take a real life scenario where a teacher tells student to draw different shape/figure having different functionalities.

Let’s say I want to draw a specific shape which already has multiple functions present as part of my program. So the functions that are dealing with shape, I’ll call them as draw(). Now based on the values that I have passed to these functions, it will draw different shapes. Let’s say in case of a rectangle, I am passing two values – length and breadth. Similarly for a circle, I am passing a radius. Based on the values you pass, different function will be called that serve different purposes. So this can be achieved through function overloading. Stay tuned, the concept of function overloading will be covered in detail in my next blog.

Abstraction: It is basically the quality of dealing with ideas rather than events. Abstraction is the methodology of hiding the implementation details from the user and only providing the functionality to the users. Let’s see this real-life example of a car where i’ll help you understand what exactly abstraction is.

If you consider the case of this car, here the mechanic is repairing a certain function in a car. But the user or you can say driver doesn’t want to know about these things, he just wants his car back in a working condition. So here, you basically segregate the implementation and show the other person what he actually wants to see and that exactly refers to abstraction.

Java Tutorial For Beginners - Learn Java Programming - Part 3/5

<strong>Java Tutorial For Beginners - Learn Java Programming: Java for Testers and Developers</strong>

Java Tutorial For Beginners - Learn Java Programming: Java for Testers and Developers

Why Learn Java?

Java is a general-purpose, versatile and popular programming language. It’s great as a first language because it is concise and easy to read, and it is also a good language to have in any programmer’s stack as it can be used for everything from web development to software development and scientific applications.

What you’ll learn

  • You will learn how to write a complete Java program that takes user input, processes and outputs the results
  • You will learn OOPS concepts in Java
  • You will able to use Java for Selenium in testing and development

Learn More

Java Programming Masterclass for Software Developers

Selenium WebDriver with Java -Basics to Advanced+Frameworks

Java In-Depth: Become a Complete Java Engineer!

JSP, Servlets and JDBC for Beginners: Build a Database App

JSP, Servlet, JSLT + Hibernate: A complete guide

Functional programming for Java developers

Object Oriented Programming (OOP) Java Tutorial for Beginners

50+ Java Interview Questions for Programmers

An Introduction to Spring Boot

A Study List for Java Developers