Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 
Search the JavaFAQ.nu
1000 Java Tips ebook

1000 Java Tips - Click here for the high resolution copy!1000 Java Tips - Click here for the high resolution copy!

Java Screensaver, take it here

Free "1000 Java Tips" eBook is here! It is huge collection of big and small Java programming articles and tips. Please take your copy here.

Take your copy of free "Java Technology Screensaver"!.

Easy Learn Java: Programming Articles, Examples and Tips - Page 481


Previous 1060 Stories (530 Pages, 2 Per Page) Next

Easy Java Lecture 12: Classes. Teach/learn online

Go to all tips in Java Lectures by Anatoliy Malyarenko

Classes

by: Anatoliy Malyarenko

Abstract

Contents of the lecture.

  • Creating classes.
  • The class declaration.
  • The class body.
  • Providing constructors for your classes.
  • Declaring member variables.
  • Implementing methods.
  • Controlling access to members of a class.
  • Understanding instance and class members.

Creating classes

Consider a small example that implements a last-in-first-out (LIFO) stack. The following diagram lists the class and identifies the structure of the code.


This implementation of a stack uses another object, a Vector, to store its elements. Vector is a growable array of objects and does a nice job of allocating space for new objects as space is required. The Stack class makes use of this code by using a Vector to store its elements. However, it imposes LIFO restrictions on the Vector -- that is, you can only add elements to and remove elements from the top of the stack.

The class declaration

The left side of the following diagram shows the possible components of a class declaration in the order they should or must appear in your class declaration. The right side describes their purposes. The required components are the class keyword and the class name and are shown in bold. All the other components are optional, and each appears on a line by itself (thus "extends Super" is a single component). Italics indicates an identifier such as the name of a class or interface. If you do not explicitly declare the optional items, the Java compiler assumes certain defaults: a non-public, non-abstract, non-final subclass of Object that implements no interfaces.

The following list provides a few more details about each class declaration component.

public

By default, a class can be used only by other classes in the same package. The public modifier declares that the class can be used by any class regardless of its package.

abstract

Declares that the class cannot be instantiated.

final

Declares that the class cannot be subclassed.

class NameOfClass

The class keyword indicates to the compiler that this is a class declaration and that the name of the class is NameOfClass.

extends Super

The extends clause identifies Super as the superclass of the class, thereby inserting the class within the class hierarchy.

implements Interfaces

To declare that your class implements one or more interfaces, use the keyword implements followed by a comma-separated list of the names of the interfaces implemented by the class.

The class body

The class body contains all of the code that provides for the life cycle of the objects created from it: constructors for initialising new objects, declarations for the variables that provide the state of the class and its objects, methods to implement the behaviour of the class and its objects, and in rare cases, a finalize method to provide for cleaning up an object after it has done its job.

Variables and methods collectively are called members.

Note: Constructors are not methods. Nor are they members.

The Stack class defines one member variable in its body to contain its elements -- the items Vector. It also defines one constructor -- a no-argument constructor -- and three methods: push, pop, and isEmpty.

Providing constructors for your classes

All Java classes have constructors that are used to initialise a new object of that type. A constructor has the same name as the class. For example, the name of the Stack class's constructor is Stack, the name of the Rectangle class's constructor is Rectangle, and the name of the Thread class's constructor is Thread. Stack defines a single constructor:

public Stack() {
    items = new Vector(10);
}

Java supports name overloading for constructors so that a class can have any number of constructors, all of which have the same name. Following is another constructor that could be defined by Stack. This particular constructor sets the initial size of the stack according to its parameter:

public Stack(int initialSize) {
    items = new Vector(initialSize);
}

Both constructors share the same name, Stack, but they have different parameter lists. The compiler differentiates these constructors based on the number of parameters in the list and their types.

Typically, a constructor uses its arguments to initialise the new object's state. When creating an object, choose the constructor whose arguments best reflect how you want to initialise the new object.

Based on the number and type of the arguments that you pass into the constructor, the compiler can determine which constructor to use. The compiler knows that when you write the following code, it should use the constructor that requires a single integer argument:

new Stack(10);

Similarly, when you write the following code, the compiler chooses the no-argument constructor or the default constructor:

new Stack();

When writing your own class, you don't have to provide constructors for it. The default constructor is automatically provided by the runtime system for any class that contains no constructors. The default provided by the runtime system doesn't do anything. So, if you want to perform some initialisation, you will have to write some constructors for your class.

The constructor for the following subclass of Thread performs animation, sets up some default values, such as the frame speed and the number of images, and then loads the images:

class AnimationThread extends Thread {
    int framesPerSecond;
    int numImages;
    Image[] images;

    AnimationThread(int fps, int num) {
        super("AnimationThread");
        this.framesPerSecond = fps;
        this.numImages = num;

        this.images = new Image[numImages];
        for (int i = 0; i <= numImages; i++) {
            . . .
            // Load all the images.
            . . .
    }
}
. . .
}

Note how the body of a constructor is like the body of a method; that is, it contains local variable declarations, loops, and other statements. However, one line in the AnimationThread constructor that you wouldn't see in a method is the second line:

super("AnimationThread");

This line invokes a constructor provided by the superclass of AnimationThread, namely, Thread. This particular Thread constructor takes a String that sets the name of Thread. Often a constructor wants to take advantage of initialisation code written in a class's superclass. Indeed, some classes must call their superclass constructor in order for the object to work properly. If present, the superclass constructor must be the first statement in the subclass's constructor: An object should perform the higher-level initialisation first.

You can specify what other objects can create instances of your class by using an access specifier in the constructors' declaration:

private

No other class can instantiate your class. Your class may contain public class methods (sometimes called factory methods), and those methods can construct an object and return it, but no other classes can.

protected

Only subclasses of the class and classes in the same package can create instances of it.

public

Any class can create an instance of your class.

no specifier gives package access

Only classes within the same package as your class can construct an instance of it.

Declaring member variables

Stack uses the following line of code to define its single member variable:

private Vector items;

This declares a member variable and not some other type of variable (like a local variable) because the declaration appears within the class body but outside of any methods or constructors. The member variable declared is named items, and its data type is Vector.

Also, the private keyword identifies items as a private member. This means that only code within the Stack class can access it.

This is a relatively simple member variable declaration, but declarations can be more complex. You can specify not only type, name, and access level, but also other attributes, including whether the variable is a class or instance variable and whether it's a constant. Each component of a member variable declaration is further defined below:

accessLevel

Lets you control which other classes have access to a member variable by using one of four access levels: public, protected, package, and private. You control access to methods in the same way.

static

Declares this is a class variable rather than an instance variable. You also use static to declare class methods.

final

Indicates that the value of this member cannot change. The following variable declaration defines a constant named AVOGADRO, whose value is Avogadro's number (6.022 · 1023) and cannot be changed:

final double AVOGADRO = 6.022e23;

It's a compile-time error if your program ever tries to change a final variable. By convention, the name of constant values are spelled in uppercase letters.

transient

The transient marker is not fully specified by The Java Language Specification but is used in object serialisation to mark member variables that should not be serialised.

