my-guide

to keep track of my learning journey

View on GitHub

JAVA

⬅️ Back to home

Quiz

Documentation / Specification

Java API 13 Java SE specifications

Notes

1️⃣🚩Reference Course: Java In-Depth: Become a Complete Java Engineer! by Dheeru Mundluru from Udemy other recommended books/materials: Reference: https://www.coolworkx.com/Effective%20Java,%203rd%20Edition.pdf

📘 Section 1: Java - a High level overview

What is Java ?

A General purpose(not dependent on any domain, can be used to develop wide variety of applications), object-oriented(helps real world scenarios), platform independent(write once and run anywhere), concurrent(multi-threading) programming language that runs very fast.

Assembly Language —-> assembler —-> Machine language Source code(High level languages) —-> Compiler —-> target language

Compiler

Compilation -> Converting of sourcecode to target language(machine code, byte code, programming lanugage),

  1. it verifies syntax and semantics
  2. Code optimization
  3. Generates machine code

source code —> [compiler] —> machine code —> [CPU] —> results

Pros Cons
Fast execution No platform independence
No compilation step Interpreter is loaded into the memory
Easier to update  

Interpreter

Interpretation -> Directly executing source code to get results

  1. Its a virtual machine that simulates a CPU
  2. An interpreter does not generate machine code like a compiler, but it maintains a library of pre-compiled machine code and executes the appropriate machine code corresponding to the statement in the source code

source code —> [Interpreter] —> results

Pros Cons
Platform independence Slow, costly memory access, Source code is reinterpreted every time
No compilation step Interpreter is loaded into the memory
Easier to update  

Java uses compilation for fast execution and interpretation for platform independence.

Java Source code –> [Java compiler] –> Java bytecode –> [Java interpreter] –> result

JVM

Java is a interpreted language as we are using JVM to interpret the Java byte code

Commands used for compilation and interpretation of JAVA Java source code, Hello.java –> compile using javac Hello.java –> output is Hello.class (java bytecode) –> JVM executes it in any platform using java Hello

Execution speed of JVM(performance)
Core Responsibilities of JVM
JVM Instance
JVM Architecture

image

  1. JVM instance loads in memory
  2. Get memory allocated to it for its use
  3. Class Loader loads the Hello.class
  4. Bytecode Verifier its verifies bytecode to ensure the loaded class is not corrupted
  5. If there are not issues reported by the ‘Bytecode Verifier’ it is executed by then Execution Engine
  6. Execution Engine includes JIT Compiler and Interpreter
  7. Garbage Collector is responsible for automatic memory management
  8. Security Manager is responsible for security, like having additional checks to stop executing of bytecode which can access the filesystem, and having it execute in more restricted environment called the sandbox environment

Java Software family

Java SE - is a set of specifications which includes Java Language Specification(JLS), Java Virtual Machine specification(JVMS), Java API Specification

Java SE implementations(JDK’s) - are Oracle JDK(official), Oracle OpenJDK,AdoptOpenJDK, Amazon Corretto, Red Hat’s OpenJDK etc..,

JDK or Java SDK - has Dev tools(like java compiler), JVM, Java API

image

JSR - Java specification request, describes the features added to a release, each release will have a JSR. JCP - Java community process, The process of developing JSR through different stages.

Installation

jdk download from - https://www.oracle.com/java/technologies/downloads/

Windows: set environment variable JAVA_HOME to C:\Program Files\Java\jdk-18 add to path PATH - add new C:\Program Files\Java\jdk-18\bin or %JAVA_HOME%\bin

uninstall -> control panel -> uninstall a program -> select java 18 -> click ‘uninstall’

Setting classpath

Windows: set environment variable classpath to .;

Classes

Class
variable declarations
constructors
methods
nested classes

HelloWorld.java

first program

‘Hello world’ program in Java


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

main() method

📘 Section 3: Classes, Objects and their Members

Object-Oriented Programming




class Student {
  // variable declaration
  int id;
  String name;
  String gender;

  // method definitions
  boolean updateProfile(String newName) {
    name = newName;
    return true;
  }
}

class StudentTest {
  public static void main (String[] args) {
    // 1. creating a new student object
    Student s = new Student();

    // 2. setting student's state
    s.id = 1000;
    s.name = "joan";
    s.gender = "male";

    // 3. updating profile with correct name
    s.updateProfile("john");
  }
}

