java

UNIT – I

1. Features of Java (Java Buzzwords)

Java is a high-level, object-oriented language. Its main features are:

  1. Simple – the syntax is similar to C/C++, and pointers and operator overloading are removed.

  2. Object-oriented – everything is written using classes and objects.

  3. Platform independent – source code is compiled into bytecode, which runs on any OS that has a JVM (“Write Once, Run Anywhere”).

  4. Secure – there are no explicit pointers, and bytecode is verified by the JVM.

  5. Robust – it has strong type checking, exception handling and automatic garbage collection.

  6. Architecture neutral – the size of primitive types is fixed on every machine.

  7. Portable – bytecode can be carried to any machine.

  8. High performance – the JIT compiler speeds up bytecode execution.

  9. Distributed – applications can be built over networks (RMI, sockets).

  10. Multithreaded – several tasks can run at the same time.

  11. Dynamic – classes are loaded at runtime.

  12. Interpreted – bytecode is executed by the JVM.

2. Structure of a Java program

  1. Documentation section (comments)

  2. Package statement

  3. Import statements

  4. Class definition(s)

  5. Class with the main() method

java

import java.util.Scanner;              // import section
class Hello {                          // class definition
    public static void main(String[] args) {   // main method
        System.out.println("Hello Java");
    }
}

Execution starts from public static void main(String[] args).

3. Identifiers and keywords

Identifier: a name given to a variable, method, class, object, array, etc. for identification purposes.

