Post

Java 1 - Datatypes and Type Casting

Introduction

  • Java is a high-level, class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible.
  • It is a general-purpose programming language intended to let application developers write once, run anywhere (WORA), meaning that compiled Java code can run on all platforms that support Java without the need for recompilation.
  • Java applications are typically compiled to bytecode that can run on any Java virtual machine (JVM) regardless of the underlying computer architecture.
  • The syntax of Java is similar to C and C++, but it has fewer low-level facilities than either of them.
  • As of 2019, Java was one of the most popular programming languages in use according to GitHub, particularly for client-server web applications, with a reported 9 million developers.
  • Java was originally developed by James Gosling at Sun Microsystems (which has since been acquired by Oracle Corporation) and released in 1995 as a core component of Sun Microsystemsโ€™ Java platform.

File Naming Conventions

  • File names should be in camel case.(e.g. MyClass.java)
  • File names should be the same as the class name.
  • Each class should have a main method.
1
2
3
4
5
6
public class MyClass {
    // main method
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Packages and Imports

  • Packages are used to organize classes into namespaces.
1
2
3
4
5
6
7
package mypackage;

public class MyClass {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
  • Packages are defined at the top of the file.
  • Imports are used to import classes from other packages.
  • Imports are defined after the package declaration and before the class declaration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package mypackage;

import java.util.Scanner;

public class MyClass {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

// in main class

import mypackage.MyClass;

public class Main {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
    }
}
  • Letโ€™s say we have a class called MyClass in a package called mypackage, and we want to use this class in the Main class.
  • We can import the MyClass class by using the following syntax:
1
import mypackage.MyClass;
  • The path to the folder and subfolders should be separated by dots (e.g. mypackage.subpackage.MyClass).

Data Types

  • In Java, there are three main categories of data types:
  • Primitive Data Types - such as int, float, double, char, boolean, etc.
  • Immutable Object Data Types - such as String, Integer, Float, Double, Character, Boolean, etc.
  • Mutable Object Data Types - such as Array, ArrayList, or any other object that can be updated.

Working with Variables - Primitive Data Types

  • Primitive data types are the most basic data types available within the Java language.
  • They store single values and have no methods.

Creating (Declaring) Variables

  • Variables are containers for storing data values.
  • In Java, there are different types of variables, for example:

    • int - stores integers (whole numbers in the 2 billion range), without decimals, such as 123 or -123
    • long - stores integers (whole numbers in the quantillion range) but larger than int, such as 1000000L
    • double - stores floating point numbers, with decimals, such as 19.99 or -19.99
    • char - stores single characters, such as โ€˜aโ€™ or โ€˜Bโ€™. Char values are surrounded by single quotes
    • boolean - stores values with two states: true or false
    • String - stores text, such as โ€œHelloโ€. String values are surrounded by double quotes

    It is advisable to use the smallest amount of memory possible!

  • Variables can be declared by using the following syntax:
    • type variable = value;
    • type is the type of variable, variable is the name of the variable, and value is the value of the variable.
  • Variables are named using lowerCamelCase.(e.g. myVariable, myVariableName)
  • To create a variable, you must specify the type and assign it a value:
1
2
3
4
5
int myNum = 5;               // Integer (whole number)
float myFloatNum = 5.99f;    // Floating point number
char myLetter = 'D';         // Character
boolean myBool = true;       // Boolean
String myText = "Hello";     // String

Updating Variables

  • You can update the value of a variable by using the following syntax:
    • variable = new value;
  • You can also add, subtract, multiply, or divide the value of a variable by using the following syntax:
    • variable = variable + value; or variable += value;
    • variable = variable - value; or variable -= value;
    • variable = variable * value; or variable *= value;
    • variable = variable / value; or variable /= value;

Working with Strings

  • Strings are used for storing text.
  • A string variable contains a collection of characters surrounded by double quotes.
  • An empty string is a string takes up 24 bits of memory.
  • the more characters in a string, the more memory it takes up.

Some Basic Guidelines

  • Use Char for single characters instead of String.
  • When performing Calculations, use double for at least one of the numbers.
  • When performing math operations, never use int because it will always round off the result.
  • When performing math operations within a String, use brackets to ensure the correct order of operations.
1
2
3
4
5
6
7
public class MyClass {
    public static void main(String[] args) {
        int x = 5;
        int y = 3;
        System.out.println("The sum of x and y is: " + (x + y));
    }
}

Type Casting