BasicsDemo.java

Java’s Reserved Keywords


class, interface, enum, abstract, implements, extends, this, super 
byte, short, char, int, long, float, double, boolean 
break, continue, for, do, while, if, else, new, switch, default, case, goto 
try, catch, final, assert, throw, throws 
package, import 
public, private, protected 
synchronized, instanceof, return, transient, static, void, finally, strictfp, volatile, const, native

Following is the reference link from where the above information is taken: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html

Statically vs Dynamically typed languages

Below are few advantages of static typing:

References dynamic-type-languages-versus-static-type-languages what-do-people-find-so-appealing-about-dynamic-languages what-is-the-difference-between-statically-typed-and-dynamically-typed-languages

Primitive Data types

8 primitive types are:

Integer Primitive data types

Type Bit depth Value range Default
byte 8 bits -2^7 to 2^7 -1 0
short 16 bits -2^15 to 2^15 -1 0
int 32 bits -2^31 to 2^31 -1 0
long 64 bits -2^63 to 2^63 -1 0
Literals
Primitive variables of type int and long
// Binary - 65 number representation
int binary = 0b01000001;
int binary2 = 0b0100_0001;
long binary3 = 0b0100_0001L;
// Hexadecimal
int hexaDecimal = 0x0041;
// Octal
int octalInteger = 0101; // 65

Floating point data types

Type Bit depth Value range Default Precision
float 32 bits -3.4E38 to 3.4E38 0.0f 6-7 decimal digits
double 64 bits -1.7E308 to 1.7E308 0.0d 15-16 decimal digits

stick with int and double use byte, short, float, only if memory saving is important

// double
double doubleNumber = 3.5;
double doubleNumber2 = 3.5d;
double doubleNumber3 = 3.5e4;
double doubleNumber4 = 3.88888888888888888889; // 3.888888888888889 - 15 decimal places with rounding the last number

// float
float floatNumber = 3.8f;
float floatNumber2 = 3.88888888888888888889f; // 3.8888888 - 7 decimal places

BigDecimal

Avoid float and double if exact answers are required, use BigDecimal.

// BigDecimal
BigDecimal first = new BigDecimal("0.1");
BigDecimal second = new BigDecimal("0.2");
System.out.println(first.add(second));

Characters Primitive type

Type Bit depth Value range Default
char 16 bits 0 to 2^16-1 ‘\u0000’(null character)

‘B’ -> UTF-16 hexadecimal number 0042 -> 16 bit unsigned representation 00000000 01000010

Reference: Unicode characters https://unicode-table.com/en/

// ways to initialize a char
char alphabet = 'B'; // char literal
char degree = '\u0042'; // unicode escape sequence
char charInt = 65; // int literal
char charHex = 0x0041; // int literal
char charBinary = 0b0100_0001; // int literal
char charOctal = 0101; // int literal

Boolean primitive type

// ways to initialize a boolean
boolean international = true;
boolean byDefault; // equals false

Variable kinds

Instance & static variables are also referred to as fields or attributes. Attributes is probably more commonly associated with instance variables.

Multiple variable declaration

// other ways to initialize a variable
double tuitionFee = 12000.0, internationalFee = 5000.0;

double tuitionFee, internationalFee = 5000.0;
tuitionFree = 12000.0;

double tuitionFee = 12000.0;
double internationalFee = tuitionFee = 5000.0; // tuitionFee is re-initialization here
tuitionFree = 100.0; // re-initialization on class level is not allowed, but can be done as mentioned above.

Type Casting

Implicit Casting

// Implicit casting examples
int x = 65;
long y = x; // implicit casting by compiler

Explicit Casting

// Explicit casting examples

long y = 42;
int x = (int) y;

byte b = 65;
char c = (char) b; // c = 'A', both widening and narrowing is done as byte is converted to int and then int to char

char c = 65; // c = 'A' (implicit)

short s = 'A'; // s = 65; (implicit)
Information loss in Explicit casting
Information loss in Implicit casting

Casting Use-cases

// Implicit Casting
float f1 = 3.133f;
float f2 = 4.135f;

go(double d1, double d2) {
  
}