volatile

The volatile keyword is used to prevent the compiler from performing certain optimisations on a member. This is an advanced Java feature, used by only a few Java programmers.

type

Like other variables, a member variable must have a type. You can use primitive type names such as int, float, or boolean. Or you can use reference types, such as array, object, or interface names.

name

A member variable's name can be any legal Java identifier and, by convention, begins with a lowercase letter. You cannot declare more than one member variable with the same name in the same class, but a subclass can hide a member variable of the same name in its superclass. Additionally, a member variable and a method can have the same name. For example, the following code is legal:

public class Stack {
    private Vector items;
    // a method with same name as a member variable
    public Vector items() {
        . . .
    }
}

Implementing methods

This figure shows the code for Stack's push method. This method pushes an object, the one passed in as an argument, onto the top of the stack, and returns it.

Like a class, a method has two major parts: method declaration and method body. The method declaration defines all of the method's attributes, such as access level, return type, name, and arguments, as illustrated here:

The method body is where all the action takes place. It contains the Java instructions that implement the method.

Details of a method declaration

A method's declaration provides a lot of information about the method to the compiler, to the runtime system, and to other classes and objects. Included is not only the name of the method, but also such information as the return type of the method, the number and type of the arguments required by the method, and which other classes and objects can call the method.

While this may sound like writing a novel rather than simply declaring a method, most method attributes can be declared implicitly. The only required elements of a method declaration are the method's name, its return type, and a pair of parentheses (). This figure shows the elements of a method declaration.

Each element of a method declaration is further defined below:

accessLevel

As with member variables, you control which other classes have access to a method using one of four access levels: public, protected, package, and private.

static

As with member variables, static declares this method as a class method rather than an instance method.

abstract

An abstract method has no implementation and must be a member of an abstract class.

final

A final method cannot be overridden by subclasses.

native

If you have a significant library of functions written in another language such as C, you may wish to preserve that investment and use those functions from Java. Methods implemented in a language other than Java are called native methods and are declared as such using the native keyword.

synchronized

Concurrently running threads often invoke methods that operate on the same data. These methods may be declared synchronised to ensure that the threads access information in a thread-safe manner.

returnType

Java requires that a method declare the data type of the value that it returns. If your method does not return a value, use the keyword void for the return type.

methodName

A method name can be any legal Java identifier. You need to consider several issues in regards to Java method names.

(paramlist)

You pass information into a method through its arguments.

[throws exceptions]

If your method throws any checked exceptions, your method declaration must indicate the type of those exceptions.

Returning a value from a method

You declare a method's return type in its method declaration. Within the body of the method, you use the return operator to return the value. Any method that is not declared void must contain a return statement. The Stack class declares the isEmpty method, which returns a boolean:

public boolean isEmpty() {
    if (items.size() == 0)
        return true;
    else
        return false;
}

The data type of the return value must match the method's return type; you can't return an Object type from a method declared to return an integer. The isEmpty method returns either the boolean value true or false, depending on the outcome of a test. A compiler error results if you try to write a method in which the return value doesn't match the return type.

The isEmpty method returns a primitive type. Methods also can return a reference type. For example, Stack declares the pop method that returns the Object reference type:

public synchronized Object pop() {
    int len = items.size();
    Object obj = null;
    if (len == 0)
        throw new EmptyStackException();
    obj = items.elementAt(len - 1);
    items.removeElementAt(len - 1);
    return obj;
}

When a method returns an object such as pop does, the class of the returned object must be either a subclass of or the exact class of the return type. This can be a source of confusion, so let's look at this more closely. Suppose you have a class hierarchy where ImaginaryNumber is a subclass of java.lang.Number, which is, in turn, a subclass of Object, as illustrated here:

Now suppose you have a method declared to return a Number:

public Number returnANumber() {
    . . .
}

The returnANumber method can return an ImaginaryNumber but not an Object. ImaginaryNumber "is a" Number because it's a subclass of Number. However, an Object is not necessarily a Number -- it could be a String or some other type. You also can use interface names as return types. In this case, the object returned must implement the specified interface.

A method's name

Java supports method name overloading so that multiple methods can share the same name. For example, suppose you are writing a class that can render various types of data (strings, integers, and so on) to its drawing area. You need to write a method that knows how to render each data type. In other languages, you have to think of a new name for each method, for example, drawString, drawInteger, drawFloat, and so on. In Java, you can use the same name for all of the drawing methods but pass a different type of parameter to each method. So, in your data rendering class, you can declare three methods named draw, each of which takes a different type of parameter:

class DataRenderer {
    void draw(String s) {
        . . .
    }
    void draw(int i) {
        . . .
    }
    void draw(float f) {
        . . .
    }
}

Overloaded methods are differentiated by the number and type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types. You cannot declare more than one method with the same name and the same number and type of arguments because the compiler cannot differentiate them. So, draw(String s) and draw(String t) are identical and result in a compiler error.

A class may override a method in its superclass. The overriding method must have the same name, return type, and parameter list as the method it overrides.

Passing information into a method

When you write your method, you declare the number and type of the arguments required by that method. You declare the type and name for each argument in the method signature. For example, the following is a method that computes the monthly payments for a home loan based on the amount of the loan, the interest rate, the length of the loan (the number of periods), and the future value of the loan (presumably the future value of the loan is zero because at the end of the loan, you've paid it off):

double computePayment(double loanAmt,
                    double rate,
                    double futureValue,
                    int numPeriods) {
    double I, partial1, denominator, answer;
    I = rate / 100.0;
    partial1 = Math.pow((1+I), (0.0-numPeriods));
    denominator = (1 - partial1) / I;
    answer = ((-1 * loanAmt) / denominator)
                        - ((futureValue * partial1) / denominator);
    return answer;
}

This method takes four arguments: the loan amount, the interest rate, the future value and the number of periods. The first three are double-precision floating point numbers, and the fourth is an integer.

As with this method, the set of arguments to any method is a comma-separated list of variable declarations where each variable declaration is a type/name pair:

type name

As you can see from the body of the computePayment method, you simply use the argument name to refer to the argument's value.

Argument types

In Java, you can pass an argument of any valid Java data type into a method. This includes primitive data types such as doubles, floats and integers as you saw in the computePayment method, and reference data types such as objects and arrays. Here's an example of a factory method that accepts an array as an argument. In this example, the method creates a new Polygon object and initialises it from a list of Points (Point is a class that represents an x, y coordinate):

static Polygon polygonFrom(Point[] listOfPoints) {
    . . .
}

Unlike some other languages, you cannot pass methods into Java methods. But you can pass an object into a method and then invoke the object's methods.

Argument names

When you declare an argument to a Java method, you provide a name for that argument. This name is used within the method body to refer to the item.

A method argument can have the same name as one of the class's member variables. If this is the case, then the argument is said to hide the member variable. Arguments that hide member variables are often used in constructors to initialise a class. For example, take the following Circle class and its constructor:

class Circle {
    int x, y, radius;
    public Circle(int x, int y, int radius) {
        . . .
    }
}

The Circle class has three member variables: x, y and radius. In addition, the constructor for the Circle class accepts three arguments each of which shares its name with the member variable for which the argument provides an initial value.

The argument names hide the member variables. So using x, y or radius within the body of the constructor refers to the argument, not to the member variable. To access the member variable, you must reference it through this -- the current object:

class Circle {
    int x, y, radius;
    public Circle(int x, int y, int radius) {
        this.x = x;
        this.y = y;
        this.radius = radius;
    }
}

Names of method arguments cannot be the same as another argument name for the same method, the name of any variable local to the method, or the name of any parameter to a catch clause within the same method.

Pass by value

In Java methods, arguments are passed by value. When invoked, the method receives the value of the variable passed in. When the argument is of primitive type, pass-by-value means that the method cannot change its value. When the argument is of reference type, pass-by-value means that the method cannot change the object reference, but can invoke the object's methods and modify the accessible variables within the object.

This is often the source of confusion -- a programmer writes a method that attempts to modify the value of one its arguments and the method doesn't work as expected. Let's look at such method and then investigate how to change it so that it does what the programmer originally intended.

Consider this series of Java statements which attempts to retrieve the current colour of a Pen object in a graphics application:
. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red = " + r +
                                ", green = " + g +
                                ", blue = " + b);
