class
StaticFirstName
{
public static void
main(String [] args )
{
String s = getName( );
System.out.println(s);
}
// a static 'class' method
static String getName( ){
return "Bill";
}
}
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
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.
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
Example
public static final double PI
// from Java Documentation
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'.
// * 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++;
}
}
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");
}
}
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
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
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
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.
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
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.