Key Modifiers & Argument Passing

Peter Komisar       ©        Conestoga College     latest  version    5.5    2008


This note is hard to name as we deal with three short but
important topics in Java. We look at the use the 'static'
keyword to create 'class' vs. 'instance' methods and
variables. This is extended to show how constants are
created in Java.
We also inspect the process of passing
arguments to methods and illustrate the differences
between passing primitive vs. reference type variables. 
Finally we also look at the access modifiers, which allow
the Java programmer to variably control access to class
members.



Static vs Instance Members


We touch earlier on an example that showed two
member types
of the class, static members and
instance members. Static members are directly
callable from the static method main( ) while the
instance members, are called via a reference to
the instantiated class of which they are members.
We look at these differences more thoroughly
now.

In the following example, the method getName( )
can be called directly in main without a reference,
because it is a static member. It is made static by
the presence of the 'static' keyword.


Example

class StaticFirstName
         {
         public static void main(String [] args )
                {
                String s = getName( );
                System.out.println(s);
                }

// a static 'class' method

        static String getName( ){
                return "Bill";
                }
         }

// static method called directly in main( ) 

Trying to call a non-static member from main results
in a compiler error. A non-static member needs to be
referenced from the context of the class object, formed
in the instantiation process as is shown in the following
example.


Example

class InstanceFirstName
         {
         public static void main(String [] args )
                {
        InstanceFirstName fn = new InstanceFirstName( );

               // to access non-static instance methods
               // we first need a handle to the object
               // generated via an instantiation

                String s = fn.getName( );
                System.out.println(s);
                }

// a non-static instance method

                String getName( ){
                return "Bill";
                }
         }

// instance method called via a reference
// to the instantiated class

Static members are callable directly while instance
members are only callable via the instantiated
object.

The 'static' Keyword

The static keyword is used to fix a class member's
definition, such as a variable or method with the class
definition rather than with an instance of that class.
The following diagram attempts to summarize this
information.

Class Definition
in Memory


'static' definitions remain
associated with the class
definition and are not
copied to the instance
data structure.

// non-static field
int i = 4; 

 





>- new instance-->  
Functional Object
  in Memory
instance members are
reference from where
each object is stored
in memory


// instance copy
int i = 4; 
// static members are
// shared  by objects

// static field

static k = 9;

 <-------<
The object refers back
to the class definition
to access
static members
// holds a reference back
// to class variable k


The following example shows you that a static member
is shared by all instances of the class. Run the following
code with the static modifier commented out. Each instance
creates it's own version of count and reports the number
1 as it's ticket number.

Code Sample Showing the 'static' Keyword in Action

class Ticket{
     /*static */ int count = 1;

 Ticket(String name){
     System.out.println(name + ": " + "Ticket Number: " + count);
     count = count + 1;
     }
  }
 
class RunTicket{
   public static void main(String[] args){
     Ticket bill = new Ticket("Bill Bradly\t");
     Ticket mary = new Ticket("Mary Campbell\t");
     Ticket dave = new Ticket("Dave Kay\t");
     }
 } 

OUTPUT 1 // with count as an instance variable

[peter@localhost Examples]$ java RunTicket
Bill Bradly     : Ticket Number: 1
Mary Campbell   : Ticket Number: 1
Dave Kay        : Ticket Number: 1


Uncommenting the static modifier makes count a
class variable and is shared by instances. Each
object participates in increasing the shared static
field.


OUTPUT 2
// with count as a class variable

[peter@localhost Examples]$ java RunTicket
Bill Bradly     : Ticket Number: 1
Mary Campbell   : Ticket Number: 2
Dave Kay        : Ticket Number: 3


Static Member Naming Conventions

Static members by convention are referenced by the
class name. The Math class is full of static methods.
Consider the following definition for he sqrt( ) method
in the Math class. Notice it is marked with the 'static'
keyword.

Signature of the sqrt( ) method in the Math Class

public static double sqrt(double a)

We don't instantiate Math to get a static method of
the class. We just call it on the class name.

Example  

Math.sqrt( );

Fields may also be static. Another example from
the Math class is PI.


Example
 

Math.PI;

Static fields and methods can also be referenced by
an instance reference. (We can't do that with Math as
this class is has been designed not to be instantiated
or extended.)  The following class shows that a static
variable can be referenced via the instance.

The preferred way, though is via the class name as
it signals others who may be reading your code that
you are using a static class member.

Example

class ThreeWayRef
 {
 static double apple = 9.9;
   public static void main(String[]args)
    {
    System.out.println
    ("Accessing static variable 'apple' via the class name: " + ThreeWayRef.apple);
    System.out.println
    ("Accessing static variable 'apple' locally as we are local:  " + apple);
    ThreeWayRef twf= new ThreeWayRef( );  // creating an instance reference
    System.out.println
    ("Finally, accessing variable 'apple' a via an instance reference: " + twf.apple);
    }
  }


Both variables and methods can be marked static.
(Constructors cannot be marked static, and are not
really thought of as class members anyway. A simple
block of code can be marked 'static' forming what is
called 'a static block'. Inner classes can also be static.
(We look at the 'ins' and 'outs of inner classes in a
later talk.)

Example Showing What Can be Made Static


class Static  {  // an 'outer' class can't be marked 'static'
   
Static ( ){ } // a constructor can't be marked 'static'
    static class Inner{  } // this is a minimal inner class which can be static
    static { /* a simple block can be labeled 'static' */ };

   public static void main(String [] args ){
      new Static( );       
     }
   }

The Compiler Error Shown When Static methods
Access Non-static Members

Static methods cannot reference a non-static variable
or another method that is non-static. The following code
will not compile unless the variable is made 'static'. The
output is the hallmark error report for breaking this rule.

class NoCompile  {
      int notStatic = 6;
 // won't compile as a static method tries to access a non-static variable

   public static void main(String [] args ){
      System.out.println
      ("Investigating static methods referencing non-static members: "
      + notStatic);      
     }
  }

Output
 
[peter@localhost Examples]$ javac NoCompile.java
NoCompile.java:5: non-static variable notStatic cannot be referenced from a static context
      System.out.println("A non static variable is not accessible to a static method: " + notStatic);
                                                                                          ^
1 error


The 'final' keyword

The 'final' keyword either fixes a variable to it's assigned
value, or, if it has not been assigned, allows it to be
assigned only once. It can be used on classes. The Math
class is final and as such cannot be sub-classed. The
compile error on the following example shows how final
can restrict sub-classing.


Code Sample with a Class Marked 'final'

final class RunFinal{  }      
class RunFinalChild extends RunFinal{ }


OUTPUT

[peter@localhost Examples]$ javac RunFinal.java
RunFinal.java:2: cannot inherit from final RunFinal
class RunFinalChild extends RunFinal{ }
                            ^
1 error


Java Constants

When final is used in conjunction with the keywords,
static and public, a typical Java constant is formed. By
convention, a Java constant is defined in all upper case
letters, with separate words separated by underscores.


Example 

A_JAVA_CONSTANT


// form of Java constant identifiers


Again we can borrow from the Math class to see the
definition of PI.The signature in the documentation is
as follows.

Example 

public static final double PI

// from Java Documentation

We can declare our own constants as follows.


Example 
  

public static final int SHORT_MONTH = 30;


It should be mentioned that Java constants are not
required to be public. The constants in the SwingUtilities
class have package access.  (They can't be accessed
from outside the package.)



Passing Primitives & Reference Types into Methods



Both primitive types and reference types can be passed
into methods. In Java a copy of the primitive value is
passed into the method. The name given to this process
is called 'call by value'.
C++ introduced the reference
notation that allows passing what was called a reference
parameter into a method. ( ie.  double& amount ). This
process is referred to as a 'call by reference'.

This has different ramifications for the two different variable
types. For a primitive, it means the copy may undergo
changes inside the method, but the original value stored
outside remain unchanged.

For a reference type, an address is passed into the
method or the original reference value. Changes made
to the object stored at that address do have an effect
on that object.

Though the actual reference outside the method cannot
be changed from inside the method, changes can be
made to properties associated with the object that is
stored at the location that the address points to.

// * check 'Computing Concepts With Java 2 Essentials' by
// Cay Hoorstmann, p. 279 for more discussion of  this notion


Examples of  Passing Primitive variables

If first we create a method that takes an int value. We
can borrow an increment operator from a later lesson
and use it to attempt to increment the passed in value
by one. We
create an an int which we print to screen,
then pass into the method and and then print to screen

again. First we create the method which increases the
value that is passed into it by one. 


Example 

void up (int n){   a method defined inside a class
  n++;
  }

The following code demonstrates what happens when
this an int int is passed into the above method.

Example Demonstrating the Above Method

class Copy{
  public static void main(String[]args){
    int x = 2;
    System.out.println("x before: "+ x);
    up(x);    
    System.out.println("x after: "+ x);
 }
 
// method
static void up (int n){ 
     n++;
    }
   } 

Output

> java Copy
x before: 2
x after: 2

Nothing happened! Well things did happen. The copy
had it's value changed and the method exited. The
original was left untouched.

If you want to effect a change on a primitive variable,
there are a couple approaches that can be taken. In the
following code example first the scenario described
above is repeated.

Technique 1: Change Value via the Return Type

In code then shows a second case, where a method,
returnUp( ) is defined that returns a value reflecting the
change which can be assigned to the class variable.

Example

    int returnUp(int n){
           n++;
          return n;
          }

//  defining the method to return a value reflecting
//  changes made to argument


Technique 2: Change value using 'this' Keyword

The third method variation uses the 'this keyword to
assign the value to the original variable outside the
method that was first passed to the method.


Example

void thisInUp (int n){
            n++;
           this.x = n;
           }

The following example includes all three method variations.


Example

class PassInTest{
       int x = 2;
    PassInTest( ){   // first the scenario where the original is uneffected
      System.out.println("x before is:  " + x );
      up(x);
      System.out.println ("x after the call still is: " + x + ". Only the copy changed.");
           // in the second scenario the method return type is assigned to the value
      x=returnUp(x);
      System.out.println("Now x is " + x);
   // in the third scenario this is used inside the method to effect the change on variable
           thisInUp(x);
           System.out.println("After using the this version, x is " + x);
           }
    public static void main(String[]  args){
       PassInTest pt=new PassInTest( );
       }
        /* here the three methods are defined */
      void up (int n){
         n++;
         System.out.println("Inside the method n is  " + n);
         }
      int returnUp(int n){
          n++;
          return n;
          }
      void thisInUp (int n){
          n++;
          this.x = n;
          }
     }

Examples of Passing Object References into Methods

With object reference we mentioned earlier the copy of
the address is passed into the method. In the case of
a reference type though this is effectively the same as

passing in the address.

While changes to the address do not have an effect on
the original value that was passed in, any changes made
to the data structure stored at this address will in fact
make changes to the object stored there.


Investigating Passing In By Reference

The following code shows that the address is the same
outside the method and also in the local scope of the
method. The idea that a copy of the address is passed
in is supported by the call that nulls the local value.

Example

class O{
      Object o;
      O(){
         o=new Object();
         System.out.println(o);
         add(o);
         nullO(o);
         System.out.println(o);
         } 
 
void add(Object o){
     System.out.println(o);
     }

void nullO(Object o){
       o=null;
       }
     

public static void main(String[] args){
    new O( );
    }
}

OUTPUT

C:\Documents and Settings\Peter.XP_STUDIO\My Documents\J1\Examples>java O
java.lang.Object@3e25a5
java.lang.Object@3e25a5
java.lang.Object@3e25a5

Showing an Object Associated with an Address Being Changed

As an example of this we create a method that changes
the text inside
a text field object. Though it is only a copy
of the reference to a TextField object that is passed in,
the name
associated with that object is still changed.

First we show you what the add2( ) method does, namely
it changes the
text associated with the text field object
it is passed to Y.

Example   

void add2(TextField t){
              t.setText("Y");
              }

TextField tf=new TextField("X");
System.out.println(tf.getText( ));
add2(tf);
System.out.println(tf.getText( ));

This is shown in the following example.

String Class is Exceptional because of it's Immutability

There is an interesting exception to this rule. String class,
the same one that forms the argument to main, is said to
be 'immutable'. This means the object that is assigned to
a string object cannot itself be changed.

Example 

String s = " diamond ";

If you go into the String class library you will find methods
like concat( ). If we call concat on the String object defined
above, as in s.concat(" tip" ), sure enough the word diamond
tip would now be stored at the location referenced by s.


The Immutable Characteristic

What the immutable characteristic means is that the object at
that location doesn't change. Instead a different object was
created with the desired changes in it and put into a new
memory location. Then reference, here 's' is made to point to
the new object. The old object is discarded, still unchanged.


String Behave
Like Primitives

Another way to look at String is that is really is a array of
char type, which is a primitive. Effectively, though String
is a reference type, it behaves like a primitive, as if it was
passed by copy.


How it works

It is this behaviour that makes String act differently when
passed into a method than other reference types. When

String objects are modified they use a new StringBuffer
to effect changes that are then 'readdressed' to the original
object reference.  In the case of String objects being passed
in and modified the actual address is modified if an action is
taken on the String object.

When the method returns though, the original copy is still
pointing to the old immutable String object so nothing
is changed!

One way to think of it is, when it comes to String objects, the
behaviour is like that of passing primitive variables into
methods.  The full code is listed below.


Example Code Showing Passing Object References Into Methods

import java.awt.*;

class PassInT{
  PassInT(){

  TextField tf=new TextField("X");
  System.out.println(tf.getText());
  add2(tf);
  System.out.println(tf.getText());
  // StringBuffer represents a mutable String
  // and behaves like TextField
  StringBuffer qb= new StringBuffer("Plane");
  System.out.println(qb);
  add3(qb);
  System.out.println(qb);

  String q=new String("Name");
  System.out.println(q);
  add(q);
  System.out.println(q);

// String is not doing what we might expect. This gets back
// to Strings being
immutable and how the objects are replaced
// behind the scenes in the address
space. The copy of the
// reference passed in will no longer be pointing to the
same
// address after the action on the String has been executed.
// So in the case
of the String class, the behaviour is like that
of the primitive.

}
//main

public static void main(String[]args){
  new PassInT();
  }
//  methods
void up (int n){
    n++;
    }
void add (String s){
  s.concat(" is a String");
  }
void add2(TextField t){
  t.setText("Y");
  }
void add3(StringBuffer sb){
  sb.append(" is a StringBuffer");
 }
}



The Access Modifiers


One group of keywords, private, protected and public, are
used to control the access of different class members with
respect to where they reside inside Java classes
and packages.
Following is an explanation of the each of the access modifiers.

private  

The private keyword limits the accessibilty of a class member
to other members of the same class. In other words a variable
that is marked private can only be referenced, from within the
class, say by a method of that class. The following example
shows two classes in the same package. The private variable
'internal' is accessible through the method memo( ) but not
directly from another class.

Example  

class Privacy{
   private String internal = "Internal Use Only";
    // a method of this class may access this private member
   void memo(String memoText ){
         System.out.println( internal);
         System.out.println(memoText);
         }
      }
 class RunConfidential{
    public static void main(String [] args){
    String s = " Sell 10000 shares at $ 14 ";
    Privacy privacy = new Privacy( );
    privacy.memo(s);
                        
// But RunConfidential can't directly access  the private
// String 'internal'. Uncomment the following line & the
// code will not compile

// System.out.println(privacy.internal);
     }
  }

In the above example, commented out is an attempt in
RunConfidential to access the private variable directly.

Example        

System.out.println(privacy.internal);

The compile fails and the error report is as follows.

Output 
// generated when line with  'privacy.internal' is entered into code


[peter@localhost Examples]$ javac RunConfidential.java
RunConfidential.java:17: internal has private access in Privacy
                         System.out.println(privacy.internal);
                                                   ^
1 error

// Mentioned in the Inheritance note, a private member
// is inaccessible to it's child classes

Another illustration of the private variable might be inside
a class would be a 'fridge' inside an apartment. The apartment
is analogous to the class. The fridge would be a 'private'
aspect of your apartment. People who are strangers to you
would not routinely enter your
house, open your fridge and
grab an apple!


Example

class MyApartment {
     private String fridge = "half-full";

    void openFridge( ){
     System.out.println( " Fridge is " + fridge);
    }

The fridge variable  is a private member. The openFridge( )
method is a member of this class and has access rights
to the private variable fridge.
Accordingly it is perfectly legal
for the method
openFridge( ) to be able to access the member
fridge.

In a program we might create a String variable called fridge
which we mark private inside
a class called MyApartment.
In this class we might create a method openFridge( ). It too

could be marked private and only be called within the class.


JavaBean Make Common Use of Private Members

JavaBeans encapsulate a commonly used form
where data members are marked private and are
only accessible through accessor mutator methods.
In this example a Guard will have an alias. The alias
variable is marked 'private' while the methods that
can change or retrieve the information stored in the
variable are marked 'public'.


Example

// This class conforms to simple JavaBean specifications
//  in that it has a no-arg constructor and has set
and get
// methods that return a simple property. Guard
is a simple
// JavaBean and by convention might have been called

// 'GuardBean'

class Guard{
   // variable
   private String alias;
   // no-args constructor
     Guard( ){
        this.alias="NoName";  
        }
   // set / get methods
public void setAlias(String alias){
     this.alias=alias;
     }

public String getAlias(){
     return this.alias;
     }
  }

public class InspectGuard{
  public static void main(String[]args){
     Guard guard= new Guard();          
     System.out.println
     ("At this point the Guard instance variable, \'alias\', stores: " +      guard.getAlias());
     // Let's reset alias
     guard.setAlias("Rumples"); 
     System.out.println
     ("Having called set method, alias now stores: " + guard.getAlias());
     }
   }


No Modifier, a.k.a. 'package', 'default' or 'friendly' Access 

Even if there is not an access modifier associated with a
class member
there is still an access state being described.
This is 'default' access. There is no 'default' keyword.
Default access
restricts access to the package. Although
it isn't apparent, all classes are in a
package. If a class
like our HelloPlanet is created, and we don't specify a
package,
a no-name default package is assigned that
corresponds to the current directory
that the class is stored
in.

Example

/* Acess Modifier Absent */  

int  i = 9; 

// describes 'package access'

Getting back to our apartment analogy, where the apartment
is a class, it's apartment building would be it's package. We
simply add the line package Apartment_A to the code. Lets
create two renamed versions of the apartment class, Xavier
and Yvonne, and put them into the same package. While we
are at it we can define some shared 'package' territory in a
class called 'TheHall'.

Note though we have not put these classes into an explicit
package, a default package is supplied implicitly for us by
Java corresponding to the current directory.


Example

class Xavier{
     private String fridge = "full";

     void openFridge( ){
     System.out.println( " Xavier's fridge is " + fridge);
     System.out.println( new TheHall().getResources());
    }
// method defined using default access to another package
// class with a default access method


String getHallResources( ){
    TheHall hall = new TheHall( );
    return "I'm Xavier and I have used Hall's resource method \n " + hall.getResources( );
}
}

class Yvonne{
    private String fridge = "nearly empty";

    void openFridge(){
    System.out.println( " Yvonne's Fridge is " + fridge);
    System.out.println( new TheHall().getResources());
    }
// method that uses the default access variable of another class in the package

     String getIce( ){
        TheHall hall = new TheHall( );
         return "I'm Yvonne. I have accessed the hall and have " + hall.ice.toUpperCase( );

       // used toUpperCase( ) method just to accentuate the access 
   }
 }

class TheHall{
       String ice="lots of ice";
       String phone="pay phone has a tone ";
       String candy="working";
    
// in this demo variables and method have default access

       String getResources( ){ String report=" ICE: " +  ice 
       + "\n PHONE: " + phone + "\n CANDY: " + candy;
       return report;
       }

       }

class ApartmentManager{
 public static void main(String[]args){
     
      Yvonne y= new Yvonne( );
      Xavier x= new Xavier( );
      String yvonneStuff = y.getIce( );
      System.out.println(yvonneStuff);
      String xavierStuff = x.getHallResources();
      System.out.println(xavierStuff);
     
    }
}
                                         

To reiterate, Yvonne cannot access Xavier's fridge as it
cannot access the private method openFridge( )
defined
in Xavier's class and visa versa. Both Xavier and Yvonne
though, can access
the members of 'TheHall' class which
are defined as default or as having 'package' or 'default
access.

// You might test accessing another classes private
// members to confirm they are unavailable


public

The public keyword is easy to understand. It defines open
access. All the methods
we routinely access in the Java
library are defined as public access. This means that
class
members are available regardless of the class you are in.
( You still need to
import the package or use the fully
qualified name of the class you wish to import.)

Example

package ApartmentBuilding _B;

class CareTaker{
 // Can call public members on MyApartment even
 // though MyApartment is in a different package

 }

protected

The protected access modifier is the harder to explain
as it is tied to
inheritance. The protected keyword creates
an access that is a hybrid of public and package access.
Protected access is the same as default
access, and
additonally, sub-classes of the class can access protected
members whether those
subclasses are defined inside or
outside the package.

The 'protected' keyword serves the important purpose of
allowing specialized sub-classes to retain access to parent
variables while these variables remain 'protected' from any
other outside access.

The following example defines an extension class to
the parent, 'MyApartment'. MyApartment defines a
protected member, 'keyLocation'. The student has
access to this variable. This demonstrates an access
that is equivalent to 'default' or 'package' access.


Example

class MyApartment {
      private String fridge = "full";
      protected String keyLocation="It's under the broken tile";

      private void openFridge( ){
      System.out.println( " Fridge is " + fridge);
      }
      }


class Students extends MyApartment{
      Students(){
      System.out.println(super.keyLocation);
      }
     
      public static void main(String[]args){
      new Students( );
      }
      }

The next example demonstrates protected access across
packages.
Save the following in separate source code files.
Remember each will be in it's own package directory, 'home'
and 'away'.

Parent Code with 'protected' Member

package home;

public class Dwelling {
      protected String message = "11 messages";
      }


Child Code in Separate Package accessing Parent's
'protected' Member


package away;
  

class Away extends home.Dwelling{
      Away(){
      System.out.println(super.message);
      }
    
      public static void main(String[]args){
      new Away();
      }
      }

OUTPUT

[peter@localhost Examples]$ java away.Away
11 messages


Following is a quick summary of the access modifiers
and the scopes that they control.


Summary of Access Modifier


Summary of Where Can the Modifier's Be Applied

Classes cannot be private or protected, (though inner
classes can be private.) Fields and Methods can be
any access. Constructors can be of any access.



Self Test                         Self Test With Answers

1) True or False? A non-static method can be called locally,
    without class or object reference, from inside a static method.
    True / False                                            

2)  True or False? A outer class can be marked static. True / False
                                                                 