. . .

At the time when the getRGBColor method is called, the variables r, g, and b all have the value -1. The caller is expecting the getRGBColor method to pass back the red, green and blue values of the current colour in the r, g, and b variables.

However, the Java runtime passes the variables' values (-1) into the getRGBColor method; not a reference to the r, g, and b variables. So you could visualise the call to getRGBColor like this: getRGBColor(-1, -1, -1).

When control passes into the getRGBColor method, the arguments come into scope (get allocated) and are initialised to the value passed into the method:

class Pen {
    int redValue, greenValue, blueValue;
    void getRGBColor(int red, int green,
    int blue) {
        // red, green, and blue have been created
        // and their values are -1
        . . .
    }
}

So getRGBColor gets access to the values of r, g, and b in the caller through its arguments red, green, and blue, respectively. The method gets its own copy of the values to use within the scope of the method. Any changes made to those local copies are not reflected in the original variables from the caller.

Now, let's look at the implementation of getRGBColor within the Pen class that the method signature above implies:

int redValue, greenValue, blueValue;
. . .
// this method does not work as intended
void getRGBColor(int red, int green,
                                int blue) {
    red = redValue;
    green = greenValue;
    blue = blueValue;
    }
}
This method will not work as intended. When control gets to the println statement in the following code, which was shown previously, getRGBColor's arguments, red, green, and blue, no longer exist. Therefore the assignments made to them within the method had no effect; r, g, and b are all still equal to -1.

. . .
int r = -1, g = -1, b = -1;
pen.getRGBColor(r, g, b);
System.out.println("red = " + r +
                        ", green = " + g +
                        ", blue = " + b);
. . .

Passing variables by value affords the programmer some safety: Methods cannot unintentionally modify a variable that is outside of its scope. However, you often want a method to be able to modify one or more of its arguments. The getRGBColor method is a case in point. The caller wants the method to return three values through its arguments. However, the method cannot modify its arguments, and, furthermore, a method can only return one value through its return value. So, how can a method return more than one value, or have an effect (modify some value) outside of its scope?

For a method to modify an argument, it must be of a reference type such as an object or array. Objects and arrays are also passed by value, but the value of an object is a reference.

So the effect is that arguments of reference types are passed in by reference. Hence the name. A reference to an object is the address of the object in memory. Now, the argument in the method is referring to the same memory location as the caller.

Let's rewrite the getRGBColor method so that it actually does what you want. First, you must introduce a new type of object, RGBColor, that can hold the red, green and blue values of a colour in RGB space:

class RGBColor {

    public int red, green, blue;
}

Now, we can rewrite getRGBColor so that it accepts an RGBColor object as an argument. The getRGBColor method returns the current colour of the pen by setting the red, green and blue member variables of its RGBColor argument:

class Pen {
    int redValue, greenValue, blueValue;
    void getRGBColor(RGBColor aColor) {
        aColor.red = redValue;
        aColor.green = greenValue;
        aColor.blue = blueValue;
    }
}

And finally, let's rewrite the calling sequence:

. . .
RGBColor penColor = new RGBColor();
pen.getRGBColor(penColor);
System.out.println("red = " + r +
                ", green = " + g +
                ", blue = " + b);
. . .


The modifications made to the RGBColor object within the getRGBColor method affect the object created in the calling sequence because the names penColor (in the calling sequence) and aColor (in the getRGBColor method) refer to the same object.

The method body

In the code sample that follows, the method bodies for the isEmpty and pop methods are shown in bold:

class Stack {
        static final int STACK_EMPTY = -1;
        Object[] stackelements;
        int topelement = STACK_EMPTY;
        . . .
        boolean isEmpty() {
            if (topelement == STACK_EMPTY)
                return true;
            else
                return false;

        }
        Object pop() {
            if (topelement == STACK_EMPTY)
                return null;
            else {
                return stackelements[topelement--];

        }
    }
}

Besides regular Java language elements, you can use this in the method body to refer to members in the current object. The current object is the object whose method is being called. You can also use super to refer to members in the superclass that the current object has hidden or overridden. Also, a method body may contain declarations for variables that are local to that method.

this

Typically, within an object's method body you can just refer directly to the object's member variables. However, sometimes you need to disambiguate the member variable name if one of the arguments to the method has the same name.

For example, the following constructor for the HSBColor class initialises some of an object's member variables according to the arguments passed into the constructor. Each argument to the constructor has the same name as the object's member variable whose initial value the argument contains.

class HSBColor {
    int hue, saturation, brightness;
    HSBColor (int hue, int saturation,
    int brightness) {
        this.hue = hue;
        this.saturation = saturation;
        this.brightness = brightness;
    }
}

You must use the this keyword in this constructor because you have to disambiguate the argument hue from the member variable hue (and so on with the other arguments). Writing hue = hue; makes no sense. Argument names take precedence and hide member variables with the same name. So to refer to the member variable you must do so through the current object -- using the this keyword to refer to the current object -- explicitly.

Some programmers prefer to always use the this keyword when referring to a member variable of the object whose method the reference appears. Doing so makes the intent of the code explicit and reduces errors based on name sharing.

You can also use the this keyword to call one of the current object's methods. Again this is only necessary if there is some ambiguity in the method name and is often used to make the intent of the code clearer.

super

If your method hides one of its superclass's member variables, your method can refer to the hidden variable through the use of the super keyword. Similarly, if your method overrides one of its superclass's methods, your method can invoke the overridden method through the use of the super keyword.

Consider this class:

class ASillyClass {
    boolean aVariable;
    void aMethod() {
        aVariable = true;
    }
}

and its subclass which hides aVariable and overrides aMethod:

class ASillierClass extends ASillyClass {
    boolean aVariable;
    void aMethod() {
        aVariable = false;
        super.aMethod();
        System.out.println(aVariable);
        System.out.println(super.aVariable);
    }
}

