Basics of Java Syntax - ilya-khadykin/notes-outdated GitHub Wiki

Variables (1)

An object stores its state in fields. In the Java programming language, the terms "field" and "variable" are both used; this is a common source of confusion among new developers, since both often seem to refer to the same thing.

The Java programming language defines the following kinds of variables:

  • Instance Variables (Non-Static Fields) - Technically speaking, objects store their individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one bicycle is independent from the currentSpeed of another.
  • Class Variables (Static Fields) - A class variable is any field declared with the static modifier; this tells the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated. A field defining the number of gears for a particular kind of bicycle could be marked as static since conceptually the same number of gears will apply to all instances. The code static int numGears = 6; would create such a static field. Additionally, the keyword final could be added to indicate that the number of gears will never change.
  • Local Variables - Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.
  • Parameters - the signature for the main method is public static void main(String[] args). Here, the args variable is the parameter to this method. The important thing to remember is that parameters are always classified as "variables" not "fields". This applies to other parameter-accepting constructs as well (such as constructors and exception handlers)

Naming

The rules and conventions for naming your variables can be summarized as follows:

  • Variable names are case-sensitive. A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "". The convention, however, is to always begin your variable names with a letter, not "$" or "". Additionally, the dollar sign character, by convention, is never used at all. You may find some situations where auto-generated names will contain the dollar sign, but your variable names should always avoid using it. A similar convention exists for the underscore character; while it's technically legal to begin your variable's name with "_", this practice is discouraged. White space is not permitted.
  • Subsequent characters may be letters, digits, dollar signs, or underscore characters. Conventions (and common sense) apply to this rule as well. When choosing a name for your variables, use full words instead of cryptic abbreviations. Doing so will make your code easier to read and understand. In many cases it will also make your code self-documenting; fields named cadence, speed, and gear, for example, are much more intuitive than abbreviated versions, such as s, c, and g. Also keep in mind that the name you choose must not be a keyword or reserved word.
  • If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names gearRatio and currentGear are prime examples of this convention. If your variable stores a constant value, such as static final int NUM_GEARS = 6, the convention changes slightly, capitalizing every letter and separating subsequent words with the underscore character. By convention, the underscore character is never used elsewhere.

A data type is a set of values and a set of operations on those values

The Java programming language is statically-typed, which means that all variables must first be declared before they can be used. The scope of a variable is the part of the program where it is defined.

The Java programming language supports eight primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:

  • byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
  • short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.
  • int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -2^31 and a maximum value of 2^31-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
  • long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2^63 and a maximum value of 2^63-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2^64-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
  • float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead.
  • double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.
  • boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
  • char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).

In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such.

Default Values of primitive data types in Java

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

The following chart summarizes the default values for the above data types.

Data Type Default Value (for fields)
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object) null
boolean false

Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.

Literals

You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:

boolean result = true;
char capitalC = 'C';
byte b = 100;
short s = 10000;
int i = 100000;

Character and String Literals

Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED Se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.

The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), " (double quote), ' (single quote), and \ (backslash).

There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.

Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.

Using Underscore Characters in Numeric Literals

In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example. to separate groups of digits in numeric literals, which can improve the readability of your code.

For instance, if your code contains numbers with many digits, you can use an underscore character to separate digits in groups of three, similar to how you would use a punctuation mark like a comma, or a space, as a separator.

The following example shows other ways you can use the underscore in numeric literals:

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi =  3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

A Java program manipulates variables that are named with identifiers. Each variable is associated with a data type and stores one of the permissible data-type values. We use expressions to apply the operations associated with each type. (2)

Java Building Blocks

public class Variables {

   public static void main(String[] args) {
     // <variable_type> <varibale_name> = <value>
     // Naming convention - exampleName

     // numeric values, all signed
     byte   aByte     = 127; // 8 bits
     short  aShort    = 037654; // 16 bits
     int    anInteger = 123456; // 32 bits
     long   aLong     = 0xCAFE; // 64 bits

     // floating point numbers
     float aFloat     = 99.9F; // 32 bits, real number with single precision 
     double aDouble   = 98.0E+99;

     // unsigned number represents a character
     // coded using Unicode
     // use only '', "" is used for Strings
     char  aCharacter = 'A';      // behaves like 16 bits
           aCharacter = '\u0041'; // hexadecimal literal
           aCharacter = '\n';     // newline

    // logical value; true or false
    boolean aBoolean  = true;     // behaves like one bit
   }
}

Operators

The following table summarizes the set of values and most common operations on those values for Java's int, double, boolean, and char data types. (2)

primitive-data-types.png

public class Operators {
  
  public static void main(String[] args) {
    int i = 0;
    short aShort = 1;
    long aLong = 0xCAFEBABE;

    i++; // i = i + 1;
    i /= 2; i = i/2;

    aShort = (short) aLong;  // can 'cast' to force the assignment
  }
}

Comparisons

  • equal (==)
  • not equal (!=)
  • less than (<)
  • less than or equal (<=)
  • greater than (>)
  • greater than or equal (>=)

Statements

public class Conditions {
  
  public static void main(String[] args) {
    int a = 100;
    int b = 199;

    if (a < b) {
      System.out.println(a + " is less than " + b);
    } else {
      System.out.println(a + " is greater than " + b);
    }

    switch (a) {
      case 98:
      case 99:
          System.out.println("a is 98 or 99");
          break;
      case 100:
          System.out.println("a is 100");
          break;
      default:
          System.out.println("a is something else");
          break;
    }

    int a = 0;
    while (a < 10) {
      System.out.println("a is " + a);
      a++;
    }

    do {
      System.out.println("a is " + a);
      a++;
    } while (a < 10);

    for (int x = 0; x < 10; x++) {  // x is scoped only inside the loop
      System.out.println("x is " + x);
    }

    for (  ; a < 20;  ) {  // equivalent to while (a < 20)
      System.out.println("a is " + a++);
    }

    for (;;) {
      System.out.println("a is " + a++);
      if (a > 25) {
        break;  // stop execution of the loop and continue the execution
      }
    }
  }
}

The following table illustrates different kinds of Java statements. (2)

java-statements.png

Arrays

java-array.png

An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed.

Once we create an array, its size is fixed. A program can refer to the length of an array a[] with the code a.length. Java does automatic bounds checking—if you access an array with an illegal index your program will terminate with an ArrayIndexOutOfBoundsException.

As with variables of other types, the declaration does not actually create an array; it simply tells the compiler that this variable will hold an array of the specified type.

Similarly, you can declare arrays of other types:

byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;
public class Arrays {
    
  public static void main(String[] args) {
    int[] values = { 1, 2, 3, 4, 5, 6, 13, 21, 34 };

    System.out.println("The fifth element of values is " + values[4]);

    System.out.println("There are " + values.length + " elements in values");

    for (int idx = 0; idx < values.length; idx++) {
      System.out.println("values[" + idx + "] is " + values[idx]);
    }

    int[] moreValues = new int[20];
    System.arraycopy(values, 0, moreValues, 0, values.length);

    int [][] raggedMatrix = {
        { 1, 2, 3 },
        { 4, 5 },
        { 6, 7, 8, 9 }
    };
    System.out.println("raggedMatrix[0][2] is " + raggedMatrix[0][2]);
  }
}

Aliasing. An array name refers to the whole array—if we assign one array name to another, then both refer to the same array, as illustrated in the following code fragment:

int[] a = new int[N];
...
a[i] = 1234;
...
int[] b = a;
...
b[i] = 5678;   // a[i] is now 5678.

Multidimensional arrays

You can also declare an array of arrays (also known as a multidimensional array) by using two or more sets of brackets, such as String[][] names. Each element, therefore, must be accessed by a corresponding number of index values.

In the Java programming language, a multidimensional array is an array whose components are themselves arrays. This is unlike arrays in C or Fortran. A consequence of this is that the rows are allowed to vary in length, as shown in the following MultiDimArrayDemo program:

class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}

Finally, you can use the built-in length property to determine the size of any array. The following code prints the array's size to standard output:

 System.out.println(anArray.length);

Copying Arrays