go(f1, f2);

// Explicit Casting
double avg = (2+3)/2; //2.0, not 2.5F
double avg = (double)(2+3)/2;

Variables holding Object references

Student s = new Student(); new Student() -> Allocate space for new Student object = -> s <- student object's address Sutdent s -> Allocate space for reference variable

Student s;
s.updateProfile(); // NullPointerException

Statements

Array

// Array initialization
// int scores[] = new int[4]; or
int[] scores = new int[4];

scores[0] = 90;
scores[1] = 70;
scores[2] = 80;
scores[3] = 100;

int[] scores = new int[] {90, 70, 80, 100}; // second way of initializing an array

int[] scores = {90, 70, 80, 100}; // third way of initializing an array

2D Arrays

// first way
int[][] myArray = new int[4][2];
myArray[0][0] = 9;
myArray[0][1] = 11;
myArray[1][0] = 2;
myArray[1][1] = 5;


// second way
int[][] myArray = new int[][] {{ 9, 11 }, { 2, 5 }, { 4, 4 }, { 6, 13 }};

// third way
int[][] myArray = {{ 9, 11 }, { 2, 5 }, { 4, 4 }, { 6, 13 }};


// Array with irregular rows
int[][] myArray = new int[2][];
myArray[0] = new int[5];
myArray[1] = new int[2];

3D Arrays creation and Initialization

// first way
int[][][] myArray = new int[4][4][4];
myArray[0][3][1] = 850;

// second way
int[][][] myArray = new int[1][1][1] };

// third way
int[][][] myArray = };

Methods

// Defining method
returnType methodName(type param1, type param2, ...) {
  ...
  return someValue;
}
// method signature -> methodName(type param1, type param2, ...)

// invocation of method
type varName = methodName(arg1, arg2, ...) // arguments are passed

Return Type

Method Types

Instance Methods
Static Methods

Assignment: MoneyTransferService.java

Data passing in Java

image

Primitives in Memory
Object References in Memory
Pass by Value
// Pass by Value: Primitives
void updateId(int newId) {
  newId = 1001;
}

int id = 1000;
updateId(id);
// s value here remains 1000

// Pass by Value: Object References
void updateId(Student s1) {
  s1.id = 1001;
}
Student s = new Student();
s.id = 1000;
updateId(s);
// s.id value here is changed to 1001

Java is always pass by value!!

Method OverLoading

// Valid Examples
void updateProfile(int newId) {}
void updateProfile(int newId, char gender) {}
void updateProfile(char gender, int newId) {}
void updateProfile(short newId) {}

// Method invocation
// Complier picks the most specific one
updateProfile(1000, 'F'); // compiler picks, 'void updateProfile(int newId) {}'
updateProfile(1000); // complier picks, `void updateProfile(int newId, char gender) {}`
byte b = 50;
updateProfile(b); // compiler picks, `void updateProfile(short newId) {}`

varargs

Constructors

// syntax
ClassName(type param1, type param2) {
  ...
}

// Constructor
class Student {
  int id;
  Student(int newId) {
    id = newId;
  }
}
Students = new Student(1001); 

Constructor Overloading

// Example
FileOutputSteam(String name, boolean append) // append
FileOutputSteam(String name) // for overwrite
FileOutputSteam(File file)
FileOutputSteam(File file, boolean append) // true - append, false - overwrite
FileOutputSteam(FileDescriptor fdObj)

// Invocation
new FileOutputStream("blah.txt"); // instead of
new FileOutputStream(new File("blah.txt"), false);

this()

StudentWithConstructor.java Assignment: Arrays with Object Reference, Instructor.java, Book.java

📘 Section 4: Method Building Blocks: Operators and Control-flow Statements

Operators

Unary, Binary & Ternary Operator

Arithmetic Operators

Shorthand Operators

Pre and Post increment
int x = 5;

// Post increment
int y = x++; // y = 5, x = 6
// equals to
int y = x;
x = x + 1;

// Pre increment
int y = ++x; // y = 6, x = 6
// equals to
x = x + 1;
int y = x;

// Post decrement
int y = x--; // y = 5, x = 4

// Pre decrement
int y = --x; // y = 4, x = 4

Arithmetic Operations Rules

Operator Precedence

5 + 9 - 3 + 2 * 5