First aMethod sets aVariable (the one declared in ASillierClass that hides the one declared in ASillyClass) to false. Next aMethod invoked its overridden method with this statement:

super.aMethod();

This sets the hidden version of the aVariable (the one declared in ASillyClass) to true. Then aMethod displays both versions of aVariable which have different values:

false
true

Local variables

Within the body of the method you can declare more variables for use within that method. These variables are local variables and live only while control remains within the method. This method declares a local variable i that it uses to iterate over the elements of its array argument.

Object findObjectInArray(Object o,
                Object[] arrayOfObjects) {
    int i; // local variable
    for (i = 0; i < arrayOfObjects.length; i++) {
        if (arrayOfObjects[i] == o)
            return o;
    }
    return null;
}

After this method returns, i no longer exists.

Controlling access to members of a class

One of the benefits of classes is that classes can protect their member variables and methods from access by other objects. Why is this important? Well, consider this. You're writing a class that represents a query on a database that contains all kinds of secret information, say employee records or income statements for your startup company.

Certain information and queries contained in the class, the ones supported by the publicly accessible methods and variables in your query object, are OK for the consumption of any other object in the system. Other queries contained in the class are there simply for the personal use of the class. They support the operation of the class but should not be used by objects of another type -- you've got secret information to protect. You'd like to be able to protect these personal variables and methods at the language level and disallow access by objects of another type.

In Java, you can use access specifiers to protect both a class's variables and its methods when you declare them. The Java language supports four distinct access levels for member variables and methods: private, protected, public, and, if left unspecified, package.

The following chart shows the access level permitted by each specifier.

Specifier class subclass package world
private v -- -- --
protected v v* v --
public v v v v
no specifier v -- v --

The first column indicates whether the class itself has access to the member defined by the access specifier. As you can see, a class always has access to its own members. The second column indicates whether subclasses of the class (regardless of which package they are in) have access to the member. The third column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The fourth column indicates whether all classes have access to the member.

Private

The most restrictive access level is private. A private member is accessible only to the class in which it is defined. Use this access to declare members that should only be used by the class. This includes variables that contain information that if accessed by an outsider could put the object in an inconsistent state, or methods that, if invoked by an outsider, could jeopardise the state of the object or the program in which it's running. Private members are like secrets you never tell anybody.

To declare a private member, use the private keyword in its declaration. The following class contains one private member variable and one private method:

class Alpha {
    private int iamprivate;
    private void privateMethod() {
        System.out.println("privateMethod");
    }
}

Objects of type Alpha can inspect or modify the iamprivate variable and can invoke privateMethod, but objects of other types cannot. For example, the Beta class defined here:

class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iamprivate = 10; // illegal
        a.privateMethod(); // illegal
    }
}

cannot access the iamprivate variable or invoke privateMethod on an object of type Alpha because Beta is not of type Alpha.

When one of your classes is attempting to access a member variable to which it does not have access, the compiler prints an error message similar to the following and refuses to compile your program:

Beta.java:9: Variable iamprivate in class Alpha
not accessible from class Beta.
        a.iamprivate = 10; // illegal
^
1 error

Also, if your program is attempting to access a method to which it does not have access, you will see a compiler error like this:

Beta.java:12: No method matching privateMethod() found in class Alpha.
a.privateMethod(); // illegal
1 error
New Java programmers might ask if one Alpha object can access the private members of another Alpha object. This is illustrated by the following example. Suppose the Alpha class contained an instance method that compared the current Alpha object (this) to another object based on their iamprivate variables:

class Alpha {
    private int iamprivate;
    boolean isEqualTo(Alpha anotherAlpha) {
        if (this.iamprivate ==
                anotherAlpha.iamprivate)
            return true;
        else
            return false;

     }
}

This is perfectly legal. Objects of the same type have access to one another's private members. This is because access restrictions apply at the class or type level (all instances of a class) rather than at the object level (this particular instance of a class).

Protected

The next access level specifier is protected, which allows the class itself, subclasses and all classes in the same package to access the members. Use the protected access level when it's appropriate for a class's subclasses to have access to the member, but not unrelated classes. Protected members are like family secrets -- you don't mind if the whole family
knows, and even a few trusted friends but you wouldn't want any outsiders to know.

To declare a protected member, use the keyword protected. First, let's look at how the protected specifier affects access for classes in the same package. Consider this version of the Alpha class which is now declared to be within a package named Greek and which has one protected member variable and one protected method declared in it:

package Greek;
public class Alpha {
    protected int iamprotected;
    protected void protectedMethod() {
        System.out.println("protectedMethod");
    }
}

Now, suppose that the class Gamma was also declared to be a member of the Greek package (and is not a subclass of Alpha). The Gamma class can legally access an Alpha object's iamprotected member variable and can legally invoke its protectedMethod:

package Greek;

class Gamma {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iamprotected = 10; // legal
        a.protectedMethod(); // legal
    }
}

That's pretty straightforward. Now, let's investigate how the protected specifier affects access for subclasses of Alpha.

Let's introduce a new class, Delta, that derives from Alpha but lives in a different package -- Latin. The Delta class can access both iamprotected and protectedMethod, but only on objects of type Delta or its subclasses. The Delta class cannot access
iamprotected or protectedMethod on objects of type Alpha. accessMethod in the following code sample attempts to access the iamprotected member variable on an object of type Alpha, which is illegal, and on an object of type Delta, which is legal. Similarly, accessMethod attempts to invoke an Alpha object's protectedMethod which is also illegal:

package Latin;
import Greek.*;
class Delta extends Alpha {
    void accessMethod(Alpha a, Delta d) {
        a.iamprotected = 10; // illegal
        d.iamprotected = 10; // legal
        a.protectedMethod(); // illegal
        d.protectedMethod(); // legal
    }
}

If a class is both a subclass of and in the same package as the class with the protected member, then the class has access to the protected member.

Public

The easiest access specifier is public. Any class, in any package, has access to a class's public members. Declare public members only if such access cannot produce undesirable results if an outsider uses them. There are no personal or family secrets here; this is for stuff you don't mind anybody else knowing.

To declare a public member, use the keyword public. For example,

package Greek;

public class Alpha {
    public int iampublic;
    public void publicMethod() {
        System.out.println("publicMethod");
    }
}

Let's rewrite our Beta class one more time and put it in a different package than Alpha and make sure that it is completely unrelated to (not a subclass of) Alpha:

package Roman;

import Greek.*;
class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iampublic = 10; // legal
        a.publicMethod(); // legal
    }
}

As you can see from the above code snippet, Beta can legally inspect and modify the iampublic variable in the Alpha class and can legally invoke publicMethod.

No specifier

The package access level is what you get if you don't explicitly set a member's access to one of the other levels. This access level allows classes in the same package as your class to access the members. This level of access assumes that classes in the same package are trusted friends. This level of trust is like that which you extend to your closest friends but wouldn't trust even to your family.

For example, this version of the Alpha class declares a single package-access member variable and a single package-access method. Alpha lives in the Greek package:

package Greek;

