OOPNotes
OOPNotes
When you declare an object of a class, you are creating an instance of that class.
Thus, a class is a logical construct. An object has physical reality. (That is, an object occupies
space in memory.)
💨Object
Objects are characterized by three essential properties:
State
Identity
behavior.
The state of an object is a value from its data type. The identity of an object distinguishes one
object from another.
It is useful to think of an object’s identity as the place where its value is stored in memory.
The behavior of an object is the effect of data-type operations.
The dot operator links the name of the object with the name of an Instance Variable (All
the Variables inside the object).
Example= sout(student1.rollno)
Although commonly referred to as the dot operator, the formal specification for Java
categorizes the . as a separator.
The 'new' keyword dynamically allocates(that is, allocates at run time)memory for an
object & returns a reference to it.
This reference is, more or less, the address in memory of the object allocated by new.
This reference is then stored in the variable.
Thus, in Java, all class objects must be dynamically allocated.
💨New Keyword:-
Box mybox; // declare reference to object
mybox = new Box(); // allocate a Box object
The first line declares mybox as a reference to an object of type Box. At this point,
mybox does not yet refer to an actual object.
The next line allocates an object and assigns a reference to it to mybox.
After the second line executes, you can use mybox as if it were a Box object. But in
reality, mybox simply holds, in essence, the memory address of the actual Box object.
The key to Java’s safety is that you cannot manipulate references as you can actual pointers.
Thus, you cannot cause an object reference to point to an arbitrary memory location or
manipulate it like an integer.
You might be wondering why you do not need to use new for such things as integers or
characters.
The answer is that Java’s primitive types are not implemented as objects.
Rather, they are implemented as “normal” variables.
This is done in the interest of efficiency.
It is important to understand that new allocates memory for an object during run time.
NOTE:
Bus bus = new Bus();
lhs(reference i.e. bus) is looked be compiler & rhs (object i.e. new Bus()) is looked by jvm
💨this Keyword:
Sometimes a method will need to refer to the object that invoked it. To allow this, Java defines
the “this” keyword. this can be used inside any method to refer to the current object. That is, this
is always a reference to the object on which the method was invoked.
💨final Keyword:
A field can be declared as final. Doing so prevents its contents from being modified, making it,
essentially, a constant.
This means that you must initialize a final field when it is declared.
It is a common coding convention to choose all uppercase identifiers for final fields:
final int FILE_OPEN = 2;
Unfortunately, final guarantees immutability only when instance variables are primitive types,
not reference types.
If an instance variable of a reference type has the final modifier, the value of that instance
variable (the reference to an object) will never change—it will always refer to the same object—
but the value of the object itself can change.
Example:-
final Student Arti = new A("Arti manputra");
Arti.name= "Neha";
💨Constructor
Definition: Constructor is a special function, that runs when you create an object and it
allocates some variable.
Once defined, the constructor is automatically called when the object is created, before the new
operator completes.
Constructors look a little strange because they have no return type, not even void.
This is because the implicit return type of a class’ constructor is the class type itself.
In the line
Box mybox1 = new Box();
new Box( ) is calling the Box( ) constructor.
In Java, constructor of base class with no argument gets automatically called in derived class
constructor.
For example, output of following program given below is:
Base Class Constructor Called
Derived Class Constructor Called
// filename: Main.java
class Base {
Base() {
System.out.println("Base Class Constructor Called ");
}
}
Any class will have a default constructor, does not matter if we declare it in the class or not. If
we inherit a class,
then the derived class must call its super class constructor. It is done by default in derived class.
If it does not have a default constructor in the derived class, the JVM will invoke its default
constructor and call
the super class constructor by default. If we have a parameterised constructor in the derived class
still it calls the
default super class constructor by default. In this case, if the super class does not have a default
constructor,
instead it has a parameterised constructor, then the derived class constructor should call
explicitly call the
parameterised super class constructor.
💨Packages:
Packages are containers for classes. They are used to keep the class name space
compartmentalized.
For example, a package allows you to create a class named List, which you can store in your own
package without concern that it will collide with some other class named List stored elsewhere.
Packages are stored in a hierarchical manner and are explicitly imported into new class
definitions.
Java uses file system directories to store packages. For example, the .class files for any
classes you declare to be part of MyPackage must be stored in a directory called
MyPackage. Remember that case is significant, and the directory name must match the
package name exactly.
A package hierarchy must be reflected in the file system of your Java development
system.
For example, a package declared as
package java.awt.image;
needs to be stored in java\awt\image in a Windows environment. Be sure to choose
your package names carefully.
You cannot rename a package without renaming the directory in which the classes are
stored.
✨How does the Java run-time system know where to look for packages that you create?
The answer has three parts.
1. First, by default, the Java run-time system uses the current working directory as its
starting point. Thus, if your package is in a subdirectory of the current directory, it will be
found.
2. Second, you can specify a directory path or paths by setting the CLASSPATH
environmental variable.
3. Third, you can use the -classpath option with java and javac to specify the path to your
classes.
When a package is imported, only those items within the package declared as public will be
available to non-subclasses in the importing code.
💨Understanding static:
When a member is declared static, it can be accessed before any objects of its class are
created, and without reference to any object. You can declare both methods and variables to
be static.
The most common example of a static member is main( ).
main( ) is declared as static because it must be called before any objects exist.
Static method in Java is a method which belongs to the class and not to the object.
A static method can access only static data. It cannot access non-static data (instance
variables)
A non-static member belongs to an instance. It's meaningless without somehow resolving
which instance of a class you are talking about. In a static context, you don't have an
instance, that's why you can't access a non-static member. without explicitly mentioning
an object reference.
In fact, you can access a non-static member in a static context by specifying the object
reference explicitly :
public class Human {
A static method can call only other static methods and cannot call a non-static method
from it.
A static method can be accessed directly by the class name and doesn’t need any object
A static method cannot refer to "this" or "super" keywords in anyway
If you need to do computation in order to initialize your static variables, you can declare
a static block that gets executed exactly once, when the class is first loaded.
As soon as the UseStatic class is loaded, all of the static statements are run. First, a is set to 3,
then the static block executes, which prints a message and then initializes b to a*4 or 12. Then
main( ) is called,
which calls meth( ), passing 42 to x. The three println( ) statements refer to the two static
variables a and b,
as well as to the local variable x.
You cant override the inherited static methods, as in java overriding takes place by
resolving the type of object at run-time and not compile time, and then calling the
respective method.
Static methods are class level methods, so it is always resolved during compile time.
Static INTERFACE METHODS are not inherited by either an implementing class or a
sub-interface.
NOTE:
public class Static {
💨Inheritance:
To inherit a class, you simply incorporate the definition of one class into another by using the
extends keyword.
Syntax:-
class subclass-name extends superclass-name {
// body of class
}
You can only specify one superclass for any subclass that you create.
Java does not support the inheritance of multiple superclasses into a single subclass
You can, as stated, create a hierarchy of inheritance in which a subclass becomes a
superclass of another subclass.
However, no class can be a superclass of itself.
Although a subclass includes all of the members of its superclass, it cannot access those
members of the superclass that have been declared as private.
plainbox = weightbox;
(superclass) (subclass)
SUPERCLASS ref = new SUBCLASS(); // HERE ref can only access methods which are
available in SUPERCLASS
Using super:
Whenever a subclass needs to refer to its immediate superclass, it can do so by use of the
keyword super.
Super has two general forms.
The first calls the superclass constructor.
The second is used to access a member of the superclass that has been hidden by a
member of a subclass.
Here, BoxWeight( ) calls super( ) with the arguments w, h, and d. This causes the Box
constructor to be called, which initializes width, height, and depth using these values.
BoxWeight no longer initializes these values itself.
It only needs to initialize the value unique to it: weight. This leaves Box free to make these
values private if desired.
Thus, super( ) always refers to the superclass immediately above the calling class.
This is true even in a multileveled hierarchy.
class Box {
private double width;
private double height;
private double depth;
Notice that super() is passed an object of type BoxWeight—not of type Box.This still invokes the
constructor Box(Box ob).
NOTE: A superclass variable can be used to reference any object derived from that class.
Thus, we are able to pass a BoxWeight object to the Box constructor.Of course,Box only has
knowledge of its own members.
super.member
Here, member can be either a method or an instance variable. This second form of super is most
applicable to situations in which member names of a subclass hide members by the same name in
the superclass.
💨If you think about it, it makes sense that constructors complete their execution in order of
derivation.
💨Because a superclass has no knowledge of any subclass, any initialization it needs to perform is
separate from and possibly prerequisite to any initialization performed by the subclass.
Therefore, it must complete its execution first.
NOTE: If super( ) is not used in subclass' constructor, then the default or parameterless
constructor of each superclass
will be executed.
NOTE: Declaring a class as final implicitly declares all of its methods as final, too.
As you might expect, it is illegal to declare a class as both abstract and final since an abstract
class is incomplete
by itself & relies upon its subclasses to provide complete implementations.
# NOTE: Although static methods can be inherited ,there is no point in overriding them in child
classes because the
method in parent class will run always no matter from which object you call it. That is why static
interface methods
cannot be inherited because these method will run from the parent interface and no matter if we
were allowed to
override them, they will always run the method in parent interface.
That is why static interface method must have a body.
💨Polymorphism:
Compile-time Polymorphism / Overloading Methods:
In Java, it is possible to define two or more methods within the same class that share the same
name, as long as their parameter declarations are different.
While overloaded methods may have different return types, the return type alone is insufficient
to distinguish two versions of a method. When Java encounters a call to an overloaded method, it
simply executes the version of the method whose parameters match the arguments used in the
call.
In some cases, Java’s automatic type conversions can play a role in overload resolution.
class OverloadDemo {
void test(double a){
System.out.println("Inside test(double) a: " + a);
}
}
class Overload {
public static void main(String args[]) {
OverloadDemo ob = new OverloadDemo();
int i = 88;
ob.test(i); // this will invoke test(double)
ob.test(123.2); // this will invoke test(double)
}
}
As you can see, this version of OverloadDemo does not define test(int). Therefore, when test( ) is
called with an integer argument inside Overload, no matching method is found. However, Java
can automatically convert an integer into a double, and this conversion can be used to resolve the
call. Therefore, after test(int) is not found, Java elevates i to double and then calls test(double).
Of course, if test(int) had been defined, it would have been called instead.
Java will employ its automatic type conversions only if no exact match is found.
Returning Objects:
// Returning an object.
class Test {
int a;
Test(int i) {
a = i;
}
Test incrByTen() {
Test temp = new Test(a+10);
return temp;
}
}
class RetOb {
public static void main(String args[]) {
Test ob1 = new Test(2);
Test ob2;
ob2 = ob1.incrByTen();
System.out.println("ob1.a: " + ob1.a);
System.out.println("ob2.a: " + ob2.a);
}
}
Output:
ob1.a: 2
ob2.a: 12
As you can see, each time incrByTen( ) is invoked, a new object is created, and a reference to it
is returned to the
calling routine. Since all objects are dynamically allocated using new, you don’t need to worry
about an object going
out-of-scope because the method in which it was created terminates. The object will continue to
exist as long as there
is a reference to it somewhere in your program. When there are no references to it, the object will
be reclaimed the
next time garbage collection takes place.
Method overriding occurs only when the names and the type signatures of the two
methods are identical.
If they are not, then the two methods are simply overloaded.
The object type defines which one to run and the reference type defines which one to
acess
If B extends A then you can override a method in A through B with changing the return type of
method to B.
💨Encapsulation:
Definition:- wrapping up the implementation of the data members and methods in class
💨Abstarct:
Sometimes you will want to create a superclass that only defines a generalized form that will be
shared by all of its subclasses, leaving it to each subclass to fill in the details. Such a class
determines the nature of the methods that the subclasses must implement.
You may have methods that must be overridden by the subclass in order for the subclass to have
any meaning.
In this case, you want some way to ensure that a subclass does, indeed, override all necessary
methods.
Java’s solution to this problem is the abstract method.
You can require that certain methods be overridden by subclasses by specifying the abstract type
modifier.
These methods are sometimes referred to as subclass's responsibility because they have no
implementation specified in the superclass.
Thus, a subclass must override them—it cannot simply use the version defined in the superclass.
Any class that contains one or more abstract methods must also be declared abstract.
# There can be no objects of an abstract class.
# You cannot declare abstract constructors, or abstract static methods.
# You can declare static methods in abstract class.
Because there can be no objects for abstract class. If they had allowed to call abstract static
methods,
it would that mean we are calling an empty method (abstract) through classname because it is
static.
Any subclass of an abstract class must either implement all of the abstract methods in the
superclass,
or be declared abstract itself.
Abstract classes can include as much implementation as they see fit i.e.there can be concrete
methods(methods with body)
in abstract class.
Although abstract classes cannot be used to instantiate objects, they can be used to create object
references,
because Java’s approach to run-time polymorphism is implemented through the use of superclass
references.
A public constructor on an abstract class doesn't make any sense because you can't instantiate an
abstract class directly
(can only instantiate through a derived type that itself is not marked as abstract)
Check: https://stackoverflow.com/questions/260666/can-an-abstract-class-have-a-constructor
💨Interfaces:
Multiple inheritance is not available in java.
(Same functions in 2 classes it will skip that hence no multiple inheritance)
Instead we have java interfaces. they have abstract functions (no body of functions)
Interfaces specify only what the class is doing, not how it is doing it.
The problem with MULTIPLE INHERITANCE is that two classes may define different ways of
doing the same thing,
and the subclass can't choose which one to pick.
Key difference between a class and an interface: a class can maintain state information
(especially through the use of instance variables), but an interface cannot.
Using interface, you can specify a set of methods that can be implemented by one or more
classes.
Although they are similar to abstract classes, interfaces have an additional capability:
A class can implement more than one interface. By contrast, a class can only inherit a single
superclass
(abstract or otherwise).
Using the keyword interface, you can fully abstract a class’ interface from its implementation.
That is, using interface, you can specify what a class must do, but not how it does it.
Interfaces are syntactically similar to classes, but they lack instance variables, and, as a general
rule,
their methods are declared without any body.
By providing the interface keyword, Java allows you to fully utilize the “one interface, multiple
methods”
aspect of polymorphism.
NOTE: Interfaces are designed to support dynamic method resolution at run time.
Normally, in order for a method to be called from one class to another, both classes need to be
present at compile time
so the Java compiler can check to ensure that the method signatures are compatible. This
requirement by itself makes for
a static and nonextensible classing environment. Inevitably in a system like this, functionality
gets pushed up higher
and higher in the class hierarchy so that the mechanisms will be available to more and more
subclasses. Interfaces are
designed to avoid this problem. They disconnect the definition of a method or set of methods
from the inheritance
hierarchy. Since interfaces are in a different hierarchy from classes, it is possible for classes that
are unrelated
in terms of the class hierarchy to implement the same interface. This is where the real power of
interfaces is realized.
NOTE: The methods that implement an interface must be declared public. Also, the type
signature of the implementing method must match exactly the type signature specified in the
interface definition.
It is both permissible and common for classes that implement interfaces to define additional
members of their own.
NOTE:
You can declare variables as object references that use an interface rather than a class type.
This process is similar to using a superclass reference to access a subclass object.
Any instance of any class that implements the declared interface can be referred to by such a
variable.
When you call a method through one of these references, the correct version will be called based
on the actual instance of the interface being referred to. Called at run time by the type of object it
refers to.
The method to be executed is looked up dynamically at run time, allowing classes to be created
later than the code which
calls methods on them.
The calling code can dispatch through an interface without having to know anything about the
“callee.”
CAUTION: Because dynamic lookup of a method at run time incurs a significant overhead when
compared with the normal
method invocation in Java, you should be careful not to use interfaces casually in performance-
critical code.
Nested Interfaces:
For example, you might have a class that implements two interfaces.
If each of these interfaces provides default methods, then some behavior is inherited from both.
# In all cases, a class implementation takes priority over an interface default implementation.
# In cases in which a class implements two interfaces that both have the same default method,
but the class does not
override that method, then an error will result.
# In cases in which one interface inherits another, with both defining a common default method,
the inheriting
interface’s version of the method takes precedence.
NOTE: static interface methods are not inherited by either an implementing class or a
subinterface.
i.e. static interface methods should have a body! They cannot be abstract.
NOTE : when overriding methods, the access modifier should be same or better i.e. if in Parent
Class it was protected, then then overridden should be either protected or public.
Type of methods:
Interface can have only abstract methods.
Abstract class can have abstract and non-abstract methods. From Java 8, it can have default and
static methods also.
Final Variables:
Variables declared in a Java interface are by default final.
An abstract class may contain non-final variables.
Type of variables:
Abstract class can have final, non-final, static and non-static variables.
Interface has only static and final variables.
Implementation:
Abstract class can provide the implementation of interface.
Interface can’t provide the implementation of abstract class.
Inheritance vs Abstraction:
A Java interface can be implemented using keyword “implements”
and abstract class can be extended using keyword “extends”.
Multiple implementation:
An interface can extend another Java interface only,
an abstract class can extend another Java class and implement multiple Java interfaces.