Operand Promotion
Same-Type Operations
Mixed-Type Operations
Comparison operators
age > 21;
age >= 21;
age < 21;
age <= 21;
age == 21;
age != 21;
Student s1 = new Student(1000, "Dee");
Student s2 = new Student(1000, "Dee");

System.out.println("s1 == s2: " + (s1 == s2));
Logical Operators
if(age > 35 ) { // comparison operators test one condition
  if (salary > 90000) {
    // approve load
  }
}

if(age > 35 && salary > 90000) { // Logical operators test multiple conditions
  // approve loan
}

age = 37 and salary = 80000
(age > 35 && salary > 90000) false
(age > 35 || salary > 90000) true
!(age > 35) false
if (s!= null && s.age > 21) {
  // ...
}

Assignment: CarPriceEstimator.java

Bitwise Operators

& -> Bitwise AND -> returns 1 if both input bits are 1 -> (1 & 3) => 1 | -> Bitwise OR -> returns 1 if either of the input bits is 1 -> (1 | 3) => 3 ^ -> Bitwise XOR (Exclusive OR) -> Returns 1 only if one of the input bits is 1, but not both -> (1 ^ 3) => 2 ~ -> Bitwise Not -> inverts bits of the operand -> (~1) => -2

Compound Bitwise Assignment

NOTE: (1) Among bitwise, &, |, and ^ can be used with boolean operands. Bitwise NOT (~) will not even compile with boolean. If we need such a behavior, then we would use logical NOT (!) operator.

(2) Also, strictly speaking to be consistent with the Java Language Specification (JLS), &, and ^ when applied on boolean operands are referred to as logical operators and not bitwise. In other words, the operators &, , ^, ~ are referred to as bitwise ONLY when they are applied on integer operands and this is the common scenario as we discussed. Also note that, as we discussed && and   are also logical operators, but recall that they have the short-circuit property due to which JLS refers to them as conditional AND and condition OR respectively. With & and , as discussed in the lecture, they do not have the short-circuit property, i.e., they always force JVM to evaluate both operands.
Bit Shift Operators

There are 3 bit shift operators “«” - left-shift “»>” - right shift “»” - signed right shift

Left-Shift operator(«)
// 6 (binary representation in full 32 bits) -> 00000000 00000000 00000000 00000110
6 << 1 // 12 (binary representation in full 32 bits) -> 00000000 00000000 00000000 00001100
6 << 1 -> 6 * 2^1 -> 12
6 << 3 -> 6 * 2^3 -> 48
Unsigned Right-Shift operators(»>)
// 12 (binary representation in full 32 bits) -> 00000000 00000000 00000000 00001100
12 >>> 1 // 6 (binary representation in full 32 bits) -> 00000000 00000000 00000000 00000110
12 >>> 1 -> 12/2^1 -> 6
Signed Right-shift operator (»)
-2,147,483,552 -> 10000000 00000000 00000000 01100000
-2,147,483,552 >> 4-> 11111000 00000000 00000000 00000110 // -134,217,722
Applications
Compound Bit Shift Assingment

Control Flow statements

if-statement

static boolean ifStatement() {
  boolean approved = false;

  int age = 27;
  int salary = 60000;
  boolean hasBadCredit = false;

  if(age >= 25 && age <=35 && salary >=50000) {
    approved = true;
  }
  return approved;
}

switch

Boxed primitive or wrapper classes byte —> Byte short —-> Short char —-> Character int —–> Integer

Constant variables are declared using final.

int month = 3;

switch(month) {
  case 1: System.out.println("January"); break;
  case 2: System.out.println("February"); break;
  case 3: System.out.println("March"); break;
}

ternary operator


float result = true ? 25 : 65.5f;

result will be 25.0f as int literal 25 will be promoted to float as the false expression 65.5f is of the larger type float.

for statement

int[] iArray = {0, 1, 2, 3, 4};
for(int i = 0; i < iArray.length; i++) {
  System.out.println(iArray[i]);
}
// syntax
for (initialization; condition-expression; expression-list) {
  ...
}