class Alpha {
    int iampackage;
    void packageMethod() {
        System.out.println("packageMethod");
    }
}

The Alpha class has access both to iampackage and packageMethod. In addition, all the classes declared within the same package as Alpha also have access to iampackage and packageMethod. Suppose that both Alpha and Beta were declared as part of the Greek package:

package Greek;

class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iampackage = 10; // legal
        a.packageMethod(); // legal
    }
}

Beta can legally access iampackage and packageMethod as shown.

Understanding instance and class members

When you declare a member variable such as aFloat in MyClass:

class MyClass {
    float aFloat;
}

you declare an instance variable. Every time you create an instance of a class, the runtime system creates one copy of each class's instance variables for the instance.

Instance variables are in contrast to class variables (which you declare using the static modifier). The runtime system allocates class variables once per class regardless of the number of instances created of that class. The system allocates memory for class variables the first time it encounters the class. All instances share the same copy of the class's class variables. You can access class variables through an instance or through the class itself.

Methods are similar: Your classes can have instance methods and class methods. Instance methods operate on the current object's instance variables but also have access to the class variables. Class methods, on the other hand, cannot access the instance variables declared within the class (unless they create a new object and access them through the object). Also, class methods can be invoked on the class, you don't need an instance to call a class method.

By default, unless otherwise specified, a member declared within a class is an instance member. The class defined below has one instance variable -- an integer named x -- and two instance methods ­ x and setX -- that let other objects set and query the value of x:

class AnIntegerNamedX {
    int x;
    public int x() {
        return x;
    }
    public void setX(int newX) {
        x = newX;
    }
}

Every time you instantiate a new object from a class, you get a new copy of each of the class's instance variables. These copies are associated with the new object. So, every time you instantiate a new AnIntegerNamedX object from the class, you get a new copy of x that is associated with the new AnIntegerNamedX object.

All instances of a class share the same implementation of an instance method; all instances of AnIntegerNamedX share the same implementation of x and setX. Note that both methods, x and setX, refer to the object's instance variable x by name. "But", you ask, "if all instances of AnIntegerNamedX share the same implementation of x and setX isn't this ambiguous?" The answer is "no." Within an instance method, the name of an instance variable refers to the current object's instance variable, assuming that the instance variable isn't hidden by a method parameter. So, within x and setX, x is equivalent to this.x.

Objects outside of AnIntegerNamedX that wish to access x must do so through a particular instance of AnIntegerNamedX. Suppose that this code snippet was in another object's method. It creates two different objects of type AnIntegerNamedX, sets their x values to different values, then displays them:

. . .
AnIntegerNamedX myX = new AnIntegerNamedX();
AnIntegerNamedX anotherX = new AnIntegerNamedX();
myX.setX(1);
anotherX.x = 2;
System.out.println("myX.x = " + myX.x());
System.out.println("anotherX.x = " + anotherX.x());
. . .

Notice that the code used setX to set the x value for myX but just assigned a value to anotherX.x directly. Either way, the code is manipulating two different copies of x: the one contained in the myX object and the one contained in the anotherX object. The output produced by this code snippet is:

myX.x = 1
anotherX.x = 2

showing that each instance of the class AnIntegerNamedX has its own copy of the instance variable x and each x has a different value.

You can, when declaring a member variable, specify that the variable is a class variable rather than an instance variable. Similarly, you can specify that a method is a class method rather than an instance method. The system creates a single copy of a class variable the first time it encounters the class in which the variable is defined. All instances of that class share the same copy of the class variable. Class methods can only operate on class variables -- they cannot access the instance variables defined in the class.

To specify that a member variable is a class variable, use the static keyword. For example, let's change the AnIntegerNamedX class such that its x variable is now a class variable:

class AnIntegerNamedX {
    static int x;
    public int x() {
        return x;
    }
    public void setX(int newX) {
        x = newX;
    }
}

Now the exact same code snippet from before that creates two instances of AnIntegerNamedX, sets their x values, and then displays them produces this, different, output.

myX.x = 2
anotherX.x = 2

The output is different because x is now a class variable so there is only one copy of the variable and it is shared by all instances of AnIntegerNamedX, including myX and anotherX. When you invoke setX on either instance, you change the value of x for all instances of AnIntegerNamedX.

You use class variables for items that you need only one copy of and which must be accessible by all objects inheriting from the class in which the variable is declared. For example, class variables are often used with final to define constants; this is more memory efficient than final instance variables because constants can't change, so you really only need one copy.

Similarly, when declaring a method, you can specify that method to be a class method rather than an instance method. Class methods can only operate on class variables and cannot access the instance variables defined in the class.

To specify that a method is a class method, use the static keyword in the method declaration. Let's change the AnIntegerNamedX class such that its member variable x is once again an instance variable, and its two methods are now class methods:

class AnIntegerNamedX {
    int x;
    static public int x() {
        return x;
    }
    static public void setX(int newX) {
        x = newX;
    }
}

When you try to compile this version of AnIntegerNamedX, the compiler displays an error like this one:

AnIntegerNamedX.java:4: Can't make a static reference to
nonstatic variable x in class AnIntegerNamedX.
return x;
^

This is because class methods cannot access instance variables unless the method created an instance of AnIntegerNamedX first and accessed the variable through it.

Let's fix AnIntegerNamedX by making its x variable a class variable:

class AnIntegerNamedX {

    static int x;
    static public int x() {
        return x;
    }
    static public void setX(int newX) {
        x = newX;
    }
}

Now the class will compile and the same code snippet from before that creates two instances of AnIntegerNamedX, sets their x values, and then prints the x values produces this output:

myX.x = 2
anotherX.x = 2

Again, changing x through myX also changes it for other instances of AnIntegerNamedX.

Another difference between instance members and class members is that class members are accessible from the class itself. You don't need to instantiate a class to access its class members. Let's rewrite the code snippet from before to access x and setX directly from the AnIntegerNamedX class:

. . .
AnIntegerNamedX.setX(1);
System.out.println("AnIntegerNamedX.x = "
+ AnIntegerNamedX.x());
. . .

Notice that you no longer have to create myX and anotherX. You can set x and retrieve x directly from the AnIntegerNamedX class. You cannot do this with instance members, you can only invoke instance methods from an object and can only access instance variables from an object. You can access class variables and methods either from an instance of the class or from the class itself.

Initialising instance and class members

You can use static initialisers and instance initialisers to provide initial values for class and instance members when you declare them in a class:

class BedAndBreakfast {
    static final int MAX_CAPACITY = 10;
    boolean full = false;
}

This works well for members of primitive data type. Sometimes, it even works when creating arrays and objects. But this form of initialisation has limitations, as follows:

  • Initialisers can perform only initialisations that can be expressed in an assignment statement.
  • Initialisers cannot call any method that can throw a checked exception.
  • If the initialiser calls a method that throws a runtime exception, then it cannot do error recovery.

If you have some initialisation to perform that cannot be done in an initialiser because of one of these limitations, you have to put the initialisation code elsewhere. To initialise class members, put the initialisation code in a static initialisation block. To initialise instance members, put the initialisation code in a constructor.

