Java Introduction Notes
Lesson Overview
- By the end of this lesson, you should be able to:
- Discuss key differences between Java and Python.
- Install the Java Development Kit and a Java IDE on your computer.
- Use JShell to run Java REPL sessions.
- Use a Java IDE to create, compile, and run a simple Java program.
What You Already Know
- Computers perform very simple instructions very quickly.
- See: https://www.youtube.com/watch?v=Z5JC9Ve1sfI
- A computer program is a sequence of instructions.
- Programming languages are formal languages understood by both humans and computers.
- Teams of people must be able to express complex computations and understand/update code.
- Interpreters/compilers convert code files into machine language.
- Most programming languages are 'equivalent' in that they can perform:
- Data retrieval (Input).
- Data storage (Output).
- Arithmetic operations (Increment/Multiply/etc).
- Conditional execution (If/else).
- Repetition (loops, recursive functions).
- Some languages are more effective at expressing certain computations.
Programming Languages Task Applicability
- Desktop apps: C#, Java
- Web apps: C#, Elixir, Go, Java, JavaScript, PHP, Python
- Scripting: Bash, Lua, Python
- Database programming: SQL
- Concurrent systems: Elixir, Erlang, Go
- Embedded & OS: Assembly, C, C++, Rust
- Scientific computing: Python, R, Julia
- Games: C++, C#, Java, Lua
- Mobile Apps: Java, Kotlin, Swift
- Mind expansion: Haskell, LISP, Racket, esolangs
Language Types: Interpreted
- Code files are executed directly by an interpreter.
- The interpreter converts code into machine code at run time.
- Execution is limited to platforms on which the interpreter can run.
- Examples: JavaScript, PHP, Python, Ruby.
Language Types: Compiled
- A compiler converts code files into executable files for the target platform.
- Executable files are executed directly.
- Examples: C, C++, Rust, Swift.
Language Types: Hybrid
- A compiler converts code files into an intermediate bytecode.
- The bytecode is executed by a virtual machine (a bytecode interpreter).
- Can be executed on any platform supported by the virtual machine.
- Examples: C#, Java, Erlang.
Compiled vs Interpreted vs Hybrid
- An advanced interpreter has many features of a compiler.
- There's a historical perspective:
- Initially, the difference between an interpreter and a compiler is unclear.
- After experience, the distinction becomes obvious.
- With more experience, the lines blur again.
Java
- Java is a hybrid language.
- The compiler converts Java code files into Java bytecode.
- The Java Virtual Machine (JVM) runs Java bytecode files.
- JVM is supported on many hardware platforms.
Java vs JavaScript
- Java and JavaScript are distinct languages.
- Similar names are due to 1990s marketing.
- Be careful when searching for information about either language!
Java Development Kit (JDK)
- To run Java programs, the JVM must be installed.
- To create Java programs, the JDK is needed.
- The JDK includes:
- JVM (java).
- Compiler (javac).
- REPL shell (jshell).
- Multiple JDKs can be installed on one device.
- Ensure the correct JDK is used when creating a Java program.
JDK Implementations and Versions
- The Java language has a programming language specification.
- Oracle owns the specification.
- Vendors produce JDK implementations:
- Amazon (Corretto).
- Microsoft (Microsoft Build of OpenJDK).
- Oracle (Oracle JDK, OpenJDK).
- Implementations vary in licensing and performance.
- The Java language specification is updated regularly.
- Long-Term Support (LTS) versions receive regular security updates and patches.
- Using an LTS version is recommended for production development.
- Version 1.0: 1996, First release of Java
- Version 5: 2004, Generic classes, annotations
- Version 8 (LTS): 2014, Lambda expressions, streams
- Version 11 (LTS): 2018, Java FX, Java EE removed from JDK
- Version 21 (LTS): 2023, Most recent LTS
Java REPL
- As of Java 9, the JDK comes with a REPL shell named jshell.
- Example usage:
$ jshell
// | Welcome to JShell -- Version 17.0.1
// | For an introduction type: /help intro
jshell> int x = 1;
x ==> 1
jshell> int y = 2;
y ==> 2
jshell> x + y
$3 ==> 3
jshell> /exit
Java Syntax
- A programming language's syntax is its 'grammatical rules'.
- Syntax errors occur when you break those rules.
- In a compiled language, syntax errors are detected by the compiler and are sometimes called compile-time errors.
- Java is case-sensitive.
- The Java compiler will consider these three different tokens:
- Instructions end in semi-colons.
- Code blocks are wrapped in curly braces.
- Indentation is NOT part of syntax (unlike Python).
- Use newlines and indentation to make your code more readable!
// This is a one-line comment
int x = 1; // Everything until the end of the line is a comment
/* This is a multi-line comment.
It can span multiple lines.
Everything inside the opening slash-star and the closing star-slash is a comment */
Values and Variables
- A value is data that can be represented by a program.
- Usually stored in computer memory.
- Variables are labels for the locations where values are stored.
- Example:
Memory Address | Value
--------------|------
0x1001 | 42
Static vs Dynamic Typing
- Python is dynamically typed; variable type is determined at run-time.
- Java is statically typed; variable type must be declared in code and is verified at compile time.
- Example:
int x = 42; // OK!
Static Typing in Java
- Values assigned to variables must correspond to their declared types.
int x = 1; // OK
String greet = "Hi"; // OK
boolean isHappy = true; // OK
int x = "12"; // Error!
String s = 12; // Error!
Declaration and Assignment
- In Java, variable declaration and assignment can be separate.
// Declarations:
int x;
String s;
boolean b;
// Assignment:
x = 1;
s = "abc";
b = true;
- Variable type is only necessary on declaration.
Common Mistakes in Variable Assignment
int x;
String s;
boolean b;
x = s; // Error! Type mismatch
y = 2; // Error! Undeclared variable
boolean c = b; // Error! Variable b has no value
Variable Assignment
- Assignment is a statement, not a mathematical equality.
int x = 1;
int y = x; // y has value 1
x = 2; // y STILL has value 1
y = x; // y NOW has value 2
Type Inference
- The var keyword can be used in place of a variable's type if it is initialized upon declaration.
var x = 42; // x is an int
var s = "abc"; // s is a String
var y; // Error! Cannot use 'var' without initialization
- Useful for complex types:
var L = new ArrayList<HashMap<String,String>>();
Variable Names
- May include:
- Alphabetical symbols.
- Numbers (but not as the first character).
- Underscore (_).
- Keywords may NOT be used as variable names.
- Convention: camelCasing (lower-case first letter, upper-case for subsequent words).
int typicalVariableNameInJava = 1;
Types in Java
- Every value has a type.
- Two categories of types:
- Primitive types.
- Object types.
Primitive Types
- Pure values with no methods.
| Primitive | Description |
|---|
| boolean | 1 bit – either true or false |
| byte | 8-bit integer |
| short | 16-bit integer |
| int | 32-bit integer |
| long | 64-bit integer |
| float | 32-bit floating point number |
| double | 64-bit floating point number |
| char | 16-bit Unicode character |
- Primitive type names start with a lowercase letter.
Object Types
- Anything that is not one of the 8 primitive types is an object type.
- Variables store a reference to the location where the actual data is stored
- Object types may be composite.
- Names start with an uppercase letter (by convention).
String s; // Java Strings are objects
Object o; // The 'supertype' of all object types in Java
ArrayList list; // Much like Python's list
Object Types - References
- Object type variables are references.
String s = "Hi!";
String t = s; // Aliasing assignment!
Arrays
- Ordered collection of values.
- Similar to Python's lists, but more limited.
| Feature | Python list | Java Array |
|---|
| Element Types | May be of different types | All elements must be of the same type |
| Methods/Properties | Many built-in methods and properties | Only one built-in property: length |
| Resizable | Can be resized | Fixed length |
| Literal | [1, 2, 3] | {1, 2, 3} |
| Type Declaration | No type declaration | int[] |
| Indexing | myArray[0] | myArray[0] |
| Reference/Object Types | Is a reference type | Is a reference (object) type |
Array Declaration
int[] myArray = { 1, 2, 3 };
- int[]: Type declaration specifying an ARRAY of ints.
- { 1, 2, 3 }: Array literal using curly braces.
myArray.length evaluates to 3.
Creating Java Programs
- Any text editor can be used to write Java programs.
- The
javac command compiles .java files into Java bytecode (.class files). - The
java command runs Java bytecode.
$ ls MyApp.java
$ javac MyApp.java
$ ls MyApp.class MyApp.java
$ java MyApp
IDEs for Java
- Most Java coders use an Integrated Development Environment (IDE).
- Examples:
- IntelliJ IDEA
- Eclipse
- Netbeans
- Visual Studio Code
Classes
- Object types are defined using classes.
- The JDK has many pre-defined classes.
- You can define your own classes (custom object types).
- In Java, EVERY code file must be a class.
- The file name MUST be the same as the class name.
public class MyApp { }
class keyword defines a class.public keyword indicates the 'visibility' of this class- All code belonging to the class must go in its body (inside the curly braces).
Function Definition Statements
- A function (a.k.a procedure, or subroutine) consisting of a set of instructions may be created using a function definition statement
- Functions may be called/applied to execute the set of instructions
- Functions may return a value
- Arguments may be used to provide input values to a function
- Arguments are assigned to local variables called parameters in the function's instruction set
Functions
- In Java, functions must belong to a class.
- Two kinds of functions:
- Class methods
- Associated with the class
- Call from class name, as in
Math.sqrt(25)
- Instance methods
- Associated with an instance of the class (an object)
- Call from object reference, as in
file.write("something")
Class Methods
- For now, only class methods will be written (though instance methods may be called).
- Class methods are as close as you can get in Java to Python-style top-level functions
Function Definitions in Java
- Must specify:
- Visibility.
- Binding.
- Return type.
- Name.
- Type and name of each parameter.
Function Example
public class MyApp {
public static void greet(String name) {
System.out.println("Hello, " + name);
}
}
- Visibility:
public (can be called from outside the class), or private (only from inside the class). - Binding:
static (class method), or non-static (instance method). - Return Type: Specify the type of the value returned from the function or
void if no value is returned. - Function Name: Same naming rules as variables, convention is to start with a lowercase letter
- Parameter List: Each parameter requires a type and a name, separated by commas.
System.out.println(): Java's equivalent to Python's print function.
Program Execution
- Python: Execution begins at the first instruction of the executed code file.
- Java: Execution begins at the first instruction of the main class method in the executed bytecode file.
public class MyApp {
public static void greet(String name) {
System.out.println("Hello, " + name);
}
public static void main(String[] args) {
greet("world");
}
}
- The
main method receives command line arguments as an array of String objects (similar to Python's sys.argv). - Could also write
MyApp.greet("world") but since we are in the MyApp class already it is not necessary.
Static Typing Revisited
- Yes, Java programs are typically more verbose than equivalent Python programs. This is partly because Java is statically typed…
- Writing statically typed programs that run can feel more challenging than writing programs in a dynamically typed language.
- More code necessary to declare types
- Program won't compile unless all assigned values match type declarations
- BUT! Never need to write code like this:
def triple(n):
assert isinstance(n, (int, float)), "n must be a number!"
return n*3
print(triple("this shouldn't work"))
- Statically typed languages force you to fix type errors
- More initial work to get program to run, more verbose code
- Less likely to encounter type errors during run-time
- Better code navigation and automated refactoring tools in IDEs
- Usually better for large software projects and/or teams
- Dynamically typed languages allow you to 'ignore' types
- Quick prototyping, usually more concise code
- BUT type errors can cause run-time errors
- Less powerful code navigation and automated refactoring tools in IDEs
- More appropriate for prototyping and smaller software projects
Static Typing Benefits
- Static typing allows the compiler to catch an entire category of bugs before you even run the program!
public class MyApp {
public static int triple(int n) {
return n * 3;
}
public static void main(String[] args) {
System.out.println(triple("This won't compile!"));
}
}
- The compiler checks all calls of triple and verifies that arguments are correct type
Static vs. Dynamic
static == compile-time; dynamic == run-time- Terms that involve the term static refer to aspects of a program that are determined at compile-time
- Static typing – types of variables/parameters must be declared and correct at compile-time
- In contrast, terms that involve the term dynamic usually refer to aspects of a program that are determined at run-time
- Dynamic typing – types of variables/parameters not determined until run-time
Static Typing Revisited
- Working in a dynamically typed language can feel more productive initially, but this is often a false sense of security
- All the type errors that a statically typed language forces you to deal with are lurking as potential bugs in your dynamically typed code
Errors
- Compile-time errors
- Errors caught during compilation
- I.e., your code involves an instruction that cannot be compiled/interpreted
- Syntax and Type errors are compile-time errors
- Run-time errors
- Errors that occur while the program is running
- I.e., your code involves an instruction that is impossible at run-time
- Semantic / logic errors
- Errors in program logic / behaviour
- I.e., your code is logically incorrect
Compile-time Errors
- Occur when attempting to compile the program
- Often indicated by IDE even before compilation
- Prevent code from being compiled (and hence from being executed)
- Examples.
- Syntax errors
- Type errors
- Only in a statically typed language
- In a dynamically typed language, type errors are run-time errors
Run-time Errors
- Occur while program is running
- Cause program to end (unless the error is explicitly handled)
- Examples
- Division by 0
- I/O errors (file not found, invalid permission, etc.)
Semantic Errors
- Cause unexpected / incorrect program behavior
- Usually do NOT cause program to crash
- Caused by incorrect logic in program