  • Since it is advisable to use at least one double when performing math operations, you may need to convert the result to an int or long if you want to store the result in an int or long variable.
  • We can therefore convert from one data type to another by using the following syntax:
    • type variable = (type) value;
1
2
3
4
5
6
7
8
public class MyClass {
    public static void main(String[] args) {
        int myIncome = 130000;
        int daysInYear = 365;
        double myDailyIncome =  myIncome / (double) daysInYear;
        System.out.println("My daily income is: " + myDailyIncome); // 356.1643835616438
    }
}

Immutable Object Data Types Vs Primitive Data Types

  • Immutable object data types are objects that cannot be changed once they are created.
  • They take up more memory than primitive data types.
  • You may be wondering why you should use immutable object data types if they take up more memory.
  • One reason is that Integer for example is a class that has methods. So each time you use an Integer, you are simply creating a new object of the Integer class.
  • int on the other hand is a primitive data type that has no methods.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int myNum = 5;               // Primitive data type = 4 bytes
Integer myNum2 = 5;          // Immutable object data type = 16 bytes

char myLetter = 'D';         // Primitive data type = 2 bytes
Character myLetter2 = 'D';   // Immutable object data type = 16 bytes

boolean myBool = true;       // Primitive data type = 1 bit
Boolean myBool2 = true;      // Immutable object data type = 16 bytes

float myFloatNum = 5.99f;    // Primitive data type = 4 bytes
Float myFloatNum2 = 5.99f;   // Immutable object data type = 16 bytes

double myDoubleNum = 5.99;   // Primitive data type = 8 bytes
Double myDoubleNum2 = 5.99;  // Immutable object data type = 24 bytes

long myLongNum = 15000000000L; // Primitive data type = 8 bytes
Long myLongNum2 = 15000000000L; // Immutable object data type = 24 bytes
  • Because immutable objects take up more memory, it is advisable to use primitive data types whenever possible.
  • Immutable objects can be null, while primitive data types cannot.
    • Nullis a reference that points to nothing.
    • Each object has a reference in memory that points to its location in memory.
    • If an object is null, it means that the reference is pointing to nothing.
    • Primitive data types do not have references, so they cannot be null.
1
2
3
4
Integer myNum = null; // OK.  This is initialized to null which can be assigned to an Integer object later.
myNum = 5;            // the value of myNum is an Integer object with a value of 5.
int myNum2 = null;    // Error. Primitive data MUST have a value.
int myNum3 = 5;       // OK
  • Immutable objects can call methods, while primitive data types cannot.
    • Immutable objects are objects that have methods.
    • Primitive data types are not objects and therefore do not have methods.
1
2
3
4
5
Integer myNum = 5;
System.out.println(myNum.toString()); // 5

int myNum2 = 5;
System.out.println(myNum2.toString()); // Error

Immutable Object Data Types Vs Mutable Object Data Types