The System class has an arraycopy method that you can use to efficiently copy data from one array into another:

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) The two Object arguments specify the array to copy from and the array to copy to. The three int arguments specify the starting position in the source array, the starting position in the destination array, and the number of array elements to copy.

The following program, ArrayCopyDemo, declares an array of char elements, spelling the word "decaffeinated." It uses the System.arraycopy method to copy a subsequence of array components into a second array:

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));
    }
}

For your convenience, Java SE provides several methods for performing array manipulations (common tasks, such as copying, sorting and searching arrays) in the java.util.Arrays class.

Some other useful operations provided by methods in the java.util.Arrays class, are:

  • Searching an array for a specific value to get the index at which it is placed (the binarySearch method).
  • Comparing two arrays to determine if they are equal or not (the equals method).
  • Filling an array to place a specific value at each index (the fill method).
  • Sorting an array into ascending order. This can be done either sequentially, using the sort method, or concurrently, using the parallelSort method introduced in Java SE 8. Parallel sorting of large arrays on multiprocessor systems is faster than sequential array sorting.

Static Methods or Variables

With static you declare a class method or variable

java-static-method.png

public class Methods {

  public static float average(float[] fa) {
      float sum = 0.0F;
      for (int idx = 0; idx < fa.length; idx++) {
          sum += fa[idx];
      }
      return sum / fa.length;
  } 
  
  // initial code
  public static void main(String[] args) {
      float[] fal = { 1.2F, 3.2F, 5.9F, 9.6F };

      float sum = 0.0F;
      for (int idx = 0; idx < fal.length; idx++) {
          sum += fal[idx];
      }
      float average = sum / fal.length;
      System.out.println("Average of the numbers is " + average);

      float[] fa2 = { 19.0F, 9.9F, 5.9F, 9.6F, 7.8F, 2.8F };

      sum = 0.0F;
      for (int idx = 0; idx < fa2.length; idx++) {
          sum += fa2[idx];
      }
      average = sum / fa2.length;
      System.out.println("Average of the numbers is " + average);


      // refactored code
      System.out.println("Average of the first set of numbers is " + average(fal));
      System.out.println("Average of the first set of numbers is " + average(fa2));

  }
}

Data Structures

/*
 *  Item.java
 */
package structures1;

public class Item {
    
    public String name;
    public int price;
    public int quantity;
}
/*
 *  Structure1.java
 */
package structures1;

public class Structures1 {
    public static void main(String[] args) {
         Item an Item = new Item();
         anItem.name = "Frosty Crunches";
         anItem.price = 250;
         anItem.quantity 
    }
}

Date Data Structure (1)

/*
 *  Date.java
 */
package date1;

public class Date {
  public int day;
  public int month;
  public int year;

  public boolean isLeapYear(int year) {
      return (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0);
  }

  public int daysInMonth(int month, int year) {
    int rv;
    switch(month) {
        case 9: // Thirty days hath September
        case 4: // April
        case 6: // June
        case 11: // and November
            rv = 30;
            break;
        case 2:
            if (isLeapYear(year)) {
                rv = 29;
            } else {
                rv = 28;
            }
            break;
        default:
            rv = 31;
            break;
    }
    return rv;
  }

  public void nextDay() {
      int dayCount = daysInMonth(this.month, this.year);
      this.day++;
      if (this.day > dayCount) {
          this.day = 1;
          this.month++;
          if (this.month > 12) {
              this.month = 1;
              this.year++;
          }
      }
  }

  // Constructor
  public Date(int m, ind d, int, y) {
      this.day = d;
      this.month = m;
      this.year = y;
  }
}
/*
 *  Date1.java
 */
package date1;

public class Date1 {
  
  public static void main(String[] args) {
      Date meetingDate = new Date(2, 29, 2012);

      System.out.println("Meeting will be on "
                + meetingDate.month + "/"
                + meetingDate.day + "/"
                + meetingDate.year);
  }
}

References

  1. Java Programming Basics by Simon Roberts
  2. Algorithms, 4th Edition by Robert Sedgewick and Kevin Wayne
  3. Primitive Data Types
  4. Arrays
⚠️ **GitHub.com Fallback** ⚠️