Initialization

  for(int i = 0;;)
  for(int i=0, j=0;;)
  for(int i=0, int j=1;;) // invalid
  for(int i=0, double j=1.0;;) // invalid
  for(int i=1, j=2;;)
  for(int i=1, double d=10.0;;) // invalid
  for(i++;;)
  for(System.out.println(i);;)
  for(System.out.println(i), i++;;)

Condition Expression

for(int i=0;;i++) {
  System.out.println(i);
}

Expression List

for-each

for-each: Prefer for-each loops to traditional for loops

for(int i: iArray) {
  System.out.print(i + " ");
}

variable scope

int x = 10;

void foo() {
  int x = 0; // shadows class variable x
  x++;
  this.x++; // accessing class level variable
}
void foo() {
  int x = 0;
  bar();
}

void bar() {
  x++; // invalid
}

while statement

while(condition) {

};

do {

} while(condition);

break statement


b: for(;;) {
  for(;;) {
    break b;
  }
}

label1: if() {
  for() {
    break label1;
  }
}

// invalid
if() {
  break;
}

✏️ BasicsDemo.java - labeledBreak

continue


while(condition-expression) {
  if(condition) {
    continue;
  }
}

// invalid as there is no enclosed loop
label1: if() {
  for() {
    continue label1;
  }
}

✏️ BasicsDemo.java > labeledContinue

Recursion

✏️ Recursion.java > factorialNR, factorialR, BinarySearch

📘 Section 5: Packages, Strings and information hiding design principle

Java API

Packages

Why Packages?

Important packages

Header1 Header2
java.lang Fundamental classes
java.util Data structures
java.io Reading and Writing
java.net Networking
java.sql Databases
Accessing Classes

// import
import java.util.ArrayList;

class FooClass {
  void foo() {
    ArrayList list = new ArrayList();
  }
}
Importing Single vs Multiple classes
Fully-qualified class Name
import java.util.Date; // explicit import
import java.sql.*; // start import

Date date; // from util
java.sql.Date date2; // full-qualified class name
Any Side Affects in Using import?

java.lang is imported by default

Creating Packages

Setting classpath for packages
// BasicsDemoTest.java
package com.semanticsquare.basictest;

import java.util.ArrayList;
import com.semanticsquare.basics.BasicsDemo;

public class BasicsDemoTest {
  public static void main(String[] args) {
    new BasicsDemo().foo();
  }
}
> javac BasicsDemoTest.java
# setting of classpath only for the current execution
set classpath=.;C:\project;
# clearing of classpath
set classpath=
# to set it permanently use environment variables

# set using flag, only for the current command
> javac -cp C:\javaindepth\src BasicsDemoTest.java
# or
> javac -classpath C:\javaindepth\src BasicsDemoTest.java
Sub packages

java.util - import java.util.* java.util.concurrent - sub package - import java.util.concurrent.*

Note: to create class files in a directory for all the file execute, com\semanticsquare\basics\*.java or javac *.java

Access Levels

Accessibility for Classes/Interfaces

// "public" is the access modifier, added before class keyword
public class BasicsDemo {

}
Accessibility for Class Members

Strings

Strings: Introduction

// not recommended
String s = new String(); // empty string
String s = new String("hello!");

char[] cArray = {'h', 'e', 'l', 'l', 'o'};
String s = new String(cArray);

// recommended // internally implemented in efficient way
String s = "hello"; // string literal // recommended

String object ~ immutable sequence of unicode characters

Strings: Common Operations

✏️ BasicsDemo.java > stringExamples

Strings: 3rd Party String Utilities

String: String Literal vs Using new

image

String Pool

✏️ BasicsDemo.java > stringPool

String Concatenation


// + operator
// Concatenation happens from left to right
String s = "hello" + "world!" + 125 + 25.5 // "hello world!12525.5"
String s = 125 + 25.5 + "hello" + "world!" // "150.5hello world!"
StringBuilder

StringBuilder sb = new StringBuilder();
sb.append("hello");
sb.append(" world!");
String s = sb.append("Good").append("morning").toString();
StringBuffer

Time complexity of + operator


s += "a"; // copy of "" and a are made to generate a
s += "b"; // copy of a and b are made to generate ab
s += "c"; // copy of ab and c are made to generate abc

Time complexity of StringBuilder

📔 Refer resources/string_builder_performance.pdf

Escape Sequences

💯 exercises > SentimentAnalyzer

Information Hiding