Using static initialisation blocks

Here's an example of a static initialisation block:

The errorStrings resource bundle must be initialised in a static initialisation block. This is because error recovery must be performed if the bundle cannot be found. Also, errorStrings is a class member and it doesn't make sense for it to be initialised in a constructor. As the previous example shows, a static initialisation block begins with the static keyword and is a normal block of Java code enclosed in curly braces {}.

A class can have any number of static initialisation blocks that appear anywhere in the class body. The runtime system guarantees that static initialisation blocks and static initialisers are called in the order (left-to-right, top-to-bottom) that they appear in the source code.

Initialising instance members

If you want to initialise an instance variable and cannot do it in the variable declaration for the reasons cited previously, then put the initialisation in the constructor(s) for the class.
Suppose the errorStrings bundle in the previous example is an instance variable rather than a class variable. Then you'd use the following code to initialise it:

import java.util.ResourceBundle;
class Errors {
    ResourceBundle errorStrings;
    Errors() {
        try {
            errorStrings = ResourceBundle.
                            getBundle("ErrorStrings");
        } catch (java.util.MissingResourceException e) {
            // error recovery code here
        }
    }
}

The code that initialises errorStrings is now in a constructor for the class.
Sometimes a class contains many constructors and each constructor allows the caller to provide initial values for different instance variables of the new object. For example, java.awt.Rectangle has these three constructors:

Rectangle(); Rectangle(int width, int height);
Rectangle(int x, int y, int widt
65535 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 0

Posted by jalex on Saturday, October 21, 2006 (21:00:00) (5175 reads)

Java Lecture 11: Numbers and arrays, examples. Teach/learn online

Go to all tips in Java Lectures by Anatoliy Malyarenko

Numbers and arrays

by: Anatoliy Malyarenko

Abstract

Contents of the lecture.

  • Formatting numbers.
  • Creating and using arrays.
  • Arrays of objects.
  • Arrays of arrays.
  • Copying arrays.
  • Summary of arrays.

Formatting numbers


Programs store and operate on numbers in a locale-independent way. Before displaying or printing a number, a program must convert it to a String that is in a locale-sensitive format. For example, in France the number 123456.78 should be formatted as 123456, 78, and in Germany it should appear as 123.456, 78.

You can use the NumberFormat methods to format primitive-type numbers, such as double, and their corresponding wrapper objects, such as Double.

The following code example formats a Double according to Locale. Invoking the getNumberInstance method returns a locale-specific instance of NumberFormat. The format method accepts the Double as an argument and returns the formatted number in a String.

Double amount = new Double(345987.246);

NumberFormat numberFormatter;
String amountOut;

numberFormatter =
    NumberFormat.getNumberInstance(currentLocale);
amountOut = numberFormatter.format(amount);
System.out.println(amountOut + " " +
                                    currentLocale.toString());

The output from this example shows how the format of the same number varies with Locale:

345 987,246 fr_FR
345.987,246 de_DE
345,987.246 en_US

Currencies

If you're writing business applications, you'll probably need to format and to display currencies. You format currencies in the same manner as numbers, except that you call getCurrencyInstance to create a formatter. When you invoke the format method, it returns a String that includes the formatted number and the appropriate currency sign.

This code example shows how to format currency in a locale-specific manner:

Double currency = new Double(9876543.21);

NumberFormat currencyFormatter;
String currencyOut;

currencyFormatter =
        NumberFormat.getCurrencyInstance(currentLocale);
currencyOut = currencyFormatter.format(currency);
System.out.println(currencyOut + " " +
                                currentLocale.toString());

The output generated by the preceding lines of code is as follows:

9 876 543,21 F fr_FR
9.876.543,21 DM de_DE
$9,876,543.21 en_US

At first glance this output may look wrong to you, because the numeric values are all the same. Of course, 9876543, 21 F is not equivalent to 9.876.543, 21 DM. However, bear in mind that the NumberFormat class is unaware of exchange rates. The methods belonging to the NumberFormat class format currencies but do not convert them.

Percentages

You can also use the methods of the NumberFormat class to format percentages. To get the locale-specific formatter, invoke the getPercentInstance method. With this formatter, a decimal fraction such as 0.75 is displayed as 75%.

The following code sample shows how to format a percentage.

Double percent = new Double(0.75);
NumberFormat percentFormatter;
String percentOut;

percentFormatter =
        NumberFormat.getPercentInstance(currentLocale);
percentOut = percentFormatter.format(percent);

Customising formats

You can use the DecimalFormat class to format decimal numbers into locale-specific strings. This class allows you to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. If you want to change formatting symbols, such as the decimal separator, you can use the DecimalFormatSymbols in conjunction with the DecimalFormat class. These classes offer a great deal of flexibility in the formatting of numbers, but they can make your code more complex.

You specify the formatting properties of DecimalFormat with a pattern String. The pattern determines what the formatted number looks like.

The example that follows creates a formatter by passing a pattern String to the DecimalFormat constructor. The format method accepts a double value as an argument and returns the formatted number in a String:

DecimalFormat myFormatter = new DecimalFormat(pattern);

String output = myFormatter.format(value);
System.out.println(value + " " + pattern + " " + output);

The output for the preceding lines of code is described in the following table. The value is the number, a double, that is to be formatted. The pattern is the String that specifies the formatting properties. The output, which is a String, represents the formatted number.

value pattern output
1 2 3
123456.789 ###,###.### 123, 456.789
The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator.
123456.789 ###.## 123456.79
The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up.
123.78 000000.000 000123.780
The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#).
12345.67 $###,###.### $12, 345.67
The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output.
12345.67 \u00A5###,###.### ¥12,345.67
The pattern specifies the currency sign for Japanese yen (¥) with the Unicode value 00A5.

Locale-sensitive formatting

The preceding example created a DecimalFormat object for the default Locale. If you want a DecimalFormat object for a non-default Locale, you instantiate a NumberFormat and then cast it to DecimalFormat. Here's an example:

NumberFormat nf = NumberFormat.getNumberInstance(loc);
DecimalFormat df = (DecimalFormat)nf;
        df.applyPattern(pattern);
String output = df.format(value);
System.out.println(pattern + " "
        + output + " " + loc.toString());

Running the previous code example results in the output that follows. The formatted number, which is in the second column, varies with Locale:
###,###.### 123,456.789 en_US
###,###.### 123.456,789 de_DE
###,###.### 123 456,789 fr_FR

So far the formatting patterns discussed here follow the conventions of U.S. English. For example, in the pattern ###,###.## the comma is the thousands-separator and the period represents the decimal point. This convention is fine, provided that your end users aren't exposed to it. However, some applications, such as spreadsheets and report generators, allow the end users to define their own formatting patterns. For these applications the formatting patterns specified by the end users should use localised notation. In these cases you'll want to invoke the applyLocalizedPattern method on the DecimalFormat object.

Altering the formatting symbols

You can use the DecimalFormatSymbols class to change the symbols that appear in the formatted numbers produced by the format method. These symbols include the decimal separator, the grouping separator, the minus sign, and the percent sign, among others.
The next example demonstrates the DecimalFormatSymbols class by applying a strange format to a number. The unusual format is the result of the calls to the setDecimalSeparator, setGroupingSeparator, and setGroupingSize methods.

DecimalFormatSymbols unusualSymbols =
        new DecimalFormatSymbols(currentLocale);
unusualSymbols.setDecimalSeparator('|');
unusualSymbols.setGroupingSeparator('^');

String strange = "#,##0.###";
DecimalFormat weirdFormatter =
    new DecimalFormat(strange, unusualSymbols);
weirdFormatter.setGroupingSize(4);

String bizarre = weirdFormatter.format(12345.678);
System.out.println(bizarre);

When run, this example prints the number in a bizarre format:

1^2345|678

Summary of numbers

You use an instance of one of the Number classes -- Byte, Double, Float, Integer, Long, and Short -- to contain a number of primitive type. You can also use BigInteger and BigDecimal for arbitrary-precision numbers.

The Number classes include class methods and constants, which are useful in a variety of ways. The MIN VALUE and MAX VALUE constants contain the smallest and largest values that can be contained by an object of that type. The byteValue, shortValue, and similar methods convert one numeric type to another. The valueOf method converts a string to a number, and the toString method converts a number to a string.

To format a number to display to an end user, you use the NumberFormat class in the java.text package. When using NumberFormat, you can get a default format for decimal numbers, percentages, or currency. Or, you can design a custom format using patterns.

The Math class contains a variety of class methods for performing mathematical functions. This class includes the trigonometric functions, such as computing sine, cosine, and so on. Math also includes functions for logarithm calculations, as well as basic arithmetic functions, such as rounding. Finally, Math contains a method, random, for generating random numbers.

Arrays

An array is a structure that holds multiple values of the same type. The length of an array is established when the array is created (at runtime). After creation, an array is a fixed-length structure.

An array element is one of the values within an array and is accessed by its position within the array.

If you want to store data of different types in a single structure, or if you need a structure whose size can change dynamically, use a Collection implementation, such as Vector, instead of an array.

Creating and using arrays

Here's a simple program, called ArrayDemo, that creates the array, puts some values in it, and displays the values.

public class ArrayDemo {
    public static void main(String[] args) {
        int[] anArray; // declare an array of integers

        anArray = new int[10]; // create an array of integers

         // assign a value to each array element and print
        for (int i = 0; i < anArray.length; i++) {
            anArray[i] = i;
            System.out.print(anArray[i] + " ");
        }
        System.out.println();
    }
}

Declaring a variable to refer to an array

This line of code from the sample program declares an array variable:

int[] anArray; // declare an array of integers

Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written type[], where type is the data type of the elements contained within the array, and [] indicates that this is an array. Remember that all of the elements within an array are of the same type. The sample program uses int[], so the array called anArray will be used to hold integer data. Here are declarations for arrays that hold other types of data:

float[] anArrayOfFloats; boolean[] anArrayOfBooleans;

Object[] anArrayOfObjects; String[] anArrayOfStrings;

As with declarations for variables of other types, the declaration for an array variable does not allocate any memory to contain the array elements. The sample program must assign a value to anArray before the name refers to an array.

Creating an array

You create an array explicitly using Java's new operator. The next statement in the sample program allocates an array with enough memory for ten integer elements and assigns the array to the variable anArray declared earlier.

anArray = new int[10]; // create an array of integers

In general, when creating an array, you use the new operator, plus the data type of the array elements, plus the number of elements desired enclosed within square brackets ('[' and ']').

new elementType[arraySize]

If the new statement were omitted from the sample program, the compiler would print an error like the following one and compilation would fail.

ArrayDemo.java:4: Variable anArray may not have been initialized.

Accessing an array element

Now that some memory has been allocated for the array, the program assign values to the array elements:

for (int i = 0; i < anArray.length; i++) {
    anArray[i] = i;
    System.out.print(anArray[i] + " ");
}

This part of the code shows that to reference an array element, either to assign a value to it, or to access the value, you append square brackets to the array name. The value between the square brackets indicates (either with a variable or some other expression) the index of the element to access. Note that in Java, array indices begin at 0 and end at the array length
minus 1.

Getting the size of an array

To get the size of an array, you write

arrayname.length

Be careful: Programmers new to the Java programming language are tempted to follow length with an empty set of parenthesis. This doesn't work because length is not a method. length is a property provided by the Java platform for all arrays.

The for loop in our sample program iterates over each element of anArray, assigning values to its elements. The for loop uses anArray.length to determine when to terminate the loop.

Array initialisers

The Java programming language provides a shortcut syntax for creating and initialising an array. Here's an example of this syntax:

boolean[] answers =
        true, false, true, true, false ;

The length of the array is determined by the number of values provided between { and }.

Arrays of objects

Arrays can hold reference types as well as primitive types. You create such an array in much the same way you create an array with primitive types. Here's a small program, ArrayOfStringsDemo that creates an array containing three string objects then prints the strings in all lower case letters.

public class ArrayOfStringsDemo {
    public static void main(String[] args) {
        String[] anArray = { "String One", "String Two",
                                    "String Three" };
        for (int i = 0; i < anArray.length; i++) {
            System.out.println(anArray[i].toLowerCase());
        }
    }
}

This program creates and populates the array in a single statement. However, you can create an array without putting any elements in it. This brings us to a potential stumbling block, often encountered by new programmers, when using arrays that contain objects. Consider this line of code:

String[] anArray = new String[5];

After this line of code is executed, the array called anArray exists and has enough room to hold 5 string objects. However, the array doesn't contain any strings yet. It is empty. The program must explicitly create strings and put them in the array. This might seem obvious, however, many beginners assume that the previous line of code creates the array and creates 5 empty strings in it. Thus they end up writing code like the following, which generates a NullPointerException:

String[] anArray = new String[5];

for (int i = 0; i < anArray.length; i++) {
    // ERROR: the following line gives a runtime error
    System.out.println(anArray[i].toLowerCase());
}

The problem is more likely to occur when the array is created in a constructor or other initialiser and then used somewhere else in the program.

Arrays of arrays

Arrays can contain arrays. ArrayOfArraysDemo creates an array and uses an initialiser to populate it with four sub-arrays.

public class ArrayOfArraysDemo {
    public static void main(String[] args) {
        String[][] cartoons = {
                { "Flintstones", "Fred", "Wilma", "Pebbles", "Dino" },
                { "Rubbles", "Barney", "Betty", "Bam Bam" },
                { "Jetsons", "George", "Jane", "Elroy", "Judy",
                            "Rosie", "Astro" },
             { "Scooby Doo Gang", "Scooby Doo", "Shaggy", "Velma",
                    "Fred", "Daphne" }
        };
        for (int i = 0; i < cartoons.length; i++) {
            System.out.print(cartoons[i][0] + ": ");
            for (int j = 1; j < cartoons[i].length; j++) {
                System.out.print(cartoons[i][j] + " ");
            }
        System.out.println();
        }
    }
}

Notice that the sub-arrays are all of different lengths. The names of the sub-arrays are cartoons[0], cartoons[1], and so on.

As with arrays of objects, you must explicitly create the sub-arrays within an array. So if you don't use an initialiser, you need to write code like the following, which you can find in ArrayOfArraysDemo2

public class ArrayOfArraysDemo2 {
    public static void main(String[] args) {
        int[][] aMatrix = new int[4][];
        //populate matrix
        for (int i = 0; i < aMatrix.length; i++) {
            aMatrix[i] = new int[5]; //create sub-array
            for (int j = 0; j < aMatrix[i].length; j++) {
                aMatrix[i][j] = i + j;
            }
        }
        //print matrix
        for (int i = 0; i < aMatrix.length; i++) {
            for (int j = 0; j < aMatrix[i].length; j++) {
                System.out.print(aMatrix[i][j] + " ");
            }
            System.out.println();
        }
    }
}

You must specify the length of the primary array when you create the array. You can leave the length of the sub-arrays unspecified until you create them.

Copying arrays

Use System's arraycopy method to efficiently copy data from one array into another. The arraycopy method requires five arguments:

public static void arraycopy(Object source,
                                            int srcIndex,
                                            Object dest,
                                            int destIndex,
                                            int length );

The two Object arguments indicate the array to copy from and the array to copy to. The three integer arguments indicate the starting location in each the source and the destination array, and the number of elements to copy. This diagram illustrates how the copy takes place:

The following program, ArrayCopyDemo, uses arraycopy to copy some elements from the copyFrom array to the copyTo array.

public class ArrayCopyDemo {
    public static void main(String[] args) {
        char[] copyFrom =
                'd', 'e', 'c', 'a', 'f', 'f', 'e',
                'i', 'n', 'a', 't', 'e', 'd' ;
                char[] copyTo = new char[7];
        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
}

The arraycopy method call in this example program begins the copy at element number 2 in the source array. Recall that array indices start at 0, so that the copy begins at the array element 'c'. The arraycopy method call puts the copied elements into the destination array beginning at the first element (element 0) in the destination array copyTo. The copy copies 7 elements: 'c', 'a', 'f', 'f', 'e', 'i', and 'n'. Effectively, the arraycopy method takes the "caffein" out of "decaffeinated", like this:

Note that the destination array must be allocated before you call arraycopy and must be large enough to contain the data being copied.

Summary of arrays

An array is a fixed-length data structure that can contain multiple objects of the same type. An array can contain any type of object, including arrays. To declare an array, you use the type of object that the array can contain and brackets.

The length of the array must be specified when it is created. You can use the new operator to create an array, or you can use an array initialiser. Once created, the size of the array cannot change. To get the length of the array, you use the length attribute.

An element within an array can be accessed by its index. Indices begin at 0 and end at the length of the array minus 1.

To copy an array, use the arraycopy method in the System class.


27899 bytes more | comments? | Printer Friendly Page  Send to a Friend | Score: 0
Posted by jalex on Wednesday, October 18, 2006 (21:00:00) (12077 reads)

Previous 1060 Stories (530 Pages, 2 Per Page) Next

530| 529| 528| 527| 526| 525| 524| 523| 522| 521| 520| 519| 518| 517| 516| 515| 514| 513| 512| 511| 510| 509| 508| 507| 506| 505| 504| 503| 502| 501| 500| 499| 498| 497| 496| 495| 494| 493| 492| 491| 490| 489| 488| 487| 486| 485| 484| 483| 482|
481
| 480| 479| 478| 477| 476| 475| 474| 473| 472| 471| 470| 469| 468| 467| 466| 465| 464| 463| 462| 461| 460| 459| 458| 457| 456| 455| 454| 453| 452| 451| 450| 449| 448| 447| 446| 445| 444| 443| 442| 441| 440| 439| 438| 437| 436| 435| 434| 433| 432| 431| 430| 429| 428| 427| 426| 425| 424| 423| 422| 421| 420| 419| 418| 417| 416| 415| 414| 413| 412| 411| 410| 409| 408| 407| 406| 405| 404| 403| 402| 401| 400| 399| 398| 397| 396| 395| 394| 393| 392| 391| 390| 389| 388| 387| 386| 385| 384| 383| 382| 381| 380| 379| 378| 377| 376| 375| 374| 373| 372| 371| 370| 369| 368| 367| 366| 365| 364| 363| 362| 361| 360| 359| 358| 357| 356| 355| 354| 353| 352| 351| 350| 349| 348| 347| 346| 345| 344| 343| 342| 341| 340| 339| 338| 337| 336| 335| 334| 333| 332| 331| 330| 329| 328| 327| 326| 325| 324| 323| 322| 321| 320| 319| 318| 317| 316| 315| 314| 313| 312| 311| 310| 309| 308| 307| 306| 305| 304| 303| 302| 301| 300| 299| 298| 297| 296| 295| 294| 293| 292| 291| 290| 289| 288| 287| 286| 285| 284| 283| 282| 281| 280| 279| 278| 277| 276| 275| 274| 273| 272| 271| 270| 269| 268| 267| 266| 265| 264| 263| 262| 261| 260| 259| 258| 257| 256| 255| 254| 253| 252| 251| 250| 249| 248| 247| 246| 245| 244| 243| 242| 241| 240| 239| 238| 237| 236| 235| 234| 233| 232| 231| 230| 229| 228| 227| 226| 225| 224| 223| 222| 221| 220| 219| 218| 217| 216| 215| 214| 213| 212| 211| 210| 209| 208| 207| 206| 205| 204| 203| 202| 201| 200| 199| 198| 197| 196| 195| 194| 193| 192| 191| 190| 189| 188| 187| 186| 185| 184| 183| 182| 181| 180| 179| 178| 177| 176| 175| 174| 173| 172| 171| 170| 169| 168| 167| 166| 165| 164| 163| 162| 161| 160| 159| 158| 157| 156| 155| 154| 153| 152| 151| 150| 149| 148| 147| 146| 145| 144| 143| 142| 141| 140| 139| 138| 137| 136| 135| 134| 133| 132| 131| 130| 129| 128| 127| 126| 125| 124| 123| 122| 121| 120| 119| 118| 117| 116| 115| 114| 113| 112| 111| 110| 109| 108| 107| 106| 105| 104| 103| 102| 101| 100| 99| 98| 97| 96| 95| 94| 93| 92| 91| 90| 89| 88| 87| 86| 85| 84| 83| 82| 81| 80| 79| 78| 77| 76| 75| 74| 73| 72| 71| 70| 69| 68| 67| 66| 65| 64| 63| 62| 61| 60| 59| 58| 57| 56| 55| 54| 53| 52| 51| 50| 49| 48| 47| 46| 45| 44| 43| 42| 41| 40| 39| 38| 37| 36| 35| 34| 33| 32| 31| 30| 29| 28| 27| 26| 25| 24| 23| 22| 21| 20| 19| 18| 17| 16| 15| 14| 13| 12| 11| 10| 9| 8| 7| 6| 5| 4| 3| 2| 1|


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy