First Java Program - Input/Output, Debugging and Datatypes

Lecture Link : Link


  • Convention : class Name should start with a capital letter.

Primitives :

  • By default all decimal type values are of type double, if we want to store these decimal values in lets say 'float' then we have to add 'f' at the end like this : float marks = 98.67f;
  • by default all the integer values are of type integers, if we want to store these integers in let's say 'long' then we'll have to add 'L' at the end like this : long largeIntegerNumbers = 1212514513452234234L;
package com.hitarth;

public class Primitives {
    public static void main(String[] args) {

        // String is not a primitive
        // Primitive is basically a data type that you cannot break further

        // Primitives :
        int rollno = 64;
        char letter = 'r';
        float marks = 98.67f; // TN: that we have to add 'f' here.
        double largeDecimalNumbers = 456234.3234234;
        long largeIntegerNumbers = 1212514513452234234L; // TN: we have to add 'L' here.
        boolean check = false;

        // 1.) by default all the decimal values are of type double if we want to store these decimal values in lets say 'float' then we have to add 'f' at the end like this : `float marks = 98.67f;`

        // 2.) by default all the integer values are of type integers, if we want to store these integers in let's say 'long' then we'll have to add 'L' at the end like this : `long largeIntegerNumbers = 1212514513452234234L;`
    }
}

Inputs

  • Strings, Input
package com.hitarth;

import java.util.Scanner;

public class L3_Inputs {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Please enter some input: ");
        int rollno = input.nextInt();
        System.out.println("Your roll number is " + rollno);

        /*Literals and Identifiers*/

        int a = 10; // here 10 is a literal
        // LITERALS are a syntactical representation of boolean, character, number, string data

        int b = 234_000_000;
        System.out.println(b); // -> 234000000 // notice that the underscores are ignored.

        /* STRINGS */
        String word = input.next(); // takes the next word only
        String sentence = input.nextLine(); // takes the next line (sentence w/ white spaces)
        int number = input.nextInt(); // takes the next integer
        float marks = input.nextFloat(); // takes the next integer (float) // if we give an integer (for e.g. '10') as an input, it'll be converted to a float value (10.0)
        System.out.println(word);
        System.out.println(sentence);
    }
}
		Scanner input = new Scanner(System.in);
        char res = input.next().charAt(2); // → abc
        System.out.println(res); // → c
        Scanner input = new Scanner(System.in);
        int res = input.next().indexOf("3"); // input: 123
        System.out.println(res); // Prints: 2

Primitives :

package com.hitarth;

public class L3_Primitives {
    public static void main(String[] args) {

        // String is not a primitive
        // Primitive is basically a data type that you cannot break further

        // Primitives :
        int rollno = 64;
        char letter = 'r';
        float marks = 98.67f; // TN: that we have to add 'f' here.
        double largeDecimalNumbers = 456234.3234234;
        long largeIntegerNumbers = 1212514513452234234L; // TN: we have to add 'L' here.
        boolean check = false;

        // 1.) by default all the decimal values are of type double if we want to store these decimal values in lets say 'float' then we have to add 'f' at the end like this : `float marks = 98.67f;`

        // 2.) by default all the integer values are of type integers, if we want to store these integers in let's say 'long' then we'll have to add 'L' at the end like this : `long largeIntegerNumbers = 1212514513452234234L;`
    }
}

Sum Program :

package com.hitarth;
import java.util.Scanner;

public class L4_Sum {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        float num1 = input.nextInt();
        float num2 = input.nextFloat(); // if we take nextInt here instead then the code will work as long as we'll enter an integer, the moment we enter a decimal value it'll given an error.

        float sum = num1 + num2;
        System.out.println("Sum = " + sum); // -> 23.0 type value
    }
}

Type Conversion and Casting :

package com.hitarth;
import java.util.Scanner;