  • Immutable object data types are objects that cannot be changed once they are created.
  • Mutable object data types are objects that can be changed once they are created.
  • When one immutable objects points to another immutable object, the first object is not affected when the second object is changed.
1
2
3
4
Integer myNum = 5; // Immutable object data type
Integer myNum2 = myNum

myNum2 = 10; // myNum2 is now 10, but myNum is still 5
  • When one mutable object points to another mutable object, the first object is affected when the second object is changed.
  • This is because both objects point to the same location in memory.
  • Therefore, when one object is changed, the other object is also changed.
  • This can lead to unexpected results.
1
2
3
4
City myCity = new City("New York"); // Mutable object data type
City myCity2 = myCity;

myCity2.setName("Los Angeles"); // myCity is now Los Angeles
  • To avoid this, you can create a copy constructor that creates a new object with the same values as the original object.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class City {
    private String name;

    public City(String name) {
        this.name = name;
    }

// Copy constructor
    public City(City city) {
        this.name = city.name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • You can then create a new object by using the copy constructor.
1
2
3
4
5
6
7
8
City myCity = new City("New York");

// Create a new object with the same values as the original object
City myCity2 = new City(myCity);
myCity2.setName("Los Angeles");

System.out.println(myCity.getName()); // New York
System.out.println(myCity2.getName()); // Los Angeles

Static Vs Non-Static Fields

  • Static fields belong to the class itself, while non-static fields belong to the object.
  • Static fields are shared by all objects of the class, while non-static fields are unique to each object.
  • Static fields are declared using the static keyword.
  • Static fiels should always be private.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class User {
    // Non-static fields
    private String name;
    private int age;

    // Static fields
    private static int count = 0;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        count++;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }

// Static getter method
    public static int getCount() {
        return count;
    }
}
  • You can then access the static field by using the class name.
1
2
3
4
5
6
7
8
9
// main class

public class Main {
    public static void main(String[] args) {
        User john = new User("John", 30);
        User jane = new User("Jane", 20);
        System.out.println(User.getCount()); // 2
    }
}

Static final Constants

  • Static final constants are constants that cannot be changed once they are created.
  • They are declared using the static final keywords.
  • They are typically declared in all uppercase letters and separated by underscores.
1
2
3
4
public class User {
    // Static final constant
    public static final int MAX_AGE = 65;
}
  • It is recommended to use static final constants instead of loose variables.
  • You can then access the static final constant by using the class name, followed by the constant name.
1
2
3
4
5
6
7
// main class

public class Main {
    public static void main(String[] args) {
        System.out.println(User.MAX_AGE); // 65
    }
}
  • In order not to alway have to use the class name, you can import the constant by using the following syntax:
  • import static package_name.class_name.constant_name;
1
2
3
4
5
6
7
import static mypackage.User.MAX_AGE;

public class Main {
    public static void main(String[] args) {
        System.out.println(MAX_AGE); // 65
    }
}
  • What if we could import ALL the constants in a class?๐Ÿค”
  • You can import all the constants in a class by using the following syntax:
  • import static package_name.class_name.*;
  • This will import all the constants and static members in the class.
1
2
3
4
5
6
7
import static mypackage.User.*;

public class Main {
    public static void main(String[] args) {
        System.out.println(MAX_AGE); // 65
    }
}
  • If in the future you want to change the value of the constant, you can do so in one place.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class User {
    // Static final constant
    public static final int MAX_AGE = 30;
}

// main class

public class Main {
    public static void main(String[] args) {
        System.out.println(User.MAX_AGE); // 30

    }
}
  • constants improve code readability and maintainability.

Enumerations (Enums)

  • Enums consist of a limited set of constants.
  • Enums are declared using the enum keyword.
  • The name of the enum should be in UpperCamelCase.
1
2
3
public enum TrafficLight = {
    RED, GREEN, YELLOW
}
  • To fully understand when to use enums, consider the following example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package model;
public class Car {
    private String make;
    private int year;

    public Car(String make, int year) {
        this.make = make;
        this.year = year;
    }

    public String getMake() {
        return this.make;
    }

    public void setMake(String make) {
        this.make = make;
    }

    public int getYear() {
        return this.year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void drive(String trafficLight) {
        if (!trafficLight.equals("RED") && !trafficLight.equals("GREEN") && !trafficLight.equals("YELLOW")) {
            throw new IllegalArgumentException("TRAFFIC LIGHT CAN ONLY BE RED, GREEN, YELLOW");
        }

        switch (trafficLight) {
            case "RED": System.out.println("STOP"); break;
            case "GREEN": System.out.println("DRIVE"); break;
            case "YELLOW": System.out.println("SLOW DOWN"); break;
        }
    }

    // public void drive(TrafficLight trafficLight) {
    //     if (trafficLight == null) throw new IllegalArgumentException("Traffic Light cannot be null");
    //     switch (trafficLight) {
    //         case RED: System.out.println("STOP"); break;
    //         case GREEN: System.out.println("DRIVE"); break;
    //         case YELLOW: System.out.println("SLOW DOWN"); break;
    //     }
    // }


}
  • In the above example, the drive method takes a String parameter.
  • The trafficLight parameter can only be RED, GREEN, or YELLOW.
  • If the trafficLight parameter is not one of these values, an IllegalArgumentException is thrown.
  • This can be improved by using Enums.
  • First we create an Enum called TrafficLight.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package model;
public class Car {
    private String make;
    private int year;

    // Enum
    public enum TrafficLight {
        RED, GREEN, YELLOW
    }

  // ... remaining code


}
  • We can then update the drive method to take a TrafficLight parameter.
  • This will restrict the parameter to only the values in the TrafficLight enum.
1
2
3
4
5
6
7
8
public void drive(TrafficLight trafficLight) {
    if (trafficLight == null) throw new IllegalArgumentException("Traffic Light cannot be null");
    switch (trafficLight) {
        case RED: System.out.println("STOP"); break;
        case GREEN: System.out.println("DRIVE"); break;
        case YELLOW: System.out.println("SLOW DOWN"); break;
    }
}
  • Enums are static by default.
  • So we need to import them as static members.
  • We can import the TrafficLight enum by using the following syntax:
  • import static package_name.class_name.enum_name.*;
  • This will import all the constants in the enum.
  • We can then use the constants without the class name.
1
2
3
4
5
6
7
8
9
10
11
12
// main class

import static model.Car.TrafficLight.*;// the enum is in a class called Car in a package called model

public class Main {
    public static void main(String[] args) {
        Car car = new Car("Toyota", 2022);
        car.drive(RED); // STOP
        car.drive(GREEN); // DRIVE
        car.drive(YELLOW); // SLOW DOWN
    }
}
This post is licensed under CC BY 4.0 by the author.