Rich is a great teacher. He listened and understood. If your job is moving towards Basecamp then take this class....More Testimonials »

Java Basics

In this lesson, you will learn about basic syntax, data types, and various writing methods.

Lesson Goals

  • Understand Java's basic syntax rules, including statements, blocks, and comments.
  • Declare variables and construct statements using variables and literal (constant) values.
  • Become familiar with the primitive data types, as well as the String class.
  • Understand many of Java's operators and the concept of operator precedence.
  • Understand the rules that apply when data is converted from one type to another.
  • Declare, write, and use simple methods.

Basic Java Syntax

General Syntax Rules

Java is case-sensitive. main(), Main(), and MAIN() would all be different methods.

There are a limited number of reserved words that have a special meaning within Java. You cannot use these words for your own variables or methods.

Some examples of reserved words are:

  • public
  • void
  • static
  • do
  • for
  • while
  • if

Most keyboard symbol characters (the set of characters other than alphabetic or numeric) have a special meaning.

Names may contain alphabetic characters, numeric characters, currency characters, and connecting characters such as the underscore ( _ ) character:

  • Names may not begin with a numeric character.
  • Note that the set of legal characters draws from the entire Unicode character set.
  • Also note that it is probably impossible to write a succinct set of rules about what are valid characters, other than to say a character, that when passed to Character.isJavaIdentifierPart(char ch), results in a true value.

The compiler parses your code by separating it into individual entities called tokens or symbols in computer science jargon:

  • Names (of classes, variables, and methods).
  • Command keywords.
  • Single or compound symbols (compound symbols are when an operation is signified by a two-symbol combination).

Tokens may be separated by spaces, tabs, carriage returns, or by use of an operator (such as +, -, etc.).

Since names may not contain spaces, tabs, carriage returns, or operator characters, these characters imply a separation of what came before them from what comes after them.

Extra whitespace is ignored. Once the compiler knows that two items are separate, it ignores any additional separating whitespace characters (spaces, tabs, or carriage returns).

Java Statements

  • A Java statement is one step of code, which may span across multiple lines.
  • Java statements end with a semicolon (the ; character).
  • It is OK to have multiple statements on a single line.
  • Program execution is done statement by statement, one statement at a time from top to bottom (if there is more than one statement on a line, execution goes from left to right).
  • Within a statement, execution of the individual pieces is not necessarily left to right. There are concepts called operator precedence and associativity that determine the order of operations within a statement.

Blocks of Code

A block of code:

  • Is enclosed in curly braces - start with { and end with }.
  • Consists of zero, one, or more statements.
  • Behaves like a single statement to the outside world..
  • May be nested (e.g., it may contain one or more other blocks of code inside).
  • Generally belong to whatever comes before it. Although it is perfectly OK to create a block that does not, this is almost never done.

A complete method is a single block of code, most likely with nested blocks.

The diagram below illustrates how blocks of code can be nested: Nested blocks example

If you want, go ahead and modify your Hello World program to match this example.

Comments

A comment:

  • Is additional, non-executable text in a program used to document code.
  • May also be used to temporarily disable a section of code (for debugging).

Block Comments

Block comments are preceded by /* and followed by */.

Some rules for block comments:

  • May not be nested.
  • May be one or more lines.
    /* this is a block comment
    * asterisk on this line not necessary, but looks nice
    */
  • May span part of a line, for example, to temporarily disable part of a statement:
    x = 3 /* + y */ ;

Single-line Comments

A single line can be commented by preceding the comment with two forward slashes: //. Note that:

  • The comment ends at the end of that line.
  • Single-line comments may be nested inside block comments.
    y = 7;
    /*
    * temporarily disable this line
    * which has a comment to end of line
    x = 3 + y; // add 3 for some reason
    */

Java specifies a third type of comment, the javadoc comment:

  • Java contains a self-documentation utility, javadoc, which builds documentation from comments within the code.
  • javadoc comments begin with /** and end with */.
  • Comments only work as javadoc comments when placed at specific locations in your code (immediately above anything documentable - the class itself and its members), otherwise they are treated as ordinary comments.
    /**
    * Represents a person, with a first name and last name.
    */
    public class Person {
    	/** The person's first name */
    	public String firstName;
    	/** The person's last name */
    	public String lastName;
    }

