Intro to Programming

In this class, we will write programs.

But first, what is a program?

A program is a sequence of instructions that specifies how to perform a computation.

Every program you've ever used, no matter how complicated, is made up of small instructions that look much like the following:

  • input: get data from the keyboard, a file, a sensor, or some other device

  • output: display data on the screen, or send data to a file or other device.

  • math: perform basic mathematical operations like addition and division.

  • decisions: check for certain conditions and execute the appropriate code

  • repetition: perform some action repeatedly, usually with some variation.

We can think of programming as the process of: breaking down a large, complex task into smaller and smaller subtasks.

The process continues until the subtasks are simple enough to be performed with the basic instructions provided by the computer.



What is Computer Science?

One of the most interesting aspects of writing programs is deciding how to solve a particular problem, especially when there are multiple solutions.

In order to determine which way is best for a given situation, we need techniques for describing and analyzing solutions formally.

Computer science is the science of algorithms, including their discovery and analysis.

An algorithm is a sequence of steps that specifies how to solve a problem.

  • Some algorithms are faster than others, and some use less space in computer memory.

Designing algorithms and writing code is difficult and error-prone.

For historical reasons, programming errors are called bugs, and the process of tracking them down and correcting them is called debugging.



Programming Languages

The programming language you will learn in this class is Java, which is a high-level language.

A high-level language is any programming language that enables development of a program in a much more user-friendly programming context and is generally independent of the computer's hardware architecture.

Other high-level languages you may have heard of include:

  • Python
  • C and C++
  • Ruby
  • JavaScript
Before they can run, programs in high-level languages have to be translated into a low-level language, also called “machine language”.

This translation takes some time, which is a small disadvantage of high-level languages.

High-level languages have two advantages:

  1. It is much easier to program in a high-level language.
    • Programs take less time to write, they are shorter and easier to read, and they are more likely to be correct.

  2. High-level languages are portable, meaning they can run on different kinds of computers with few or no modifications.
    • Low-level programs can only run on one kind of computer, and have to be rewritten to run on another.
Two kinds of programs translate high-level languages into low-level languages: interpreters and compilers
  • An interpreter reads a high-level program and executes it, meaning that it does what the program says. It processes the program a little at a time, alternately reading lines and performing computations

  • A compiler reads the entire program and translates it completely before the program starts running. In this context, the high-level program is called the source code, and the translated program is called the object code or the executable. Once a program is compiled, you can execute it repeatedly without further translation. As a result, compiled programs often run faster than interpreted programs.




What is Java?

As aforementioned, Java is a high-level, class-based, object-oriented programming language and software platform that runs on billions of devices, including notebook computers, mobile devices, gaming consoles, medical devices and many others. The rules and syntax of Java are based on the C and C++ languages.

Here are some specific examples of real world applications that use Java:

  • LinkedIn
  • Minecraft
  • Amazon Web Services (AWS)

To create an application using Java, you will need:

  • to download and install the Java Development Kit (JDK), which is available for Windows, macOS, and Linux.

  • A command-line interface (CLI) on your computer that allows you to create and delete files, run programs, and navigate through folders and files (On a Mac, it's called Terminal, and on Windows, it's Command Prompt) OR an integrated development environment (IDE) - a software application that helps programmers develop software code efficiently by combining capabilities such as software editing, building, testing, and packaging in an easy-to-use application, such as Eclipse, NetBeans, IntelliJ, DrJava, etc.

You write the program in the Java programming language, then a compiler turns the program into Java bytecode—the instruction set for the Java Virtual Machine (JVM) that is a part of the Java runtime environment (JRE). Java bytecode runs without modification on any system that supports JVMs, allowing your Java code to be run anywhere. The Java software platform consists of the JVM, the Java API, and a complete development environment. The JVM parses and runs (interprets) the Java bytecode.

Java Process

The Java API consists of an extensive set of libraries including basic objects, networking and security functions; Extensible Markup Language (XML) generation; and web services. Taken together, the Java language and the Java software platform create a powerful, proven technology for enterprise software development.




