07 Java - Classes (Part I)


1. Concrete Class
These are classes that can be instantiated using the
new
keyword.All the methods in the is class have implementation
It can also be a subclass that implements an interface or extends an abstract class.
A class access modifier can be either "public" or "package private" (no explicit modifier defined/ No keyword present)
public class Person {
int empId;
public Person(int empId) {
this.empId = empId;
}
public int getEmpId() {
return empId;
}
}
public interface Shape {
public void computeArea();
}
public class Rectangle implements Shape{
@Override
public void computeArea() {
System.out.println("Area of rectangle");
}
}
2. Abstract Class (0 to 100% Abstraction)
Show only important features to users and hide its internal implementation.
2 ways to achieve abstraction:
Class is declared as abstracted through keyword "abstract".
It can have both abstract (method without body) and non abstract methods.
We can not create an instance of this class.
We parent has some features which all child classes have in common, then this can be used.
Constructors can be created inside them. And with super keyword from child classes we can access them.
If all the methods are abstract then it is 100% abstraction. Interface is by default it is 100% abstraction.
Example:
Abstract class Car
public abstract class Car {
int mileage;
public Car(int mileage) {
this.mileage = mileage;
}
public abstract void pressBreak();
public abstract void pressClutch();
public int getNumberOfWheels(){
return 4;
}
}
Abstract class LuxuryCar inherited Car
public abstract class LuxuryCar extends Car{
public LuxuryCar(int mileage) {
super(mileage);
}
@Override
public void pressBreak() {
//Implementation of break in luxury car
}
public abstract void pressDualBreakSystem();
}
Concrete class Audi
public class Audi extends LuxuryCar{
public Audi(int mileage) {
super(mileage);
}
@Override
public void pressClutch() {
//implementation of clutch
}
@Override
public void pressDualBreakSystem() {
//implementation of dual break system
}
}
3. Super and Sub Class
A class that is derived from another class is called a Subclass
And from class through which Subclass is dervied its called superclass.
In Java, in the absence of any other explicit superclass, every class is implicitly a subclasss of Object class.
Object is the topmost class in java
Object: It has some common methods like clone(), toString(), equals(), notify(), wait() etc...
package learn;
public class ObjectTest {
public static void main(String[] args) {
ObjectTest test = new ObjectTest();
Object person = new Person();
Object audi = new Audi(1);
System.out.println(person.getClass());
System.out.println(audi.getClass());
}
}
/* Output:
class learn.Person
class learn.Audi
*/
4. Nested Class
A nested class is a class defined within another class.
When to Use Nested Classes
Single Usage: If a class (Class A) is only going to be used by one other class (Class B), you can define Class A as a nested class within Class B. This avoids the need for a separate file for Class A.
Logical Grouping: Nested classes help in logically grouping related classes together in one file, making the code more organized and easier to manage.
Scope
The scope of a nested class is the same as its outer class. If the outer class is public, the nested class will also be public.
Types of Nested Classes
Static Nested Class
Non Static Nested Class (Inner Class)
Member Inner Class
Local Inner Class
Annonymous Inner Class
Static Nested Class
It do not have access to the non static instance variable and method of outer class.
Its object can be initiated without initiating the object of outer class.
It can be private, public, protected or package-private (default, no explicit declaration)
Note: Outer class is same as class so it can be public or package-private
Example 1:
package learn;
public class OuterClass {
int instanceVariable = 10;
static int classVariable = 20;
static class NestedClass{
public void print(){
System.out.println(classVariable);
}
}
}
/* Usage
OuterClass.NestedClass nest = new OuterClass.NestedClass();
nest.print();
*/
Example 2:
package learn;
public class OuterClass {
int instanceVariable = 10;
static int classVariable = 20;
private static class NestedClass{
public void print(){
System.out.println(classVariable);
}
}
public void display(){
NestedClass nest = new NestedClass();
nest.print();
}
}
/*
OuterClass outerClass = new OuterClass();
outerClass.display();
*/
Non Static Nested Class:
It has access to all the instance variables and methods of outer class.
An instance of the outer class must be created before initializing an object of the inner class.
1. Member Inner Class:
It can be private, public, protected, default
If an inner class is private, its object can only be instantiated within the outer class.
package learn;
public class OuterClass {
int instanceVariable = 10;
static int classVariable = 20;
class InnerClass{
public void print(){
System.out.println(classVariable+instanceVariable);
}
}
}
/* Usage -
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass inner = outerClass.new InnerClass();
*/
2. Local Inner Class
These are those classes which are defined in any block like for loop, while loop block, if condition block, method etc
It can not be declared as private, protected, public. Only default (not defined explicit) access modifier is used.
It can not be initiated outside of this block.
package learn;
public class OuterClass {
int instanceVariable = 10;
static int classVariable = 20;
public void display(){
int methodLocalVariable = 3;
class LocalInnerClass{
int localInnerVariable = 4;
public void print(){
System.out.println(instanceVariable+classVariable+methodLocalVariable+localInnerVariable);
}
}
LocalInnerClass localObj= new LocalInnerClass();
localObj.print();
}
}
/* Usage -
OuterClass outerClass = new OuterClass();
outerClass.display();
*/
Inheritance in Nested classes
Example 1: One inner class inherit another inner class in same outer class
package learn;
public class OuterClass {
int instanceVariable = 10;
static int classVariable = 20;
class InnerClass1{
int innerClass1Variable = 3;
}
class InnerClass2 extends InnerClass1{
int innerClass2Variable = 4;
void display(){
System.out.println(innerClass1Variable+innerClass2Variable+instanceVariable+classVariable);
}
}
}
/* Usage
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass2 innerClass2Obj = outerClass.new InnerClass2();
innerClass2Obj.display();
*/
Example 2: Static Inner Class inherited by different class
package learn;
public class OuterClass {
static class NestedClass{
public void display(){
System.out.println("Inside Innerclass");
}
}
}
Inheritacne usage
public class SomeOtherClass extends OuterClass.NestedClass{
public void display1(){
display();
}
}
Example 3: Non Static Inner Class inherited by different class
package learn;
public class OuterClass {
class InnerClass{
public void display(){
System.out.println("Inside Innerclass");
}
}
}
Inheritance usage
package learn;
public class SomeOtherClass extends OuterClass.InnerClass{
SomeOtherClass(){
new OuterClass().super();
//Imp step
// as you know, when child class constructor invoked, it first invoked the constructor of parent.
// but here the parent is Inner class, so it can only be accessed by the object of outerclass only
}
public void display1(){
display();
}
}
3. Anonymous Class
An inner class without a name called Anonymous class
Why its used
- When we want to override the behaviour of the method without even creating any subclass.
package learn.anonymous;
public abstract class Car {
public abstract void pressBreak();
}
Anonymous Usage -
package learn.anonymous;
public class Test {
public static void main(String[] args) {
Car audiCarObj = new Car() {
@Override
public void pressBreak() {
//my audi specific implementation here
System.out.println("Audi specific break changes");
}
};
audiCarObj.pressBreak();
}
}
Internal Working - 2 things happened behind the scene:
Sub class is created, name decided by the compiler
Creates an object of subclass and assign its reference to object "audiCarObj"
Similarly for interface also, it works in the same way...
command to get the byte code
javac Test.java Car.java
/* 3 Class files
Test.class
Test$1.class
Car.class
*/
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package learn.anonymous;
class Test$1 extends Car {
Test$1() {
}
public void pressBreak() {
System.out.println("Audi specific break changes");
}
}
Subscribe to my newsletter
Read articles from Chetan Datta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Chetan Datta
Chetan Datta
I'm someone deeply engrossed in the world of software developement, and I find joy in sharing my thoughts and insights on various topics. You can explore my exclusive content here, where I meticulously document all things tech-related that spark my curiosity. Stay connected for my latest discoveries and observations.