Variables

Variables store data that your code can use.

There are two fundamental categories of variables, primitive data and references:

  • With primitive data, the compiler names a memory location and uses itto store the actual data - numeric values such as integers, floating point values, and the code values of single individual text characters are stored as primitives.
  • With references, the data is accessed indirectly - the compiler selects a memory location, associates it with the variable name, and stores in it a value that is effectively the memory address of the actual data - in Java, all objects and arrays are stored using references.

In the diagram below, the boxes are areas in memory:

Object storage and reference variable

Declaring Variables

Variables must be declared before they are used.

A declaration informs the compiler that you wish to:

  • Create an identifier that will be accepted by the compiler within a section of code (exactly what that section is depends on how and where the variable is declared; that is the concept of scope, which will be addressed later).
  • Associate that identifier with a specified type of data, and enforce restrictions related to that in the remainder of your code.
  • Create a memory location for the specified type of data.
  • Associate the identifier with that memory location.

Java uses many specific data types; each has different properties in terms of size required and handling by the compiler:

  • The declaration specifies the name and datatype.
  • Generally the declaration also defines the variable, meaning that it causes the compiler to allocate storage space in memory of the requested type's size.
  • A declaration may also assign an initial value (to initialize the variable).
  • Multiple variables of the same type can be declared in a comma-separated list.
Code
Effect
int a;

declares the name a to exist, and allocates a memory location to hold a 32-bit integer

int a = 0;

same as above, and also assigns an initial value of 0

int a = 0, b, c = 3;

declares three integer variables and initializes two of them

Note that different languages have different rules regarding variables that have not been initialized:

  • Some languages just let the value be whatever happened to be in that memory location already (from some previous operation).
  • Some languages initialize automatically to 0.
  • Some languages will produce a compiler or runtime error.
  • Java uses both of the last two: local variables within methods must be initialized before attempting to use their value, while variables that are fields within objects are automatically set to zero.

Advanced Declarations

Local variables, fields, methods, and classes may be given additional modifiers; keywords that determine special characteristics.

Any modifiers must appear first in any declaration, but multiple modifiers may appear in any order.

Keyword
Usage
Comments
final local variables, fields, methods, classes

The name refers to a fixed item that cannot be changed.

For a variable, that means that the value cannot be changed.

For a method, the method cannot be overridden when extending the class.

A final field does not, however, have to be initialized immediately; the initial assignment may be done once during an object's construction.

static fields, methods, inner classes

Only for fields and methods of objects.

One copy of the element exists regardless of how many instances are created.

The element is created when the class is loaded.

transient fields

The value of this element will not be saved with this object when serialization is used (for example, to save a binary object to a file, or send one across a network connection).

volatile fields

The value of this element may change due to outside influences (other threads), so the compiler should not perform any caching optimizations.

public, protected, private fields, methods classes

Specifies the level of access from other classes to this element - covered in depth later.

abstract methods, classes

Specifies that a method is required for a concrete extension of this class, but that the method will not be created at this level of inheritance - the class must be extended to realize the method.