Hello World

To start programming in Java, we can write a simple program that outputs "Hello, World!" on the screen. Since it's a very simple program, it's often used to introduce a new programming language to a newbie! 😃

Let's explore how Java "Hello, World!" program works:

// Our First Program
public class HelloWorld {
    public static void main(String [] args) {
        System.out.println("Hello, World!");
    }
}

How does the "Hello, World!" program work?

  1. In Java, any line starting with // is a single-line comment (We will learn more about multi-line comments in a bit). Comments are intended for users reading the code to understand the intent and functionality of the program. It is completely ignored by the Java compiler (an application that translates Java program to Java bytecode that computer can execute).

  2. Every application begins with a class definition. In this particular program, HelloWorld is the name of the class and the name of the class should match the filename in Java.

  3. Next is the main method. Every application in Java must contain the main method. The Java compiler starts executing the code from the main method, and it's mandatory in each of our executable Java programs. The signature of the main method in Java is:

    public static void main(String [] args) { ... }

  4. Lastly, we have a print statement. It prints the text Hello, World! to standard output (your screen). The text inside the quotation marks is called a String literal in Java. Notice the print statement is inside the main function, which is inside the class definition.


Comments

Comments have no effect on the execution of the program, but they make it easier for other programmers (and yourself!) to understand what you meant to do and how the program works.

There are three types of comments:

  • // single line comments

  • /*
    multiline comments
    */

  • /**
    multiline Documentation Comments to create formal documentation using Javadoc
    */



Variables

You may have seen variables before (Think back to high school algebra! Solving for X, etc.)

In programming, a variable is a location in memory (storage area) that holds data.

