Java Basics
Object​
An object is a software bundle of related state and behavior.
Objects share two characteristics: they all have state and behavior. Dogs have state (name, color, breed, hungry) and behavior (barking, fetching, wagging tail). Bicycles also have state (current gear, current pedal cadence, current speed) and behavior (changing gear, changing pedal cadence, applying brakes). Identifying the state and behavior for real-world objects is a great way to begin thinking in terms of object-oriented programming.
For each object that you see, ask yourself two questions: "What possible states can this object be in?" and "What possible behavior can this object perform?".
Take a minute right now to observe the real-world objects that are in your immediate area. For each object that you see, ask yourself two questions: "What possible states can this object be in?" and "What possible behavior can this object perform?".
Make sure to write down your observations. As you do, you'll notice that real-world objects vary in complexity;
your desktop lamp may have only two possible states (on and off) and two possible behaviors (turn on, turn off), but your desktop radio might have additional states (on, off, current volume, current station) and behavior (turn on, turn off, increase volume, decrease volume, seek, scan, and tune).
You may also notice that some objects, in turn, will also contain other objects. These real-world observations are a starting point to understand the world of object-oriented programming.
Software objects consist of state and related behavior.
An object stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages).
Methods operate on an object's internal state and serve as the primary mechanism for object-to-object communication.
Hiding internal state and requiring all interaction to be performed through an object's methods is known as data encapsulation — a fundamental principle of object-oriented programming.
So Finally!!!
Bundling code into individual software objects provides a number of benefits, including:
- Modularity: The source code for an object can be written and maintained independently of the source code for other objects. Once created, an object can be easily passed around inside the system.
- Information-hiding: By interacting only with an object's methods, the details of its internal implementation remain hidden from the outside world.
- Code re-use: If an object already exists (perhaps written by another software developer), you can use that object in your program. This allows specialists to implement/test/debug complex, task-specific objects, which you can then trust to run in your own code.
- Pluggability and debugging ease: If a particular object turns out to be problematic, you can simply remove it from your application and plug in a different object as its replacement. This is analogous to fixing mechanical problems in the real world. If a bolt breaks, you replace it, not the entire machine.
Ref: OOP Basics
Class​
A class is the blueprint from which individual objects are created.
In your applications, you will often find many individual objects all of the same kind. There may be thousands of other bicycles in existence, all of the same make and model. Each bicycle was built from the same set of blueprints and therefore contains the same components.
In object-oriented terms, we say that your bicycle is an instance of the class of objects known as bicycles.
The following Bicycle class is one possible implementation of a bicycle:
class Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
The syntax of the Java programming language may look new to you, but the design of this class is based on the previous discussion of bicycle objects. The fields cadence, speed, and gear represent the object's state, and the methods (changeCadence(), changeGear(), speedUp() etc.) define its interaction with the outside world.
You may have noticed that the Bicycle class does not contain a main() method. That is because it is not a complete application; it is just the blueprint for bicycles that might be used in an application. The responsibility of creating and using new Bicycle objects belongs to some other class in your application.
Here is a BicycleDemo class that creates two separate Bicycle objects and invokes their methods:
class BicycleDemo {
public static void main(String[] args) {
// Create two different
// Bicycle objects
Bicycle bike1 = new Bicycle();
Bicycle bike2 = new Bicycle();
// Invoke methods on
// those objects
bike1.changeCadence(50);
bike1.speedUp(10);
bike1.changeGear(2);
bike1.printStates();
bike2.changeCadence(50);
bike2.speedUp(10);
bike2.changeGear(2);
bike2.changeCadence(40);
bike2.speedUp(10);
bike2.changeGear(3);
bike2.printStates();
}
}
Interface​
An interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types.
Method bodies exist only for default methods and static methods. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces.
Defining An Interface
An interface declaration consists of modifiers, the keyword interface, the interface name, a comma-separated list of parent interfaces (if any), and the interface body. For example:
public interface GroupedInterface extends Interface1, Interface2, Interface3 {
// constant declarations
// base of natural logarithms
double E = 2.718282;
// method signatures
void doSomething (int i, double x);
int doSomethingElse(String s);
}
The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, then your interface is accessible only to classes defined in the same package as the interface.
An interface can extend other interfaces, just as a class subclass or extend another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces. The interface declaration includes a comma-separated list of all the interfaces that it extends.
The Interface Body
The interface body can contain abstract methods, default methods, and static methods. An abstract method within an interface is followed by a semicolon, but no braces (an abstract method does not contain an implementation). Default methods are defined with the default modifier, and static methods with the static keyword. All abstract, default, and static methods in an interface are implicitly public, so you can omit the public modifier.
In addition, an interface can contain constant declarations. All constant values defined in an interface are implicitly public, static, and final. Once again, you can omit these modifiers.
When you extend an interface that contains a default method, you can do the following:
Not mention the default method at all, which lets your extended interface inherit the default method.
Redeclare the default method, which makes it abstract.
Redefine the default method, which overrides it.
In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.)
This makes it easier for you to organize helper methods in your libraries; you can keep static methods specific to an interface in the same interface rather than in a separate class.
Inheritence​
Definitions: A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).
Excepting Object, which has no superclass, every class has one and only one direct superclass (single inheritance). In the absence of any other explicit superclass, every class is implicitly a subclass of Object.
Classes can be derived from classes that are derived from classes that are derived from classes, and so on, and ultimately derived from the topmost class, Object. Such a class is said to be descended from all the classes in the inheritance chain stretching back to Object.
Object-oriented programming allows classes to inherit commonly used state and behavior from other classes. In this example, Bicycle now becomes the superclass of MountainBike, RoadBike, and TandemBike. In the Java programming language, each class is allowed to have one direct superclass, and each superclass has the potential for an unlimited number of subclasses:
Different kinds of objects often have a certain amount in common with each other.
Tandem bikes,
Road bikes, and
Mountain bikes,
for example, all share the characteristics of bicycles (current speed, current pedal cadence, current gear). Yet each also defines additional features that make them different:
Tandem bicycles have two seats and two sets of handlebars;
Road bikes have drop handlebars;
Mountain bikes have an additional chain ring, giving them a lower gear ratio.
Complex class structures can be built through inheritance, composition, and aggregation.
Inheritance establishes an “is-a” relationship between classes.
- The subclass has the same features and functionality as its base class, with some extensions.
- A Car is-a Vehicle. An Apple is-a Food.
Composition and aggregation are the construction of complex classes that incorporate other objects.
- They establish a “has-a” relationship between classes.
- A Car has-a Engine. A Customer has-a CreditCard.
In composition, the component object exists solely for the use of its composite object.
I. If the composite object is destroyed, the component object is destroyed as well. II. For example, an Employee has-a name, implemented as a String object. There is no need to retain the String object once the Employee object has been destroyed
In aggregation, the component object can (but isn’t required to) have an existence independent of its use in the aggregate object.
I. Depending on the structure of the aggregate, destroying the aggregate may or may not destroy the component. II. For example, let’s say a Customer has-a BankAccount object. However, the BankAccount might represent a joint account owned by multiple Customers. In that case, it might not be appropriate to delete the BankAccount object just because one Customer object is deleted from the system.
Package​
A package is a namespace that organizes a set of related classes and interfaces.
Conceptually you can think of packages as being similar to different folders on your computer. You might keep HTML pages in one folder, images in another, and scripts or applications in yet another. Because software written in the Java programming language can be composed of hundreds or thousands of individual classes, it makes sense to keep things organized by placing related classes and interfaces into packages.
The Java platform provides an enormous class library (a set of packages) suitable for use in your own applications. This library is known as the "Application Programming Interface", or "API" for short. Its packages represent the tasks most commonly associated with general-purpose programming. For example, a String object contains state and behavior for character strings; a File object allows a programmer to easily create, delete, inspect, compare, or modify a file on the filesystem; a Socket object allows for the creation and use of network sockets;
Inheritence, Aggregagtion and composition - Together​
Complex class structures can be built through inheritance, composition, and aggregation.
Inheritance
Inheritance establishes an “is-a” relationship between classes.
-
The subclass has the same features and functionality as its base class, with some extensions.
-
A Car is-a Vehicle. An Apple is-a Food.
Composition
Composition and aggregation are the construction of complex classes that incorporate other objects.
-
They establish a “has-a” relationship between classes.
-
A Car has-a Engine. A Customer has-a CreditCard.
In composition, the component object exists solely for the use of its composite object.
a). If the composite object is destroyed, the component object is destroyed as well.
b). For example, an Employee has-a name, implemented as a String object. There is no need to retain the String object once the Employee object has been destroyed.
Aggregation
In aggregation, the component object can (but isn’t required to) have an existence independent of its use in the aggregate object.
-
Depending on the structure of the aggregate, destroying the aggregate may or may not destroy the component.
-
For example, let’s say a Customer has-a BankAccount object. However, the BankAccount might represent a joint account owned by multiple Customers. In that case, it might not be appropriate to delete the BankAccount object just because one Customer object is deleted from the system.
Final Thoughts:
Notice that composition and aggregation represent another aspect of encapsulation. For example, consider a Customer class that includes a customer’s birthdate as a property. We could define a Customer class in such a way that it duplicates all of the fields and methods from and existing class like Date, but duplicating code is almost always a bad idea. What if the data or methods associated with a Date were to change in the future? We would also have to change the definitions for our Customer class. Whenever a set of data or methods are used in more than one place, we should look for opportunities to encapsulate the data or methods so that we can reuse the code and isolate any changes we might need to make in the future.
Additionally when designing a class structure with composition or aggregation, we should keep in mind the principle of encapsulation when deciding where to implement functionality. Consider implementing a method on Customer that would return the customer’s age. Obviously, this depends on the birth date of the customer stored in the Date object. But should we have code in Customer that calculates the elapsed time since the birth date? It would require the Customer class to know some very Date-specific manipulation. In this case, the code would be tightly coupled –- a change to Date is more likely to require a change to Customer as well. It seems more appropriate for Date objects to know how to calculate the elapsed time between two instances. The Customer object could then delegate the age request to the Date object in an appropriate manner. This makes the classes loosely coupled –- so that a change to Date is unlikely to require a change to Customer.
Difference between interfaces and abstract classes?​
This is very common question if you are appearing interview for junior level programmer. Well, most noticeable differences are as below:
- Variables declared in a Java interface is by default final. An abstract class may contain non-final variables.
- Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behavior.
- Members of a Java interface are public by default. A Java abstract class can have the usual flavors of class members like private or abstract etc.
- Java interface should be implemented using keyword “implements“; A Java abstract class should be extended using keyword “extends“.
- A Java class can implement multiple interfaces but it can extend only one abstract class.
- Interface is absolutely abstract and cannot be instantiated; A Java abstract class also cannot be instantiated, but can be invoked if a main() exists. Since Java 8, you can define default methods in interfaces.
- Abstract class are slightly faster than interface because interface involves a search before calling any overridden method in Java. This is not a significant difference in most of cases but if you are writing a time critical application than you may not want to leave any stone unturned.
Ref: Howtodoinjava.com
Static Block and Initialization Block​
Static Block
Java supports a special block, called static block (also called static clause) which can be used for static initializations of a class. This code inside static block is executed only once: the first time you make an object of that class or the first time you access a static member of that class (even if you never make an object of that class).
The static block is executed before any constructor
Initialization Block
Instance Initialization Blocks or IIB are used to initialize instance variables. IIBs are executed before constructors. They run each time when object of the class is created.
- blocks are executed whenever the class is initialized and before constructors are invoked.
- They are typically placed above the constructors within braces.
- It is not at all necessary to include them in your classes.
*** Garbage Collection***​
The lifecycle of a Java object is managed by the JVM. Once an object is created by the programmer, we need not worry about the rest of its lifecycle. The JVM will automatically find those objects that are not in use anymore and reclaim their memory from the heap.
Garbage collection is a major operation that JVM does and tuning it for our needs, which can give a massive performance boosts to our application. There are a variety of garbage collection algorithms that are provided by modern JVMs. We need to be aware of our application’s needs to decide on which algorithm to use.
*** Java Memory Model***​
The Java memory model specifies how the Java virtual machine works with the computer’s memory (RAM). The Java virtual machine is a model of a whole computer so this model naturally includes a memory model - AKA the Java memory model.
It is very important to understand the Java memory model if you want to design correctly behaving concurrent programs. The Java memory model specifies how and when different threads can see values written to shared variables by other threads, and how to synchronize access to shared variables when necessary.
The original Java memory model was insufficient, so the Java memory model was revised in Java 1.5. This version of the Java memory model is still in use in Java 8.
The Java memory model used internally in the JVM divides memory between thread stacks and the heap.
Thread Stack
Each thread running in the Java virtual machine has its own thread stack. The thread stack contains information about what methods the thread has called to reach the current point of execution. I will refer to this as the “call stack”. As the thread executes its code, the call stack changes.
The thread stack also contains all local variables for each method being executed (all methods on the call stack). A thread can only access it’s own thread stack. Local variables created by a thread are invisible to all other threads than the thread who created it. Even if two threads are executing the exact same code, the two threads will still create the local variables of that code in each their own thread stack. Thus, each thread has its own version of each local variable.
All local variables of primitive types ( boolean, byte, short, char, int, long, float, double) are fully stored on the thread stack and are thus not visible to other threads. One thread may pass a copy of a pritimive variable to another thread, but it cannot share the primitive local variable itself.
Heap
The heap contains all objects created in your Java application, regardless of what thread created the object. This includes the object versions of the primitive types (e.g. Byte, Integer, Long etc.). It does not matter if an object was created and assigned to a local variable, or created as a member variable of another object, the object is still stored on the heap.
Where is the storage?
A local variable may be of a primitive type, in which case it is totally kept on the thread stack.
A local variable may also be a reference to an object. In that case the reference (the local variable) is stored on the thread stack, but the object itself is stored on the heap.
An object may contain methods and these methods may contain local variables. These local variables are also stored on the thread stack, even if the object the method belongs to is stored on the heap.
An object’s member variables are stored on the heap along with the object itself. That is true both when the member variable is of a primitive type, and if it is a reference to an object.
Static class variables are also stored on the heap along with the class definition.
Objects on the heap can be accessed by all threads that have a reference to the object. When a thread has access to an object, it can also get access to that object’s member variables. If two threads call a method on the same object at the same time, they will both have access to the object’s member variables, but each thread will have its own copy of the local variables.