31 August 2020

Housekeeping There are two items on the horizon.

static and final

Today, you will learn about these keywords.

final means, "Can't be re-assigned." This is a property of variables. Consider this program

/**************************************************
*   Author: Morrison
*   Date created: 31 Aug 2020
*   Date last modified: 31 Aug 2020
**************************************************/
import java.util.ArrayList;
public class Finality
{
    public Finality()
    {
    }
    
    public static void main(String[] args)
    {
        final int x = 5;
        //x++;
        System.out.println(x);
        final ArrayList<String> al = new ArrayList<String>();
        al.add("hello");
        System.out.println(al);

    }
}

If you uncomment the line with x++;, the compiler will hand you an error message. Variables marked final cannot be re-assigned. However, whatever is being stored under a final variable has no idea about finality.

The ArrayList we create is pointed at by a final varialble. This means the variable can't be reassigned. However, the state of this mutable list can be changed.

Constness This means a that an object cannot changed in any way via a variable.

  • If you create a constant, its idenfiter should be all-caps.
  • What does a variable store? If it iss primitive, it stores its value. If it is of object type, the variable stores a heap memory address.

    static Cling

    We will put some static elements in our Point class. We will also learn about some static service classes that are class-strated in the sense that you never make an instance of them.

    .

    Here is the picture of instance world and static world in a class.

    
                              -|g
     This side of the world   -|r 
     has a ladder.  It can    -|e 
     reach over to the        -|a 
     other side               -|s 
                              -|e 
                              -|  
                              -|  
                              -|g 
                              -|r 
      non-static (instance)   -|e 
      methods                 -|a static methods, including main()
                              -|s  
      state variables         -|e static variables
                              -|
      instance world          -|  static world
        --------------------------------------------------
    

    Because of the greased wall, static items do not have direct access to instance items.

    /**************************************************
    *   Author: Morrison
    *   Date created: 31 Aug 2020
    *   Date last modified: 31 Aug 2020
    **************************************************/
    
    public class Naughty
    {
        private int x;
        public Naughty()
        {
            x = 42;
        }
        
        public static void main(String[] args)
        {
            //Illegal; attempt to climb greased wall
            //System.out.println(x);
            //legal: works via an instance of the class
            Naughy n = new Naughy();
            System.out.println(n.x);
        }
    }
    

    Uncomment the illegal line. See the ugly error message. Then re-comment it and run the program again (successfully).

    Let's give our Point class a static constant ORIGIN.

    Notice the poopsmith, which is a private helper method.

    public class Point
    {
        public static Point ORIGIN;
        // initalize your static data members here
        //this is called a "static block."  
        static
        {
            ORIGIN = new Point();
        }
        //state or instance variable
        final private int x;
        final private int y;
        //signature: list of types in the argment list
        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
        //method name overloading. Two methods can have
        //the same name if their sigs are different.
        public Point()
        {
            this(0,0);
        }
        @Override
        public String toString()
        {
            return String.format("(%s, %s)", x, y);
        }
        @Override
        public boolean equals(Object o)
        {
            //the species test
            if( !(o instanceof Point))
            {
                return false;
            }
            Point that = (Point) o;
            return that.x == x && that.y == y;
        }
        public int getX()
        {
            return x;
        }
        public int getY()
        {
            return y;
        }
        public double distanceTo(Point that)
        {
            return Math.hypot(x - that.x, y - that.y);
        }
        public int taxiCabDistance(Point that)
        {
            return abs(x - that.x) + abs(y - that.y);
        }
        //poopsmith
        private int abs(int x)
        {
            // ternary operator:   P? ifTrue: ifFalse
            // predicate: boolean valued expression.
            // P is one of these
            return x < 0? -x : x;
        }
        public static void main(String[] args)
        {
            Point p = new Point(3,4);
            Point origin = new Point();
            Point q = new  Point(3,4);
            System.out.println(p);
            System.out.println(origin);
            System.out.println(origin.distanceTo(p));
            System.out.println(p.distanceTo(origin));
            System.out.println(origin.taxiCabDistance(p));
            System.out.println(p.taxiCabDistance(origin));
            System.out.println(p == q);
            System.out.println(p.equals(q));
            System.out.println(Point.ORIGIN);
        }
    }
    

    Finally, an interesting use of static to give serial numbers to objects

    /**************************************************
    *   Author: Morrison
    *   Date created: 31 Aug 2020
    *   Date last modified: 31 Aug 2020
    **************************************************/
    
    public class Minter
    {
        private static int idWell;
        static
        {
            idWell = 1;
        }
        private final int ID;
        public Minter()
        {
            ID = idWell;
            idWell++;
        }
        public static int nextID()
        {
            return idWell;
        }
        @Override
        public String toString()
        {
            return String.format("Minter(%s)", ID);
        }
        
        public static void main(String[] args)
        {
            for(int k = 0; k > 10; k++)
            {
                System.out.println(new Minter());
            }
            //Minter q = new Minter();
            System.out.println(Minter.nextID());
        }
    }
    

    Run it and see this.

    unix> java Minter
    Minter(1)
    Minter(2)
    Minter(3)
    Minter(4)
    Minter(5)
    Minter(6)
    Minter(7)
    Minter(8)
    Minter(9)
    Minter(10)
    11
    unix>