For a class, specifies that the class itself may not be instantiated; only an extending class that is not abstract may be instantiated (a class must be abstract if one or more of it's methods are abstract) - covered in depth later

native methods

The method is realized in native code (as opposed to Java code) - there is an external tool in the JDK for mapping functions from a DLL to these methods.

strictfp methods, classes

For a method, it should perform all calculations in strict floating point (some processors have the ability to perform floating point more accurately by storing intermediate results in a larger number of bits than the final result will have; while more accurate, this means that the results might differ across platforms).

For a class, this means that all methods are strictfp.

synchronized methods, code blocks

No synchronized code may be accessed from multiple threads for the same object instance at the same time.

Data

Primitive Data Types

  • The primitive data types store single values at some memory location that the compiler selects and maps to the variable name you declared .
  • Primitive values are not objects - they do not have fields or methods.
  • A primitive value is stored at the named location, while an object is accessed using a reference.
  • An object reference variable does not store the object's data directly - it stores a reference to the block of data, which is somewhere else in memory (technically, the reference stores the memory address of the object, but you never get to see or use the address).
Primitives Data Types
Primitive Type
Storage Size
Comments
boolean 1 bit not usable mathematically, but can be used with logical and bitwise operators
char 16 bits unsigned, not usable for math without converting to int
byte 8 bits signed
short 16 bits signed
int 32 bits signed
long 64 bits signed
float 32 bits signed
double 64 bits signed
void None not really a primitive, but worth including here

Object Data Types

Objects can be data, which can be stored in variables, passed to methods, or returned from methods.

References

As we will see later, objects are stored differently than primitives. An object variable stores a reference to the object (the object is located at some other memory location, and the reference is something like a memory address).

Text Strings

A sequence of text, such as a name, an error message, etc., is known as a string.

In Java, the String class is used to hold a sequence of text characters.

A String object:

  • Is accessed through a reference, since it is an object.
  • Has a number of useful methods, for case-sensitive or case-insensitive comparisons, obtaining substrings, determining the number of characters, converting to upper or lower case, etc.
  • Is immutable; that is, once created it cannot be changed (but you can make your variable reference a different String object at any time).

Literal Values

A value typed into your code is called a literal value.

The compiler makes certain assumptions about literals:

  • true and false are literal boolean values.
  • null is a literal reference to nothing (for objects).
  • A numeric value with no decimal places becomes an int, unless it is immediately assigned into a variable of a smaller type and falls within the valid range for that type.
  • A value with decimal places becomes a double.
  • To store a text character, you can put apostrophes around the character.
Code
Effect
char e = 'X'; Creates a 16-bit variable to hold the Unicode value for the uppercase X character.

You can add modifiers to values to instruct the compiler what type of value to create (note that all the modifiers described below can use either uppercase or lowercase letters).

Modifying prefixes enable you to use a different number base:

Prefix
Effect
0X or 0x A base 16 value; the extra digits can be either uppercase or lowercase, as in char c = 0x1b;
0 A base 8 value, as in int i = 0765;
  • Note: using these prefixes will always result in number that is considered positive (so that 0x7F for a byte would be OK, but 0x80 would not, since the latter would have a value of 128, outside the range of byte).
  • Also note that a long value would need the L modifier as discussed below.

Modifying suffixes create a value of a different type than the default:

Suffix
Effect
L or l a long value (uses 64 bits of storage), as in long l = 1234567890123456L;
Note: An int value will always implicitly be promoted to a long when required, but the reverse is not true; the above notation is necessary because the literal value is larger than 32 bits
F or f A float value, as in float f = 3.7F;

Escape Sequences for Character Values

There are a number of escape sequences that are used for special characters:

Escape Sequence
Resulting Character
\b Backspace
\f Form feed
\n Linefeed character - note that it produces exactly one character, Unicode 10 (\u000A in hex)
\r Carriage return
\t Tab
\" Quote mark
\' Apostrophe
\\ Backslash
\uNNNN Unicode value, where N is a base 16 digit from 0 through F; valid values are \u0000 through \uFFFF
\NNN Value expressed in octal; ranging from \000 to \377

The escape sequences can either be used for single characters or within strings of text:

char c = '\u1234';
System.out.println("\t\tHello\n\t\tWorld");

Constants and the final Keyword

Java has a means for defining contants, which are like variables in that they have names, but are not changeable once set.

If a variable is declared as final, it cannot be changed:

  • Even though the variable's value is not changeable once a value has been established, you are allowed to set a unique value once.
  • Local variables within methods may be declared as final.
  • Constants' values may be set in an explicit initialization, in a separate line of code, or, as method parameters passed when the method is called.
  • Fields within a class may be declared as final.
  • Contants' values may be set in an explicit initialization, in a separate line of code within an initialization block, or in a constructor.

Fields of a class may be declared as public static final - that way they are available to other classes, but cannot be changed by those other classes. An example is Math.PI.

Classes and methods may also be marked as final. We will cover this later.

Code Sample:

Java-Basics/Demos/FinalValues.java
public class FinalValues {

  // a constant
  final int scale = 100;
  
  // value below is dynamically created, 
  // but cannot change afterward
  final int answer = (int)(Math.random() * scale);
  
  public static void main(String[] args) {
    FinalValues fv = new FinalValues();
    System.out.println(fv.answer);
    
    // line below would not compile:
    // fv.answer = 44;
  }
}

The class has two final fields, scale and answer. The scale is fixed at 100, while the answer is initialized dynamically, but, once established, the value cannot be changed. Try removing the comment from the line that attempts to set it to 44, and you will see the compiler error message that results.

Mathematics in Java

Looks and behaves like algebra, using variable names and math symbols:

int a, b, c, temp;
a = b/c + temp;
b = c * (a - b);

Basic Rules

  • What goes on the left of the = sign is called an lvalue. Only things that can accept a value can be an lvalue (usually this means a variable name - you can't have a calculation like a + b in front of the equal sign).
  • Math symbols are known as operators; they include:
    Operator Purpose (Operation Performed)
    + for addition
    - for subtraction
    * for multiplication
    / for division
    % for modulus (remainder after division)
    ( and ) for enclosing a calculation
  • Note that integer division results in an integer - any remainder is discarded.

Expressions

An expression is anything that can be evaluated to produce a value. Every expression yields a value.

Examples (note that the first few of these are not complete statements):

Two simple expressions:

a + 5
5/c

An expression that contains another expression inside, the (5/c) part:

b + (5/c)

A statement is an expression; this one that contains another expression inside - the b + (5/c) part, which itself contains an expression inside it (the 5/c part):

a = b + (5/c);

Since an assignment statement (using the = sign) is an expression, it also yields a value (the value stored is considered the result of the expression), which allows things like this:

d = a = b + (5/c);
  • The value stored in a is the value of the expression b + (5/c).
  • Since an assignment expression's value is the value that was assigned, the same value is then stored in d.
  • The order of processing is as follows:
    1. Retrieve the value of b.
    2. Retrieve the 5 stored somewhere in memory by the compiler.
    3. Retrieve the value of c.
    4. perform 5 / c
    5. Add the held value of b to the result of the above step.
    6. Store that value into the memory location for a.
    7. Store that same value into the memory location for d.

Here is a moderately complicated expression; let's say that a, b, and c are all double variables, and that a is 5.0, b is 10.0, and c is 20.0:

d = a + b * Math.sqrt(c + 5);
  1. Since the c + 5 is in parentheses, the compiler creates code to evaluate that first, but to perform the c + 5 operation, both elements must be the same type of data, so the thing the compiler creates is a conversion for the 5 to 5.0 as a double.
    d = a + b * Math.sqrt(c + 5.0);
  2. Then the compiler creates code to evaluate 20.0 + 5.0 (at runtime it would become 25.0), reducing the expression to:
    d = a + b * Math.sqrt(25.0);
  3. Next, the compiler adds code to call the Math.sqrt method to evaluate its result, which will be 5.0, so the expression reduces to:
    d = a + b * 5.0;
  4. Note that the evaluated result of a method is known as the return value, or value returned.
  5. Multiplication gets done before addition, the compiler creates that code next, to reduce the expression to:
    d = a + 50.0;
  6. Then the code will perform the addition, yielding:
    d = 55.0;
  7. And finally, the assignment is performed so that 55.0 is stored in d.

As implied by the examples we have seen so far, the order of evaluation of a complex expression is not necessarily from left to right. There is a concept called operator precedence that defines the order of operations.

Operator Precedence

Operator precedence specifies the order of evaluation of an expression.

Every language has a "table of operator precedence" that is fairly long and complex, but most languages follow the same general rules:

  • Anything in parentheses gets evaluated before what is outside the parentheses.
  • Multiply or divide get done before add and subtract.

Example

  • In the expression a = b + 5/c, the 5/c gets calculated first, then the result is added to b, then the overall result is stored in a.
  • The equal sign (=) is an operator; where on the table do you think it is located?

The basic rule programmers follow is: when in doubt about the order of precedence, use parentheses.

Try the following program:

Code Sample:

Java-Basics/Demos/ExpressionExample.java
public class ExpressionExample {
  public static void main(String[] args) {
    double a = 5.0, b = 10.0, c = 20.0;
    System.out.println("a+b is " + (a + b));
    System.out.println("a+b/c is " + (a + b  / c));
    System.out.println("a*b+c is " + (a * b + c));
    System.out.println("b/a+c/a is " + (b / a + c / a));
  }
}

Multiple Assignments

Every expression has a value. For an assignment expression, the value assigned is the expression's overall value. This enables chaining of assignments:

x = y = z + 1; is the same as y = z + 1; x = y;

i = (j = k + 1)/2; is the same as j = k + 1; i = j/2;

Quite often, you may need to calculate a value involved in a test, but also store the value for later use:

double x;
if ( (x = Math.random()) < 0.5 ) {
	System.out.println(x);
}

You might wonder why not just generate the random number when we declare x? In this case, that would make sense, but in a loop the approach shown above might be easier such that:

  • generates the random number and stores it in x.
  • as an expression, that results in the same value, which is then tested for less than 0.5, and the loop body executes if that is true.
  • the value of x is then available within the block.
  • after the loop body executes, another random number is generated as the process repeats.

It is usually not necessary to code this way, but you will see it often.

Order of Evaluation

The order of operand evaluation is always left to right, regardless of the precedence of the operators involved.

Code Sample:

Java-Basics/Demos/EvaluationOrder.java
public class EvaluationOrder {
  public static int getA() {
    System.out.println("getA is 2");
    return 2;
  }
  public static int getB() {
    System.out.println("getB is 3");
    return 3;
  }
  public static int getC() {
    System.out.println("getC is 4");
    return 4;
  }
  public static void main(String[] args) {
    int x = getA() + getB() * getC();
    System.out.println("x = " + x);
  }
}

The operands are first evaluated in left to right order, so that the functions are called in the order getA(), then getB(), and, lastly, getC()

But, the returned values are combined together by multiplying the results of getB() and getC(), and then adding the result from getA()

Bitwise Operators

Java has a number of operators for working with the individual bits within a value.

Operator
Description
Example
Effect
Bit Pattern
& Bitwise AND, combines individual bits with an AND operation, so that in the resulting value, a bit position is only 1 if that position had a 1 for both operands.
int a = 2; has the 2 bit set 0...00000010
int b = 6; has the 2 and 4 bits set 0...00000110
int c = a & b; results in 2 0...00000010
| Bitwise OR, combines individual bits with an OR operation, so that in the resulting value, a bit position is 1 if that position had a 1 for either operand.
int a = 2; has the 2 bit set 0...00000010
int b = 4; has the 4 bit set 0...00000100
int c = a | b; results in 6 0...00000110
^ Bitwise exclusive OR (XOR), combines individual bits so that any position that is the same in both operands yields a 0, any bits that differ yield a 1 in that position; this is often used in encryption, since repeating the operation on the result yields the original value again
int a = 3; has the 1 and 2 bits set 0...00000011
int b = 6; has the 2 and 4 bits set 0...00000110
int c = a ^ b; results in 5 0...00000101
int d = c ^ b; results in 3 again 0...00000011
~ Bitwise complement. Reverses the state of all bits.
int a = 0; has no bits set 0...00000000
int b = ~a; has all bits set 1...11111111

Bitwise Shift Operators

These operators shift the bits left or right within a 32-bit int value (they do not work with any other type).

Operator Description
Example Effect Bit Pattern
<< left shift the bits by the second operand
int a = 4; has the 4 bit set 0...00000010
int b = a << 2; now has the 16 bit set 0...00001000
>> right shift the bits by the second operand with sign-extension (if the first bit is a 1, new bits introduced to fill in on the left come in as 1 bits)
int a = -126; has all bits except the rightmost set to 1 10...0000010
int b = a >> 1; now has all bits set to 1 (the 0 rolled off the right end, and a 1 was added on the left to match the original leftmost bit; the resulting value is 63) 110...000001
>>> right shift the bits by the second operand without sign-extension (bits added on the left always come in as 0)
int a = -1; has all bits set to 1 11...1111111
int b = a >>> 31; now has all bits set to 0 except the rightmost (all bits except the first rolled off the right end, and 0's were added on the left 0000000...01

Compound Operators

Combine multiple effects in one operation: calculation and storage into memory

Operator
Purpose (Operation Performed)
++ increment a variable
-- decrement a variable; note that ++ and -- can precede or follow a variable
if preceding (called prefix), apply the operator and then use the resulting value
if following (called postfix), retrieve the value of the variable first, use it as the result of the expression, and then apply the operator
+= add an amount to a variable
-= subtract an amount from a variable
*= multiply a variable by an amount
/= divide a variable by an amount
%= set variable equal to remainder after division by an amount
&= perform bitwise AND between left and right, store result into left operand
|= perform bitwise OR between left and right, store result into left operand
^= perform bitwise XOR between left and right, store result into left operand
>>= shift the variable's bits to the right by an amount with sign-extension
>>>= shift the variable's bits to the right by an amount without sign-extension
<<= shift the variable's bits to the left by an amount

Compound Operator Examples

Statement
Result
i++; increment i
i--; decrement i
j = i++; retrieve current value of i, hold it as the result of the expression, assign its value to j, then increment i
j = ++i; increment i, then j = i;
x *= 3; x = x * 3;
y -= z + 5; y = y - (z + 5);

It is inevitable that a certification exam will ask a question that requires understanding the steps involved in a postfix increment or decrement: try the following program:

Code Sample:

Java-Basics/Demos/IncrementTest.java
public class IncrementTest {
  public static void main(String[] args) {
    int i = 0, j;
    
    i = i++;
    System.out.println("i = " + i);
    
    j = i++ + i;
    System.out.println("i = " + i + ", j = " + j);
  }
}
  • In the first statement, i = i++;, the original value of i (0) is retrieved and held. Then, i is incremented. But, after that, the held value of 0 is put back into i, overwriting the 1!
  • In the second part, j = i++ + i;, the operands are evaluated from left to right, but each operand is fully evaluated before proceeding to the next. Which means that the increment part of i++ has taken effect before the second appearance of i in the equation, so that the expression reduces to 0 + 1 (recall that the previous operation resulted in i being 0).

Expressions that Mix Data Types: Typecasting

Expressions will often mix different types of data, for example:

double x = 15.6 / 4;
double y = 12.2 + 15 / 4;

The compiler must choose a specific type of data (either integer or floating-point, and the specific size) for each individual expression it evaluates within a statement.

  • In general, the processor will choose the larger or more complex unit to work with.
  • In the first case the value 4 will be promoted to a double, which will then be used in the division.
  • The conversion is done one expression at a time within a statement; so, in the second example, the division will be performed with integer math, resulting in a value of 3, which will then be promoted to a double to finish the statement.

The process of changing the data type of a value is known a typecasting (or casting):

  • A wideningcast converts a smaller or less precise value into a larger or more precise type - this is done automatically (the compiler does an implicitcast, as above).
  • A narrowing cast converts a larger or more precise value into a smaller or less precise type (such as from double to int) - this must be coded with an explicit cast.
  • To code an explicit typecast, put the desired type in parentheses in front of the expression to be converted; for example:
    int a = (int) (15.6 / 4);
  • The division will be evaluated as before, meaning the 4 is promoted to a double, and the result is a double, but a double can't be stored in a, so the cast to int is necessary.
  • Note that casting is an operation, therefore it has a precedence (which is fairly high on the operator precedence table).

The allowable sequence of implicit casts is shown below: Integral promotion sequence

Small Integral Types and Expressions

One aspect of Java that is important to understand is the result of expressions involving the small integral types: byte, char, and short any expression involving these types, other than the compound assignment expressions, is done with int values, so that the result will always be an int.

Try the following (it is the same as the earlier postfix increment example, using byte instead of int):

byte i = 0, j = 6, k;
i++;
k = i + j;
System.out.println("i = " + i + ", j = " + j);

Note that the increment expression is accepted by the compiler; it is the simple addition in the third line that causes an error.

The Java Language Specification states the promotion rules as follows (note that this concept does not apply to all operators; again, the operators that include assignment do not use it):

When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value of a numeric type, the following rules apply, in order, using widening conversions to convert operands as necessary:

  • If either operand is of type double, the other is converted to double.
  • Otherwise, if either operand is of type float, the other is converted to float.
  • Otherwise, if either operand is of type long, the other is converted to long.
  • Otherwise, both operands are converted to type int.

Creating and Using Methods

The method is the basic complete unit of code to perform one task within an object:

  • In procedural languages, these are called functions, but in OOP they are usually called methods.
  • Almost all executable code is in some method.
  • Technically, there is one other place an object-oriented program could have executable code, but that is an advanced topic.
  • Examples: calculate a trigonometry function like cosine, print data on the screen, read from a file, open a window.
  • Methods are defined by a name followed by parentheses.
  • Inputs to the method go inside the parentheses; they are called parameters or arguments to the method.

Using a method in your code, causing it to run, is known as calling the method.

A method call is an expression, so it may result in a value (the method call is evaluated like any other expression).

  • this value is called the return value, and the method is said to return a value.
  • the following is an example of a method used as an expression within a larger expression:
z = Math.sin(Math.PI / Math.sqrt(x));

Methods must be called with arguments that matching their specified form, known as the function signature:

  • the signature is the combination of the name of the method with the pattern of its parameters.
  • the documentation for library-supplied methods will tell you the signature for those methods.
  • when you call a method, the name of the method and the parameters you pass to it will determine which method will be called, based on the available signatures.
  • for each argument, Java expects a value - which could be a literal value, a variable, or expression; it must be either the correct type or a value that can be implicitly typecast to the correct type.

All methods in Java must be defined within a class definition. They have complete access to all other elements of the class (fields and other methods, regardless of the access modifier used for that element).

Code Sample:

Java-Basics/Demos/UseMethodsExample.java
public class UseMethodsExample {
  public static void main(String[] args) {
    int x = 16;
    double y = Math.sqrt(x);
    System.out.println("Square root of " + x + " is " + y);

    double z = Math.sin(Math.PI / 2);
    System.out.println("Sine of pi/2 is " + z);
  }
}

This class calls two methods from the Math class: sqrt and sin, both of which expect one parameter which is a double.

When we call sqrt and pass an integer, the compiler converts that to a double to provide the type of data that sqrt expects

Note that even if your program does not call any methods, it has one method that will be called: main(). Things to note:

  • The definition of main() is that it provides a start point and end point for your program.
  • Program execution starts with the first statement in main().
  • If the last statement in main() is executed, the program ends.
  • The main() does have arguments (any other words typed on the command line).

Creating Methods

There are three things you need to decide for any method:

  1. what it does.
  2. what inputs it needs.
  3. what answer it gives back.
[modifiers] dataType methodName(parameterList) {
	methodBody
	return result;
}
  • modifiers include the accessibility of this method from outside the class (public, private, protected, or left blank) as well as other possibilities listed earlier in this section.
  • dataType is a type of data, like int.
  • methodName is the name of your method.
  • parameterList is a comma-separated list of parameters; each parameter is listed with its data type first, then its name.
  • methodBody is the set of statements that perform the task of the method.
  • return is a keyword that says to use the result expression value as the result of calling the method, and send that value back to the code that called the method (as an expression, a call to a method evaluates to the returned value; i.e., calling Math.sqrt(4) evaluates to the value that sqrt returned).
  • if a method declares that it returns a value of a certain type, then it must explicitly return a value of that type.

Method Examples

public void sayHello() {
	System.out.println("Hello");
}
  • public methods are accessible to any other class.
  • void is a keyword for a returned data type that means no data at all - this method does not calculate a result.
  • The name of the method is sayHello.
  • This method could be called as follows:
Code When Used
sayHello(); from within the class
x.sayHello(); from outside the class, for an instance x of this class
public void showNumber(int number) {
 System.out.println("The number is: " + number);
}
  • again, this method does not calculate a result.
  • this method could be called as follows:
Code When Used
showNumber(5); from within the class
x.showNumber(5); from outside the class, for an instance x of this class
>public int calculateSum(int num1, int num2) {
 int answer = num1 + num2;
 return answer;
}
  • This method does calculate a result; the data type it calculates is int.
  • This method must be given two parameters, both of which are int data types.
  • This method could be called as follows:
Code When Used
int value = calculateSum(4, 6); from within the class
int value = x.calculateSum(4, 6); from outside the class, for an instance x of this class

Return Values

Note that the listing of a data type word in front of a name is something we have seen before, in declaring variables. The purpose is the same - to state what type of data this element provides when used in an expression.

The first statement below states that the value of a is an int, so that the compiler knows what memory size to allocate and what type of processing to use with it when it evaluates the second statement.

int a;
int b = a / 2;

The effect is no different using a method; recall the function signature (the first line) of our calculateSum method:

public int calculateSum(int num1, int num2)

It states that the result of evaluating calculateSum is an int, so that the compiler knows what memory size to allocate for the result, and what type of processing to use with it when it evaluates a statement like:

int b = calculateSum(4, 6) / 2;

When this statement gets processed, the calculateSum method will run and return its result (which will be the value 10 as an int).

Thus the statement in effect is reduced to:

int b = 10 / 2;

Method Parameters

Method parameters are also declarations. They declare a type of data received by the method, and also provide a name for each value so it can be used within the method.

Back to our method:

public int calculateSum(int num1, int num2) {
 int answer = num1 + num2;
 return answer;
}
  • The parameter list declares two variables that will exist in this method: num1 and num2.
  • The order is important - num1 will be the first value given to the method, num2 will be the second.
  • The difference between method parameter declarations and the variable declarations we saw before is that the method parameters receive their values when the method is called.

Variable Scope

The variable scope rules are similar to those in C++.

Variables can be declared at any point in your code, not just at the top of a block:

  • Local variables (those within methods) are not visible to any code that precedes the declaration.
  • Object elements are visible to any code within the object, regardless of the order of declaration.

Variables declared within a set of curly braces cease to exist after the closing brace has been reached (it is said that they go out of scope); therefore, local variables exist only within that method.

Variables can be declared in the control portion of a for loop, and will exist for the duration of the loop

Parameters to a method are local variables within that method

It is legal to use the same variable name in different scopes, as long as the two scopes have no irresolvable conflicts. Some explanation:

  • Non-overlapping scopes. For example, two different methods could each have a local variable called firstName.
  • Overlapping scopes. It is valid for a method to have a variable whose name conflicts with a property name for that class - in that case, the local variable hides the property, but there is a special syntax that allows the method to access the property; we will cover this later.
  • It is legal for a method and a field of a class to have the same name, although it is not considered a good practice to do so.
  • An example of an irresolvable conflict is declaring a local variable within a block when the same name is already in scope in that method as a local variable.

Code Sample:

Java-Basics/Demos/MethodExample.java
public class MethodExample {
  public static void sayHello() {
    System.out.println("Hello");
  }
  public static void showNumber(int number) {
    System.out.println("The number is: " + number);
  }
  public static int calculateSum(int num1, int num2) {
    int answer = num1 + num2;
    return answer;
  }
  public static void main(String[] args) {
    sayHello();
    showNumber(5);
    int b = calculateSum(4, 6);
    System.out.println("The sum of 4 and 6 is:" + b);
    b = calculateSum(4, 6) / 2;
    System.out.println("That divided by 2 is: " + b);
  }
}

We will cover the concept of static elements later, but, for now, since main is static, the methods it calls must be static as well

Method Exercise

Duration: 5 to 10 minutes.
  1. Create a class called Calculator.
  2. In it create a method called add that accepts two double parameters, adds them together, and returns the result - mark it as public and static, and returning a double.
  3. In a similar manner, create methods called subtract, multiply, and divide.
  4. In main, create three double variables a, and b, initialized with values of your choice, and c, which we can leave uninitialized.
  5. Call each of your methods in turn, passing a and b, and accepting the returned value into c, and printing all three values.

Solution:

Solutions/Basics/Calculator.java
public class Calculator {
	public static void main(String[] args) {
		double a = 10.0, b = 20.0, c;
		c = add(a, b);
		System.out.println(a + " + " + b + " = " + c);
		c = subtract(a, b);
		System.out.println(a + " - " + b + " = " + c);
		c = multiply(a, b);
		System.out.println(a + " * " + b + " = " + c);
		c = divide(a, b);
		System.out.println(a + " / " + b + " = " + c);
	}
	
	public static double add(double x, double y) {
	  return x + y;
	}
	public static double subtract(double x, double y) {
	  return x - y;
	}
	public static double multiply(double x, double y) {
	  return x * y;
	}
	public static double divide(double x, double y) {
	  return x / y;
	}
}

Java Objects → ← Java Introduction

Client Success
  1. Compare Us
  2. Client List
  3. Testimonials
Join The Team
  1. Learn how you can become a Webucator Trainer
  2. Career Opportunities
Locations
© Webucator, Inc. All rights reserved. |Toll Free: 1-877-932-8228Toll Free: 1-877-932-8228 |Outside the USA: 315-849-2724|Fax: 315-849-2723