public class L5_TypeConversion_and_Casting {
    public static void main(String[] args) {
    // When one type of data is assigned to another type of variable an automatic type conversion will take place if the following conditions are met:

        // 1.) The two types should be compatible. Basically float will only convert a number to a float value and not a string. Common sense.

        // 2.) Destination type should be greater than source type. We know that float > int (as in float you can add both float and int values)
            // for e.g. : int num = input.nextFloat(); // this will give an error

        // 3.)
        Scanner input = new Scanner(System.in);
        float num = input.nextFloat(); // here even if we enter an integer the number will automatically get converted into a float.
        float res = input.nextInt(); // is also valid
        System.out.println(num);

    // TYPE CASTING :

        // This is sometimes called narrowing conversion as you are explicitly asking for a float value to be converted to an int.

        int num2 = (int)(67.56f);
        System.out.println(num2); //-> 67

    // Automatic type promotion in expressions
        int a = 257;
        byte b = (byte)a; // a byte is of 1 byte i.e. range is from 0 to 256.
        System.out.println(b); // -> 1
        //even after typecasting 'a' we can't hold the value 257 in a byte. The reason we are getting the value '1'. This happens because we've given byte more than it can handle, so it'll just store the remainder in the 'byte b' instead. Therefore, 257 % 256 = 1 is being stored here.

        byte x = 40;
        byte y = 50;
        int z = x * y;
        System.out.println(z); // -> 2000
        // if range of byte is only 0 - 256 then how is the calculation x * y which is equal to 2000 being stored in a byte format ?
        // What happens is that the result of the intermediate term x*y exceeds the range of the byte variable type. To handle this kind of problem java is automatically *promoting* each byte to an integer when it's  evaluating the expression.

        byte b1 = 50;
        // b = b*2;
        // this gives an error since the evaluated value of the expression b*2 is an int and we can't store int in a byte variable.
        // b = (byte)(b*2); // however we can resolve this problem by typecasting the result to byte.

        int number = 'A';
        System.out.println(number); // -> 65 // ASCII value of A = 65
        // JAVA follows the UNICODE system so all the languages are supported, we can even print the UNICODE values of Chinese Alphabets.

        byte b2 = 42;
        char c ='a';
        short s = 1024;
        float f = 2.3f;

        float result = (b2*c) / (s*f);
        System.out.println((b2*c) + ", " + (s*f)); // -> 4074, 2355.2
        System.out.println(result); // -> 1.7297895
    }
}

Conditional Operators and Loops :

package com.hitarth;

import java.util.Scanner;
public class L6_Conditional_Operators {
    public static void main(String[] args) {

        // IF
        int a = 10;
        if (a==10)
        {
            System.out.println("Hello World!");
        }


        // WHILE LOOP
        int count = 5;
        while(count != 0)
        {
            System.out.print(count); // -> 54321
            count--;
        }
        System.out.println();

        // FOR LOOP
        for(int i = 1; i <= 5; i++)
        {
            System.out.print(i); // -> 12345
        }
    }
}

To check CASE of a letter (Program):

package com.hitarth;
import java.util.Scanner;


public class L6_Conditional_Operators_and_Loops {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        // there is no such thing as input.nextChar()
        // we'll take the input as a string then trim it to get the first character
        //.trim removes the extra spaces (both leading and trailing)
        char ch = input.next().trim().charAt(0);

        //to check if char ch is upper case or not.
        if( ch >= 'A' && ch <='Z')
            System.out.println(ch + " : is UPPERCASE");
        else
            System.out.println(ch + " : is lowercase");
    }
}

.equals() vs == :

== :

  • If both a and b point to same objects then => true
  • otherwise => false
  • Basically == reference bhi check karta hai.
    Pasted image 20231226235607.png

.equals() :

  • it will give true in both the above cases as it only checks the value and not the reference.
public class L6_Conditional_Operators_and_Loops {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        String a = "real";
        String b = "real";

//        if (a.equals(b))
        if (a == b)
            System.out.println(true);
        else
            System.out.println(false);
    }
}

Switch Case Statements :

public class L6_Conditional_Operators_and_Loops {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        String fruit = "mango";
//        String b = "real";

        switch (fruit)
        {
            case "mango":
                System.out.println("Yellow");
                break;
            case "Apple":
                System.out.println("Red");
                break;
            default:
                System.out.println("IDK");
        }

    }
}

Better/Enhanced Switch Case :

package com.hitarth;
import java.util.Scanner;

// SWITCH CASE
public class L6_Conditional_Operators_and_Loops {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        String fruit = "apple";
//        String b = "real";


        switch (fruit) {
            case "mango" -> {
	            System.out.println("Yellow");
	            // we can add curly braces if multi line code is to be written.
            }
            case "apple" -> System.out.println("Red");
            default -> System.out.println("IDK");
        }

    }
}

Functions :

package com.hitarth;
import java.util.Scanner;

public class L8_Functions {
    public static void main(String[] args) {
        System.out.println(sum(2, 3)); // -> 5
    }
    static int sum (int x1, int x2) {
        return (x1 + x2);
    }
}

Returning a string using a function

package com.hitarth;
import java.util.Scanner;

public class L8_Functions {
    public static void main(String[] args) {
        System.out.println(greet(1)); // -> number is 1
    }
    static String greet (int x1) {
        return (x1 == 1 ? "number is 1" : "IDK the no. dawg");
    }
}

Pass By Value :

Pasted image 20231227013323.png

  • Numbers will not be swapped

NOTE: In JAVA there is no pass by reference, only pass by value exists. (see the points under the heading below for more clarity on how arrays are passed)

