Java Methods and encapsulation

Scope of variables

Local variables
class Example {
     private int v1; //instance variable
     public int getValue() {
          int res = 0;   //local variable
          res = 10*12;
          return res;
     }

    public void setValue(int value) {
         res = value;   //This will not compile as res only exists within getValue()
    }

    public int getAnotherValue() {
         if (v1 > 100) {
             int res2 = 100;    //local variable, to the if!
             res2 = res2 * v1;
             return res2;
         }
         else {
             res2 = 0;       //won't compile, this variable is not available.
             return res2;
         }
    }

    public int getAnotherExample() {
         for (int counter = 0; counter < 5; counter++) {
             System.out.println(v1*counter);
         }
         System.out.println("Counter is "+counter); //will not compile as counter is only available to the for loop
    }
}
Method parameters
class Example {
    private int v1;
    public void setValue(int value) { //this is a method parameter
        v1 = value;                   //it is only available in this method
    }

    public int getValueExample(int value) {  //method parameter
        int res = 100;                       //local variable
        res = (res * v1)/value;
        return res;
    }
}
Instance variables
class Example {
     private int v1;                    //instance variable
     public void setValue(int value) {
         v1 = value;                    //instance variable set by method parameter
     }

     public int getValue() {
        return v1;                     //instance variable returned
     }
}
Class variables

These belong to a class, not to the objects of the class. They are static, this defines them as a class variable.


package com.demo;

class Example {
    static int v1 = 0;
}
package com.demo;

class Test {
    public static void main(String[] args) {
         Example.v1 = 100;

         Example e1 = new Example();
         Example e2 = new Example();

         System.out.println(e1.v1);  //prints 100
         System.out.println(e2.v1);  //prints 100

    }
}

