|
|
|
|
|
|
|
|
|
|
|
|
The best way to develop and maintain a large program is to construct it from small, simple piece, called modules, a technique called divide and conquer. Modules in Java are called methods and classes. Java programs are written by combining new methods and classes the programmer writes with "prepackaged" methods and classes available in the Java API (Java Class Library). The Java API provides a rich collection of classes and methods for performing mathematical calculations, string manipulations, input/output operations, error checking, etc., making the programmer's job easier.
The programmer can write methods to define specific tasks that a programmer may use many times during its execution. The actual statements defining the methods are written only once and may be hidden from other methods. A method is invoked by a method call. When the method completes its task, it returns control to the calling method.
Math Class Methods
Math Class Methods perform mathematical calculations. Methods are called by writing the name of the method with its argument(s) in parentheses. Example, to calculate the square root of 900, Math.sqrt( 900 ). The number 900 is the argument of the method sqrt. Since all Math class methods are static they are invoked by preceding the name of the method by the class name Math and a dot (.) operator. Method arguments may be constants, variables, or expressions. If c = 13, d = 3, and f = 4 then the statement
System.out.println( Math.sqrt(
c + d * f ) ); would yield 5.
|
|
|
|
|
|
|
abs( 0.0 ) = 0.0 abs( -23.7 ) = 23.7 |
|
|
|
ceil( -9.8 ) = -9.0 |
|
|
|
cos( PI/2 ) = 0.0 |
|
|
|
exp( 2.0 ) = 7.389056 |
|
|
|
floor( -9.2 ) = -10.0 |
|
|
|
log( 7.389056 ) = 2.0 |
|
|
|
max( -2.3, -12.7 ) = -2.3 |
|
|
|
min( -2.3, -12.7 ) = -12.7 |
|
|
|
pow( 9.0, 0.5 ) = 3.0 |
|
|
|
sin( PI/2 ) = 1.0 |
|
|
|
sqrt( 2.25 ) = 1.5 |
|
|
|
tan( PI/4 ) = 1.0 |
Programmers may write their own customized methods. The method-name is any valid identifier. The return-value-type is the data type of the result returned from the method to the caller. The return-value-type void indicates that the method does not return a value. Methods can at most return one value. The parameter-list is a comma-separated list in which the method declares each parameter's name and type. There must be one argument in the method call for each parameter in the method definition. Each argument must also be compatible with the type of the corresponding parameter in the method definition. If a method does not receive any values, the parameter list is empty. Each parameter in the parameter list must be declared with a data type; otherwise, a syntax error occurs. Following the first line of the method definition (also known as the method header) declarations and statements in braces form the method body. This is also referred to as a block. Variables can be declared in any block, and blocks can be nested. A method cannot be defined inside another method. If the method does not return a result, control returns when the program flow reaches the method ending right brace or when the statement return; is encountered. If the method returns a result, the statement return expression evaluates the expression and returns the resulting value to the caller. When a return statement is executed, control returns to the statement that invoked the method.
The arguments in the calling method and in the method must be of the
same type. There is a hierarchy for types. Promotion is done
automatically. Arguments can be promoted to "higher" type.
The table below shows allowable promotions.
| Type | Allowed Promotions |
| double | None |
| float | double |
| long | float or double |
| int | long, float, or double |
| char | int, long, float, or double |
| short | int, long, float, or double |
| byte | short, int, long, float, or double |
| boolean | None (boolean values are not considered to be members in Java) |
For example, a program can call Math method sqrt with an integer argument even though the method expects to receive a double argument. The statement
System.out.println( Math.sqrt( 4 ) ); prints the value 2. The method definition's parameter list causes Java to convert the integer value 4 to the double value 4.0 before passing the value to sqrt. The promotion rules specify how to convert types to other types without losing data. Thus, it is possible to convert integer to double. However, converting a double to an int truncates the fractional part of the double value. Converting long to int may also result in changed values. Then the Java compiler requires the programmer to use a cast operator to force the conversion to occur. To invoke a square method, which uses an integer parameter, with the double variable y, the method should be called as square( (int) y ). This extra pair of parentheses explicitly casts (converts) the value of y to an integer. Thus if y's value is 4.5, the answer would be 16 and not 20.25.
The random method of class Math generates a random double value ranging from 0.0 up to, but not including 1.0. The numbers generated are pseudo-random numbers-- a sequence of values produced by complex mathematical calculation, using the current time of the day to seed the random number generator, in a manner that each execution of the program yields a different sequence of random values. These numbers meet the tests of randomness, namely, that each value has the same probability of being selected, and it is not possible to determine the next value. The java statement to generate random numbers is: double randomValue = Math.random();
The range of numbers generated is different from the range required in Java applications. A program that simulates coin tossing requires 0 for "heads" and 1 for "tails." A roll of a six-sided die would require integers from 1 to 6. This can be attained by multiplication (scaling) and shifting. The statement would be:
1 + (int) ( Math.random() * 6 ). If 0 is generated 0 * 6 is 0 + 1 = 1. If 0.9999 is generated, 0.9999 * 6 is 5.9994. Its integer value is 5. 5 1 = 6. Other values will be similarly generated.
For more information: Random Number Generators and More Random Number Generators
Identifiers are used as variable and reference names. The attributes of variables and references include name, type, size and value. In addition, identifiers may also be used as as names for user-defined methods and classes, with other attributes like duration and scope. An attributes duration (or lifetime) is the period during which the identifier exists in memory, either for brief periods, or for the entire execution of a program. Identifiers that represent local variables in a method (e.g.., parameters and variables declared in the body of the method) have automatic duration, created when program control reaches their declaration, exist when the block they are declared in is active, and destroyed when that block is exited.
The instance variables of a class are initialized automatically by the compiler if the programmer does not provide explicit initial values. Variables of primitive data type are initialized to zero, boolean variables to false, references to null. However, automatic variables must be initialized by the programmer before they can be used.
Java also has identifiers of static duration which exist from the point at which the class that defines them is loaded into memory for execution until the program terminates. Their storage is allocated and initialized when their classes are loaded intro memory. But these identifiers cannot necessarily be used throughout the program.
An identifier's scope defines where the identifier can be referenced in a program, throughout the program, or from limited portions. A local variable or reference declared in a block can be use only in that block or in blocks nested within that block. The scopes for an identifier are class scope and block scope. There is also a special scope for labels used with the break and continue statements in Control structures. A label is visible only in the body of the repetition structure that immediately follows the label.
Methods and instance variables of a class have class scope, beginning at the opening left brace, {, of the class definition and ending at the closing right brace, }. Class scopes enables methods of a class to invoke directly all methods defined in that same class or inherited into that class and to access directly all instance variables defined in the class. Identifiers defied inside a block have block scope, beginning at the identifier's declaration and ending at the right brace, }. Local variables of a method and method parameters have block scope. Any block may contain variables or reference declarations. When blocks are nested in a method's body and an identifier declared in an outer block has the same name as an identifier declared in an inner block, the compiler generates a syntax error stating that a variable is already defined. If a local variable in a method has the same name as an instance variable, the instance variable is "hidden" until the block terminates execution.
A recursive method calls itself either directly or indirectly through another method. A recursive method is called to solve a problem. The method knows how to solve the simplest case (base case). If the method is called with a base case, it returns a result. If the method s called with a more complex problem, the method divides the problem into to conceptual pieces; a piece that the method knows how to do (the base case) and a piece that the method does not know how to do. The latter piece resembles but is slightly simpler or smaller than the original problem. The method invokes a fresh copy of itself to work on the smaller problem. This procedure is referred to as a recursive call or recursion step. This includes the keyword return as the result will be combined with the portion the method knows how to solve to form a result that will be passed back to the original caller. The recursion step can result in many recursion calls, as the method divides each new subproblem into two conceptual pieces. The sequence of smaller and smaller problems must converge on the base case. A result is returned to the previous copy of the method, and a sequence of returns ensues up the line until the original method call returns the final result to the caller.
An example of recursion is the factorial of a number.
5! = 5 * 4! = 5 * 4 * 3! = 5 * 4 * 3 * 2! = 5 * 4 * 3 * 2 * 1!.
The method knows that 1! is 1. It can then calculate 2!, then 3!,
then 4! and finally 5!.
Another example is the Fibonacci Series, in which each succeeding number is the sum of the two previous numbers.
Recursion compared to Iteration.
Both iteration and recursion are based on a control structure: Iteration uses a repetition structure (such as for, while, or do/while); recursion uses a selection structure (such as if, if/else, or switch). Both involve repetition: Iteration explicitly uses a repetition structure; recursion achieves repetition through repeated method calls. Both require a termination test: Iteration terminates when the loop-continuation condition fails; recursion terminates when a base case is recognized. Both gradually approach termination. Iteration keeps modifying the counter until the counter assumes a value that makes the loop-continuation condition fail; recursion keeps producing smaller versions of the original problem until the base case is attained. Both can occur infinitely: in the case of iteration if the loop-continuation test never becomes false; in recursion if the recursion step does not reduce the problem that could enable it to converge to the base case.
The problems with recursion are:
1. It repeatedly invokes the mechanism and consequently
the overhead of method calls, which is expensive in processor time and
memory.
2. Each recursive call causes another copy of the
method's variables to be created; this set of copies can consume considerable
memory space
For more information about recursion: Recursion Theory
Java enables several methods of the same name to be defined, as long as the methods have different sets of parameters (based on the number, types, and the order). When an overloaded method is called, the Java compiler selects the proper method by examining the number, types, and order of the arguments in the call. They are used to create several methods with the same name that perform similar tasks, but on different data types.
|
|
|
|
|
|
|
Accessible by any class in the same package as its class |
|
|
|
Accessible anywhere |
|
|
|
Accessible by any class in the same package as its class |
|
|
|
Not accessible by any other class |