Contact Us Sitemap
Main Menu
Home
Learning Greek
- - - - - - -
Books
Movies
Music
Restaurants
Games
- - - - - - -
Hiking
Articles
More Articles
Blog
- - - - - - -
Java
PHP
PSP
Joomla!
CafePress Designs
- - - - - - -
Free Downloads
Web Links
Galleries
Paypal Donate
Subscribe to RSS
RSS Feed
Who's Online
We have 20 guests online
Statistics
Visitors: 1263558
Login Form





Lost Password?


Hwy777.com
Blog Directory & Search engine
Home arrow Java arrow Studying for the Java Programmer certification

Studying for the Java Programmer certification Print
Written by Mike Noel   
Thursday, 11 August 2005
Page 2 of 4

Chapter 4: Declarations and Access Control

The first section of this chapter covers arrays in quite a bit of detail. The text explains how to declare and use arrays. The remaining 9 sections in this chapter cover class and member declarations with all the varied modifiers that can be applied.

Constructor namespace

The name of the constructor is defined to be the same name as the class. For example, the constructor(s) for a class named MyClass would be called MyClass. That's fairly straight forward. The interesting wrinkle is this: the namespace for methods is different than the constructor namespace. This means that it's possible to create a method with the same name as a constructor. The only syntactical clue the compiler uses to distinguish the two is the presence or absence of a return type in the declaration. Because of the namespace distinction it is possible to have something like this:
class MyClass {    
  public int x;
  public void MyClass() {
    x = 5;
  }
  public static void main(String args[]) {
    MyClass mc = new MyClass();
    System.out.println(mc.x);
  }
}
When run this will print out "0" not "5". The reason is because from the compiler's perspective there isn't a constructor. So the member "x" is initilized to "0". The "MyClass()" method isn't called so "x" is never set to "5".

Synchronized methods

Adding the keyword "synchronized" to a method declaration tells the JVM to ensure that only one thread at a time will be executing that method. The new information for me was the fact that synchronization locking is class wide. That is, no other synchronized methods in the class will be allowed to run while any other synchronized method is running. This makes sense because a method will likely be adjusting the state of the object. If other synchronized methods can run at the same time then the object state can become corrupted. The book's example was with a stack implementation. The "push" and "pop" methods were both synchronized. This ensured that a "push" and a "pop" weren't happening at the same time.

final and static methods

Declaring a method static means that it is accessible via the class. Static methods can also be access via an object. All objects share the same static field even if that field is accessed via an object reference. Declaring a method as final means that the method can't be overridden by subclasses. There is no restriction against declaring a method both static and final.

Chapter 5: Control Flow, Exception Handling, and Assertions

For-loop initializer statements

The initializer in a for-loop has an interesting syntactical quirk. As expected you can specifiy more than one variable declaration and initial value in the loop. The following is a good example:
for (int i=0,j=0;i<10;i++,j*=2) {
  System.out.println(i + " " + j);
}
In this case the two integers i and j are declared and initialized in the for-loop header. The comma operator separates them. The quirk here is that these variables have to be of the same type. The following code won't work:
for (int i=0, double j=0;i<10;i++,j=Math.sqrt(i)) {   
  System.out.println(i + " " + j);
}
The problem seems to be with the declaration statement and the comma operation. When parsing the compiler sees type identifier = value. At that point it realizes that it's dealing with a variable declaration and initilization. At this point in the compilation it needs to see either a , or a ;. The ; terminates the statement and the , indicates that there are more identifiers and values to follow. The following for-loop does compile and run as expected.
int i; 
double j;
for (i=0, j=0;i<10;i++,j=Math.sqrt(i)) {
  System.out.println(i + " " + j);
}
Notice the difference in the for-loop initializer. In that case we don't start a variable declaration statement so when the compiler sees the , it knows that additional expressions will follow.

{;};{{};}{};{{;};}{{{{;};;}}{;}}

This is not really useful and if you think about it probably not surprising. The solitary ; is called the "empty statement". It means "do nothing". The construct {} is also valid. It is an "empty block". Empty blocks allow nesting of other empty blocks and empty statements. This leads to the possibility of very unusual legal constructs. The heading for this section is an example. It looks like there's a whole lot going on there but really it all boils down to a big bunch of empty. Kinda curious and not at all useful.

Try return finally return