Some rules:

  • local variables are normally used within a method as part of a calculation, storing the intermediate results
  • method parameters are used to pass in values
  • instance variables are used to return/set the state of the object
  • class variables used to store values against the class, which applies to all objects of the class
  • Scope of variables

    Local variables have the shortest scope, and class variables the longest, after local you have method and instance variables.

    You cannot define a static variable and instance variable with the same name.
    Local and method variables also cannot have the same name
    You CAN define local variables with the same name as instance and class variables.

    class Example {
        static int v1 = 100;
        //private int v1 = 200;                 //This line means it will not compile
        private boolean enabled = true;
        
        public void exampleMethod() {
              boolean enabled = false;
              int v1 = 800;              //Both of these exist for the duration of the method.
        }
    
        /*
        public void setValue(int value) {
              int value = 100;               //This line means it will not compile
        }
        */
    }
    

    Objects

    Creation
    class ObjectExample {
        Example e1 = new Example();             //A example object
        String s1 = new String("hello world");  //A string object
        String s2 = "hello again";              //A string object
        ObjectExample() {
            new Example();                     //A new object, but unreferenced
        }
    }
    
    class Example {
        private int value;
        private String name;
        public void setValue(int v) {
            value = v;
        }
        public void setName(String name) {
             this.name = name;
        }
    }
    
    class ObjectExample {
        public static void main(String[] args) {
             Example e1 = new Example();   //Object created
             e1.setName("hello world");    //setting value
             e1 = null;                    //reference is set to null, meaning the GC will clean it up
             ...
        }
    }
    

    When an object is out of scope (the object is created within a method, or an if statement, etc) then it will be picked up by the GC.

    Point of note, you can never be certain WHEN these objects will be garbage collect, only that they are due to be garbage collected.

    Methods

    Return types
    class Example {
        private int value;
        public void setValue(int v) {
            value = v;
        }
        public int getValue() {
            return value;
        }
    }
    
    class ObjectExample {
        public static void main(String[] args) {
           Example e1 = new Example();
           int v = e1.setValue(100);  //This line means it won't compile!
           e1.getValue();             //This line is fine (no errors), of course not sure what you are doing....
           String t = e1.getValue();  //won't compile!
    
           //NB: the value 100 is a method argument, however setValue(int v) int v is a method parameter
           // method arguments can be literals or variables
        }
    }
    
    Variable arguments
    class Example {
        public int variExample1(int... m) {
            int res = 0;
            for (int i = 0; i < m.length; i++) {
                System.out.println(m[i]);
                res += m[i];
            }
            return res;
        }
        public int variExample2(String... s, int... m) {  //multiple variables which accept variable arguments will not compile
            int res = 0;
            for (int i = 0; i < m.length; i++) {
                System.out.println(m[i]);
                res += m[i];
            }
            return res;
        }
        public int variExample3(int... m, String a) {   //the variable argument must be the last one, otherwise it will not compile
            int res = 0;
            for (int i = 0; i < m.length; i++) {
                System.out.println(m[i]);
                res += m[i];
            }
            return res;
        }
    
    }        
    
    Return types

    Three rules:

  • methods which return a value must complete with return and the value
  • void methods can return to exit, but must not return a value
  • if the return is not the “last statement to execute”, i.e. the return is before a calculation it won’t compile
  • Overloaded methods

    These:

  • must have different method parameters
  • may or may not have different return types
  • may or may not have different access modifiers
  • cannot be defined by just changing the access modifiers or return type

    Examples

    class ExampleOverload {
    
        int DoSomething(int val1, int val2) {
            return val1 * val2;
        }
    
        int DoSomething(int val1, int val2, int val3) {
            return val1 * val2 * val3;
        }
    
        int DoSomething(double val1, int val2, char val3) {
            return vl2 * val1 + val3;
        }
    
        int DoSomething(int val1, double val2) {
            return val1 * val2;
        }
    
        int DoSomething(double val1, int val2) {  //Note this is a overloaded method
            return val1 * val2;
        }
    
        //Note the last two can cause an issue if you call DoSomething(1,2) which overloaded method gets used? 
       //There are three to chose from. It will chose the fist as it has both int and int, otherwise
       //This will not compile
    
       //The following are not overloaded
    
       int doSomething(int a, int b) {
           return a * b;
       }
       
       //Just changing the return type does not overload the method
       double doSomething(int a, int b) {
           return a * b;
       }
    
       public int doSomething(int a, int b) {
           return a * b;
       }
       //Just changing the access modifier does not overload the method
       private int doSomething(int a, int b) {
           return a * b;
       }
    }
    

    Constructors

    class Example {
        String strValue0;
        int intValue0;
        Employee() {                            //Constructor - can be all four access methods
           intValue0 = 100;                     //It does not have an implicit return type
           strValue0 = "Hello World";           //It creates and returns an object of the class
        }                                       //If you define a return type it becomes a method
        Employee(int iValue, String sValue) {   //Constructor - these are public, protected, default, and private
           intValue0 = iValue;
           strValue0 = sValue;
        }
    }
    
    class TestExample {
        public static void main(String[] args) {
           Example e1 = new Example();
           Example e2 = new Example(200,"2nd test");
           System.out.println(e1.intValue0);         //prints 100
           System.out.println(e2.intValue0);         //prints 200
        }
    }
    
    
    Initializer?????
    class Example {
        Example() {
            System.out.println("Constructor!!!!");
        }
    
        {
           System.out.println("Initializer!!!!!!");
        }
    }
    class TestExample {
        public static void main(String[] args) {
            Example e1 = new Example();
    
            /*
                 The output from the line above will be:
    
                 Initializer!!!!!!
                 Constructor!!!!
            */
    

    These are for anonymous classes, to initialise the variables.

    Default Constructor and overloaded constructors

    Java creates a default constructor for a class if you don’t define one. However if you define your own constructor, Java will not create the default constructor – meaning you can’t call it. However you can define more than one constructor yourself, and you can define your own default constructor…

    class ExampleDefaultClass {
            String strValue0;
            int intValue0;
    
            ExampleDefaultClass(String x) {
                    this(x,-1);                       //Note the use of this to call the other constructor to pass in the value. It has to be named this and not Example(x,-1);
            }
    
            ExampleDefaultClass(String x, int y) {     //This is an overloaded constructor
                    strValue0 = x;                           
                    intValue0 = y;
            }
    }
    
    class TestClass {
            public static void main(String[] args) {
                    ExampleDefaultClass e1 = new ExampleDefaultClass();  //this will fail to compile!
                    ExampleDefaultClass e1 = new ExampleDefaultClass("hello",100);
            }
    }
    

    Some rules:

  • overloaded constructors must have different arguments lists
  • constructor can call another constructor with this
  • consturctor can’t call a constructor by its name
  • when using this to call another constructor it must be the first line of the constructor
  • Note, when using the this keyword, it must be the first statement!

    class Example {
         int intValue;
         String strValue;
    
         Example() {
             System.out.println("default constructor");    //This will not compile.
             this("x",-1);
         }
         Example(String a, int b) {
             strValue = a;
             intValue = b;
         }
    }
    
    Object fields

    Getters and Setters, how to pass values to private fields.

    class Example {
        private String strValue;
        private int intValue;
        
        public String getStrValue() {
            return strValue;
        }
    
        public int getIntValue() {
            return intValue;
        }
    
        public void setStrValue(String value) {
            strValue = value;
        }
    
        public void setIntValue(Int value) {
            intValue = value;
        }
    
        public int specialAdders(int... values) {
            int res = 0;
            for (int i = 0; i < values.length; i++) {
                res += values[i];
            }
            return res;
        }
    }
    
    class TestExample {
        public static void main(String args[]) {
             Example e = new Example();
             e.setStrValue("Hello world");
             e.setIntValue(99);
             System.out.println(e.getStrValue);
             System.out.println(e.getIntValue);
             System.out.println(e.specialAdders(1,2,3,4,5));
         }
    }
    

    By making the variables private, we are hiding them from other classes. The getters and setters can control the access to the classes variables. The setters, for example, can contain logic to validate the value before setting the variable. This is encapsulation, also known as information hiding.

    A well encapsulated class is where instance variables are private and access can only be gained, and controlled, by methods.

    Passing primitives
    class Prim {
        int a;
        void modifyVal(int a) {
            a = a + 1;
            System.out.println(a);
        }
    }
    
    class TestPrim {
            public static void main(String args[]) {
                    Prim p = new Prim();
                    System.out.println(p.a); //this prints 0
                    p.modifyVal(p.a);        //this prints 1
                    System.out.println(p.a); //this prints 0
            }
    }
    

    Note the value of a belonging to the class does not change because passing in the value to a method parameter of a takes precedence over the instance variable.

    Reference objects
    class Pers {
            private String name;
            Pers(String value) {
                    name = value;
            }
            public String getName() {
                    return name;
            }
            public void setName(String value) {
                    name = value;
            }
    }
    class TestPers {
            public static void swap(Pers p1, Pers p2) {
                    Pers temp = p1;                        //p1 and p2 are simply pointers to the object
                    p1 = p2;                               //this does not change the underlying objects
                    p2 = temp;
            }
    
            public static void swapV(Pers p1, Pers p2) {
                    Pers temp = new Pers(p1.getName());  //Here we create a new object and set the value
                    p1.setName(p2.getName());            //here we change p1 underlying object details
                    p2.setName(temp.getName());          //here we change p2 underlying object details
            }
    
            public static void main(String args[]) {
                    Pers pers1 = new Pers("John");
                    Pers pers2 = new Pers("Betty");
    
                    System.out.println(pers1.getName() + ":" + pers2.getName());  //prints John:Betty
                    swap(pers1, pers2);
                    System.out.println(pers1.getName() + ":" + pers2.getName());  //prints John:Betty
                    swapV(pers1, pers2);
                    System.out.println(pers1.getName() + ":" + pers2.getName());  //prints Betty:John
            }
    }
    

    reference: http://www.manning.com/gupta/

    Advertisements

    Tags: , , , , ,

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s


    %d bloggers like this: