Welcome!

PowerBuilder Authors: Chris Pollach, Yeshim Deniz, Jayaram Krishnaswamy, Kevin Benedict, Avi Rosenthal

Related Topics: PowerBuilder

PowerBuilder: Article

Java vs. Power - Leverage your knowledge of PowerScript to learn and build java programs quickly

Java vs. Power - Leverage your knowledge of PowerScript to learn and build java programs quickly

In Parts I and II of this article (PBDJ, Vol. 7, issues 1, 2) I started comparing Java to PowerScript. We covered some of the fundamentals of the Java language - identifiers, primitive datatypes and wrappers - and PowerBuilder's Any datatype, operators, flow control statements and more.

Object orientation is an area in which Java as a language really begins to shine. Sun Microsystems has gone to great lengths to keep Java simple and easy to learn. At the same time, Java enables developers to design and implement generic object-oriented libraries that are easy to understand and reuse. In this article I'll discuss a number of the object-oriented constructs and features of the Java language.

In PowerBuilder the root of all objects is called PowerObject and in Java the root is Object. The starting point of a Java object is the class, a blueprint the Java VM uses to create the object at runtime. In PowerBuilder custom class user objects are conceptually similar to a Java class. Once a class is defined, methods and fields are added to the class to give the class behaviors and properties. Earlier we saw a couple of examples of classes in Java: HelloWorld, GraphicalHelloWorld, HelloWorldApplet and CDPlayer. Each class declared itself by starting with the keyword "class". The basic template for a class in Java is as follows:

class ClassName {
}
Once the class is defined, it can then be created or instantiated at runtime using the new operator. When the new operator is used, the Java VM locates the definition of the class, loads it into memory and then creates an instance of the class so it can be programmed. To create our example class, we first need to declare a field to store the created instance:
ClassName cn = new ClassName();

or you can use the following:

ClassName cn;
cn = new ClassName();

In Java terms we'd say that "we instantiated an instance of the class called ClassName". The new operator must be used to instantiate any class in Java. In PowerBuilder nonvisual objects are created with the "create" operator and visual objects are created when they're opened.

Java Fields and PB Variables
Properties are the elements of object-oriented programs that describe features of objects. In Java these are represented by fields within a class. In PowerBuilder's custom class, properties are represented as shared or instance variables.

In PowerBuilder we know that instance variables are created each time a copy of the object is created. As for shared variables, there's only one copy of them for every instance of an object. In Java fields are by default instance unless they're explicitly declared as static, in which case they behave like shared variables.

The following illustrates two properties of a Loan object, an amount for the loan and the prime interest rate for the loan. Since each loan is based on a separate amount, the amount property is an instance field and so is the property prime.

// Java definition of a Loan class.
class Loan {
int amount;
double prime;
}

// PowerBuilder definition of a custom class:

uo_Loan
instance:
integer ii_amount
double sd_prime

Once all the properties are defined and the object is instantiated, we can use the "." operator to reference properties inside an object.
// Reference the amount and prime properties of Loan.
Loan loan = new Loan();
loan.amount = 10000;
loan.prime = 0.05;
// Reference the amount and prime properties of
// uo_Loan.
uo_Loan luo_loan
luo_loan = create uo_Loan
luo_loan.ii_amount = 10000
luo_loan.sd_prime = 0.05;
Java also permits fields to be assigned an initial value when they're declared. Earlier I mentioned that Java assigns a default value to fields when they're declared, which can be overridden with an initial value. The following example illustrates an initial assignment:
// Java definition of a Loan class.

class Loan {
int amount;
double prime = 0.05;
}

To declare a field as an instance variable, the variable needs to be declared as static. When a field is declared static, it's usually referred to as a class field. At runtime all instances of an object share one copy of any static or class field. In the example below the Loan class declares a class field called prime.
// Java definition of a Loan class.
class Loan {
int amount;
static double prime = 0.05;
}

// PowerBuilder definition of a custom class:
uo_Loan
instance:
integer ii_amount
shared:
double sd_prime

A nice - and convenient - feature of class fields in Java is that they can be accessed without having first instantiated an object. Earlier we saw that if we wanted to access an object's fields, we needed to prefix the field name with the object's instance variable. To reference a class field, the field must be prefixed with class name. Notice that the following example references the Loan's prime field using the syntax "Loan.prime".

double interest;
int amount = 10000;

interest = amount * Loan.prime;

The use of static fields is common in the Java class libraries. Keep this in mind when you browse through the class library documentation. If a field is declared static, you can access it without instantiating the class first. The java.awt.Color class is a good example of a class with lots of class fields.

Fields in Java can also be declared locally within a method or scope block. The next example illustrates two local fields: fieldOne and fieldTwo:

void MethodName( ) {
int fieldOne;

{
int fieldTwo;
}

fieldOne++;
System.out.println( "fieldOne = " + fieldOne );

}

In this example fieldOne can be accessed throughout the method body; The field fieldTwo is accessible only within the inter block as defined by "{" and "}". The example also demonstrates a Java rule regarding the use of local fields. If you try to compile the example, the Java compiler will inform you that:

"Variable fieldOne may not have been initialized."
This means that all field (or local) variables must be explicitly initialized before they can be used. Even though Java assigned a default value of zero to the datatype int, the local variable must be explicitly assigned an initial value. The following line will declare the local field with an initial value of "0":

int fieldOne = 0;
Java Methods and PB Functions
Methods are the elements that represent the behaviors of objects. In Java these are represented by the methods within a class. In PowerBuilder's custom class, methods are represented as custom class user object functions.

In PowerBuilder, user object functions act upon their own instance or shared variables. The same holds true for Java: a class's methods act upon its instance or class fields. Like properties, class methods are by default instance unless explicitly declared as static. Any method declared as static is called a class method. PowerBuilder on the other hand doesn't have the concept of a shared or static function.

Listing 1 illustrates two methods of a Loan object: a method to calculate the interest on a loan and another method to calculate the interest on a Loan. Do you think this sounds redundant? Look closely as you read.

Once all the methods are defined and the object is instantiated, we can use the "." operator (like properties) to reference methods of the object.

// Call the getInterest() method in Java.
Loan loan = new Loan();
loan.amount = 10000;
System.out.println( "Interest = $" + loan.getInterest() );

// Call the uf_getInterest() method in PowerBuilder.
uo_Loan luo_loan
luo_loan = create uo_Loan
luo_loan.ii_amount = 10000
luo_loan.sd_prime = 0.05
MessageBox( "Interest", luo_loan.uf_getInterest() )

Methods in PowerBuilder and Java can have a return value or no return value. In PowerBuilder no return value is indicated by the "(none)" selection when declaring a function. In Java no return value is indicated by the keyword "void" when declaring a method, except for constructors. A constructor is a special method in Java that's called when an object is created. Constructors don't specify any return value at all. It isn't valid to specify any datatype, object or even void as a constructor return value. (Constructors will be discussed in greater detail later on.)

In our Java Loan object are two methods to calculate interest on a loan. Both are called getInterest() and return a double representing the interest. They're accessed the same way that static fields are accessed. If the method is an instance method, an instance of the object must exist before the method can be called. This is illustrated in the previous Java code in which a loan object is declared and created using the new operator. If the method is declared as static, it can be invoked without first creating an instance. The following code demonstrates calling a static method:

System.out.println( "Interest = $" + Loan.getInterest( 10000 ) );
This useful technique allows us to quickly calculate the total interest on a loan based on the prime rate. This technique is also used throughout the Java core libraries. If you examine that java.lang.Math package, you'll notice that a large percentage of the object's methods are declared as static. Please note that Java static methods are allowed to access only static fields or arguments supplied to the method. This explains why the instance method of our Loan object had no parameters and why the static version of getInterest( int amount ) passed in an argument.

Overloaded Methods
Overloading methods in Java works the same as it does in PowerBuilder. A method with the same return datatype, scope and name but a different set of parameters is overloaded. Consider the Graphics object in the java.awt package. It contains several overloaded methods:

drawImage( Image, int, int, Color, ImageObserver)
drawImage( Image, int, int, ImageObserver)
drawImage( Image, int, int, int, int, Color, ImageObserver)
drawImage( Image, int, int, int, int, ImageObserver)

The Java VM will compare method signatures to determine which version to invoke at runtime. The method's signature is composed of its return datatype, scope, name and argument list.

Java Constructors and the PB Constructor Event
Java and PowerBuilder have separate implementations of constructors. A constructor is a piece of code that's executed when an object is instantiated. In PowerBuilder, when a user object is instantiated using the create statement or open function, the PowerBuilder VM invokes the object's constructor event. Any initialization required by the object is performed in the script for the constructor event. For each object in PowerBuilder there is only one constructor event.

Java's implementation of constructors is more flexible than PowerBuilder's constructor event. To define a constructor in Java, a method with the same name as the class is declared. The second restriction of a constructor method is that it must not have a return type. For example, the following class is called Sample and defines one constructor called, of course, Simple().

class Simple {

// Constructor
Simple() {
// Place initialization code here.
}
}

Like PowerBuilder, when an object is instantiated in Java, the constructor method is called.
Simple s = new Simple();
As the Java VM executes the previous statement, it creates an instance of the Simple class and then calls the class's constructor. Note: Any constructor that returns the void datatype is treated as a class method. Be careful when declaring constructors. Don't use the void return type.

Java adds a level of flexibility to constructors that PowerBuilder doesn't have. Since the constructor acts like a method in a class, it can be overloaded. Defining overloaded constructors allows classes to be constructed with various initial properties. Consider the constructor in Listing 2, which initializes the coordinates of a point.

To invoke the specialized constructor, the Point object needs to be instantiated as follows:

// Invokes Constructor 2
Point p1 = new Point( 10, 20 );
// Invokes Constructor 1
Point p2 = new Point( );

// Invokes Constructor 3
Point p3 = new Point( 10, 20, 30 );

Notice that arguments are being supplied while the object is being instantiated. As each point is instantiated, they're initialized to different coordinates. Consider the variable p1, which supplies two integers during construction. The Java VM will search the Point class for a constructor with two integer arguments. If a matching constructor is found, the Java VM will invoke that constructor. The end result is that point p1 is located at ( 10, 20, 0 ), point p2 is located at ( 0, 0, 0 ) and point p3 is located at ( 10, 20, 30 ).

Java Destructors and the PB Destructor Event
Like constructors, Java and PowerBuilder have separate implementations of destructors. Destructors - the opposite of constructors - are a piece of code that executes when an object is destroyed. Objects in PowerBuilder are destroyed using the destroy statement, the close function or the garbage collector. In PowerBuilder, when a user object is about to be destroyed, the destructor script for the object executes. This allows the object to "clean up after itself."

Technically, Java doesn't implement destructors. It does, however, allow programmers to add to a class a method called finalize() that will be called by the Java VM when an object is about to be destroyed. There is also no means to explicitly destroy an object in Java as there is in PowerBuilder. Java's garbage collector will destroy objects as it determines they are no longer being used.

If you use the finalize method as a means of cleaning up, you should be aware of a few points about Java's garbage collection.

  1. The garbage collector runs as a low priority thread in the Java VM. As such, it's possible to run out of memory if a high-priority thread starves the garbage collection thread.
  2. Unlike PowerBuilder, the destruction process in Java isn't guaranteed and the Java VM may exit without calling any finalize methods.
  3. The Java VM can resurrect an object after the finalize() method has been invoked. This could happen if an object was holding onto a "this" pointer.
  4. The Java VM invokes the finalize() method only once! If an object happens to be resurrected, the finalize() method isn't called again if the object is destroyed.
  5. Java doesn't specify when the garbage collection occurs or in what order objects are destroyed.
  6. If any exceptions are thrown inside the finalize() method, they're ignored by the Java VM.

For additional information on object finalization see the java.lang.Object.finalize() method in the JDK documentation.

Scoping
Together, properties, methods and scoping enable programmers to encapsulate data and logic within objects they build. To achieve encapsulation, a programming language must provide three fundamental levels of scope, as presented in Table 1.

While Java and PowerBuilder support the three scope modifiers listed in the table, they also permit other language-specific scope modifiers.

PowerBuilder additionally defines protectedwrite, protectedread, privatewrite and privateread. Each contributes to the level of encapsulation and data hiding available when designing objects in PowerBuilder. Table 2 describes the specialized PowerBuilder access modifiers.

If no scope modifier is specified, then PowerBuilder assigns the default public modifier. Java, on the other hand, permits one extra scope modifier called package, which also happens to be Java's default scope modifier (see Table 3).

Packages
A package in Java is a method for grouping related objects together. It's also a method used to control the scope of classes to prevent naming conflicts. How do packages affect your Java code? Let's consider an example. Assume that I built a class called NumberFormatter, which I use to format various types of numbers in Java. This class may look something like:

class NumberFormatter {

public static String formatDollars( int amount ) {
return "$ " + amount;
}

// other formatting methods

}

Since there's no scope modifier for the class, it's assigned the default scope modifier, package. The method formatDollars() is public and thus any object can call this method. Although there's no package specified for NumberFormatter, Java does assign it to an empty package.

The problem arises when you try to use a third-party class library where it defines a class called NumberFormatter. In PowerBuilder, if you have two objects with the same name, the VM will load the first occurrence of the object found in the application's library search path. Duplicate object names can cause unknown problems, especially if the two objects are completely different.

In Java, if you group objects into packages, there is no chance of "accidentally" loading the wrong object because they exist in separate namespaces. If a third-party library defined a number formatter as follows, then the two versions of NumberFormatter are unique.

package com.company.Numbers;

class NumberFormatter {

public static String parseNumber( int amount ) {
return Integer(amount).toString();
}

}

The first version of NumberFormatter belongs to the empty package; the second, to the com.company.Numbers package. Since they belong to two different packages, the Java VM treats them as separate objects. The following example illustrates how to uniquely reference the two NumberFormatters.
class UseNumberFormatter {
public static void main( String[] args ) {
NumberFormatter nf1;
com.company.Numbers.NumberFormatter nf2;

nf1 = new NumberFormatter();
nf2 = new com.company.Numbers.NumberFormatter();
}

}

Note that the first NumberFormatter, nf1, is referenced by itself and the second, nf2, is referenced with its package. Objects in Java can be explicitly referenced to guarantee uniqueness and prevent name collision. Sometimes variables must be fully declared. Consider what would happen if you had this code:

import com.company.Numbers.*;

class UseNumberFormatter {

public static void main( String[] args ) {
NumberFormatter nf1;
NumberFormatter nf2;

Which NumberFormatter is used to create nf1 and nf2? Be careful when using the import statement to import the com.company.Numbers package because the Java compiler may not know which copy of NumberFormatter to use. Java IDEs, like PowerJ, may not use imports. Instead, it fully declares all variables. This generally makes code look a little untidy but prevents name collisions.

Another stumbling block for many beginners occurs when the programmer forgets about packages and the default scope modifier package. In the next example class A is placed in a package and is declared using the default scope modifier. The programmer then creates class B and attempts to load and instantiate class A.

package com.company;

class A {
public int a;
}

class B {
A a = new A();
}

In this case class B will not compile because it tries to reference class A, which is not public and belongs to the com.company package. Only classes within the com.company package can instantiate and use class A. If class A is an internal utility class for the package com.company, then it makes sense, from an object-oriented point of view, that class B isn't allowed to instantiate A. A common programming error is to forget to use the public class modifier when placing classes into packages.

With the information provided in this article, you should be able to start declaring fields and objects, using flow control statements, and operators, and documenting your programs as you develop them. For a complete analysis of Java versus PowerScript and more, visit www.techyoulogy.com. Enjoy!

More Stories By Kouros Gorgani

Kouros Gorgani is a software development manager with EAServer Engineering Canada of Sybase Inc. Kouros is a CPD and the author of several technical books.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.