Passing array (pass by reference (kind of))

  • Note that there is no pass by reference in java.
  • For arrays: It is not pass by reference but instead pass by copy of the value of the reference.
  • the reference itself is passed by call by value and the value that is being passed refers to the object.
package com.hitarth;
import java.util.Scanner;

public class L8_Functions {
    public static void main(String[] args) {
        int[] arr ={1,2,3,4};

        System.out.println(arr[0]); //-> 1
        change(arr);
        System.out.println(arr[0]); //-> 9

    }
    static void change (int[] arr2) {
        arr2[0] = 9;
    }
}

Scope :

Method Scope :

Pasted image 20231227230437.png

  • Scoping here is like in any other language.

Block Scoping :

package com.hitarth;

public class temp {
    public static void main(String[] args) {
        int a = 20;
        int b = 10;

        //block
        {
            int a =20; // gives error (can't initialise the same variable again even tho we're doing it inside of a block)
            a= 35; //allowed // changes the value of a to 35
            int c= 15;
        }

        c=13; // not allowed // can't access c variable (which lies inside of a block) outside the block


    }
}
package com.hitarth;

public class temp {
    public static void main(String[] args) {
        int a = 20;
        int b = 10;

        //block
        {
            a =35;
            System.out.println(a); // -> 35
        }
            System.out.println(a); // -> 35

    }
}

Just two rules are there :

  • If you initialize something inside of a block then it'll be accessible inside of that block only.
  • If something is initialized outside the block then it can be accessed & modified inside of a block as well.

Shadowing

Shadowing in java is basically a practice of using two variables with the same name within the scope that overlaps

package com.hitarth;

import org.w3c.dom.ls.LSOutput;

public class temp {
    static int x = 90; // this will be shadowed cuz lower level is overriding the upper level show the higher level is shadowed.

    public static void main(String[] args) {
        System.out.println(x); // → 90
        int x = 40;
        System.out.println(x); // → 40
        // the variable defined outside this scope (int x = 90) is now hidden hence the variable that is now being printed the int x that is defined in this scope only.
        fun(); // → 90
    }
    static void fun() {
        System.out.println(x);
    }
}

what if we initialize after declaring :

package com.hitarth;

import org.w3c.dom.ls.LSOutput;

public class temp {
    static int x = 90;

    public static void main(String[] args) {
        System.out.println(x); // → 90
        int x; // declaration
        x = 40; // initialization

        System.out.println(x); // → 40
        fun(); // → 90
    }
    static void fun() {
        System.out.println(x);
    }
}

// same results as before
// this happened because the variable defined inside the scope will be looked up for first and if the compiler doesn't find a variable inside the current scope then only it'll go outside the current scope. (see the code below)
package com.hitarth;

import org.w3c.dom.ls.LSOutput;

public class temp {
    static int x = 90;

    public static void main(String[] args) {
        System.out.println(x); // → 90
        x = 40; // initialization

        System.out.println(x); // → 40
        fun(); // → 40
    }
    static void fun() {
        System.out.println(x);
    }
}

// results are now not the same as before
  • shadowing only works in class variables and it doesn't work in methods.

Variable Arguments (VarArgs)

  • when we do not know how many inputs we are giving
  • variable argument (vararg) parameter must be the last in the list
package com.hitarth;


import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        fun(2, 3, 4, 5, 6); // all the arguments will internally be stored in an array
    }

    static void fun(int... v) {
        System.out.println(Arrays.toString((v))); // → [2, 3, 4, 5, 6]
    }
}

Mix of arguments :

package com.hitarth;


import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        multiple(1, 2, "hello", "name");
    }

    static void multiple(int a, int b, String ...v) {
        System.out.println(a + b + v[0] + v[1]); // → 3helloname
    }

}

Function / Method Overloading :

  • two or more functions with the same name can exist if the parameters are different.
package com.hitarth;


import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        fun(67); // → 67
        fun("hello!"); // → hello!
    }

    static void fun (int a)
    {
        System.out.println(a);
    }
    static void fun (String b)
    {
        System.out.println(b);
    }

}
  • same type of arguments but different number of arguments are also considered okay (see the example below) :
package com.hitarth;


import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        fun(67); // → 67
        fun(2, 3); // → 5
    }

    static void fun (int a)
    {
        System.out.println(a);
    }
    static void fun (int a, int b)
    {
        System.out.println(a+b);
    }

}
  • function overloading happens at compilation time, it'll look for functions having same type of parameters.

Another example :

package com.hitarth;


import java.util.Arrays;

public class temp {
    public static void main(String[] args) {
        fun(2, 3); // → [2, 3]
        fun("hello", "hi"); // → [hello, hi]
    }

    static void fun (int ...v)
    {
        System.out.println(Arrays.toString((v)));
    }
    static void fun (String ...v)
    {
        System.out.println(Arrays.toString((v)));
    }

}