(For now just one value at a time ... we'll come back to this later)

To indicate the storage area, each variable is given a unique name. The names of variables, called identifiers, conform to the following rules:



Declaring Variables

It is easy to declare a variable!

First we identify the necessary keyword for the variable datatype. For example, a whole number should be declared as an integer type known as int while a decimal number should be declared as a float or double.

int score = 42; 

This syntax can be used to declare both local and global variables (we'll talk about this more later 😉).

In the previous example, we have assigned value to the variable during declaration -- this is known as initialization, because we assign an initial value to a variable.

However, we can also declare variables and assign variables separately.

For example:

int score;
score = 42;

When you declare a variable, you create a named storage location.

When you make an assignment to a variable, you update its value.

The value of a variable can be modified throughout the program (that's what makes it a variable, opposed to a literal)

For example:

int score = 0;
//more code to be added here
score = 42;

Here, initially, we set the score to 0.

Later (after some more code -- not yet specified) we changed it to 42.

It is important to remember, however, that we CANNOT change the data type of a variable in Java within the same scope (we'll discuss scope a bit more later, for now just think of our scope limited to the main method)



Printing Variables

We can display the value of a variable using print or println.

int score = 42;
//What should be printed below?
System.out.println(score);

When we talk about displaying a variable, we generally mean the value of the variable.

To display the name of a variable, you have to put it in quotes.



Variable Scope

The scope of a variable is the part of the program where the variable is accessible.

In general, a set of curly brackets { } defines a scope.

A variable declared inside pair of brackets “{” and “}” in a method is only accessible within the scope of the brackets only. (This will make more sense when we explore conditional statements, loops, methods, etc.)



Global Variables

We can also declare variables directly inside the class (outside any specific method -- we will revisit this once we begin writing more methods).

These variables can be directly accessed anywhere in class.




Java Operators

Operators are symbols that perform operations on variables and values. For example, we know that + is an operator used for addition, while * is an operator used for multiplication.

Operators in Java can be classified into the following types:

  1. Arithmetic Operators
    • Arithmetic operators are used to perform arithmetic operations on variables and data.
    • The various arithmetic operators we use include:
      • + (Addition, e.g. a + b)
      • - (Subtraction, e.g. a - b)
      • * (Multiplication, e.g. a * b)
      • / (Division, e.g. a / b)
      • % (Modulus -Remainder after division, e.g. a % b)
      • ++ (Increment, e.g. a++ or ++a)
      • -- (Decrement, e.g. a-- or --a)

  2. Assignment Operators
    • Assignment operators are used in Java to assign values to variables.
    • A few assignment operators available in Java include:
      • = (Assignment, e.g. a = b)
      • += (Additional assignment, e.g. a += b is equivalent to a = a + b)
      • we can also write assignment operators for other arithmetic operations such as subtraction, multiplication, division, modulus, etc.

  3. Relational (or Comparison) operators
    • Relational/Comparison operators are used to compare two values (or variables). The values returned from comparison are known as boolean values and will either be true or false.
    • A few relational/comparison operators available in Java include:
      • == (Equal to, e.g. a == b)
      • != (Not equal to, e.g. a != b)
      • > (Greater than, e.g. a > b)
      • < (Less than, e.g. a < b)
      • >= (Greater than or equal to, e.g. a >= b)
      • <= (Less than or equal to, e.g. a <=b)

  4. Logical Operators
    • Logical operators are used to determine the logic (whether a statement is true or false) between variables or values.
    • A few logical operators available in Java include:
      • && (Logical and - returns true if both statements are true, e.g. a < 5 && b < 5)
      • || (Logical or - returns true if one of the statements is true, e.g. a < 5 || b < 5)
      • ! (Logical not - reverses the result, returns false if the result is true, e.g. !(a < 5 && b < 5)))

  5. Unary Operators
    • Unary operators are operators that need only one operand to perform any operation, such as: increment, decrement, negation, etc. It consists of various arithmetic, logical and other operators that operate on a single operand.
    • A few unary operators available in Java include:
      • + (Unary Plus - represents a positive value, e.g. +a)
      • - (Unary Minus - represents a negative value, e.g. -a)
      • ! (Greater than or equal to, e.g. a >= b)
      • ++ (Increment Operator - increments the value of a variable by 1, e.g. ++a OR a++)
      • -- (Decrement Operator - decrements the value of a variable by 1, e.g. --a OR a--)
    • The last previous two operators (increment and decrement) are especially important because not only are they incredibly useful in multiple cases but they also have two variants of these operators:
      1. Pre-increment/decrement (also known as prefix)
        • Here our code increments/decrements the value first, and then performs the specified operation.
        • // Prefix increment example
          public class PrefixExample {
              public static void main(String [] args) {
                  int a = 5;
                  System.out.println(++a);//this immediately increments to 5+1 and prints 6
                  System.out.println(a);//this reflects the modifcation in the previous line AND also prints 6
              }
          }
      2. Post-increment/decrement (also known as postfix)
        • Here our code performs the specified operation first, and then increments/decrements the value.
        • // Postfix increment example
          public class PostfixExample {
              public static void main(String [] args) {
                  int a = 5;
                  System.out.println(a++);//prints the current value of a (5) BEFORE incrementing
                  System.out.println(a);//value has been printed out, incremented, now prints 6
              }
          }

  6. Bitwise Operators

TO REMEMBER:


Precedence Table



Floating-Point Numbers

Floating-point numbers in Java are used to represent fractional values or numbers with a large range of possible values. They are primarily used when precise decimal calculations are not required.

Java uses two primitive data types to represent floating-point numbers: float and double.

  • The float data type is a 32-bit single-precision floating-point number
  • The double data type (which we will use in this class rather than float) is a 64-bit double-precision floating-point number. This makes the double data type more accurate than the float data type.

We can create double variables and assign values to them using the same syntax we used for the other types:

double payRate = 42.5;

The simplest way to convert a floating-point value to an integer is to use a type cast, so called because it molds or “casts” a value from one type to another.

The syntax for type casting is to put the name of the type in parentheses and use it as an operator.

double payRate = 42.5;
int pay = (int) payRate;

What is the value of the variable pay?

Integer vs Floating Point Division

In math, division often allows for remainders. It is why whenever a number is NOT evenly divisible by another number it can result in a decimal number opposed to a whole number e.g. 5/2 is equal to 2.5

However, integer division and division as we know from math class (also known as floating-point division) are two different ways of performing division operations.

Integer division is the division operation performed on two integers, resulting in an integer quotient. The result is obtained by discarding the fractional part of the division, if any. In other words, it performs a "round towards zero" operation.

  • For example, if you perform an integer division of 10 divided by 3, the result is 3 because it discards the fractional part.
  • Similarly, if you divide -10 by 3 using integer division, the result is -3, as it still rounds towards zero.
On the other hand, floating-point division is the division operation performed on floating-point numbers (those with decimal places). It produces a result with decimal places, including the fractional part. This type of division is typically more accurate and provides more precise results.

In Java, when dividing two integers using the '/' operator, integer division is performed if both operands are integers.

To perform floating-point division, at least one of the operands should be a floating-point number.

For example:

int result = 10 / 3;//Integer division, result is 3
double result = 10.0 / 3;//Regular division, result is approximately 3.3333

It is important to be aware of the distinction between integer division and floating-point division, especially when working with different data types and when precision is required in calculations.




Math Methods

Java has a lot of built-in Math methods that allow us to perform more complex mathematical computations. The Math class is found in the java.lang package, so you don't have to import it.

For example, if you need to get the square root of a number, we use the Math.sqrt() method.

Some frequently used Math class methods include:

  • Math.abs(n) - for computing the absolute value of a particular number
  • Math.sqrt(n) - for computing the square root of a particular number
  • Math.pow(base, exp) - for computing the result of a particular base raised to the power of a particular exponent

Although not a method, Math.PI - is a static final double constant in Java, equivalent to in π Mathematics

You can learn more about the Java Math class methods from the Java API here

Generating Random Numbers

Most computer programs do the same thing every time they run, meaning they are deterministic. Usually we want our programs to be deterministic since we expect the same calculation to yield the same result. But for certain applications (e.g. games) we want to write programs that are nondeterministic.

It is hard for a computer to generate truly random numbers. But there are algorithms that generate unpredictable sequences called pseudorandom numbers. For most applications, they are as good as random.

The Math.random() method returns a pseudorandom double type number between 0.0 and 1.0, where 0.0 is inclusive and 1.0 is exclusive.

When this method is first called, it creates a single new pseudorandom-number generator

public class RandomExample {
    public static void main(String [] args) {
        double rand = Math.random();//Generate random number
        System.out.println("Random Number:" + rand);//different each run
    }
}

to generate a random number in range:

Math.random() * (max - min) + min;



Types of Errors

There are three types of errors can occur in a program:

  1. Compiler errors
  2. Run-time errors
  3. Logic errors

Compiler errors occur when you violate the syntax rules of the Java language. For example, forgetting a semicolon at the end of a statement or that parentheses and braces have to come in matching pairs. So (1 + 2) is legal, but 8) is not. In the latter case, the program cannot be compiled, and the compiler displays an error.

  • Error messages from the compiler usually indicate where in the program the error occurred, and sometimes they can tell you exactly what the error is.

Run-time errors occur while the interpreter is executing byte code and something goes wrong. These errors are also called “exceptions” because they usually indicate that something exceptional (and bad) has happened. (Example: attempting divide by zero)

  • When a run-time error occurs, the interpreter displays an error message that explains what happened and where.

The third type of error is the logic error. If your program has a logic error, it will compile and run without generating error messages, but it will not do the right thing. Instead, it will do exactly what you told it to do (even if it isn't the right solution).

  • Usually the compiler and the interpreter CANNOT help you, since they don't know what the right thing is.




Reference

Documentation on this page is taken from the following:

  • Allen Downey and Chris Mayfield, Think Java: How to Think Like a Computer Scientist, 2nd Edition, Version 6.1.3, Green Tea Press, 2016, Creative Commons License.

  • GeeksforGeeks

  • Programiz

  • IOFLOOD