Java Programming: Key Concepts and Features
Java: An Object-Oriented Programming Language
Java is an Object-Oriented programming language developed by James Gosling in the early 1990s. The team initiated this project to develop a language for digital devices such as set-top boxes, television, etc. James Gosling and his team called their project “Greentalk” and its file extension was .gt and later became known as “OAK”. The name Oak was used by Gosling after an oak tree that remained outside his office. The Java language has experienced a few changes since JDK 1.0, just as various augmentations of classes and packages to the standard library.
Features of Java
- Simple: Java is very easy to learn, and its syntax is simple, clean, and easy to understand.
- Platform Independent: Java is platform-independent because it is different from other languages like C, C++, etc., which are compiled into platform-specific machines, while Java is a write-once, run-anywhere language.
- Secured: Java is best known for its security. With Java, we can develop virus-free systems.
- Robustness: The Java language is robust, which means reliable.
- Distributed: We can create distributed applications using the Java programming language.
- Multithreading: Java supports multithreading, enabling the concurrent execution of multiple parts of a program.
Servlets: Handling Web Requests
Servlets are Java programs that run on a Java-enabled web server or application server. They are used to handle the request obtained from the web server, process the request, produce the response, and then send a response back to the web server.
- Servlets work on the server side.
- Servlets are capable of handling complex requests obtained from the web server.
The entire life cycle of a Servlet is managed by the Servlet container, which uses the javax.servlet.Servlet interface to understand the Servlet object and manage it. So, before creating a Servlet object, let’s first understand the life cycle of the Servlet object, which is actually understanding how the Servlet container manages the Servlet object.
- Loading a Servlet.
- Initializing the Servlet.
- Request handling.
- Destroying the Servlet.
Abstraction: Hiding Implementation Details
Abstraction is a process of hiding the implementation details and showing only functionality to the user. Another way, it shows only essential things to the user and hides the internal details. For example, sending SMS where we type the text and send the message. We do not know the internal processing about the message delivery.
- An abstract class is a class that is declared with an abstract keyword.
- An abstract method is a method that is declared without implementation.
- An abstract class may or may not have all abstract methods. Some of them can be concrete methods.
Literals: Representing Values in Java
Literals are used to represent fixed values in Java.
- String literals are sequences of characters enclosed within double quotes. When the compiler encounters a string literal, it creates a String object with the specified value. String literals can contain any characters, including special characters escaped with a backslash (e.g., \n for newline, \t for tab, \” for double quote).
- Boolean literals represent truth values and can only have one of two values: true or false. They are used to represent the logical states of on/off, yes/no, or true/false.
- Integer: Can be expressed in decimal, octal, hexadecimal, or binary format.
- Decimal: 10, -25.
- Octal (prefixed with 0): 012.
- Hexadecimal (prefixed with 0x): 0xA.
- Binary (prefixed with 0b): 0b101.
System.out.println: Standard Output Stream
System.out.println is used to print output to the console.
- System: It is a final class defined in the java.lang package.
- out: This is an instance of PrintStream type, which is a public and static member field of the System class.
- println(): As all instances of the PrintStream class have a public method println(), we can invoke the same on out as well. This is an upgraded version of print(). It prints any argument passed to it and adds a new line to the output. We can assume that System.out represents the Standard Output Stream.
Inheritance: Reusing Code
Inheritance is an important pillar of OOP (Object-Oriented Programming). It is the mechanism in Java by which one class is allowed to inherit the features (fields and methods) of another class. In Java, Inheritance means creating new classes based on existing ones. A class that inherits from another class can reuse the methods and fields of that class.
- Single Inheritance: In single inheritance, a sub-class is derived from only one superclass.
- Multilevel Inheritance: In Multilevel Inheritance, a derived class will be inheriting a base class, and as well as the derived class also acts as the base class for other classes.
- Hierarchical Inheritance: In Hierarchical Inheritance, one class serves as a superclass (base class) for more than one subclass.
Preventing Class Inheritance
To prevent a class from being inherited by other classes in most programming languages, you can use the keyword “final” when declaring the class; this essentially marks the class as not able to be subclassed, generating a compile-time error if anyone tries to inherit from it.
Why Java Does Not Support Multiple Inheritance
A Java class can be inherited from only one superclass using the extends keyword. The single inheritance model ensures a clear hierarchical structure where each class has a single direct superclass, and it can facilitate easier code maintenance and reduce the potential for conflicts. The major reason behind Java’s lack of support for multiple inheritance lies in its design philosophy of simplicity and clarity over complexity. By disallowing Multiple Inheritance, Java aims to prevent the ambiguity and complexities that can arise from having multiple parent classes.
Layout Managers: Arranging Components
Layout Managers are used to arrange components in a particular manner. The Java LayoutManagers facilitates us to control the positioning and size of the components in GUI forms. LayoutManager is an interface that is implemented by all the classes of layout managers.
Final Keyword: Restricting Modifications
The final method in Java is used as a non-access modifier applicable only to a variable, a method, or a class. It is used to restrict a user in Java.
- Final variables: When a variable is declared with the final keyword, its value can’t be changed, essentially, a constant. This also means that you must initialize a final variable.
- Java Final Method: When a method is declared with the final keyword, it is called a final method in Java. A final method cannot be overridden.
- Java Final classes: When a class is declared with the final keyword in Java, it is called a final class. A final class cannot be extended (inherited).
Static Keyword: Class-Level Members
The static keyword in Java is mainly used for memory management. The static keyword in Java is used to share the same variable or method of a given class. The users can apply static keywords with variables, methods, blocks, and nested classes. The static keyword belongs to the class rather than an instance of the class. The static keyword is used for a constant variable or a method that is the same for every instance of a class.
Super and This Keywords
Super is a special keyword in Java that is used to refer to the instance of the immediate parent class. Using the super keyword, we can refer to the immediate parent class’s methods, constructor, instance, and static variables, etc. We cannot use the super keyword as an identifier in Java as it is a reserved keyword.
This is a special keyword in Java that is used to refer to an instance of the current class. Using the this keyword, we can refer to the current class’s methods, constructors, instance variables, and many more. We cannot use the this keyword as an identifier in Java.
Differences between Super and This
Super:
- super() calls the parent constructor.
- It can be used to call methods from the parent.
- It is returned with no arguments.
- It can be used with instance members.
This:
- this() can be used to invoke the current class constructor.
- It can be passed as an argument in the method call.
- It can be passed as an argument in the constructor call.
- It is used to return the current class instance from the method.
Continue and Break Statements
The continue statement is used to skip the current iteration of a loop and move to the next iteration. When used with a label, it can be even more powerful, allowing you to skip iterations of outer loops from within nested loops.
- Labeling a Loop: You assign a label to a loop using a colon (:) followed by the label name before the loop statement.
- Using continue with a Label: Inside the nested loop, use the continue statement followed by the label name to skip to the next iteration of the labeled loop.
The break statement is used to terminate a loop prematurely. When used with a label, it can break out of multiple nested loops, providing more control over loop execution.
- Labeling a Loop: Assign a label to a loop using a colon (:) followed by the label name before the loop statement.
- Using break with a Label: Inside a nested loop, use the break statement followed by the label name to break out of the labeled loop.
Applet: Embedding Java in Web Pages
An applet is a Java program that can be embedded into a web page. It runs inside the web browser and works at the client-side. An applet is embedded in an HTML page using the APPLET or OBJECT tag and hosted on a web server. Applets are used to make the website more dynamic and entertaining.
- init(): This is the first method that is being called. All the variables are initialized here. This method is only called once during the run time.
- start(): It is called after the init method. Used for starting an applet. It is also used for restarting an applet in case it is stopped.
- paint(): This method is used for painting various shapes like squares, rectangles, etc.
- stop(): This method is invoked whenever the browser is stopped, minimized, or because of abrupt failure within an application.
- destroy(): Once we are done with the applet work, this method destroys the application and is invoked only once.
AWT: Platform-Independent GUI
The Java AWT utilizes the native platform subroutine to create API components such as TextField, CheckBox, and buttons. This results in a different visual format for these components on different platforms such as Windows, MAC OS, and Unix. The reason for this is that each platform has a distinct view of its native components.
Constructors and Inheritance
Constructors are not inherited in Java. This is because a constructor’s name must match the class name, and when a subclass is created, its name is different from the superclass. When a subclass object is instantiated, the constructor of the superclass can be invoked using the super() keyword within the subclass constructor. If the super() call is not explicitly present, the compiler automatically inserts a call to the superclass’s default (no-argument) constructor. If the superclass does not have a default constructor, the subclass must explicitly call one of the superclass’s parameterized constructors using super(arguments).
Command Line Arguments
A command-line argument is an argument that is passed at the time of running the Java program. In Java, the command-line arguments passed from the console can be received in the Java program, and they can be used as input. The users can pass the arguments during the execution by passing the command-line arguments inside the main() method.
For-Each Loop: Simplified Iteration
The Java for-each loop or enhanced for loop is introduced since J2SE 5.0. It provides an alternative approach to traverse the array or collection in Java. It is mainly used to traverse the array or collection elements. The advantage of the for-each loop is that it eliminates the possibility of bugs and makes the code more readable. It is known as the for-each loop because it traverses each element one by one.
Threads: Concurrent Execution
A Thread is a very light-weighted process, or we can say the smallest part of the process that allows a program to operate more efficiently by running multiple tasks simultaneously. In order to perform complicated tasks in the background, we used the Thread concept in Java. All the tasks are executed without affecting the main program. In a program or process, all the threads have their own separate path for execution, so each thread of a process is independent.
public class ThreadExample1 extends Thread {
public void run() {
int a = 10;
int b = 12;
int result = a + b;
System.out.println("Thread started running..");
System.out.println("Sum of two numbers is: " + result);
}
public static void main(String args[]) {
ThreadExample1 t1 = new ThreadExample1();
t1.start();
}
}
Ways to Create a Thread
- Thread Class: The simplest way to create a thread in Java is by extending the Thread class and overriding its run() method. The Thread class provides constructors and methods to create and perform operations on a thread. The Thread class extends the Object class and implements the Runnable interface.
- Runnable Interface: Another approach to creating threads in Java is by implementing the Runnable interface. The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The Runnable interface has only one method named run(). This approach is preferred when we want to separate the task from the thread itself, promoting better encapsulation and flexibility.
Serializable: Object Persistence
The Serializable interface is present in the java.io package. It is a marker interface. A Marker Interface does not have any methods and fields. Thus classes implementing it do not have to implement any methods. Classes implement it if they want their instances to be Serialized or Deserialized. Serialization is a mechanism of converting the state of an object into a byte stream. The java.io.Serializable interface in Java serves as a marker interface, indicating that objects of a class implementing it can be serialized. Serialization is the process of converting an object’s state into a byte stream, which can then be stored in a file, database, or transmitted over a network.
Code Portability
Portability of code means the ability of a piece of software code to run on different operating systems, hardware platforms, or environments with minimal or no modifications, essentially allowing you to “port” the code to different systems without needing to rewrite large portions of it.
Java Program Portability
A Java program means that once written, it can run on various operating systems and hardware platforms without needing significant modifications, thanks to the concept of “Write Once, Run Anywhere” (WORA) which is achieved by compiling Java code into platform-independent bytecode that is executed by the Java Virtual Machine (JVM) on the target system; essentially, you can write a single Java program and run it on Windows, Linux, macOS, etc.
Runnable Interface: Executing Code Concurrently
Java runnable is an interface used to execute code on a concurrent thread. It is an interface that is implemented by any class if we want that the instances of that class should be executed by a thread. The runnable interface has an undefined method run() with void as the return type, and it takes in no arguments.
- Implementing the Interface: Create a class that implements the Runnable interface. Override the run() method to define the task that the thread should perform.
- Creating a Thread: Create a new Thread object, passing an instance of your Runnable class to its constructor.
- Starting the Thread: Call the start() method on the Thread object to initiate the execution of the run() method in a separate thread.
Packages: Organizing Code
A java package is a group of similar types of classes, interfaces, and sub-packages. Packages are used in Java in order to prevent naming conflicts, control access, make searching/locating and usage of classes, interfaces, enumerations, and annotations easier, etc. A Java package can be defined as a grouping of related types classes, interfaces, enumerations, and annotations providing access protection and namespace management. Packages in Java can be categorized into two forms, built-in packages and user-defined packages.
Built-in packages:
- java.lang: Bundles the fundamental classes.
- java.io: Classes for input-output functions are bundled in this package.
User-defined packages: You can define your own packages to bundle groups of classes/interfaces, etc.
Subpackages: Nested Packages
A package defined inside another package is known as a subpackage. Subpackages are nothing different than packages except that they are defined inside another package. Subpackages are similar to subdirectories, which is a directory created inside another directory. Subpackages in itself are packages, so you have to use/access them similarly as packages. They can also have any types like classes, interfaces, enums, etc., inside them.
Swing Class: Enhanced GUI Components
Swing has about four times the number of User Interface [UI] components as AWT and is part of the standard Java distribution. By today’s application GUI requirements, AWT is a limited implementation, not quite capable of providing the components required for developing complex GUIs required in modern commercial applications. The AWT component set has quite a few bugs and does take up a lot of system resources when compared to equivalent Swing resources. Netscape introduced its Internet Foundation Classes [IFC] library for use with Java. Its Classes became very popular with programmers creating GUIs for commercial applications.
Strings: Sequences of Characters
Strings, which are widely used in Java programming, are a sequence of characters. In the Java programming language, strings are treated as objects.
- Immutable: Once a String object is created, its value cannot be changed. Any operation that appears to modify a String actually creates a new String object.
- Final: The String class is declared as final, meaning it cannot be subclassed.
- Efficient: Java’s String pool optimization ensures that only one instance of a particular string exists in memory, improving performance and memory usage.
Garbage Collection: Automatic Memory Management
Garbage collection in Java is the process by which Java programs perform automatic memory management. Java programs compile to bytecode that can be run on a Java Virtual Machine, or JVM for short. When Java programs run on the JVM, objects are created on the heap, which is a portion of memory dedicated to the program. Eventually, some objects will no longer be needed. The garbage collector finds these unused objects and deletes them to free up memory. The garbage collector is the best example of the Daemon thread as it is always running in the background.