The finally block following a try block is always executed. In the case where there is no exception thrown in the try block the finally block will execute after the last line in the try block. In the case where there is a return statement in the try block the finally block is still executed. This seems a little bit odd at first. Generally the return statement means to immediately return to the caller. Even more unusual is the fact that if the finally block also has a return statement, the return value generated in the finally block overrides the value from the try block. When I compiled the following code I got a java warning concerning the second return statement. The compiler warned me that the finally block wouldn't complete normally. This confirms my instinct that having a return in a try or finally block is a bad idea.
public class TryReturn {
  public static void main(String[] args) {
    System.out.println(TryReturn.method());
  }
  static int method() {
    try {
      return(1);
    } finally {
      return(2);
    }
  }
}

Chapter 6: Object-oriented Programming

Overridden methods can only widen access

On overridden method is a method in a subclass with the same name, same parameters, and same return type as an inherited method. The access specifier from the the parent class is not inherited and has to be specified in the child class. It is possible, though, to indicate a different access level in the child but it has to be "wider" than the parent class. For example, if the parent class access level for a method is package, the child class can specify either package (by leaving off the specifier), protected, or public.
At first this didn't make sense to me. Since extending a class is a way of creating a more specialized class it seemed that one area of specialization would be to stub out a method so that it couldn't be called. But this could cause a lot of problems. One reason polymorphism works is because we can count on the fact that all subclass objects will have the same methods as the parent class(es). It is likely that subclass object will have additional methods too. If it was permissible to narrow the access of a method then there's nothing keeping me from creating a class that privatizes all of the Object public methods. Now if I tried to use an object of this class with many of the standard library classes I would end up generating IllegalAccessError exceptions. It makes sense to me now.

Final parameters in overridden methods

When overriding a method the child class can make any of the method parameters final or not regardless of whether the same parameter in the parent classes method was marked final. This makes sense because the method parameters are only local to that particular method instance. The method implementation itself will decide if the parameter can be changed or not. Since all parameters are passed by value adding the keyword final to a parameter is really just a compiler check. Any changes that the method makes to the parameter's value won't be visible to the caller either way.

Polymorphic field references vs. method calls

When an instance method is called via an object reference, the method that gets called is the method associated with that specific object. Even if the type of the reference variable is a reference to a parent class of the object the actual object's method gets called. This code illustrates that.
class Parent {
  public void printInfo() {
    System.out.println("in parent");
  }
}

class Child extends Parent {
  public void printInfo() {
    System.out.println("in child");
  }
}

class Main {
  public static void main(String args[]) {
    Parent;
    Child c;
    Child obj = new Child();
    p = obj;
    c = obj;
    obj.printInfo();
    p.printInfo();
    c.printInfo();
  }
}
In this case all three method calls end up printing "in child". This is not the case for accessing fields in a class. When accessing a field the type of the reference is used to determine which field to return. This code illustrates the issue.
class Parent {
  public int value=5;
  public void printInfo() {
    System.out.println("in parent"); 
  }
}

class Child extends Parent {
  public int value=10;
  public void printInfo() {
    System.out.println("in child");
  }
}

class Main {
  public static void main(String args[]) {
    Parent p;
    Child c;
    Child obj = new Child();
    p = obj;
    c = obj;
    System.out.println(obj.value);
    System.out.println(p.value);
    System.out.println(c.value);
  }
}
In this case the three output values will be 10, 5, 10 (in that order).

Overridden methods in constructors

Under normal circumstances when a subclass object is being constructed the constructors for all of the parent classes are called. If these constructors use any overridden methods of the class during construction the subclass implementation is used. The following example illustrates this:
class Base {
    Base() {
	System.out.println("Base ctor");  // 1
	method();
    }
    public void method() {
	System.out.println("Method in Base");  // 2
    }
}

class Extension extends Base {
    Extension() {
	System.out.println("Extension ctor");  // 3
	method();
    }
    public void method() {
	System.out.println("Method in Extension"); // 4
    }
}

public class Main {

    public static void main(String args[]) {
	Extension ext = new Extension(); // 5
    }
}
In this example the Extension object is being created at 5. This causes the Extension constructor to be called. Before this constructor executes the Base constructor is called. This results in the message at 1 being printed. The Base constructor next calls the method() method. There are two options for this method. There is the base class implementation (2) and the subclass implementation (3). Since the object being constructed is a subclass object that method is used. The final output of running this program is:
Base ctor
Method in Extension
Extension ctor
Method in Extension


Last Updated ( Tuesday, 11 July 2006 )
 

Copyright 2004 - 2008 Mike Noel. All rights reserved.
This Site is powered by Joomla!.