Rules for declaring identifiers

  1. An identifier must not start with a digit. The first letter must be a character or a special symbol.

  2. Only underscore _ and dollar sign </code>areallowedasspecialsymbols.Nootherspecialsymbolsareallowed.</p></li><li><p>Pre−definedclassesandpre−definedinterfacescanalsobeusedasidentifiers.</p></li></ol><p><strong>Examples</strong></p><tablestyle="min−width:50px;"><colgroup><colstyle="min−width:25px;"><colstyle="min−width:25px;"></colgroup><tbody><tr><thcolspan="1"rowspan="1"><p>Identifier</p></th><thcolspan="1"rowspan="1"><p>Valid?</p></th></tr><tr><tdcolspan="1"rowspan="1"><p>08sum</p></td><tdcolspan="1"rowspan="1"><p>Notvalid</p></td></tr><tr><tdcolspan="1"rowspan="1"><p>sum12</p></td><tdcolspan="1"rowspan="1"><p>Valid</p></td></tr><tr><tdcolspan="1"rowspan="1"><p>12sum</p></td><tdcolspan="1"rowspan="1"><p>Notvalid</p></td></tr><tr><tdcolspan="1"rowspan="1"><p>sum</p></td><tdcolspan="1"rowspan="1"><p>Valid</p></td></tr><tr><tdcolspan="1"rowspan="1"><p></code> are allowed as special symbols. No other special symbols are allowed.</p></li><li><p>Pre-defined classes and pre-defined interfaces can also be used as identifiers.</p></li></ol><p><strong>Examples</strong></p><table style="min-width: 50px;"><colgroup><col style="min-width: 25px;"><col style="min-width: 25px;"></colgroup><tbody><tr><th colspan="1" rowspan="1"><p>Identifier</p></th><th colspan="1" rowspan="1"><p>Valid?</p></th></tr><tr><td colspan="1" rowspan="1"><p>08sum</p></td><td colspan="1" rowspan="1"><p>Not valid</p></td></tr><tr><td colspan="1" rowspan="1"><p>sum12</p></td><td colspan="1" rowspan="1"><p>Valid</p></td></tr><tr><td colspan="1" rowspan="1"><p>12sum</p></td><td colspan="1" rowspan="1"><p>Not valid</p></td></tr><tr><td colspan="1" rowspan="1"><p>_sum</p></td><td colspan="1" rowspan="1"><p>Valid</p></td></tr><tr><td colspan="1" rowspan="1"><p>abc

    Valid

    3a

    Not valid

    (Your notes mark sum_123</code>asnotvalid.Bytherulesabove,<code></code>and<code></code> as not valid. By the rules above, <code>_</code> and <code> are allowed, so check this one with your teacher.)

    Classification of identifiers:

    • User-defined identifiers.

    • Reserved identifiers (53). These split into keywords (50) and reserved literals (3): true, false, null, which are written in smaller (lower) case.

    • Keywords are further split into used keywords (48) and unused (2): goto and const.

    Keyword: an identifier that is reserved for a special purpose.

    • A keyword can’t be used as an identifier.

    • Keywords must be written only in lowercase letters.

    Table of the 48 used keywords

    Category

    Keywords

    Primitive datatypes (8)

    byte, short, int, long, float, double, char, boolean

    Flow control (11)

    if, else, while, do, for, switch, case, default, break, return, continue

    Modifiers (11)

    public, private, protected, static, abstract, final, strictfp, volatile, transient, synchronized, native

    Class related (6)

    interface, package, class, extends, implements, import

    Object related (4)

    new, instanceof, this, super

    Exception (5)

    try, catch, throw, throws, finally

    Other (3)

    enum, void, assert

    Example program

    java

    class IdentifierDemo {
        public static void main(String[] args) {
            int sum12 = 10;       // valid identifier
            int _sum = 20;        // valid identifier
            int $abc = 30;        // valid identifier
            System.out.println(sum12 + " " + _sum + " " + $abc);
        }
    }

    Output: 10 20 30

    4. Literals

    A literal is a constant value assigned to a variable. Literals are of five types:

    1. Integral literals: byte, short, int, long

    2. Floating point literals: float, double

    3. Character literals: char

    4. Boolean literals: boolean

    5. String literals

    The first four use primitive datatypes. String literals use a non-primitive datatype.

    (i) Integral literals can be written in three notations:

    • Decimal notation: digits 0 to 9.

    • Octal notation: digits 0 to 7, with prefix 0.

    • Hexadecimal notation: digits 0 to 9 and A to F, with prefix 0x.

    java

    class IntegralLiteral {
        public static void main(String[] args) {
            int a = 10;      // decimal
            int b = 010;     // octal
            int c = 0x10;    // hexadecimal
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
        }
    }

    Output: 10, 8, 16

    (ii) Floating point literals

    java

    class FloatLiteral {
        public static void main(String[] args) {
            float f1 = 9.3f;
            double d1 = 10.6d;
            System.out.println(f1);
            System.out.println(d1);
        }
    }

    Output: 9.3, 10.6

    (iii) Character literals

    • A char can be written as a character in single quotes, as an ASCII code (0 to 255), or as a Unicode value (0 to 65535).

    • The default value of char is '\u0000'.

    java

    class CharLiteral {
        public static void main(String[] args) {
            char c1 = 'a';
            char c2 = 97;        // ASCII code
            char c3 = '\u0061';  // Unicode
            System.out.println(c1);
            System.out.println(c2);
            System.out.println(c3);
        }
    }

    Output: a, a, a

    (iv) Boolean literals (true, false values assigned to a variable)

    java

    class BooleanLiteral {
        public static void main(String[] args) {
            boolean x = true;
            boolean y = false;
            System.out.println(x + " " + y);
        }
    }

    Output: true false

    (v) String literals are a group of characters in double quotes, e.g. String s = "Java";

    5. Object-oriented features of Java

    Java is a purely object-oriented language. Its features are:

    1. Class – a template (blueprint) of an object. It is created only once and its members are accessed using objects.

    2. Object – an instance of a class. We can create any number of objects for a particular class.

    3. Inheritance – a mechanism where one class acquires the properties (variables and methods) of another class. Its main advantage is code reusability.

    4. Polymorphism – “many forms”. The same method or object reference performs different actions depending on the situation. It increases code reusability and flexibility. It is of two types:

      • Compile-time: method overloading and constructor overloading.

      • Run-time: method overriding.

    5. Encapsulation [not in notes] – wrapping data and methods into a single unit (class) and hiding data using private.

    6. Abstraction [not in notes] – hiding implementation details and showing only essential features, using abstract classes and interfaces.

    6. Datatypes and variables

    Datatype: the kind (type) of data stored in a variable. There are two types:

    1. Primitive datatypes

      • Numerical: integer (byte, short, int, long) and floating point (float, double)

      • char

      • boolean

    2. Non-primitive datatypes

      • Classes: user-defined (e.g. Sum, Addition) and pre-defined (e.g. System, String)

      • Interfaces: user-defined (e.g. Eatable) and pre-defined (e.g. Runnable)

    Variable: a name given to a memory location to store data. Based on where they are declared, variables are of three types:

    1. Instance variable (object variable)

    • Declared inside a class but outside any method or constructor, without static.

    • Each object gets its own copy.

    • If one object’s value changes, it does not affect other objects.

    • Example: student name.

    2. Static variable (class variable)

    • Declared using the static keyword.

    • It belongs to the class, not to individual objects.

    • Only one copy exists, shared by all objects.

    • Example: college name.

    3. Local variable (method variable)

    • Declared inside a method, constructor or block.

    • It exists only while that method is executing.

    • Example: a teacher writes attendance for today’s class.

    java

    class VariableDemo {
        int a = 10;              // instance variable
        static int y = 20;       // static variable
        void show() {
            int c = 30;          // local variable
            System.out.println("Instance variable is " + a);
            System.out.println("Static variable is " + y);
            System.out.println("Local variable is " + c);
        }
        public static void main(String[] args) {
            VariableDemo obj = new VariableDemo();
            obj.show();
        }
    }

    Output:

    Instance variable is 10
    Static variable is 20
    Local variable is 30

    7. Primitive type conversion

    Type conversion converts the value from one datatype to another datatype. It is of two types:

    (1) Implicit type casting (widening / upcasting)

    • Performed automatically by the compiler.

    • It happens when a lower datatype value is assigned to a higher datatype variable.

    • There is no loss of information.

    • Order: byte → short → char → int → long → float → double

    java

    class Implicit {
        public static void main(String[] args) {
            int x = 'a';        // char -> int
            double d = 10;      // int -> double
            float f = 10;       // int -> float
            System.out.println(x);
            System.out.println(d);
            System.out.println(f);
        }
    }

    Output: 97, 10.0, 10.0

    (2) Explicit type casting (narrowing / downcasting)

    • Performed explicitly by the user.

    • It happens when a larger datatype value is assigned to a smaller datatype variable.

    • There is a high chance of loss of information, and the result may not be the same.

    • Syntax: datatype variable = (datatype) value;

    java

    class Explicit {
        public static void main(String[] args) {
            int n = 130;
            byte b = (byte) n;
            System.out.println(b);
            double d = 10.75;
            int i = (int) d;
            System.out.println(i);
        }
    }

    Output: -126, 10

    Why -126: 130 in binary is 00000000 10000010. A byte keeps only the last 8 bits, 10000010. The leftmost bit is 1, so the number is negative. Its 2’s complement gives 126, so the value is -126.

    8. Operators

    An operator is a symbol used to perform operations between operands. Java has eight kinds of operators:

    1. Arithmetic

    2. Relational

    3. Logical

    4. Assignment

    5. Conditional (ternary)

    6. Increment/decrement

    7. Bitwise

    8. Special

    (1) Arithmetic operators perform arithmetic operations.

    Symbol

    Operation

    Example

    +

    Addition

    5+4 = 9

    -

    Subtraction

    5-4 = 1

    *

    Multiplication

    3*4 = 12

    /

    Division (gives quotient)

    5/4 = 1

    %

    Modulus (gives remainder)

    5%4 = 1

    (2) Relational operators compare the relation between operands. The result is either true or false.

    Symbol

    Operation

    Example

    <

    Less than

    5<6 (T)

    >

    Greater than

    5>6 (F)

    <=

    Less than or equal to

    5<=6 (T)

    >=

    Greater than or equal to

    5>=6 (F)

    ==

    Equal to

    5==6 (F)

    !=

    Not equal to

    5!=6 (T)

    (3) Logical operators combine two or more relational/conditional expressions. The result is true or false.

    • && Logical AND: true when both conditions are true.

    • || Logical OR: false when both conditions are false.

    • ! Logical NOT: true when the condition is false, and vice versa.

    a

    b

    a&&b

    a||b

    T

    T

    T

    T

    T

    F

    F

    T

    F

    T

    F

    T

    F

    F

    F

    F

    (4) Assignment operators. The symbol = assigns a value to a variable, e.g. int a = 10;. Shorthand forms:

    Symbol

    Equivalent to

    a += b

    a = a + b

    a -= b

    a = a - b

    a *= b

    a = a * b

    a /= b

    a = a / b

    (5) Conditional (ternary) operator ? : takes three operands. It is similar to the if-else statement.
    Syntax: condition ? true part : false part;
    If the condition is true, the first expression executes, otherwise the second.

    java

    import java.util.Scanner;
    class Smallest {
        public static void main(String[] args) {
            int a, b, small;
            Scanner s = new Scanner(System.in);
            System.out.println("Enter value of a, b");
            a = s.nextInt();
            b = s.nextInt();
            small = (a < b) ? a : b;
            System.out.println("Smallest = " + small);
        }
    }

    (6) Increment and decrement operators increase or decrease a value by 1. They are ++ and --, and there are four types:

    • Pre-increment (++x): first the value is incremented by 1, then assigned.

    • Post-increment (x++): first the value is assigned, then incremented by 1.

    • Pre-decrement (--x): first decremented, then assigned.

    • Post-decrement (x--): first assigned, then decremented.

    java

    int x = 10;
    int y = ++x;   // x = 11, y = 11
    int p = 10;
    int q = p++;   // p = 11, q = 10

    (7) Bitwise operators perform operations on bits (0s and 1s). There are six:

    Operator

    Rule

    & AND

    1 only when both bits are 1

    | OR

    0 only when both bits are 0

    ^ XOR

    1 when the bits are different

    << Left shift

    Moves bits left by n positions; right side is filled with zeros, left bits are discarded. 5<<1: 0101 → 1010 = 10

    >> Right shift

    Moves bits right by n positions; discards right bits, fills left with zero. 21>>1: 10101 → 1010 = 10

    ~ NOT

    Complement: 1 becomes 0 and 0 becomes 1

    Example: a = 5 (101), b = 9 (1001). a & b = 0001 = 1. a | b = 1101 = 13. a ^ b = 1100 = 12.

    (8) Special operators

    • new operator creates a new instance of a class. It allocates memory dynamically from a pool of memory and returns a reference to the object. Example: Student s1 = new Student();

    • instanceof operator tests whether an object is an instance of the specified type (class or interface). It returns true or false.

    java

    class Sample {
        public static void main(String[] args) {
            Sample s = new Sample();
            System.out.println(s instanceof Sample);   // true
        }
    }

    Operator precedence and associativity: precedence defines the order in which operators are evaluated in an expression. If operators have the same precedence, associativity decides the order (L to R or R to L).
    Example: 10 + 2 * 6 / 3 - 1: 2*6 = 12, 12/3 = 4, so 10 + 4 - 1 = 13.

    9. Conditional statements

    Statements which are executed based on a condition are called conditional (branching/selection) statements. Java has five: if, if-else, nested if-else, if-else-if ladder, and switch.

    (1) if statement – the condition is checked first. If it is true, the if block executes. It is a one-way branching statement.

    java

    if (condition) {
        statements;
    }

    Example (whole number check):

    java

    if (n >= 0) {
        System.out.println("It is whole number");
    }

    (2) if-else statement – if the condition is true, the if block executes, otherwise the else block executes. It is two-way branching.

    java

    if (condition) {
        statement 1;
    } else {
        statement 2;
    }

    Example:

    java

    int n = 5;
    if (n % 2 == 0)
        System.out.println("It is even no");
    else
        System.out.println("It is odd no");

    (3) Nested if-else – an if-else placed inside another if or else is called nested if-else. We use it when we want to check more than one condition. It is multi-way branching.

    java

    if (condition1) {
        if (condition2) { statement1; }
        else { statement2; }
    } else {
        if (condition3) { statement3; }
        else { statement4; }
    }

    Example (largest of three numbers):

    java

    if (a > b) {
        if (a > c) System.out.println(a + " is largest");
        else System.out.println(c + " is largest");
    } else {
        if (b > c) System.out.println(b + " is largest");
        else System.out.println(c + " is largest");
    }

    (4) if-else-if ladder – when we want to check multiple conditions, we place an if statement in the else of the previous if. This is called an if-else-if ladder.

    java

    if (condition1) { statement1; }
    else if (condition2) { statement2; }
    else if (condition3) { statement3; }
    ...
    else { default statement; }

    (5) switch statement – used to select one among many statements. It is an alternative to the if-else-if ladder.

    java

    switch (expression) {
        case 1: block1; break;
        case 2: block2; break;
        ...
        default: default block;
    }
    • The expression is matched with each case. If it matches, that case block executes.

    • If no case matches, the default block executes.

    • break is used to terminate a particular case block.

    10. Loop statements

    Loop statements execute a set of statements repeatedly until the condition becomes false. Java has three: while, do-while, for.

    (1) while loop

    • The condition is checked first. If true, the statements execute repeatedly until the condition is false.

    • It is an entry-controlled loop. The minimum number of executions is zero.

    java

    while (condition) {
        statements;
        increment/decrement;
    }

    Program: print numbers from 1 to 5

    java

    class WhileDemo {
        public static void main(String[] args) {
            int i = 1;
            while (i <= 5) {
                System.out.println(i);
                i++;
            }
        }
    }

    (2) do-while loop

    • The statements are executed first, then the condition is checked. If true, they are repeated until the condition is false.

    • It is an exit-controlled loop. The minimum number of executions is one.

    java

    do {
        statement;
    } while (condition);

    Program: print numbers from 100 to 50 in reverse order

    java

    class Number {
        public static void main(String[] args) {
            int i = 100;
            do {
                System.out.println(i);
                i--;
            } while (i >= 50);
        }
    }

    (3) for loop

    • A group of statements is executed repeatedly until the condition is false.

    • It is an entry-controlled loop. The minimum number of executions is zero.

    java

    for (initialization; condition; increment/decrement) {
        statements;
    }

    Program: factorial of a given number using a for loop

    java

    import java.util.Scanner;
    class Factorial {
        public static void main(String[] args) {
            int i, fact = 1;
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a value n");
            int n = s.nextInt();
            for (i = 1; i <= n; i++) {
                fact = fact * i;
            }
            System.out.println("Factorial of given number is " + fact);
        }
    }

    Jump statements (unconditional) modify the behaviour of a loop. There are two:

    • break terminates a loop or switch immediately and exits the block without executing the rest of the statements. In a switch, it terminates a particular case block.

    • continue is an unconditional statement which skips the current iteration and continues with the next iteration.

    java

    class BreakExample {
        public static void main(String[] args) {
            for (int i = 0; i <= 5; i++) {
                if (i == 3) break;
                System.out.println(i);     // prints 0 1 2
            }
        }
    }
    class ContinueExample {
        public static void main(String[] args) {
            for (int i = 0; i <= 5; i++) {
                if (i == 3) continue;
                System.out.println(i);     // prints 0 1 2 4 5
            }
        }
    }

    11. Arithmetic operations using switch

    java

    import java.util.Scanner;
    class Operations {
        public static void main(String[] args) {
            int a, b, sum, sub, mul, div, mod, choice;
            Scanner s = new Scanner(System.in);
            System.out.println("Enter value of a,b");
            a = s.nextInt();
            b = s.nextInt();
            System.out.println("Enter your choice: 1.Addition 2.Subtraction 3.Multiplication 4.Division 5.Modulus");
            choice = s.nextInt();
            switch (choice) {
                case 1: sum = a + b;
                        System.out.println("Sum = " + sum);
                        break;
                case 2: sub = a - b;
                        System.out.println("Sub = " + sub);
                        break;
                case 3: mul = a * b;
                        System.out.println("Mul = " + mul);
                        break;
                case 4: div = a / b;
                        System.out.println("Div = " + div);
                        break;
                case 5: mod = a % b;
                        System.out.println("Mod = " + mod);
                        break;
                default: System.out.println("Invalid choice");
            }
        }
    }

    12. Palindrome check

    A number is a palindrome if it is equal to its reverse (e.g. 121).

    java

    import java.util.Scanner;
    class Palindrome {
        public static void main(String[] args) {
            int n, original, digit, rev = 0;
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a value of n");
            n = s.nextInt();
            original = n;
            while (n > 0) {
                digit = n % 10;
                rev = rev * 10 + digit;
                n = n / 10;
            }
            if (original == rev)
                System.out.println(original + " is a palindrome");
            else
                System.out.println(original + " is not a palindrome");
        }
    }

    13. Sum of individual digits

    java

    import java.util.Scanner;
    class Sum {
        public static void main(String[] args) {
            int n, sum = 0, digit;
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a value");
            n = s.nextInt();
            do {
                digit = n % 10;
                sum = sum + digit;
                n = n / 10;
            } while (n > 0);
            System.out.println("Sum of individual digits = " + sum);
        }
    }

    For n = 123: 3 + 2 + 1 = 6.

    14. Prime number check [not in notes]

    A prime number has exactly two factors: 1 and itself.

    java

    import java.util.Scanner;
    class Prime {
        public static void main(String[] args) {
            Scanner s = new Scanner(System.in);
            System.out.println("Enter a number");
            int n = s.nextInt();
            int count = 0;
            for (int i = 1; i <= n; i++) {
                if (n % i == 0)
                    count++;
            }
            if (count == 2)
                System.out.println(n + " is a prime number");
            else
                System.out.println(n + " is not a prime number");
        }
    }

    15. Percentage and grade using if-else-if ladder

    Percentage = (total marks / 500) × 100 for 5 subjects. The grade ranges below are an example, so use your college’s scheme if it differs.

    java

    import java.util.Scanner;
    class Marks {
        public static void main(String[] args) {
            int a, b, c, d, e;
            float p;
            System.out.println("Enter marks of a,b,c,d,e");
            Scanner s = new Scanner(System.in);
            a = s.nextInt();
            b = s.nextInt();
            c = s.nextInt();
            d = s.nextInt();
            e = s.nextInt();
            p = (a + b + c + d + e) / (float) 500 * 100;
            System.out.println("Percentage = " + p);
            if (p >= 80)
                System.out.println("Grade A+");
            else if (p >= 70)
                System.out.println("Grade A");
            else if (p >= 60)
                System.out.println("Grade B");
            else if (p >= 40)
                System.out.println("Grade C");
            else
                System.out.println("Fail");
        }
    }

    UNIT – II

    1. Classes and objects

    Class

    • A class is a template (blueprint) of an object. It is created only once and its members are accessed using objects.

    • A class in Java may contain: (1) only the state part, (2) only the behaviour part, or (3) both state and behaviour parts together.

    • State part → variables (properties). Behaviour part → methods/constructors.

    Syntax:

    java

    class classname {
        // state part (variables)
        // behaviour part (methods / constructors)
    }

    Object

    • An object is an instance of a class. We can create any number of objects for a particular class.

    • Syntax: classname objectname = new classname();

    Method: a function which is written inside a class is called a method.

    • Methods are blocks of code that perform a specific task.

    • They allow us to reuse code, which improves efficiency and organisation of the code.

    • All methods in Java must belong to a class.

    Syntax: datatype methodname(parameters) { method body; return value (optional); }

    Example program

    java

    class Student {
        int rno;                 // state part
        String name;
        float marks;
        void display() {         // behaviour part
            System.out.println("Rno is " + rno);
            System.out.println("Name is " + name);
            System.out.println("Marks is " + marks);
        }
    }
    class StudentDemo {
        public static void main(String[] args) {
            Student s1 = new Student();
            Student s2 = new Student();
            s1.rno = 1;  s1.name = "Ravi";  s1.marks = 95;
            s2.rno = 2;  s2.name = "Ramu";  s2.marks = 98;
            s1.display();
            s2.display();
        }
    }

    Here s1 and s2 are two objects of the class Student. Each has its own copy of rno, name and marks.

    2. Types of constructors

    Constructor

    • A special method (or member function) which is used to initialise the instance variables.

    • It has the same name as the class and doesn’t have any return type.

    • The first statement inside a constructor must be either this() or super(). super() is added by default.

    • Constructors can have access modifiers, but can’t be static, abstract or final.

    • It is called automatically when an object is created.

    Types of constructors

    1. Compiler-generated constructor → default constructor

    2. User-defined constructor → no-argument constructor and parameterized constructor

    (1) Default constructor

    • If there is no constructor in the class, the compiler provides a default constructor during compilation time.

    • If there is at least one constructor, the compiler will not provide any constructor.

    • It assigns default values for instance variables based on the datatype.

    • It is automatically called when an object is created.

    java

    class Student {
        int rno;
        String name;
        float marks;
        Student() {            // default constructor (provided by compiler)
            rno = 0;
            name = null;
            marks = 0.0f;
        }
        void display() {
            System.out.println("Rno is " + rno);
            System.out.println("Name is " + name);
            System.out.println("Marks are " + marks);
        }
    }
    class DefaultConstructor {
        public static void main(String[] args) {
            Student s1 = new Student();
            Student s2 = new Student();
            s1.display();
            s2.display();
        }
    }

    Output for both objects: rno = 0, name = null, marks = 0.0

    (2) User-defined no-argument constructor

    • A constructor written by the programmer that doesn’t take any parameters.

    • It initialises the object with the values chosen by the programmer. It is called automatically when an object is created.

    • It allows different objects to be initialised with the same values.

    • Drawback: all the objects are given the same values for instance variables.

    java

    class Student {
        int rno;
        String name;
        float marks;
        Student() {                // no-arg constructor
            rno = 1;
            name = "Ravi";
            marks = 87;
        }
        void display() {
            System.out.println("Rno is " + rno);
            System.out.println("Name is " + name);
            System.out.println("Marks is " + marks);
        }
    }
    class NoargConstructor {
        public static void main(String[] args) {
            Student s1 = new Student();
            Student s2 = new Student();
            s1.display();
            s2.display();          // both print rno 1, Ravi, 87.0
        }
    }

    (3) Parameterized constructor

    • A constructor that accepts one or more parameters.

    • It is defined by the programmer to initialise the object with specific values.

    • It allows different objects to be initialised with different values.

    java

    class Student {
        int rno;
        String name;
        float marks;
        Student(int rno1, String name1, float marks1) {
            rno = rno1;
            name = name1;
            marks = marks1;
        }
        void display() {
            System.out.println("Rno is " + rno);
            System.out.println("Name is " + name);
            System.out.println("Marks is " + marks);
        }
    }
    class ParameterizedConstructor {
        public static void main(String[] args) {
            Student s1 = new Student(1, "Ram", 89);
            Student s2 = new Student(2, "Rahul", 97);
            s1.display();
            s2.display();
        }
    }

    The objects are created in heap memory. s1 and s2 are reference variables on the stack that hold the addresses of those objects.

    Direct initialization: at the time of declaration we can initialise instance variables directly (e.g. int rno = 10; String name = "Ramesh";). In the case of the default constructor, the compiler uses these initialised values in place of default values.

    3. Types of inheritance

    Inheritance

    • A fundamental feature of object-oriented programming.

    • A mechanism where one class acquires the properties of another class.

    • Its main advantage is code reusability.

    Terms used in inheritance

    1. Base class / parent class / super class – the class which is inherited by the derived class.

    2. Derived class / child class / sub class – the class which inherits all the variables and methods of the base class.

    3. extends – a keyword which means to extend the functionality.

    Syntax:

    java

    class Baseclass {
        // variables and methods
    }
    class Derivedclass extends Baseclass {
        // variables and methods
    }

    Types of inheritance

    • Supported through classes: (1) Single, (2) Multilevel, (3) Hierarchical

    • Supported through interfaces: (4) Multiple, (5) Hybrid

    (1) Single inheritance: the variables and methods of one base class are inherited by one derived class. (A ← B)

    java

    class Animal {
        void eat() { System.out.println("eating"); }
    }
    class Dog extends Animal {
        void bark() { System.out.println("barking"); }
    }
    class Single {
        public static void main(String[] args) {
            Dog d1 = new Dog();
            d1.eat();
            d1.bark();
        }
    }

    (2) Multilevel inheritance: a chain of single inheritance. (A ← B ← C ← D)

    java

    class Animal {
        void eat() { System.out.println("eating"); }
    }
    class Dog extends Animal {
        void bark() { System.out.println("barking"); }
    }
    class Cat extends Dog {
        void sleep() { System.out.println("sleeping"); }
    }
    class Multilevel {
        public static void main(String[] args) {
            Cat c = new Cat();
            c.sleep();
            c.bark();
            c.eat();
        }
    }

    (3) Hierarchical inheritance: many derived classes inherit the properties of one base class. (A ← B, C, D)

    java

    class Animal {
        void eat() { System.out.println("eating"); }
    }
    class Dog extends Animal {
        void bark() { System.out.println("barking"); }
    }
    class Cat extends Animal {
        void sleep() { System.out.println("sleeping"); }
    }
    class Hierarchical {
        public static void main(String[] args) {
            Cat c = new Cat();
            c.sleep();
            c.eat();
        }
    }

    (4) Multiple inheritance: one derived class inherits the properties from two or more base classes. It is not supported by Java through classes, but it is supported through interfaces.

    (5) Hybrid inheritance: a combination of one or more types of inheritance. It is not supported through classes, but is supported through interfaces.

    4. Arrays

    Array

    • A collection of elements of a similar datatype.

    • The elements in an array are accessed using an index, an integer value that represents the position of the element in the array.

    • Array index always starts from 0 to n-1.

    • The elements are stored in consecutive (successive) memory locations.

    Types: (1) One-dimensional array (1D), (2) Two-dimensional array (multi-dimensional).

    One-dimensional array

    • A collection of elements of the same datatype arranged in a single row.

    • It is always declared with a single set of square brackets after the datatype.

    • Syntax: datatype[] arrayname = new datatype[size];

    • Example: int[] a = new int[5]; (elements a[0] to a[4])

    Program: read and display five integer elements using a 1D array

    java

    import java.util.Scanner;
    class Integer1 {
        public static void main(String[] args) {
            int[] a = new int[5];
            System.out.println("Enter the 5 elements");
            Scanner s = new Scanner(System.in);
            for (int i = 0; i < 5; i++) {
                a[i] = s.nextInt();
            }
            System.out.println("The 5 integers are:");
            for (int i = 0; i < 5; i++) {
                System.out.println(a[i]);
            }
        }
    }

    Two-dimensional array

    • A collection of elements of a similar datatype arranged in tabular form (matrix form). It is mainly used for matrix applications.

    • It is always declared with two sets of square brackets after the datatype.

    • Syntax: datatype[][] arrayname = new datatype[size1][size2]; where size1 = number of rows and size2 = number of columns.

    • Example: int[][] A = new int[3][3]; (elements A[0][0] to A[2][2])

    Program: read and print nine integer elements using a 2D array

    java

    import java.util.Scanner;
    class Integer2 {
        public static void main(String[] args) {
            int[][] A = new int[3][3];
            System.out.println("Enter the 9 integer elements");
            Scanner s = new Scanner(System.in);
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    A[i][j] = s.nextInt();
                }
            }
            System.out.println("The 9 integer elements are:");
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    System.out.print(A[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    5. this keyword

    this is a reference variable that points to the current class object. It is mainly used to prevent confusion when the instance variables, methods and constructors share the same name.

    Four uses of this

    1. To refer to the current class variable

    2. To refer to (call) the current class method

    3. To refer to (call) the current class constructor

    4. To return the current class object

    (1) To refer to the current class variable
    Syntax: this.variablename. When we have the same name for variables at local level and class level, we use this to refer to the class-level variable.

    java

    class A {
        int i = 100, j = 200;
        A(int i, int j) {
            System.out.println(i + " " + j);              // local variables
            System.out.println(this.i + " " + this.j);    // class variables
        }
    }
    class ThisVarExample {
        public static void main(String[] args) {
            A a = new A(10, 20);
        }
    }

    Output:

    10 20
    100 200

    (2) To refer to the current class method
    Syntax: this.methodname(parameters). In Java, to access the current class method there is no need to create an object and reference variable for the class. We can directly access the method using this.

    java

    class A {
        void m1() {
            System.out.println("A's m1 method");
            m2();            // same as this.m2()
            this.m2();
        }
        void m2() {
            System.out.println("A's m2 method");
        }
    }
    class Test {
        public static void main(String[] args) {
            A a = new A();
            a.m1();
        }
    }

    Output:

    A's m1 method
    A's m2 method
    A's m2 method

    (3) To refer to the current class constructor
    Syntax: this(parameters);. When we refer to the current class constructor, the first statement must be the this statement, otherwise a compile error is generated.

    java

    class A {
        A() {
            this(10);
            System.out.println("A's constructor");
        }
        A(int i) {
            this(22.3f);
            System.out.println("A's parameterized constructor");
        }
        A(float f) {
            System.out.println("A's float parameter");
        }
    }
    class Test {
        public static void main(String[] args) {
            A a = new A();
        }
    }

    Output:

    A's float parameter
    A's parameterized constructor
    A's constructor

    (4) To return the current class object
    Syntax: return this;. If we access all the current class methods by returning this, it is called method chaining. The return type must be the class type, so that each method returns the object back to the calling method.

    java

    class A {
        A m1() {
            System.out.println("A's m1 method");
            return this;
        }
        A m2() {
            System.out.println("A's m2 method");
            return this;
        }
        A m3() {
            System.out.println("A's m3 method");
            return this;
        }
    }
    class Test {
        public static void main(String[] args) {
            A a = new A();
            a.m1().m2().m3();
        }
    }

    Output:

    A's m1 method
    A's m2 method
    A's m3 method

    6. Matrix multiplication using 2D arrays [not in notes]

    java

    import java.util.Scanner;
    class MatrixMul {
        public static void main(String[] args) {
            int[][] A = new int[3][3];
            int[][] B = new int[3][3];
            int[][] C = new int[3][3];
            Scanner s = new Scanner(System.in);
            System.out.println("Enter elements of matrix A");
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                    A[i][j] = s.nextInt();
            System.out.println("Enter elements of matrix B");
            for (int i = 0; i < 3; i++)
                for (int j = 0; j < 3; j++)
                    B[i][j] = s.nextInt();
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    C[i][j] = 0;
                    for (int k = 0; k < 3; k++) {
                        C[i][j] = C[i][j] + A[i][k] * B[k][j];
                    }
                }
            }
            System.out.println("Product matrix C:");
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++)
                    System.out.print(C[i][j] + " ");
                System.out.println();
            }
        }
    }

    Matrix multiplication is possible only when the number of columns of A equals the number of rows of B.

    7. final classes, final methods and final variables

    The final keyword is used to restrict the user. It is useful when you want a variable to always store the same value, like constants. It can be used with a variable, a method and a class.

    (1) Final variable

    • A variable which is declared with the final keyword is called a final variable.

    • Its value can’t be modified once it is assigned.

    • Final variables can be instance variables, static variables and local variables.

    java

    class Bike {
        final int speedlimit = 100;
        void run() {
            speedlimit = 60;          // error
            System.out.println(speedlimit);
        }
    }
    class Test {
        public static void main(String[] args) {
            Bike b = new Bike();
            b.run();
        }
    }

    Output: Compile error, final variables cannot be modified. speedlimit is a final variable assigned the value 100, and inside method run we try to modify it to 60, which results in a compile error.

    (2) Final method

    • A method which is declared with the final keyword is called a final method.

    • A final method can’t be overridden by the subclasses.

    • Declaring a method as final ensures that its implementation remains unchanged, which is useful for security purposes.

    java

    class Bike {
        int speedlimit = 100;
        final void run() {
            System.out.println("speedlimit is 100");
        }
    }
    class Honda extends Bike {
        void run() {
            System.out.println("speedlimit is 60kmph");
        }
    }
    class Test {
        public static void main(String[] args) {
            Honda h = new Honda();
            h.run();
        }
    }

    Output: Compile error, final methods cannot be overridden.

    (3) Final class

    • A class which is declared with the final keyword is called a final class.

    • A final class can’t be extended.

    • Declaring a class as final ensures that no other class can modify or override its behaviour through inheritance.

    java

    final class Bike {
        int speedlimit = 100;
        void run() {
            System.out.println("speedlimit is 100");
        }
    }
    class Honda extends Bike {      // error
        void run() {
            System.out.println("speedlimit is 60kmph");
        }
    }
    class Test {
        public static void main(String[] args) {
            Honda h = new Honda();
            h.run();
        }
    }

    Output: Compile error. The class Bike is declared final, so it should not be extended, but we have a derived class Honda which extends the Bike class. Hence it results in a compile error.

    Summary: a final variable can’t be modified, a final method prevents method overriding, and a final class prevents inheritance.

    8. Abstract classes

    Abstract class: a class which is declared with the keyword abstract is called an abstract class.

    Syntax:

    java

    abstract class classname {
        // concrete methods
        // abstract methods
        abstract void m1();
    }

    Rules for abstract classes

    1. Abstract classes may contain only concrete methods, only abstract methods, or both concrete and abstract methods.

    2. Abstract classes may contain concrete methods, but a class which contains at least one abstract method must be declared as abstract, otherwise it gives a compile error.

    java

    class A {                      // error: must be declared abstract
        void m1() {}
        void m2() {}
        abstract void m3();
    }
    1. Abstract classes must be extended.

    2. There must be at least one subclass which extends the abstract class.

    3. A class which extends the abstract class must provide implementation to all the abstract methods of the abstract class.

    4. For abstract classes we can’t create an object with the new operator. We can only create reference variables. A a1 = new A(); is an error, whereas A a1; is allowed.

    5. Upcasting is required to access the members of an abstract class, because for abstract classes we cannot create objects with the new operator.

    6. Abstract methods provide more flexibility when compared to concrete methods.

    Program

    java

    abstract class A {
        void m1() {
            System.out.println("A's m1 method");
        }
        abstract void m2();
        abstract void m3();
    }
    class B extends A {
        void m2() {
            System.out.println("B's m2() method");
        }
        void m3() {
            System.out.println("B's m3() method");
        }
        void m4() {
            System.out.println("B's m4 method");
        }
    }
    class AbstractDemo {
        public static void main(String[] args) {
            A a1 = new B();       // upcasting
            a1.m1();
            a1.m2();
            a1.m3();
            // a1.m4();           // compile error (m4 is not in A)
            B b1 = new B();       // subclass object
            b1.m1();
            b1.m2();
            b1.m3();
            b1.m4();
        }
    }

    a1.m4() gives a compile error because the superclass reference can access only the members of class A. b1 (subclass object) can access everything.

    9. Method overloading and constructor overloading

    Polymorphism means “many forms”. It is one of the fundamental principles of OOP and allows the same method or object reference to perform different actions depending on the situation. It increases code reusability and flexibility.

    • Compile-time polymorphism: method overloading and constructor overloading.

    • Run-time polymorphism: method overriding.

    (1) Method overloading
    If two or more methods have the same name and they may differ in either the number or type or order of arguments, but not only in the return type, then the methods are said to be overloaded.

    java

    class MethodOverload {
        void sum(int a, float b) { ... }
        int sum(float b, int a) { ... }
    }

    Here sum is overloaded because the order of arguments differs (the return type may or may not be the same).

    Note: methods are not overloaded if there is no difference in the number, order or type of arguments. Changing only the return type does not overload a method:

    java

    class Test {
        void sum(int a) { ... }
        int sum(int a) { ... }     // not overloaded -> compile error
    }

    Example program:

    java

    class MethodOverload {
        void sum(int a, int b) {
            int c = a + b;
            System.out.println(c);
        }
        void sum(int a, int b, int c) {
            int d = a + b + c;
            System.out.println(d);
        }
        void sum(float a, float b) {
            float e = a + b;
            System.out.println(e);
        }
    }
    class Test {
        public static void main(String[] args) {
            MethodOverload obj = new MethodOverload();
            obj.sum(10, 20);          // 30
            obj.sum(10, 20, 30);      // 60
            obj.sum(10.5f, 9.5f);     // 20.0
        }
    }

    (2) Constructor overloading
    If two or more constructors have the same name (class name) and differ either in the number, type or order of arguments, then the constructors are said to be overloaded.

    (a) Differ by number of arguments: Student() and Student(int rno).
    (b) Differ by order of arguments: Student(int rno, float marks) and Student(float marks, int rno).
    (c) Differ by type of arguments: Student(int rno, float marks) and Student(float marks, String name).

    Example program:

    java

    class Student {
        int rno;
        String name;
        float marks;
        Student() {                                  // no-arg
            rno = 501;
            name = "RAM";
            marks = 90;
        }
        Student(int rno, String name, float marks) { // parameterized
            this.rno = rno;
            this.name = name;
            this.marks = marks;
        }
        Student(Student obj) {                       // copy constructor
            rno = obj.rno;
            name = obj.name;
            marks = obj.marks;
        }
        void display() {
            System.out.println("Rno is " + rno);
            System.out.println("Name is " + name);
            System.out.println("Marks is " + marks);
        }
    }
    class ConstructorOverloading {
        public static void main(String[] args) {
            Student s1 = new Student();
            Student s2 = new Student(502, "RAJ", 80);
            Student s3 = new Student(s1);
            s1.display();
            s2.display();
            s3.display();
        }
    }

    Method overriding (for comparison): if the parent class and child class have the same method name, then the child class can override the parent class method. The sub-class method is called the overriding method and the super-class method is called the overridden method.

    10. super keyword

    super is a reference variable which is used to refer to the immediate parent class object.

    Uses of super

    1. To refer to the immediate parent class instance variable

    2. To refer to the immediate parent class method

    3. To invoke (call) the immediate parent class constructor

    (1) To refer to the immediate parent class instance variable
    If the parent class and the child class have the same instance variable, then to access the instance variable of the parent class inside the child class we use super.variablename.

    java

    class Animal {
        String color = "black";
    }
    class Dog extends Animal {
        String color = "white";
        void printcolor() {
            System.out.println(color);          // white
            System.out.println(super.color);    // black
        }
    }
    class SuperExample {
        public static void main(String[] args) {
            Dog d = new Dog();
            d.printcolor();
        }
    }

    Output: white, black

    (2) To refer to the immediate parent class method
    To access the parent class method inside the child class, use super.methodname().

    java

    class Animal {
        void eat() {
            System.out.println("eating");
        }
    }
    class Dog extends Animal {
        void eat() {
            System.out.println("eating food");
        }
        void bark() {
            System.out.println("barking");
        }
        void work() {
            eat();           // Dog's eat
            super.eat();     // Animal's eat
            bark();
        }
    }
    class SuperMethod {
        public static void main(String[] args) {
            Dog d = new Dog();
            d.work();
        }
    }

    Output: eating food, eating, barking

    (3) To call the immediate parent class constructor
    To access the parent class constructor inside the derived class we use super(parameters).

    java

    class Animal {
        Animal() {
            System.out.println("eating");
        }
    }
    class Dog extends Animal {
        Dog() {
            super();
            System.out.println("Dog's method");
        }
    }
    class SuperConstructor {
        public static void main(String[] args) {
            Dog d = new Dog();
        }
    }

    Output: eating, Dog's method

    11. Command line arguments [not in notes]

    Command line arguments are values passed to a program from the command line when running it. They are received as String values in the args array of main(String[] args).

    java

    class CommandLine {
        public static void main(String[] args) {
            System.out.println("Number of arguments: " + args.length);
            for (int i = 0; i < args.length; i++) {
                System.out.println(args[i]);
            }
        }
    }

    Run: javac CommandLine.java, then java CommandLine Hello Java 10
    Output:

    Number of arguments: 3
    Hello
    Java
    10

    To use a number, convert it, e.g. int n = Integer.parseInt(args[2]);.

    12. String class and its methods [not in notes]

    String is a pre-defined class in java.lang. A String object is immutable, meaning its content can’t be changed once created.

    Method

    Purpose

    length()

    Returns the number of characters

    charAt(i)

    Returns the character at index i

    concat(s)

    Joins two strings

    substring(b, e)

    Returns part of the string

    equals(s) / equalsIgnoreCase(s)

    Compares content (case-sensitive / ignoring case)

    compareTo(s)

    Lexicographic comparison

    toUpperCase() / toLowerCase()

    Changes case

    trim()

    Removes leading/trailing spaces

    replace(a, b)

    Replaces characters

    indexOf(c)

    Position of first occurrence

    java

    class StringDemo {
        public static void main(String[] args) {
            String s1 = "Welcome";
            String s2 = new String("Java");
            System.out.println(s1.length());          // 7
            System.out.println(s1.charAt(2));         // l
            System.out.println(s1.concat(s2));        // WelcomeJava
            System.out.println(s1.substring(0, 3));   // Wel
            System.out.println(s1.toUpperCase());     // WELCOME
            System.out.println(s1.equals(s2));        // false
            System.out.println(s1.indexOf('c'));      // 3
            System.out.println(s1.replace('e', 'a')); // Walcoma
        }
    }

    13. StringBuffer class and its methods [not in notes]

    StringBuffer is a pre-defined class which creates mutable strings, so its content can be changed after creation.

    Method

    Purpose

    append(s)

    Adds text at the end

    insert(i, s)

    Inserts text at index i

    delete(b, e)

    Deletes characters from b to e-1

    reverse()

    Reverses the content

    replace(b, e, s)

    Replaces part of the string

    length() / capacity()

    Current length / total capacity

    charAt(i)

    Character at index i

    java

    class StringBufferDemo {
        public static void main(String[] args) {
            StringBuffer sb = new StringBuffer("Hello");
            sb.append(" Java");                  // Hello Java
            System.out.println(sb);
            sb.insert(5, ",");                   // Hello, Java
            System.out.println(sb);
            sb.delete(0, 2);                     // llo, Java
            System.out.println(sb);
            sb.reverse();                        // avaJ ,oll
            System.out.println(sb);
            System.out.println(sb.length());     // 10
        }
    }

    14. StringTokenizer class and its methods

    StringTokenizer

    • This class in Java is used to break a string into smaller parts called tokens based on specified delimiters.

    • It keeps track of the next token and allows sequential extraction of tokens from a string.

    Constructors

    1. StringTokenizer(String str) – creates a tokenizer for the specified string and uses default delimiters such as white spaces, tabs, etc.

    2. StringTokenizer(String str, String delim) – creates a tokenizer for the specified string using the given delimiters.

    3. StringTokenizer(String str, String delim, boolean returnDelims) – creates a tokenizer for the specified string with the custom delimiter and an option to return delimiters as tokens.

    Methods

    1. countTokens() – returns the total number of tokens present in the string.

    2. hasMoreTokens() – tests whether tokens are present for the given string or not.

    3. nextElement() – returns an Object rather than a String.

    4. hasMoreElements() – returns the same value as the hasMoreTokens method.

    5. nextToken() – returns the next token from the given string tokenizer.

    Example 1

    java

    import java.util.StringTokenizer;
    class Demo1 {
        public static void main(String[] args) {
            StringTokenizer st = new StringTokenizer("Apple,Banana,Mango", ",");
            while (st.hasMoreTokens()) {
                System.out.println(st.nextToken());
            }
        }
    }

    Output: Apple, Banana, Mango

    Example 2

    java

    import java.util.StringTokenizer;
    class StringTokenizerDemo {
        public static void main(String[] args) {
            StringTokenizer st = new StringTokenizer("Welcome to Java Programming");
            StringTokenizer st1 = new StringTokenizer("");
            int c = st.countTokens();
            System.out.println(c);                                   // 4
            System.out.println("Welcome to Java Programming: " + st.hasMoreTokens());   // true
            System.out.println("Empty string: " + st1.hasMoreTokens());                 // false
            System.out.println("Traversing the string:");
            while (st.hasMoreTokens()) {
                System.out.println(st.nextElement());
            }
        }
    }

    Output of the loop: Welcome, to, Java, Programming.

    15. Upcasting and downcasting

    Type casting for non-primitive datatypes

    • It is done with reference variables and it requires an inheritance relationship between the classes.

    • It is of two types: (1) upcasting, (2) downcasting.

    Upcasting

    • Assigning a sub-class object to a super-class reference variable is known as upcasting.

    • It is automatically done by the compiler.

    • Syntax: Superclass refvariable = new Subclass(); Example: Animal a1 = new Dog();

    • With the superclass reference variable we can access all the members of the superclass except the overridden methods.

    • In case of overridden methods of the superclass, the subclass overriding methods are executed.

    Downcasting

    • Assigning a super-class reference variable to a sub-class reference variable is known as downcasting.

    • It must be always followed by upcasting.

    • It can’t be applied directly on a superclass object, as it will throw a runtime error.

    • Syntax: Subclass refvariable = (Subclass) Superclass refvariable;

    • Example: Animal a1 = new Dog(); Dog d1 = (Dog) a1;

    • We use downcasting to access specific members of the sub-class that are hidden during upcasting.

    Example program to demonstrate upcasting and downcasting

    java

    class Animal {
        void eat() {
            System.out.println("Animal eating");
        }
    }
    class Dog extends Animal {
        void eat() {                       // overriding method
            System.out.println("Dog eating food");
        }
        void bark() {
            System.out.println("Dog barking");
        }
    }
    class CastingDemo {
        public static void main(String[] args) {
            Animal a1 = new Dog();         // upcasting
            a1.eat();                      // Dog eating food (overriding method runs)
            // a1.bark();                  // compile error, hidden during upcasting
            Dog d1 = (Dog) a1;             // downcasting
            d1.bark();                     // Dog barking
            d1.eat();                      // Dog eating food
            Animal a2 = new Animal();
            // Dog d2 = (Dog) a2;          // runtime error, downcasting a real superclass object
        }
    }

    UNIT – III [none of this is in your notes, so these are standard answers]

    1. Interface and its properties

    An interface is a collection of abstract methods and constants. It specifies what a class must do, not how. It is declared with the interface keyword and implemented by a class using implements.

    java

    interface Shape {
        void area();
    }

    Properties

    1. Declared using the interface keyword.

    2. Methods are public abstract by default.

    3. Variables are public static final by default (constants).

    4. We can’t create an object of an interface, but we can create a reference variable.

    5. An interface has no constructors.

    6. A class that implements an interface must implement all its methods, otherwise it must be declared abstract.

    7. An interface can extend one or more interfaces.

    8. It supports multiple inheritance.

    2. One interface extending another

    java

    interface A {
        void m1();
    }
    interface B extends A {
        void m2();
    }
    class C implements B {
        public void m1() { System.out.println("m1 of A"); }
        public void m2() { System.out.println("m2 of B"); }
    }
    class InterfaceExtends {
        public static void main(String[] args) {
            C obj = new C();
            obj.m1();
            obj.m2();
        }
    }

    Class C must implement both m1() (inherited from A) and m2().

    3. Can an interface extend multiple interfaces?

    Yes. An interface can extend any number of interfaces, separated by commas. This is how Java supports multiple inheritance.

    Syntax:

    java

    interface C extends A, B {
        // methods
    }

    java

    interface A { void m1(); }
    interface B { void m2(); }
    interface C extends A, B { void m3(); }

    A class implementing C must implement m1(), m2() and m3().

    4. Four differences between abstract class and interface

    Abstract class

    Interface

    Declared with the abstract keyword

    Declared with the interface keyword

    Can have both concrete and abstract methods

    Methods are abstract by default

    Variables can be of any type (final or non-final, static or non-static)

    Variables are public static final

    Can have constructors

    Cannot have constructors

    A class extends it using extends; multiple inheritance is not possible

    A class implements it using implements; multiple inheritance is possible

    5. Multiple inheritance through interfaces

    java

    interface Printable {
        void print();
    }
    interface Showable {
        void show();
    }
    class Demo implements Printable, Showable {
        public void print() {
            System.out.println("Hello from print");
        }
        public void show() {
            System.out.println("Hello from show");
        }
        public static void main(String[] args) {
            Demo d = new Demo();
            d.print();
            d.show();
        }
    }

    Output: Hello from print, Hello from show

    Class Demo inherits from two interfaces. This works through interfaces because they have no implementation, so there is no ambiguity, and it is not allowed through classes.