3) Which of the following is not used in creating a Java constant?

a ) public
b) protected
c) static
d) final                                                        

4) True or False? Because String class is a reference type,
    passing in a String reference into a method allows changes
    to be made to the data structure that is referenced by the
    passed in address. True / False                   

 
5) True or False? The 'final' keyword allows an assigned
    variable to be changed only once.  True / False  


6)  Which of the following allows access from anywhere in the
   Java environment


a) private

b) no modifier
c) protected
d) public                                                       

7) Which of the following restrict access restricts access to the package 

a) private
b) no modifier
c) protected
d) public

8) True or False? Constructors  cannot be marked private. True / False
                                                                    


Exercise

1. Create a class called Access that includes the following:

a) Create two constants in a class. Use System.out.println
statements in main to print their values to screen. Use the
class name to reference them.

b) Create a method that takes a value and changes the associated
class variable, using the this keyword.

c) Create a private variable that has an associated 'get' method
that is public that returns the value of the private variable. Make
this a non-static method and call it using an instance reference,
(via the dot operator). Use a System.out.println statement to put
it's value out to console.


2) Create a short class that has a no-args constructor. Mark this
    constructor static. What does the compiler report?

// this can be as simple as the following!

public class X{ X( ){ } }

3) Using the class you created in 2) remove the static keyword
you added to the constructor and put the 'static' keyword on the
class. What does the compiler report?

4) Again remove the 'static' keyword and mark the class you
created in 2) with a private modifier. What does the compiler
report?

// i.e.      keyword  class  X {  etc.