DEV Community

Cover image for Java for Beginners Full Course
Jeff Odhiambo
Jeff Odhiambo

Posted on • Edited on

Java for Beginners Full Course

What is JAVA?

Java is a high-level, third generation programming language, like C,C++, Perl, and many others. You can use Java to write computer applications that play games, store data etc. Compared to other programming languages, Java is most similar to C++.
What's special about Java in relation to other programming languages is that it lets you write special programs called applets that can be downloaded from the Internet and played safely within a web browser.

History

Java is an object-oriented programming language created by James Gosling from Sun Microsystems (Sun) in 1991. The first publicly available version of Java (Java 1.0) was released in 1995.
Sun Microsystems was acquired by the Oracle Corporation in 2010.
Over time new enhanced versions of Java have been released. The current version of Java is Java 8.
From the Java programming language, the Java platform evolved. The Java platform is usually associated with the Java virtual machine and the Java core libraries.
In 2006, Sun started to make Java available under the GNU General Public License (GPL).

The Java compiler

A compiler is a program that converts a high-level language to a machine language, i.e. from source code to binary code.
When you program from the Java platform, you write source code with a .java file extension and then compile them. The java compiler converts high-level java code into bytecode.
The compiler checks your code against the language's syntax rules, then writes out bytecodes in a .class files. Bytecodes are standard instructions targeted to run on a Java virtual machine (JVM).
In adding this level of abstraction, the Java compiler differs from other language compilers, which write out instructions suitable for the CPU chipset the program will run on.
An interpreter is a program that translates or converts a high-level language to a machine-language line by line. In Java, the Just In Time Code generator converts the bytecode into the native machine code which are at the same programming levels. Hence java is both compiled as well as an interpreted language.

Java virtual machine(JVM)

Java programs are compiled by the Java compiler into bytecode. The JVM is a software implementation of a computer that executes programs like a real machine. At run time, the JVM reads and interprets a .class files and executes the program's instructions on the native hardware platform for which the JVM was written. The Java virtual machine is written specifically for a specific operating system, e.g., for Linux a special implementation is required as well as for Windows.
The JVM is the heart of the Java language's "write-once, run-anywhere" principle. Your code can run on any chipset for which a suitable JVM implementation is available. JVMs are available for major platforms like Linux and Windows, and subsets of the Java language have been implemented in JVMs for mobile phones and hobbyist chips.
JVM

What are the tasks of JVM?

JVM performs byte-code interpretation, garbage collection, exception handling, thread management, initialization of variables, and type definition.

Java platform

The Java platform is the name given to the computing platform from Oracle that helps users to run and develop Java applications. The platform does not just enable a user to run and develop Java applications but also features a wide variety of tools that can help developers work efficiently with the Java programming language. The platform consists of two essential components:

  • Java Runtime Environment (JRE), which is needed to run Java applications and applets.
  • Java Development Kit (JDK), which is needed to develop those Java applications and applets. If you have installed the JDK, it comes equipped with a JRE as well.

When installed on a computer the JRE provides the operating system with the means to run Java programs, whereas the JDK is a collection of tools used by a programmer to create Java applications.
The JDK has as its primary components a collection of programming tools, including:

Basic Tools

These tools are the foundation of the JDK. They are the tools you use to create and build applications.

  • appletviewer - Run and debug applets without a web browser.
  • apt - Annotation processing tool.
  • extcheck - Utility to detect Jar conflicts.
  • jar - Create and manage Java Archive (JAR) files.
  • java - The launcher for Java applications. The old deployment launcher, JRE, is no longer provided.
  • javac - The compiler for the Java programming language.
  • javadoc - API documentation generator.
  • javah - C header and stub generator. Used to write native methods.
  • javap - Class file disassembler
  • jdb - The Java Debugger. See JPDA for the debugger architecture specifications. ###Security Tools These security tools help you set security policies on your system and create applications that can work within the scope of security policies set at remote sites. keytool - Manage keystores and certificates. jarsigner - Generate and verify JAR signatures. policytool - GUI tool for managing policy files.

More

Characteristics of Java

Object Oriented
In Java, everything is an Object. Java can be easily extended since it is based on the Object model.
Simple
Java is designed to be easy to learn. If you understand the basic concept of OOP Java, it would be easy to master.
Platform Independent
When Java is compiled, it is not compiled into platform-specific machine, rather into platform-independent byte code. This byte code is distributed over the web and interpreted by the Virtual Machine (JVM) on whichever platform it is being run on.
Secure
With Java's secure feature it enables to develop virus-free, tamper-free systems. Authentication techniques are based on public-key encryption.
Portable
Being architecture-neutral and having no implementation-dependent aspects of the specification makes Java portable.
Multithreaded
With Java's multithreaded feature it is possible to write programs that can perform many tasks simultaneously. This design feature allows the developers to construct interactive applications that can run smoothly.
Architecture-neutral
Java compiler generates an architecture-neutral object file format, which makes the compiled code executable on many processors, with the presence of Java runtime system.
Interpreted
Java byte code is translated on the fly to native machine instructions and is not stored anywhere. The development process is more rapid and analytical since the linking is an incremental and lightweight process.
Dynamic
Java is considered to be more dynamic than C or C++ since it is designed to adapt to an evolving environment. Java programs can carry an extensive amount of run-time information that can be used to verify and resolve accesses to objects at run-time.
High Performance
With the use of Just-In-Time compilers, Java enables high performance.
Distributed
Java is designed for the distributed environment of the internet.

Development process with java

Java source files are written as plain text documents. The programmer typically writes Java source code in an Integrated Development Environment (IDE) for programming. An IDE supports the programmer in the task of writing code, e.g., it provides auto-formatting of the source code, highlighting of the important keywords, etc. At some point, the programmer (or the IDE) calls the Java compiler (javac). The Java compiler creates the bytecode instructions. These instructions are stored in a .class file and can be executed by the Java Virtual Machine.

Garbage collector

The JVM automatically recollects or reclaims the memory which is not in use by the program. The Java garbage collector checks all object references and finds the objects which can be automatically released. While the garbage collector relieves the programmer from the need to explicitly manage memory, the programmer still needs to ensure that he does not keep unneeded object references, otherwise the garbage collector cannot release the associated memory.
Keeping unneeded object references is typically called memory leaks.

Classpath

The classpath defines where the Java compiler and Java runtime look for a .class files to load. These instructions can be used in the Java program. For example, if you want to use an external Java library you have to add this library to your classpath to use it in your program. Java is case-sensitive, e.g., variables called jeff and Jeff are treated as different variables

Java Development Tools

Java source files are written as plain text documents. The programmer writes Java source code in an Integrated Development Environment(IDE) for programming. An integrated development environment (IDE) or interactive development
environment
is a software application that provides comprehensive facilities for programmers to use for software development. An IDE normally consists of a source code editor, build automation tools, and a debugger.
Several modern IDEs integrate with Intelli-sense coding features. An IDE also supports the programmer in the task of writing code, e.g., it provides auto-formatting of the source code, highlighting of the important keywords, etc.
Common Java IDE Tools include:

  • IntelliJ IDEA
  • Eclipse Java development tools (JDT)
  • JCreator — Java IDE
  • Java-Editor
  • NetBeans IDE among others

How do you know that you have java installed? How do you install Java? How do you write, compile and run a java code?
We will perform all these in a few minutes.

Check installation

To run Java programs on your computer you must at least have the Java runtime environment (JRE) installed. This might already be the case on your machine. You can test if the JRE is installed and in your current path by opening a terminal or cmd in windows(Win+R, enter cmd and press Enter) and by typing in the following command:

java -version
Enter fullscreen mode Exit fullscreen mode

If the JRE is installed and within your path, this command will print information about your Java installation as shown below.

C:\Users\prof>java -version
java version "17.0.2" 2022-01-18 LTS
Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
Enter fullscreen mode Exit fullscreen mode

If the command line returns the information that the program could not be found, you have to install Java.

How to install java on Ubuntu or any UNIX system

On Ubuntu, you can install the latest Java through the terminal by writing the following command.

sudo apt-get install openjdk
Enter fullscreen mode Exit fullscreen mode

or you can specify the version, e.g for Java 7 we can use

sudo apt-get install openjdk-7-jdk
Enter fullscreen mode Exit fullscreen mode

How to install Java on Windows

For Windows, Oracle provides a native installer which can be found on the Oracle website. The central website for installing Java is located under the following URL which also contains instructions on how to install
Java for other platforms. java.com

What to do if you come across an installation problem

If you have problems installing Java on your system, search via Google for How to install JDK on <YOUR_OS>. This should result in helpful links. Replace <YOUR_OS> with your operating system, e.g., Windows, Ubuntu, Mac OSX, etc.
For instance, if having problem in installing Java on windows
Search How to install java on windows which will result to results.

Validate installation

After installation, you can confirm if Java is correctly installed by running java -version on your terminal or cmd.
If successful the output will be similar to

C:\Users\prof>java -version
java version "17.0.2" 2022-01-18 LTS
Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
Enter fullscreen mode Exit fullscreen mode

How can you tell you are using a 32-bit or 64-bit version of Java?

You can run a 32b-it or a 64-bit version of Java on a 64-bit system. If you use java -version and the output contains the "64-Bit" string, then you are using the 64-bit version of Java otherwise you are using the 32-bit version.
The following is the output of a 64-bit version.

C:\Users\prof>java -version
java version "17.0.2" 2022-01-18 LTS
Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
Enter fullscreen mode Exit fullscreen mode

Writing, compiling, and running a Java program

Write source code

To create Java programs, use any text editor such as Notepad, WordPad, or gedit in ubux/Linux. After creation, save the file with .Java file extension. Example: Create file HelloWorld.java then write the following source code:

// Simplest Java program
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}
Enter fullscreen mode Exit fullscreen mode

Congratulations, you just created your first java source file.
The above Java program can be developed under Linux/Windows using a text editor and the command line. Select or create a new directory in Windows which will be used for your Java development. In this description, the path C:\Users\prof\Desktop\javalessons is used.
On Linux, you might see \home\<name>\javalessons but this will depend on how you named your folder and the location of the folder.
We will ignore the first file you created.
Once done creating a directory, open a text editor which supports plain text, e.g., gedit in Linux or
Notepad in Windows and write the following source code.

// Simplest Java program
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World, Thanks for reading this article. Did you find it useful");
    }
}
Enter fullscreen mode Exit fullscreen mode

Save the source code in your javadir directory(my case it's, C:\Users\prof\Desktop\javalessons) with the HelloWorld.java filename. The name of a Java source file must always be the same as the class name(within the source code) and end with the .java extension. In this example, the filename must be HelloWorld.java, because the class is called HelloWorld.

Compiling and Running Java Programs

Open a terminal or command line. Switch to the javadir directory using the command cd javadir, e.g, in the above example I'll use cd C:\Users\prof\Desktop\javalessons command to change directory to where the file is located.
Then use the dir command (ls in Linux) to verify that the source file is in the directory.

C:\Users\prof>cd C:\Users\prof\Desktop\javalessons

C:\Users\prof\Desktop\javalessons>dir

05/03/2022  14:54    <DIR>          .
05/03/2022  14:54    <DIR>          ..
05/03/2022  14:54               151 HelloWorld.java
               1 File(s)            151 bytes

C:\Users\prof\Desktop\javalessons>
Enter fullscreen mode Exit fullscreen mode

To compile the source code file into a class file, use the javac command. For example, the following command compiles HelloWorld.java:

javac HelloWorld.java
Enter fullscreen mode Exit fullscreen mode

Afterward, list again the content of the directory with the ls or dir command. The directory contains now a file HelloWorld.class. If you see this file, you have successfully compiled your first Java source code into bytecode.

C:\Users\prof\Desktop\javalessons>javac HelloWorld.java

C:\Users\prof\Desktop\javalessons>dir

05/03/2022  15:04    <DIR>          .
05/03/2022  15:04    <DIR>          ..
05/03/2022  15:04               425 HelloWorld.class
05/03/2022  14:54               151 HelloWorld.java
               2 File(s)            576 bytes

C:\Users\prof\Desktop\javalessons>
Enter fullscreen mode Exit fullscreen mode

You can now start to run your compiled Java program. Ensure that you are still in the jardir directory.
To run, use the java command. For example, the command java HelloWorld will display Hello World, Thanks for reading this article. Did you find it useful?.

C:\Users\prof\Desktop\javalessons>java HelloWorld
Hello World, Thanks for reading this article. Did you find it useful?

C:\Users\prof\Desktop\javalessons>
Enter fullscreen mode Exit fullscreen mode

Using the classpath

Common Error when compiling programs is:

Error
To solve the problem, set the classpath in the environmental variables as follows:

Classpath

The classpath defines where the Java compiler and Java runtime look for .class files to load. These instructions can be used in the Java program. You can use the classpath to run the program from another place in your directory.

Configure classpath in Java environment on Windows (Windows10)

  1. Click on the Start menu
  2. Search Advanced System setting Advance system setting
  3. Click on Environment Variables, under System Variables, find path, and click on it. system variables Path
  4. In the Edit windows, modify PATH by adding the location of the class to the value for PATH. If you do not have the item PATH, you may select to add a new variable and add PATH as the name and the location of the class as the value .e.g PATH= C:\ProgramFiles\Java\jdk1.7.0_45\bin. In my case, it is already configured.
  5. Reopen Command prompt window, and run your java code using the javac command.

Java Fundamentals

Java Input/Output

Java uses streams to perform input and output. A stream can be defined as a sequence of data. All streams represent an input source and an output destination.
Java uses the InputStream to read data from a source and the OutputStream is used for writing data to a destination.
The JDK has two sets of I/O packages:

  1. The Standard I/O (in package java.io), introduced since JDK 1.0 for stream-based I/O.
  2. The New I/O (in packages java.nio), introduced in JDK 1.4, for more efficient buffer-based I/O. ###Console Output
System.out.print("Hello ");
System.out.println("world");
Enter fullscreen mode Exit fullscreen mode

Console Input

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String text = in.readLine();
Enter fullscreen mode Exit fullscreen mode

GUI Input

GUI input and output is performed using the JOptionPane class of package javax.swing
String name = JOptionPane.showInputDialog(null, "What's your name?");
Output
Output

GUI Output

JOptionPane.showMessageDialog(null,"Welcome to Java Programming");
Output
Output
Example:

import javax.swing.*;
public class JOptionPaneTest1 {
    public static void main(String[] args) {
        String ans;
        ans = JOptionPane.showInputDialog(null, "Speed in miles per hour?");
        double mph = Double.parseDouble(ans);
        double kph = 1.621 * mph;
        JOptionPane.showMessageDialog(null, "KPH = " + kph);
        System.exit(0);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output
Question image
Answer image

File Output

        PrintWriter out = new PrintWriter(new FileWriter("/home/jeff/Desktop/Notes-1.pdf\n"));
        out.print("Hello ");
        out.println("world");
        out.close();
Enter fullscreen mode Exit fullscreen mode

File Input

 BufferedReader in = new BufferedReader(new FileReader("/home/jeff/Desktop/Notes-1.pdf"));
        String text = in.readLine();
        in.close();
Enter fullscreen mode Exit fullscreen mode

Converting input data

String text = in.readLine();
int x = Integer.parseInt(text);
double y = Double.parseDouble(text);
Enter fullscreen mode Exit fullscreen mode

Reading until EOF

while (in.ready()) {
    text = in.readLine();
    System.out.println(text);
}
Enter fullscreen mode Exit fullscreen mode

Variables:

Variables are named memory locations that store data to be used in a program.
Variables maintain the state of your application, and enable the user to manage data. The values stored in variables may change during program execution.

Identifier:

These are variable names. Variable name is a name given to memory cells location of a computer where data is stored. You can use any combination of those
characters as long as the name doesn’t begin with a number. Identifier is the name of a variable that is made up from combination of alphabets, digits and underscore.

Rules for naming varibales:

  • Variable names may contain only letters, numbers, underscores.
  • Should not begin with a number. First character should be letter or alphabet.
  • Keywords are not allowed to be used as a variable name.
  • White space is not allowed.
  • Java is case sensitive i.e. UPPER and lower case are significant.
  • Special characters such as space etc not allowed.

Keywords

Keywords are the system defined identifiers. All keywords have predefined meanings. White spaces are not allowed in keywords. Keyword should not be used as an identifier.

Common java keywords include:

  • abstract - Indicates that the details of a class, a method, or an interface are given elsewhere in
  • the code.
  • assert - Tests the truth of a condition that the programmer believes is true.
  • boolean - Indicates that a value is either true or false.
  • break - Jumps out of a loop or switch.
  • byte - Indicates that a value is an 8-bit whole number.
  • case - Introduces one of several possible paths of execution in a switch statement.
  • catch - Introduces statements that are executed when something interrupts the flow of execution in a try clause.
  • char - Indicates that a value is a character (a single letter, digit, punctuation symbol, and so on).
  • class - Introduces a class(a blueprint for an object).
  • continue - Forces the abrupt end of the current loop iteration and begins another iteration.
  • default - Introduces a path of execution to take when no case is a match in a switch statement.
  • do Causes the computer to repeat some statements over and over again (for example, as long as the computer keeps getting unacceptable results).
  • double - Indicates that a value is a 64-bit number with one or more digits after the decimal point.
  • else - Introduces statements that are executed when the condition in an if statement isn’t true.
  • enum - Creates a newly defined type(a group of values that a variable can have).
  • extends - Creates a subclass (a class that reuses functionality from a previously defined class.
  • final - Indicates that a variable’s value cannot be changed, that a class’s functionality cannot be extended, or that a method cannot be overridden.
  • finally - Introduces the last will and testament of the statements in a try clause.
  • float - Indicates that a value is a 32-bit number with one or more digits after the decimal point.
  • for - Gets the computer to repeat some statements over and over again (for example, for a certain number of times).
  • if - Tests to see whether a condition is true. If it’s true, the computer executes certain statements; otherwise, the computer executes the remaining other statements.
  • implements - Reuses the functionality from a previously defined interface.
  • import - Enables the programmer to abbreviate the names of classes defined in a package.
  • instanceof - Tests to see whether a certain object comes from a certain class.
  • int - Indicates that a value is a 32-bit whole number.
  • interface - Introduces an interface, which is like a class, but less specific. (Interfaces are used where one is to inherit from one or more other instances.)
  • long - Indicates that a value is a 64-bit whole number.
  • native - Enables the programmer to use code that was written in another language.
  • new - Creates an object from an existing class.
  • package - Puts the code into a package — a collection of logically related definitions.
  • private - Indicates that a variable or method can be used only within a certain class.
  • protected - Indicates that a variable or method can be used in subclass from another package.
  • public - Indicates that a variable, class, or method can be used by any other Java code.
  • return - Ends execution of a method and possibly returns a value to the calling code.
  • short - Indicates that a value is a 16-bit whole number.
  • static - Indicates that a variable or method belongs to a class, rather than to any object created from the class.
  • strictfp - Limits the computer’s ability to represent extra large or extra small numbers when the computer does intermediate calculations on float and double values.
  • super - Refers to the super class of the code in which the word super appears.
  • switch - Tells the computer to follow one of many possible paths of execution (one of many possible cases), depending on the value of an expression.
  • synchronized - Keeps two threads from interfering with one another.
  • this - A self-reference(refers to the object in which the word this appears).
  • throw - Creates a new exception object and indicates that an exceptional situation (usually something unwanted) has occurred.
  • throws - Indicates that a method or constructor may pass the buck when an exception is thrown.
  • transient - Indicates that, if and when an object is serialized, a variable’s value doesn’t need to be stored.
  • try - Introduces statements that are watched (during runtime) for things that can go wrong.
  • void - Indicates that a method doesn’t return a value.
  • volatile - Imposes strict rules on the use of a variable by more than one thread at a time.
  • while - Repeats some statements over and over again (as long as a condition is still true).

Data Types in Java

Data types dictate the kind of data that a variable can store. Data type can be defined as the type of data for a variable or constant store. When we use a variable
in a program then we have to mention the type of data.
In java, there are two types of data types : primitive data types and non-primitive data types
Data types in Java
Data size

Variable Initialization

In Java, variables aren’t necessarily assigned an initial value when they’re declared, but all variables must be assigned a value before the variable’s value is used in an assignment statement.

    int a;
    int b;
    // We're now initializing BOTH variables explicitly.
    a = 3;
    b = 7;
    a = a + b;
    System.out.println(a);
Enter fullscreen mode Exit fullscreen mode

Use of variables before they are initialized results in a compiler error.

The String Type

A String represents a sequence of zero or more Unicode characters, in other words we can say, a String is array of characters. The symbol String starts with a capital “S,” whereas the names of primitive types are expressed in all lowercase: int, float, boolean, etc.
E.g. String name = "Jeff";
This capitalization difference is deliberate and mandatory—string (lowercase) won’t
work as a type.

String concatenation

The plus sign (+) operator is normally used for arithmetic addition, but when used in conjunction with Strings. Any number of String values can be concatenated with the + operator, as the following code snippet illustrates:

public class StringCont {
    public static void main(String[] args) {
        String f_name = "Jeff";
        String l_name = "Odhiambo";
        String name = "Mr. " + f_name + " " + l_name;
        System.out.println(name);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output

Mr. Jeff Odhiambo
Enter fullscreen mode Exit fullscreen mode

Statements

A statement is basically any declaration, function call, assignment, or condition. Statements are the building blocks of any program. Statements in Java must be
terminated with a semi colon. E.g.
int a;
a=10;

Comments

Java supports three different comment styles: single line (end-of-line), Multi-line and Java documentation comments.

  1. Single line (End-of-Line Comments) We use a double slash (//) to note the beginning of a comment that automatically ends when the end of the line is reached. E.g. x = y + z; // text of comment continues through to the end of the line
  2. Multi-line Comments These comments begin with a forward slash followed by an asterisk (/) and end with an asterisk followed by a forward slash (/). Everything enclosed between these delimiters is treated as a comment and is therefore ignored by the Java compiler, no matter how many lines the comment spans.
  3. Java Documentation Comments The third and final type of Java comment, Java documentation comments (Javadoc comments), can be parsed from source code files by a special javadoc command-line utility program (which comes standard with the Java SDK) and used to automatically generate HTML documentation for an application.

Operators and Expressions

An expression is a statement that has a value. Expressions are basically any math or logical operation(s). They consist of a sequence of operators and operands that specifies a computation. E.g x = 12 + 42; that assigns 54 i.e., 12+42 to variable x.
A simple expression in Java is either

  • A constant: a=7;, payment_status=false;
  • A char(acter) literal enclosed in single quotes: grade = 'A', mark = '3'
  • A String literal enclosed in double quotes: f_name = "Jeff", "l_name = Odhiambo"
  • The name of any properly declared variables: myString, x, etc
  • Any two of the preceding types of expression that are combined with one of the Java binary operators (discussed in detail later in this chapter). y = 2x+3;
  • Any one of the preceding types of expression that is modified by one of the Java unary operators (discussed in detail later in this chapter): i++
  • Any of the preceding types of expression enclosed in parentheses: (x + 2) etc.
  • Expressions of arbitrary complexity can be assembled from the various different simple expression types by nesting parentheses, for example: ((((4/x) + y) * 7) +z). ##Operators Operators are symbols that specifies operations to be performed on operands. Common operators include: Assignment (=) The assignment operator assigns a value to a variable. a = 5;

*Arithmetic operators ( +, -, *, /, *% )

  • -> addition
  • -> subtraction
  • -> multiplication / -> division % -> modulo Compound assignment (+=,-=,*=,/=, %=,>>=,<<=) When we want to modify the value of a variable by performing an operation on the value currently stored in that variable we can use compound assignment operators which include: value += increase; -> value = value + increase; a -= 5; -> a = a - 5; a /= b; -> a = a / b; price *= units + 1; -> price = price * (units + 1); Increment and Decrement operators The increment operator ( ++ ) and the decrement operator ( -- ) increase or reduce by one the value stored in a variable. They are equivalent to +=1 and to -=1 , respectively. Thus: c++;c+=1;c=c+1; are all equivalent in its functionality. Relational and equality operators (==,!=,>,<,>=,<= ) These operators are used for comparison between two expressions. The result of a relational operation is a Boolean value that can only be true or false, according to its Boolean result. We may want to compare two expressions, for example, to know if they are equal or if one is greater than the other is. The relational and equality operators that can be used include: == -> Equal to != -> Not equal to > -> Greater than < -> Less than >= -> Greater than or equal to <= -> Less than or equal to Logical operators ( !, &&, || ) The Operator !, Is used to perform the Boolean operation NOT, it has only one operand, located at its right, and the only thing that it does is to inverse the value of it, producing false if its operand is true and true if its operand is false. The logical operators && and || are used when evaluating two expressions to obtain a single relational result. The operator && corresponds with Boolean logical operation AND. This operation results true if both its two operands are true, and false otherwise. The operator || corresponds with Boolean logical operation OR. This operation results true if either one of its two operands is true, thus being false only when both operands are false themselves. Operators Conditional operator ( ? ) The conditional operator evaluates an expression returning a value if that expression is true and a different one if the expression is evaluated as false. Its format is: condition ?result1 : result2 Precedence of operators Precedence of operators determines which operand is evaluated first and which one is evaluated later. For example, in this expression: a = 5 + 7 % 2 we may doubt if it really means:
a = 5 + (7 % 2) // with a result of 6, or
a = (5 + 7) % 2 // with a result of 0
Enter fullscreen mode Exit fullscreen mode

Types of expressions in Java

Arithmetic expressions

A unary expression consists of either a unary operator prepended to an operand, or the sizeof keyword followed by an expression. A binary expression consists of two operands joined by a binary operator. A ternary expression consists of three operands joined by the conditional-expression operator.

The easiest example of an expression is in the assignment statement. An expression is evaluated, and the result is saved in a variable. A simple example might look like y = (m * x) + c
This assignment will save the value of the expression in variable y.
Short hand assignments
Assignments

Logical expressions

Logical connectors allow several comparisons to be combined into a single test. They use And, Or and Not operators.
They are frequently used to combine relational operators, for example x< 20 && x >= 10
They evaluate their left hand operand, and then only evaluate the right hand one if this is required. Not operates on a single logical value, its effect is to reverse its state. Here is an example of its use.

boolean acceptable = false;
if(!acceptable){
    System.out.println("Not acceptable");
}
Enter fullscreen mode Exit fullscreen mode

Comparison Expressions

Comparison takes two numbers and produces a logical result. Comparisons are usually found controlling if statements or loops. Example
Coparison expression
Note that == is used in comparisons and = is used in assignments. Comparison operators are used when creating comparisons expressions. E.g.
x == y
i> 10
a + b != c

Object, Class, Abstract, Polymorphism etc

Object-oriented programming takes advantage of our perception of world. An object is an encapsulated completely-specified data aggregate containing attributes and behavior.

Data hiding protects the implementation from interference by other objects and defines approved interface. An object-oriented program is a growing and shrinking collection of objects that interact via messages.

You can send the same message to similar objects--the target decides how to implement or respond to a message at run-time. Objects with same characteristics are called instances of a class.

Benefits of object-oriented programming include:

  • Troubleshooting is easy in OOP through modularity
  • Benefit of code re-usability through inheritance
  • Data redundancy is reduced
  • Code flexibility emphasis through polymorphism
  • Effective problem solving.

Java Classes

A class is essentially an abstract data type that provides a template from which objects are created. Class consists of a collection of data together with functions that operate on the data.
Data is referred to as data members and functions are referred to as member functions of a class. By declaring a class we create a new data type that is as powerful as any of the basic types.

class syntax

class <classname>{
    //body
}
Enter fullscreen mode Exit fullscreen mode

Example

class Student{
    //body
}
Enter fullscreen mode Exit fullscreen mode

Class data member

In a class, the members are by default hidden within the class and cannot be accessed from outside. We say that the members of a class are declared private by default. However, if we want to, we can declare members of a class to be public.
Syntax

class <classname>{
    <data_type> <variable_name>;
    //body
}
Enter fullscreen mode Exit fullscreen mode


java
Example

class Student{
    String student_name;
    int marks;
    Character grade;
    //body
}
Enter fullscreen mode Exit fullscreen mode

Class member functions (methods)

Member functions of a class are also referred to as methods. If we make the member data of our student class private, we should provide functions to access the data for setting, manipulating or printing.

Encapsulation and data hiding

Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class.
Encapsulation can be described as a protective barrier that prevents the code and data being randomly accessed by other code defined outside the class. Access to the data and code is tightly controlled by an interface.
Encapsulation gives maintainability, flexibility and extensibility to our code. Data encapsulation led to the important OOP concept of data hiding.

Java Variable Types

In Java, all variables must be declared before they can be used. The basic form of a variable declaration is shown here:
<type> <identifier> = <value>; e.g
String name = "Jeff Odhiambo";
The type is one of Java's data types. The identifier is the name of the variable. To declare more than one variable of the specified type, use a comma-separated list.
Java supports the following types of variables:

1. Local variables

Local variables are declared in methods, constructors, or blocks. Local variables are created when the method, constructor or block is entered and the variable will be destroyed once it exits the method, constructor or block. Access modifiers cannot be used for local variables. Local variables are visible only within the declared method, constructor or block. Local variables are implemented at stack level internally. There is no default value for local variables so local variables
should be declared and an initial value should be assigned before the first use.

2. Class (static) Variables

Class variables are shared by all the instances of the class. Class variables also known as static variables are declared with the static keyword in a class, but outside a method, constructor or a block. Class methods are not tied to a specific object.
There would only be one copy of each class variable per class, regardless of how many objects are created from it. Static variables are created when the program starts and destroyed when the program stops. Static variables can be accessed by calling with the class name. Syntax ClassName.VariableName e.g Math.PI.

3. Constants (Final Variables)

Any variable either member variable or local variable (declared inside method or block) modified by final keyword is called final variable. Final variables are often declare with static keyword in java and treated as constant. A final variable can only be initialized once, either via an initializer or an assignment statement.
Class constants are final variables shared by all the instances of the class. Class variables, constants, and methods are used with class name, such as Math.pow(2,3), Math.PI.
To declare class variables, constants, and methods, use the static modifier.
When declaring class variables as public static final, then variables names (constants) are all in upper case. If the static variables are not public and final
the naming syntax is the same as instance and local variables.
Example

import java.io.*;
public class Employee{
    // salary variable is a private static variable
    private static double salary;
    // DEPARTMENT is a constant
    public static final String DEPARTMENT = "Development ";
    public static void main(String args[]){
        salary = 1000;
        System.out.println(DEPARTMENT+"average salary:"+salary);
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Instance variables

Instance variables are declared in a class, but outside a method, constructor or any block. When a space is allocated for an object in the heap a slot for each instance variable value is created. Instance variables are created when an object is created with the use of the key word 'new' and destroyed when the object is destroyed.
Instance variables hold values that must be referenced by more than one method, constructor or block, or essential parts of an object’s state that must be present throughout the class. Instance variables can be declared in class level before or after use. Access modifiers can be given for instance variables.

The instance variables are visible for all methods, constructors and block in the class. Normally it is recommended to make these variables private (access level). However visibility for sub classes can be given for these variables with the use of access modifiers.
Instance variables have default values. For numbers the default value is 0, for Booleans it is false and for object references it is null. Values can be assigned during the declaration or within the constructor.
Instance variables can be accessed directly by calling the variable name inside the class. However within static methods and different class ( when instance variables are given accessibility) the should be called using the fully qualified name . ObjectReference.VariableName.

Scope of Variables

The scope of instance and class variables is the entire class. They can be declared anywhere inside a class. They are global variables. The scope of a local variable starts from its declaration and continues to the end of the block that contains the variable. A local variable must be declared before it can be used.
E.g.
Scope of variable

Visibility Modifiers and Accessor Methods

By default, the class, variable, or data can be accessed by any function in the class in which they are declared. Visibility modifiers include:
Public - The class, data, or method is visible to any class in any package.
Private - The data or methods can be accessed only by the declaring class.
Protected

Accessor methods(Setters and Getters Methods)

The getter and setter accessor methods are used to read and modify private properties in a class. These methods are also called accessor methods.
The syntax for accessor methods is:

public class AccessorExample {
    private String attribute;
    public String getAttribute() {
        return attribute;
    }
    public void setAttribute(String attribute) {
        this.attribute = attribute;
    }
}
Enter fullscreen mode Exit fullscreen mode

Java this Keyword

The keyword this in Java refers to the current class instance. Within an instance method or a constructor, this is a reference to the current object. Therefore, this can be used inside any method to refer to the current object. You can refer to any member of the current object from within an instance method or a constructor by using this . The keyword can also be used to call overloaded constructors.

Using this to access a shadowed field

The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.
For example, the Point class was written like this

public class Point {
    public int x = 0;
    public int y = 0;
    //constructor
    public Point(int a, int b) {
        x = a;
        y = b;
    }
}
Enter fullscreen mode Exit fullscreen mode

but it could have been written like this:

public class Point {
    public int x = 0;
    public int y = 0;
    //constructor
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
Enter fullscreen mode Exit fullscreen mode

Each argument to the constructor shadows one of the object's fields — inside the constructor x is a local copy of the constructor's first argument. To refer to the Point field x , the constructor must use this.x .

Using this to call a Constructor from another constructor

From within a constructor, you can also use the this keyword to call another constructor in the same class. Doing so is called an explicit constructor invocation. Here's another Rectangle class, with a different implementation from the one in the Objects section.

public class Rectangle {
    private int x, y;
    private int width, height;
    public Rectangle() {
        this(0, 0, 0, 0);
    }
    public Rectangle(int width, int height) {
        this(0, 0, width, height);
    }
    public Rectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
}
Enter fullscreen mode Exit fullscreen mode

This class contains a set of constructors. Each constructor initializes some or all of the rectangle's member variables. The constructors provide a default value for any member variable whose initial value is not provided by an argument.

Data encapsulation

Data encapsulation is a mechanism of bundling the data, and the functions that use them.
Example

public class Student {
    private String name;
    private String idNum;
    private int age;

    public int getAge() {
        return age;
    }
    public String getName() {
        return name;
    }
    public String getIdNum() {
        return idNum;
    }
    public void setAge(int newAge) {
        age = newAge;
    }
    public void setName(String newName) {
        name = newName;
    }
    public void setIdNum(String newId) {
        idNum = newId;
    }
}
Enter fullscreen mode Exit fullscreen mode

Encapsulation using “this” Example

public class Student{
    private String name;
    private String idNum;
    private int age;
    public int getAge(){
        return age;
    }
    public String getName(){
        return name;
    }
    public String getIdNum(){
        return idNum;
    }
    public void setAge( int age){
        this.age = age;
    }
    public void setName(String name){
        this.name = name;
    }
    public void setIdNum( String idNum){
        this.idNum = idNum;
    }
}
Enter fullscreen mode Exit fullscreen mode

Advantage of Encapsulation in Java and OOPS

Here are few advantages of using Encapsulation while writing code in Java or any Object oriented programming language:

  1. Encapsulated Code is more flexible and easy to change with new requirements.
  2. Encapsulation in Java makes unit testing easy.
  3. Encapsulation in Java allows you to control who can access what.
  4. Encapsulation also helps to write immutable class in Java which are a good choice in multi-threading environment.
  5. Encapsulation reduce coupling of modules and increase cohesion inside a module because all piece of one thing are encapsulated in one place.
  6. Encapsulation allows you to change one part of code without affecting other part of code.

Relationships among Classes

Association

Association is a relationship between two objects. Association represents a general binary relationship that describes an activity between two classes.
The association relationship is a way of describing that a class knows about and holds a reference to another class.
You may be aware of one-to-one, one-to-many, many-to-one, many-to-many all these words define an association between objects.

Aggregation

Aggregation is a relationship between two classes that is best described as a "has-a" and "whole/part" relationship.
Aggregation models the relationship like has-a, part-of, owns, and employed-by. When an object ‘has-a’ another object, then you have got an aggregation between them.
Direction between them specifies which object contains the other object. Aggregation is also called a “Has-a” relationship.
Example
There is an aggregation relationship between Student class and the Subject class:

public class Subject {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
public class Student {
    private Subject[] studyAreas = new Subject[10];
}
Enter fullscreen mode Exit fullscreen mode

Find more examples here

Composition

Composition is restricted aggregation. When an object contains the other object,i.e., if the contained object cannot exist without the existence of container object, then it is called composition.
Example: A class contains students. A student cannot exist without a class.
There exists composition between class and students.

Abstraction

Abstraction is specifying the framework and hiding the implementation level information. Concreteness will be built on top of the abstraction. It gives you a
blueprint to follow to while implementing the details. Abstraction reduces the complexity by hiding low level details.
Example: A wire frame model of a car.

Generalization

Generalization uses a “is-a” relationship from a specialization to the generalization class. Common structure and behavior are used from the specialization to the generalized class. At a very broader level you can understand this as inheritance. Why I take the term inheritance is, you can relate this term very well.
Example: Consider there exists a class named Person. A student is a person. A faculty is a person. Therefore here the relationship between student and person, similarly faculty and person is generalization.

Realization

Realization is a relationship between the blueprint class and the object containing its respective implementation level details. This object is said to
realize the blueprint class. In other words, you can understand this as the relationship between the interface and the implementing class.
Example: A particular model of a car ‘GTB Fiorano’ that implements the blueprint of a car realizes the abstraction.

Dependency

Change in structure or behavior of a class affects the other related class, then there is a dependency between those two classes. It need not be the same on the vice-
versa. When one class contains the other class this happens.
Example: Relationship between shape and circle is dependency.

Inheritance (developed from)

Inheritance models the “is-a” relationship between two classes. It is a mechanism where a new class is derived from an existing class.
In Java, classes may inherit or acquire the non private properties and methods of other classes. A class derived from another class is called a subclass, whereas
the class from which a subclass is derived is called a super class. A subclass can have only one super class, whereas a super class may have one or more sub classes.

Any class in java that does not extend any other class implicitly extends Object class. Therefore, the java.lang.Object class is always at the top of any Class inheritance hierarchy.
In Java, inheritance is used for two purposes:
1. Class inheritance - create a new class as an extension of another class, primarily for the purpose of code reuse. That is, the derived class inherits the public methods and public data of the base class. Java only allows a class to have one immediate base class,
i.e., single class inheritance. The keyword “extends” is used to derive a subclass from the superclass, as illustrated by the following syntax:
syntax

public class derived-class-name extends base-class-name {
// derived class methods extend and possibly override those of the base class
}
Enter fullscreen mode Exit fullscreen mode

example

class A{
//properties and methods of A
}
class B extends A {
}
Enter fullscreen mode Exit fullscreen mode

Class inheritance defines a is-a relationship between a superclass and its subclasses. Therefore inheritance is achieved at class level. We can therefore define inheritance in java as mechanism is used to build new classes from existing classes.
For example:

public class Animal{
}
public class Mammal extends Animal{
}
public class Reptile extends Animal{
}
public class Dog extends Mammal{
}
Enter fullscreen mode Exit fullscreen mode

In Object Oriented terms following are true:

  • Animal is the super class of Mammal class.
  • Animal is the super class of Reptile class.
  • Mammal and Reptile are sub classes of Animal class.
  • Dog is the subclass of both Mammal and Animal classes.

Now if we consider the IS-A relationship we can say:

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal
  • Hence : Dog IS-A Animal as well With use of extends keyword the sub classes will be able to inherit all the properties of the super class except for the private properties of the super class. Below is a sample implementation of the Dog class:
public class Dog extends Mammal{
    public static void main(String args[]){
        Animal a = new Animal();
        Mammal m = new Mammal();
        Dog d = new Dog();
        System.out.println(m instanceof Animal);//Outputs true
        System.out.println(d instanceof Mammal); //Outputs true
        System.out.println(d instanceof Animal); //Outputs true
    }
}
Enter fullscreen mode Exit fullscreen mode

The Boolean instanceof operator is used to determine whether Mammal is actually an Animal, and dog is actually an Animal.

super keyword

‘super’ is used for pointing the super class instance. That is, it is a reference variable that is used to refer immediate parent class object.
The keyword super will therefore be used when referring to the super class of an object.

Uses of super Keyword

super is used to refer immediate parent class instance variable.
super() is used to invoke immediate parent class constructor.
super is used to invoke immediate parent class method.
Using the super keyword to call immediate parent class constructor
The syntax for calling a super class constructor is
super(); or super(parameter list);
NB: In a constructor, super MUST always be the first statement to appear:
Example:

class Vehicle{
    Vehicle(){
        System.out.println("Vehicle is created");
    }
    Void start(){
        System.out.println("Vehicle is starting...");
    }
}
class Bike extends Vehicle{
    Bike(){
        super();//will invoke parent class constructor
        System.out.println("Bike is created");
    }
    public static void main(String args[]){
        Bike b=new Bike();
    }
}
Enter fullscreen mode Exit fullscreen mode

Output:

Vehicle is created
Bike is created
Enter fullscreen mode Exit fullscreen mode

With super(), the super class no-argument constructor is called. With super(parameter list), the super class constructor with a matching parameter list is called. If accessing a method in super class, we use the syntax:
super.methodName( argument(s))
super.start();

Method Overriding

When a sub class defines a method that has same name signature and return type (or compatible with return type of super class method) it is called method overriding. In object oriented terms, overriding means to override the functionality of any existing method.
The benefit of overriding is: ability to define a behavior that's specific to the sub class type. Which means a subclass can implement a parent class method based on its requirement.
Consider the following example

class Animal{
    public void move(){
        System.out.println("Animals can move");
    }
}
class Dog extends Animal{
    public void move(){
        System.out.println("Dogs can walk and run");
    }
}
public class TestDog{
    public static void main(String args[]){
        Animal a = new Animal(); // Animal reference and object
        Animal b = new Dog(); // Animal reference but Dog object
        a.move();// runs the method in Animal class
        b.move();//Runs the method in Dog class
    }
}
Enter fullscreen mode Exit fullscreen mode

This would produce following result:

Animals can move
Dogs can walk and run
Enter fullscreen mode Exit fullscreen mode

In the above example you can see that the even though b is a type of Animal it runs the move method in the Dog class. The reason for this is : In compile time the check is made on the reference type. However in the runtime JVM figures out the object type and would run the method that belongs to that particular object.
Therefore in the above example, the program will compile properly since Animal class has the method move. Then at the runtime it runs the method specific for that object.
Consider the following example :

class Animal {
    public void move() {
        System.out.println("Animals can move");
    }
}
class Dog extends Animal {
    public void move() {
        System.out.println("Dogs can walk and run");
    }

    public void bark() {
        System.out.println("Dogs can bark");
    }
}
public class TestDog {
    public static void main(String args[]) {
        Animal a = new Animal(); // Animal reference and object
        Animal b = new Dog(); // Animal reference but Dog object

        a.move();// runs the method in Animal class
        b.move();//Runs the method in Dog class
        b.bark();
    }
}
Enter fullscreen mode Exit fullscreen mode

This would produce following result:

TestDog.java:30: cannot find symbol
symbol : method bark()
location: class Animal
b.bark();
  ^
Enter fullscreen mode Exit fullscreen mode

This program will throw a compile time error since b's reference type Animal doesn't have a method by the name of bark.

Using the super keyword to call overridden method

When invoking a super class version of an overridden method the super keyword is used.

class Animal{
    public void move(){
        System.out.println("Animals can move");
    }
}
class Dog extends Animal{
    public void move(){
        super.move(); // invokes the super class method
        System.out.println("Dogs can walk and run");
    }
}
public class TestDog{
    public static void main(String args[]){
        Animal b = new Dog(); // Animal reference but Dog object
        b.move(); //Runs the method in Dog class
    }
}
Enter fullscreen mode Exit fullscreen mode

This would produce following result:

Animals can move
Dogs can walk and run
Enter fullscreen mode Exit fullscreen mode

Rules for method overriding:

  • The argument list should be exactly the same as that of the overridden method.
  • The return type should be the same or a sub type of the return type declared in the original overridden method in the super class.
  • The access level cannot be more restrictive than the overridden method's access level. For example: if the super class method is declared public then the overridding method in the sub class cannot be either private or protected.
  • Instance methods can be overridden only if they are inherited by the subclass.
  • A method declared final cannot be overridden.
  • A method declared static cannot be overridden but can be re-declared.
  • If a method cannot be inherited then it cannot be overridden.
  • A subclass within the same package as the instance's superclass can override any superclass method that is not declared private or final.
  • A subclass in a different package can only override the non-final methods declared public or protected.
  • An overriding method can throw any uncheck exceptions, regardless of whether the overridden method throws exceptions or not. However the overriding method should not throw checked exceptions that are new or broader than the ones declared by the overridden method. The overriding method can throw narrower or fewer exceptions than the overridden method.
  • Constructors cannot be overridden.

Data abstraction

Abstraction is the concept of object-oriented programming that “shows” only essential attributes and “hides” unnecessary information. The main purpose of abstraction is hiding the unnecessary details from the users. The implementation details is hidded from the user. Abstraction is achieved using either abstract classes or interfaces.

Class Abstraction

Class abstraction means to separate class implementation from the use of the class. The creator of the class provides a description of the class and let the user know how the class can be used. The user of the class does not need to know how the class is implemented. The detail of implementation is encapsulated and hidden from the user.

Abstract Classes and Abstract Methods

An abstract class is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class). An abstract class leaves one or more method implementations unspecified by declaring one or more methods abstract. An abstract can only be used as a super class for other classes that
extend the abstract class. Abstract classes are declared with the abstract keyword. Abstract classes are used to provide a template or design for concrete subclasses down the inheritance tree.
Abstract methods are methods with no body specification (implementation).
Abstract methods can only be used in an abstract class, and it does not have a body. I.e Abstract method would have no definition, and its signature is followed by a semicolon, not curly braces. The body is provided by the subclass (inherited from).
The abstract keyword is a non-access modifier, used for classes and methods. The abstract keyword is used to declare a class or a method as abstract. An abstract method consists of a method signature, but no method body.
Example

abstract class Shape {
    public String color;

    public Shape() {
    }

    public void setColor(String c) {
        color = c;
    }

    public String getColor() {
        return color;
    }

    abstract public double area();
}
Enter fullscreen mode Exit fullscreen mode

Note that If a class has at least one abstract method, the class must be declared as abstract.
A subclass is therefore required to override the abstract method and provide an implementation. Subclasses must provide the method statements for their particular meaning. If the method was one provided by the superclass, it would require overriding in each subclass. Hence, an abstract class is incomplete and cannot be instantiated, but can be used as a base class.
The abstract class guarantees that each shape will have the same set of basic properties. We declare this class abstract because there is no such thing as a generic shape. There can only be concrete shapes such as squares, circles, triangles etc.

public class Point extends Shape {
    static int x, y;

    public Point() {
        x = 0;
        y = 0;
    }

    public double area() {
        return 0;
    }

    public double perimeter() {
        return 0;
    }

    public static void print() {
        System.out.println("point: " + x + "," + y);
    }

    public static void main(String args[]) {
        Point p = new Point();
        p.print();
    }
}
Enter fullscreen mode Exit fullscreen mode

Points to Remember

  • An abstract class must be declared with an abstract keyword.
  • It can have abstract and non-abstract methods.
  • It cannot be instantiated.
  • It can have constructors and static methods also.
  • It can have final methods which will force the subclass not to change the body of the method. ##Interfaces An interface in Java is a blueprint of a class. It consists of static constants and abstract methods. In Java, an interface is a mechanism to achieve abstraction. There can be only abstract methods in a Java interface. No need to include keyword abstract when declaring abstract methods in in interface. Just like an abstract class, an interface cannot be instantiated. You can declare an interface in its own file like a class. In such a case, File name must be the same as the class name. Java Interface also represents the IS-A relationship. ###Declaring Interfaces The interface keyword is used to declare an interface. Syntax:
interface <interface_name>{
// declare constant fields
// declare abstract methods
}
Enter fullscreen mode Exit fullscreen mode

Example:

/* File name : Animal.java */
interface Animal {
    public void eat();
    public void travel();}
}
Enter fullscreen mode Exit fullscreen mode

Implementing an interface

Class inheritance in java uses the keyword extends. To access the interface methods, the interface must be "implemented" (inherited) by another class using the implements keyword (instead of extends). During implementation the body of each interface method is provided by the "implementing" class:
Syntax:

public class class-name implements interface-name {
// class provides an implementation for the methods
// as specified by the interface
}
Enter fullscreen mode Exit fullscreen mode

Example:

interface Animal {
    public void makeSound(); // interface method (does not have a body)

    public void sleep(); // interface method (does not have a body)}

    //Donkey "implements" the Animal interface
    class Donkey implements Animal {
        public void makeSound() {
            // The body of animalSound() is provided here
            System.out.println("The donkey says: hee hoo");
        }

        public void sleep() {
            // The body of sleep() is provided here
            System.out.println("Zzz");
        }
    }

    public class DonkeyImpl {
        public static void main(String[] args) {
            Donkey dnk = new Donkey();
            // Create a Donkey object
            dnk.makeSound();
            dnk.sleep();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Why use Java interface?

There are mainly three reasons to use interface. They are given below.

  • It is used to achieve abstraction.
  • By interface, we can support the functionality of multiple inheritance.
  • It can be used to achieve loose coupling. Interfaces are preferred to classes because they help us to to achieve abstraction as well as multiple inheritance in Java.

Extending Interfaces

An interface can extend another interface in the same way that a class can extend another class. The extends keyword is used to extend an interface, and the child
interface inherits the methods of the parent interface.
Example

// Filename: Sports.java
public interface Sports {
    public void setHomeTeam(String name);
    public void setVisitingTeam(String name);
}
// Filename: Football.java
public interface Football extends Sports {
    public void homeTeamScored(int points);
    public void visitingTeamScored(int points);
    public void endOfQuarter(int quarter);
}
// Filename: Hockey.java
public interface Hockey extends Sports {
    public void homeGoalScored();

    public void visitingGoalScored();

    public void endOfPeriod(int period);

    public void overtimePeriod(int ot);
}
Enter fullscreen mode Exit fullscreen mode

Multiple Class Inheritance in Java

A class can extends ONLY one parent class using the extends keyword. Multiple class inheritance is not allowed.
Class inheritance inheritance in java has the following limitations.

  • A subclass cannot inherit private members of its super class.
  • A subclass can have only one super class.
  • Constructor and initializer blocks cannot be inherited by a subclass. Interfaces are not classes, thus you are allowed to inherit one or more interfaces. Multiple inheritance by interface occurs if a class implements multiple interfaces or also if an interface itself extends multiple interfaces.

Extending Multiple Interfaces

To achieve multiple inheritance, java allows you to implement more than one parent interfaces by declaring them in a comma-separated list. E.g.
public interface Hockey extends Sports, Event
Note that an interface can extend more than one parent interface
interface

Difference between Abstraction and Encapsulation

abstraction

Difference between Abstract Class and Interface

interfaces

Polymorphism in Java

Polymorphism is the ability of an object to take on many forms. In OOP, polymorphism is the capability of an action or method to do different things based on the object that it is acting upon.
This is the third basic principle of object oriented programming. Polymorphism in Java has two types: Compile time polymorphism (static binding) and Runtime polymorphism (dynamic binding).

Compile time (Static) polymorphism

A static polymorphism is one which method binds at compile time, also known as Compile time or static polymorphism. Static polymorphism is achieved through method(function) overloading or operator overloading. But Java doesn’t support the Operator Overloading.

Overloaded methods

When there are multiple functions (methods) with same name but different parameters (implementation) then these functions are said to be overloaded. Thus, functions can be overloaded by change in number of arguments or/and change in type of arguments.
These overloaded methods have same name signature but either a different number of parameters or different types in the parameter list. Overloaded methods:

  1. Appear in the same class or a subclass.
  2. Have the same name but.
  3. Have different parameter lists.
  4. Can have different return types.

At compile time, Java knows which method to invoke by checking the method signatures. So, this is called compile time polymorphism or static binding. The concept will be clear from the following example:

class DemoOverload{
    public int add(int x, int y){ //method 1
        return x+y;
    }
    public int add(int x, int y, int z){ //method 2
        return x+y+z;
    }
    public int add(double x, int y){ //method 3
        return (int)x+y;
    }
    public int add(int x, double y){ //method 4
        return x+(int)y;
    }
}
class Test{
    public static void main(String[] args){
        DemoOverload demo=new DemoOverload();
        System.out.println(demo.add(2,3));
        //method
        System.out.println(demo.add(2,3,4));
        //method
        System.out.println(demo.add(2,3.4));
        //method
        System.out.println(demo.add(2.5,3));
        //method
    }
}
Enter fullscreen mode Exit fullscreen mode

Constructor Overloading:

  • Constructor overloading is a technique in Java in which a class can have any number of constructors that differ in parameter lists.
  • The compiler differentiates these constructors by taking into account the number of parameters in the list and their type.
class Room
{
    double length,breadth,height;
    Room(double l,double b,double h)
    {
        length=l;
        breadth=b;
        height=h;
    }
    Room()
    {
        length=-1;
        breadth=-1;
        height=-1;
    }
    Room(double len)
    {
        length=breadth=height=len;
    }
    double volume()
    {
        return length*breadth*height;
    }
}
class OverloadConstructors
{
    public static void main(String args[])
    {
        Room a=new Room(20,30,40);
        Room b=new Room();
        Room c=new Room(10);
        double vol;
        vol=a.volume();
        System.out.println("Volume of room a is " + vol);
        vol=b.volume();
        System.out.println("Volume of room b is " + vol);
        vol=c.volume();
        System.out.println("Volume of room c is " + vol);
    }
}
Enter fullscreen mode Exit fullscreen mode

Limitation: Poor utilization of memory resource (main memory).

Dynamic (Run Time) Polymorphism:

It is a process in which a function call to the overridden method is resolved at Runtime. This type of polymorphism is achieved by Method Overriding.
Run time polymorphism occurs when a sub class overrides a particular method of the super class.

Dynamic Binding (Late Binding)

When a method is invoked, the code to be executed is only determined at run-time. During the compilation, the compiler checks whether the method exists and performs type check on the arguments and return type, but does not know which piece of codes to execute at run-time. When a message is sent to an object to invoke a method, the object figures out which piece of codes to execute at run-time. This mechanism is called dynamic binding (or late-binding or run-time binding).

In polymorphism, Dynamic (or late) method binding is the ability of a program to resolve references to subclass methods at runtime.

Overridden Methods

Overridden methods are methods of a super class that are redefined(defined again) within a subclass.
In Java, you can create a method in a superclass (or parent class), then in a subclass ALSO define that
method.

class Vehicle{
    public void move(){
        System.out.println("Vehicles can move!!");
    }
}
class MotorBike extends Vehicle{
    public void move(){
        System.out.println("MotorBike can move and accelerate too!!");
    }
}
class Test{
    public static void main(String[] args){
        Vehicle vh=new MotorBike();
        vh.move(); // prints MotorBike can move and accelerate too!!
        vh=new Vehicle();
        vh.move(); // prints Vehicles can move!!
    }
}
Enter fullscreen mode Exit fullscreen mode

It should be noted that in the first call to move(), the reference type is Vehicle and the object being referenced is MotorBike. So, when a call to move() is made, Java waits until runtime to determine
which object is actually being pointed to by the reference. In this case, the object is of the class MotorBike. So, the move() method of MotorBike class will be called. In the second call to move(), the object is of the class Vehicle. So, the move() method of Vehicle will be called. As the method to call is determined at runtime, this is called dynamic binding or late binding.

Overriding:

  • applies ONLY to inherited methods is related to polymorphism
  • object type (NOT reference variable type) determines which overridden method will be used at runtime
  • overriding method MUST have the same argument list (if not, it might be a case of overloading)
  • overriding method MUST have the same return type; the exception is covariant return (used as of Java 5) which returns a type that is a subclass of what is returned by the overridden method
  • overriding method MUST NOT have more restrictive access modifier, but MAY have less restrictive one
  • overriding method MUST NOT throw new or broader checked exceptions, but MAY throw fewer or narrower checked exceptions or any unchecked exceptions
  • abstract methods MUST be overridden
  • final methods CANNOT be overridden
  • static methods CANNOT be overridden
  • constructors CANNOT be overridden ##Upcasting & Downcasting Upcasting a Subclass Instance to a Superclass Reference Substituting a subclass instance for its superclass is called "upcasting". This is because, in a UML class diagram, subclass is often drawn below its superclass. Upcasting is always safe because a subclass instance possesses all the properties of its superclass and can do whatever its superclass can do. The compiler checks for valid upcasting and issues error "incompatible types" otherwise. For example,
Circle c1 = new Cylinder(); // Compiler checks to ensure that R-value is a subclass of L-value
Circle c2 = new String(); // Compilation error: incompatible types
Enter fullscreen mode Exit fullscreen mode

Downcasting a Substituted Reference to Its Original Class
You can revert a substituted instance back to a subclass reference. This is called "downcasting". For
example,

Cycle c1 = new Cylinder(5.0); // upcast is safe
Cylinder aCylinder = (Cylinder) c1; // downcast needs the casting operator
Enter fullscreen mode Exit fullscreen mode

Downcasting requires explicit type casting operator in the form of prefix operator (new-type).
Downcasting is not always safe, and throws a runtime ClassCastException if the instance to be downcasted does not belong to the correct subclass. A subclass object can be substituted for its superclass, but the reverse is not true.
Compiler may not be able to detect error in explicit cast, which will be detected only at runtime.
For example,

Circle c1 = new Circle(5);
Point p1 = new Point();
c1 = p1; // compilation error: incompatible types (Point is not subclass of Circle)
c1 = (Circle)p1; // runtime error: java.lang.ClassCastException: Point cannot be casted to Circle
Enter fullscreen mode Exit fullscreen mode

The instanceof Operator
Java provides a binary operator called instanceof which returns true if an object is an instance of a particular class. The syntax is as follows:

//anObjectinstanceofaClass
Circle c1 = new Circle();
System.out.println(c1 instanceof Circle); // true
if (c1 instanceof Cirlce){
    //body
}
Enter fullscreen mode Exit fullscreen mode

An instance of subclass is also an instance of its superclass. For example,

Circle c1 = new Circle(5);
Cylinder cy1 = new Cylinder(5, 2);
System.out.println(c1 instanceof Circle); //true
System.out.println(c1 instanceof Cylinder); //false
System.out.println(cy1 instanceof Cylinder); //true
System.out.println(cy1 instanceof Circle);  //true

Circle c2 = new Cylinder(5, 2);
System.out.println(c2 instanceof Circle); //true
System.out.println(c2 instanceof Cylinder); //true
Enter fullscreen mode Exit fullscreen mode

Summary:

  • The method binding happens at the compile time i.e which methods can be invoked on a given reference type is decided at the compile time.
  • The selection of the method’s implementation to execute happens at the run time i.e which implementation of the method to be executed i.e the super class version or one of the subclass’s version is decided at the run time and this is what leads to the runtime polymorphism.
  • An object in Java that passes more than one IS-A tests is polymorphic in nature
  • Static polymorphism in Java is achieved by method overloading
  • Dynamic polymorphism in Java is achieved by method overriding.

A package can be defined as a group of similar types of classes, interface, enumeration and sub-package. Enumerations and annotation types are special kinds of classes and interfaces. Packages provide access protection and name space management in a java program. Therefore, a package provides a mechanism for organizing Java classes into namespaces similar to the modules in VB.
Packages are used in Java in order to prevent naming conflicts, to control access, to make searching/locating and usage of classes, interfaces, enumerations and annotations easier, etc. Using package it becomes easier to locate the related classes.

Package are categorized into two forms:
Built-in Package:-Existing Java package for example java.lang and java.util
User-defined-package:- Java package created by user to categorize source files.

Built-in Packages

These packages consist of a large number of classes which are a part of Java API. Some of the commonly used built-in packages are:

  • java.lang: Contains language support classes(e.g classed which defines primitive data types, math operations). This package is automatically imported.
  • java.io: Contains classed for supporting input / output operations.
  • java.util: Contains utility classes which implement data structures like Linked List, Dictionary and support ; for Date / Time operations.
  • java.applet: Contains classes for creating Applets.
  • java.awt: Contain classes for implementing the components for graphical user interfaces (like button , ;menus etc).
  • java.net: Contain classes for supporting networking operations. And many others. ##User-defined packages Programmers can define their own packages to bundle group of classes/interfaces etc. It is a good practice to group related classes implemented by you so that a programmers can easily determine that the classes, interfaces, enumerations, annotations are related. Since the package creates a new namespace there won't be any name conflicts with names in other packages. Using packages, it is easier to provide access control and it is also easier to locate the related classed. To set up the programmer-defined packages for general reuse, not just use by the programs in the same folder, we have to perform the following tasks:
  • Include the statement package myutil; as the first statement of the source file for the Fraction class.
  • The class declaration must include the visibility modifier public as public class Fraction {}
  • Create a folder named myutil , the same name as the package name. In Java, the package must have a one-to-one correspondence with the folder.
  • Place the modified Fraction class into the myutil folder and compile it.
  • Modify the CLASSPATH environment variable to include the folder that contains the myutil folder.

Creating a package

To group classes into a package each class must have a package statement defined at the top of a java file. It lets the compiler know which package the class belongs to and must be the first line of code. The syntax for defining a package is:
package <package name>
NB: A package name is a fully qualified variable name. e.g. package diploma_students. To create your own package, you need to understand that Java uses a file system directory to store them. Just like folders on your computer.

Java Package Names and Directory Structure

Organizing classes in a program can take multiple levels so that each package can have as many sub-packages as needed. The Java Package name consists of words separated by periods. The first part of the name represents the organization which created the package. The remaining words of the Java Package name reflect the contents of the package. The Java Package name also reflects its directory structure.
The period "." is used to distinguish the package and sub-package. The period is placed in-between the package names. E.g. package university.college.department.course
The first part of that package name "university" represents the organization that developed the package. The second part of the package name "college" stands for the contents of the package, in this case the department and lastly the course offered by a given department.

The import Keyword

Import keyword is used to import built-in and user-defined packages into your java source file. Packages allow your class to refer to a class that is in another package by directly using its name.
There are 3 different ways to refer to class that is present in different package.

  1. Using fully qualified name (which is not a good practise). Example
class myDate extends java.util.Date{
    //body
}
Enter fullscreen mode Exit fullscreen mode
  1. Import the only class you need Example
import java.util.Date;
class myDate extends Date{
    //body
}
Enter fullscreen mode Exit fullscreen mode
  1. Import all classes from a particular package Example
import java.util.*;
class myDate extends Date{
    //body
}
Enter fullscreen mode Exit fullscreen mode

Importing a Class from an Existing Java Package using the import Keyword:
If a class wants to use another class in the same package, the package name does not need to be used. Classes in the same package find each other without any special syntax.
If a class in one package uses details of another class in different package, the class to be used MUST be included in current class using the import statement. E.g.
import javax.swing.JOptionPane;
Note: The import statement is terminated with a semicolon.

How to access Package from another package

There are three ways to access the package from outside the package.

  • import package.*;
  • import package.classname;
  • fully qualified name.

Using packagename.*

If you use package.* then all the classes and interfaces of this package will be accessible but not sub-packages. The import keyword is used to make the classes and interface of another package accessible to the current package.

Static import

Static import is a feature that extends the capabilities of import keyword. It is used to import static member of a class.We will know that static member are referred in association with its class name outside the class. Using static import, its possible to refer to the static member directly without its class name.

The 2 general form of static statement are:

  1. The first form of static import statement, import only a single static member of a class. Syntax:
import static package.class-name.static-member-name
Enter fullscreen mode Exit fullscreen mode

Example:

import static java.lang.Math.sqrt; 
//importing static method sqrt of Math class 
Enter fullscreen mode Exit fullscreen mode
  1. Second form of static import statement, imports all the static member of a class. Syntax:
import static package.class-type-name.*;
Enter fullscreen mode Exit fullscreen mode

Example:

import static java.lang.Math.*;
//importing all static method of Math class 
Enter fullscreen mode Exit fullscreen mode

Example without using static import

public class Test {
    public static void main(String[] args) {
        System.out.println(Math.sqrt(144));
    }
}
Enter fullscreen mode Exit fullscreen mode

Output: 12
Example using static import

import static java.lang.Math.*;
public class Test{
    public static void main(String[] args) {
        System.out.println(sqrt(144));
    }
}
Enter fullscreen mode Exit fullscreen mode

Handling name conflicts

The only time we need to pay attention to packages is when we have a name conflict . For example both, java.util and java.sql packages have a class named
Date. So if we import both packages in program as follows:

import java.util.*;
import java.sql.*;
Enter fullscreen mode Exit fullscreen mode

//And then use Date class, then we will get a compile-time error :
Date today ; //ERROR-- java.util.Date or java.sql.Date?
The compiler will not be able to figure out which Date class do we want. This problem can be solved by using a specific import statement:

import java.util.Date;
import java.sql.*;
Enter fullscreen mode Exit fullscreen mode

If we need both Date classes then, we need to use a full package name every time we declare a new object of that class.
For Example:

java.util.Date deadLine = new java.util.Date();
java.sql.Date today = new java.sql.Date();
Enter fullscreen mode Exit fullscreen mode

How to compile the Package (if not using IDE)

If you are not using any IDE, you need to follow the syntax given below:
javac -d <directory or dot operator> <javafilename>
For example
javac -d . Simple.java
The -d switch specifies the destination where to put the generated class file. You can use any directory name like /home (in case of Linux), d:/abc (in case of windows) etc. If you want to keep the package within the same directory, you can use . (dot).
For more visit Java Installation.
How to run the Package (if not using IDE)
You need to use fully qualified name e.g. mypack.Simple etc to run the class.
To Compile: javac - d . Simple.java
The -d is a switch that tells the compiler where to put the class file i.e. it represents destination. The . represents the current folder.

This marks the end of the Java for beginners.
You can learn more about Java through the urls below:
https://beginnersbook.com/2013/03/packages-in-java/
https://www.geeksforgeeks.org/packages-in-java/
https://www.javatpoint.com/package

Hope you gained something from this article, if yes, let me know in the comment section.

Top comments (3)

Collapse
 
antoniolup profile image
antonio lopez

insane

Collapse
 
nyangweso profile image
Rodgers Nyangweso

good stuff

Collapse
 
abdessalambou profile image
abdessalambou

hi thank you for this article: please I have a question: why we use Java Static Initializer Block?