Takeaways on Jan 28 2024


  •  Object[] anyArray = new Object[3]; ->Here, you initialize an array of object with the length of 3
  • anyArray[0] = new String[]{"a", "b", "c"}; anyArray[1] = new String[][]{ {"1", "2"}, {"3", "4", "5"}, {"6", "7", "8", "9"}}; anyArray[2] = new String[2][2][2];
  • System.out.println(Arrays.deepToString(anyArray)); - we use deepToString to print the entire array with nested dimensions
public class ArrayExample {

    public static void main(String[] args) {
        Object[] anyArray = new Object[3];
        System.out.println(Arrays.toString(anyArray));

        anyArray[0] = new String[]{"a", "b", "c"};
        System.out.println(Arrays.deepToString(anyArray));

        anyArray[1] = new String[][]{
                {"1", "2"},
                {"3", "4", "5"},
                {"6", "7", "8", "9"}};

        System.out.println(Arrays.deepToString(anyArray));

        anyArray[2] = new String[2][2][2];
        System.out.println(Arrays.deepToString(anyArray));

        for (Object element : anyArray) {
            System.out.println("Element type = " + element.getClass().getSimpleName());
            System.out.println("Element toString() = " + element);
            System.out.println(Arrays.deepToString((Object[]) element));
        }
    }
}

I practised the above mentioned code while learning multi dimensional arrays.

When i learned this for the first time i grappled with multiple questions:

1) Why are we using Object here?  - Object[] anyArray = new Object [3];
  •     I learned that we are initializing an array of objects to be able to store heterogeneous data (different types of data) in a single array.
Object[] myObjects = new Object[3];
    myObjects[0] = new String("Hello");
      myObjects[1] = new Integer(42);
        myObjects[2] = new Double(3.14);
        •  And also processing polymorphism and inheritance becomes easy. Well, it read so but i didn't follow at that time so i continued questioning. I wanted to know how?
        interface Shape {
            double calculateArea();
            void draw();
        }

        class Circle implements Shape {
            private double radius;

            // Constructor, getters, and setters

            @Override
            public double calculateArea() {
                return Math.PI * radius * radius;
            }

            @Override
            public void draw() {
                System.out.println("Drawing a circle");
                // Code to draw a circle
            }
        }

        class Rectangle implements Shape {
            private double length;
            private double width;

            // Constructor, getters, and setters

            @Override
            public double calculateArea() {
                return length * width;
            }

            @Override
            public void draw() {
                System.out.println("Drawing a rectangle");
                // Code to draw a rectangle
            }
        }

        class Triangle implements Shape {
            private double base;
            private double height;

            // Constructor, getters, and setters

            @Override
            public double calculateArea() {
                return 0.5 * base * height;
            }

            @Override
            public void draw() {
                System.out.println("Drawing a triangle");
                // Code to draw a triangle
            }
        }

        • well, in the set of codes above we can see an interface with two methods that are implimented further in differents shape classes using mehtod overriding.
        • Now how to use these cluster of classes?
        public class DrawingApp {
            public static void main(String[] args) {
                Shape[] shapes = new Shape[3];
                shapes[0] = new Circle(5.0); // Circle with radius 5.0
                shapes[1] = new Rectangle(4.0, 6.0); // Rectangle with length 4.0 and width 6.0
                shapes[2] = new Triangle(3.0, 4.0); // Triangle with base 3.0 and height 4.0

                // Iterate through the shapes, polymorphically calling methods
                for (Shape shape : shapes) {
                    System.out.println("Area: " + shape.calculateArea());
                    shape.draw();
                    System.out.println("--------------------");
                }
            }
        }

        Here in the above example you must have noticed Shape [] shapes = new Shape[3]; in interface is instantiated even though it's an interface, be that as it may, interfaces can be implemented in other associated classes with constructors and then one can instantiate interfaces just in the way mentioned in the above code block.

          System.out.println(Arrays.deepToString((Object[]) element)); 

        This caused confusion too. Well, looking up on the internet i learned the reason for casting element to 

        • element is declared as Object, and the compiler only knows that it's an object.
        • (Object[]) element is a casting operation, telling the compiler to treat element as an array of Object during this specific operation.
        • Arrays.deepToString((Object[]) element) then uses the Arrays.deepToString() method on the assumed array.

        for (int i = 0; i < array2.length; i++) {
            var innerArray = array2[i];
            for (int j = 0; j < innerArray.length; j++) {
                System.out.print(innerArray [i] [j] + " ");
            }
            System.out.println();
        }

        in the code block mentioned above, it shows var without the operator [] in the second line and it makes sense as it is a local variable type inference that gets the compiler to infer the type of the variable based on the initializer.

        In this code, var innerArray = array2[i]; is equivalent to explicitly writing int[] innerArray = array2[i];. The type is inferred to be an array of int. The square brackets are part of the array type, and they are not specified explicitly when using var. The type inference is based on the fact that array2[i] is an array.

        Using var in this context makes the code more concise while still providing clear type information to the compiler.


        not to put too fine a point on it but when you are learning to code it's highly likey that you forget what you have learned so far. I wrote this at it heppened to me in the code block mentioned above we can see the nested for loop. well, up until now it had slipped my mind how the nested loop worked. Ergo, to make sure it never happnes again i am writing the explanation in layman's term.
         
        So at first it moves, according to the first for loop, to Row0 whose values is assigned to a var variable innerArray and reaches the second for loop whose argument makes it clear that it loops throught the first row Row0 as long as the length of the row that is array2[i] and no sooner does it cover all the elements of the row than it moves back to the first for loop and now its Row1 whose values the second for loop covers. 
         

        Comments