
Explore the dev.java website, learn about Java 17 and the JDK/JVM, and access tutorials, news, and community proposals guiding Java learning.
Learn the basics of getting started with Java: set up a JDK, create a first Java project, compile and run hello world, and understand Eclipse's build and classpath.
Create your first Java class and learn how source files, extensions, packages, and package level access organize code, with public class per file rules and working directory context.
Learn how Java compiles your first class into class files with javac and how the JVM loads and unloads those classes at runtime.
Discover how to download and set up the Java development kit, choose between open JDK and Oracle builds, and configure the path environment variable for the JVM.
Set up a Java development environment by installing the JDK, creating JAVA_HOME, and updating PATH across Windows, Mac, and Linux to enable Java and Java tools like javac and Maven.
Learn to set up the JDK, configure PATH and JAVA_HOME, and compile your first Java class with javac. Understand imports, checked exceptions, and how class files are produced across platforms.
Explore the important concept of CLASSPATH while building Java programs: set up the JDK and PATH, create classes with templates in Eclipse, and run with the JVM.
Explore single file Java applications by running the JVM with the main class, leveraging the JDK path and classpath, while grasping working directory, relative versus absolute paths, and IDE behavior.
Learn Java language basics, including variables, operators, expressions, statements, and blocks, and master scope, declarations versus initialization, and the difference between primitive types and objects.
Explore how Java stores state in fields, distinguishing static class variables from non-static instance variables. Learn about access modifiers, encapsulation, and camel case naming.
Examine how fields and local variables define state and scope in Java, using this to disambiguate, understand shadowing, and differentiate instance, static, and class-wide fields.
Explore Java naming rules and conventions for variables, including camel case, case sensitivity, valid identifiers, and how to distinguish constants with all caps and underscores.
Understand primitive types and variables in Java, including declaration versus definition, default values, literals, and size ranges like 8-bit bytes with two's complement, plus primitive versus wrapper concepts.
Explore Java primitive types and their wrappers, learn about signed numbers, overflow and underflow, and master integer and floating-point literals, casting, and readability with underscores.
Learn Java primitive types such as short, long, float, and double, with precision notes and double as the default for literals, and boolean values that drive conditions and JVM bytecode.
Explore booleans, final optimization, and compile-time evaluation in the Java bytecode path. Learn about char data types, UTF-16, ASCII, and immutable strings with the string pool.
Explore integer literals in decimal, hex, and binary, and use bit masks and shifts to extract rgba color components from packed values.
Examine how Java handles floating point literals, the default double precision, and scientific notation, and explore formatting, type inference with var, and string literals.
Explore how underscores group digits in Java numeric literals, including integers, floats, hex and binary, and learn valid positions, forbidden starts, and suffix rules like L and F.
Explore how Java arrays are fixed-size objects, zero-based, with primitive and reference types. Learn how to declare, initialize, access elements by index, and handle bounds with array length.
Becoming the master of Java: array initializer explains that Java arrays are built-in object types with fixed length, declared as type[] name, allocated with new, and initialized.
Explore how to create, initialize, and access arrays in Java using the new operator, covering primitive and reference types, multi-dimensional arrays, and default initialization rules.
Becoming master of Java explains copying arrays in Java using System.arraycopy with a memcopy for efficient data transfer, and why Arrays class provides type-safe copies for primitive and object arrays.
Explore Java arrays, from declaration and initialization to copying with Arrays and System.arraycopy, then sort, search, and manipulate with type-safe utilities, comparators, and streams.
Explore var, Java's local variable type inference, as a type identifier that lets the compiler infer the exact type for local variables, with caveats about scope, parameters, and type safety.
Master java var in local variables by letting the compiler deduce type from the right hand side. Do not use var for fields, parameters, or compound declarations.
Explore Java operator precedence by examining plus, minus, multiplication, division, and modulus, and see how integer division, remainder, and the ternary operator interact with var type inference.
Explore operator overloading across C++, Python, and Java, with practical point class examples and how Eclipse plugins enable or simulate overloading in each language.
Learn the assignment operator in Java, how the right-hand side is evaluated before assignment, and how primitives and object references differ from equality and copy constructor behavior.
Explore Java arithmetic operators, assignment semantics, and the modulus for circular buffers, with fixed-size arrays, int indexing, and string concatenation via plus and StringBuilder.
Explore unary operators in Java, including incrementing, negation, and logical negation, and learn how prefix and postfix forms affect evaluation.
Explore equality and relational operators in Java, learn how binary expressions evaluate left to right with potential side effects on operands, and see how booleans and comparisons map to bytecode.
Explore natural ordering for a class by overriding equals and hashCode and implementing comparable (compareTo) to support sorted collections like tree sets and navigable sets.
Explore Java's logical and and or operators, their short-circuiting behavior, and the ternary operator, with bytecode insight and practical examples.
Discover how the java instanceof operator tests at runtime whether an object is a specific class, subclass, or interface. Learn through examples with parent, child, and interface implementations.
Explore bitwise and shift operators in Java, including not, and, or, xor, and left and right shifts on primitive integer types; understand two's complement and practical examples.
Explore Java operators and expressions, including assignment, arithmetic, relational, and logical operators, with emphasis on precedence, evaluation order, and short-circuiting. Learn how expressions become statements and the floating-point equality caveats.
Java statements and expressions, including assignment, increment, method invocation, and object creation, with emphasis on semicolon termination, declarations, and control flow. Use Eclipse formatter to enforce consistent braces.
Learn the basic Java if statement with boolean conditions, the role of braces for scope, and how final local variables enable compile-time and bytecode optimizations.
Explore how while and do-while loops differ in condition testing, with examples on arrays in Java, and how break and continue control flow.
Explore the bytecode of a while loop in Java, detailing how the JVM uses stack frames, local variables, and goto and if comparisons to control loops.
Explore how for loops compare to while and do while, covering initialization, termination, and increment, with emphasis on scope, braces, and bytecode behavior.
Explore the for loop and the enhanced for loop in Java, including initialization, termination, and increment, and how to iterate arrays and collections.
This lecture examines the enhanced for loop in Java, shows its bytecode translation, array-based iteration, and how breaks, including labeled breaks, control nested loops.
Explore how break and continue shape loop flow, including labeled continues, and learn how return statements exit methods, with examples on counting letters and avoiding unreachable code.
Understand how the return statement controls Java method flow, matching types and handling void versus non-void returns, with finally interactions and the yield keyword in switch expressions.
Master the Java switch statement to control program flow with cases and break, learn about fall through, default behavior, and the transition to switch expressions for broader use.
This lecture explains the enhanced switch in Java, detailing comma-separated case labels, fall-through behavior, the role of break, and the transition to switch expressions from Java 14 onward.
Explore when to use switch statements versus if-else, focusing on compile-time constant case labels, default behavior, and the role of final and static in Java.
Explore how strings and wrapper primitives serve as switch arguments, including compile-time labels, equals-based string matching, null handling, auto boxing, and the bytecode underpinnings with hashCode and table switches.
Explore switch expressions in java 14 and beyond, returning values with arrow syntax, comma-separated cases, and yield for multi-line code, while handling default cases.
Learn how the yield keyword turns switch statements into expressions in Java, with arrow and colon forms, defaults, and exhaustive multi-line case blocks.
Explore the fundamentals of object oriented programming in Java: objects, classes, interfaces, packages, and inheritance, plus encapsulation, getters and setters, and composition for building robust software.
Learn how a class serves as a blueprint for objects, grouping data and behavior, enabling separation of concerns, loose coupling, and modular, testable design in Java.
Discover how inheritance establishes is-a relationships for code reuse and why composition can be preferred in some cases. Learn java's single inheritance, base and derived classes, and interfaces.
Explore how interfaces add capabilities without single inheritance, acting as a contract of methods. Learn that interfaces define types, use abstract methods, and support default and static methods in Java.
Explore how a class extends a superclass and implements multiple interfaces, with abstract methods, default interface methods, and override annotations.
Explore how packages organize Java code and how fully qualified names resolve imports. Understand the difference between built-in types and user-defined classes and the role of automatic imports.
Explore how Java uses packages and fully qualified names to locate class definitions, and how to set and troubleshoot the classpath with -cp, -classpath, and runtime search.
Understand how packages and fully qualified names map to class files and classpath, and how import statements simplify referencing types across Java packages.
Explore declaring classes in Java by creating classes and objects, defining fields and constructors, applying access modifiers, and working with nested, local, and anonymous classes.
Explore how to declare classes and interfaces in Java, use public and package level access, understand extends and implements, and leverage default and static interface methods.
Declare Java classes with access modifiers, package and import rules, including nested classes, and naming conventions; then manage fields, static vs instance fields, and encapsulation via getters and setters.
Learn how Java access modifiers—public, protected, private, and default—govern field access within the same class, same package, and other packages, with examples of private and default behavior.
Learn how Java enforces access modifiers on fields, methods, and constructors, including public, protected, private, and package level access, and how Eclipse outline and bytecode illustrate the access rules.
Define methods with modifiers, return types, and parameter lists, and examine static, abstract, and native options. Understand method signatures, overloading rules, and camel case naming to ensure valid, unique declarations.
learn how Java supports method overloading by using the same method name with different parameter types, numbers, or orders, while return types and modifiers do not affect the signature.
Constructors are special methods that create objects from a class blueprint using unique signatures; the new operator allocates memory and initializes the object, while access modifiers control constructor visibility.
Explore how to define and call methods and constructors, initialize superclass state, and distinguish parameters from arguments while mastering final fields and return type compatibility.
Learn how variable arguments (varargs) in Java let a method accept any number of arguments as a syntactic sugar for an array, with behind-the-scenes bytecode and overload implications.
Explore how Java varargs work with the dots syntax, how the compiler converts arguments to arrays, and how to handle field shadowing with this.
Understand how primitive data types are passed by value in Java, where the JVM copies the argument into the method's local parameter and the original variable remains unchanged.
Java passes values by value for primitives and reference types; primitives copy the value while references copy the address, enabling object mutation but not reference reassignment.
Explore how Java allocates objects using the new operator, stores object state on the heap, and manages memory with the garbage collector, heap vs. stack, and runtime memory details.
Explore how the JVM allocates memory at startup, tracks free, total, and max memory, and how gc and 32-bit vs 64-bit addressing affect xms and xmx settings.
Explore how the new operator creates objects, allocates memory on the Java heap, initializes state via constructors, and how references and garbage collection manage memory in Java.
Explains how the Java new operator allocates memory and invokes a constructor to instantiate objects, while clarifying null initialization, local versus field defaults, and temporary objects becoming garbage.
Master how implicit default no-argument constructors work and why explicit constructors remove automatic no-arg options. Understand constructor overloading and why subclass constructors must call superclass constructors to avoid runtime errors.
Learn how the dot operator accesses an object's state and how static fields are shared across all instances, while private fields use getters and this for safe access.
Explore how Java creates objects with new and allocates non-static state on the heap. Understand how automatic garbage collection reclaims memory, the non-deterministic destruction, and the deprecation of finalize.
Discover how Java garbage collection identifies object eligibility for garbage collection, and how finalize() behavior and GC flags influence invocation and memory reclamation across versions.
Explore how polymorphism affects return types in Java methods, returning subclass objects as superclass types, and manage compatibility, casting, and method termination across try, catch, and finally.
Demonstrate how polymorphism lets a method with a super type return a subclass or interface implementation. Examine covariant return types, primitive and reference type compatibility, and casting with runtime checks.
Explore how the this keyword references the current object in instance methods and constructors, distinguish local variables from fields, and qualify static fields with the class name.
Explore Java access modifiers and compile-time constants, including public, private, protected, and package-private, and learn data encapsulation by exposing only through public methods.
Explore static fields and methods as class-wide state shared by all objects, contrast with non-static instance state, and note memory allocation and compile-time constants, and private constructors in utility classes.
Master static class members and static imports in Java, accessing shared state via the class name, and using static methods and constants like toRadians and PI without qualification.
Explain how static initializers initialize static fields when the class is loaded and how this differs from instance initialization. Follow the execution order: the superclass constructor, static initialization, then instance initialization, and the rest of the subclass constructor.
Explore how instance initializers and static initialization blocks initialize class state in Java, how the compiler separates declarations from initialization, and the impact on constructors and order.
Learn how inner classes work in Java, how an inner class accesses the outer class’s state, and how to instantiate it with an outer instance, via a car and battery.
Explore nested and inner classes in Java, including static nested classes, their access to outer state, initialization order, and naming conventions for inner types.
Explore when to use nested classes to logically group helpers and manage dependencies, including dependency injection, inner vs static nested classes, and encapsulation in a car battery wheel example.
Explore how the hierarchy of nested classes resolves shadowing and the this pointer across levels. Use qualified this and fully qualified class names to access outer and inner fields.
Explore how nested and inner classes interact, including static nested classes, and examine how synthetic constructors enable outer-class references, bytecode access, and serialization considerations.
Explore nested classes and inner types in Java, including method local and anonymous classes, and preview a data structure with a custom iterator for even numbers.
Learn how method local inner classes in java are declared inside a method, can access that method’s locals, are not accessible outside, and receive unique compiler names with dollar markers.
Explore local and method local inner classes in Java, their scope and state, how they access enclosing variables, and the final or effectively final requirements for captures.
Explore anonymous classes and functional interfaces in Java, compare local and inner classes, local interfaces, static and non static state, and embrace lambda expressions for concise implementations.
This course will take you on a journey of fundamentals of Java all the way through the bytecodes to the more advanced topics of programming.
Understanding and mastering Java programming will immediately put you in a good position for learning other languages such as C++ and Python.
The syntax of Java was designed to be similar to that of the C++ programs, hence if you are coming from the C++ world, then you are already halfway through mastering the Java language! Similarly, Python operates based on the assumption that every type is represented by an Object, hence closely resembles the philosophy that Java language follows.
This course is structured in a way to be very congruent with the official Oracle website for learning Java called dev dot java website. I will walk you through all the items discussed on dev dot java website and give very detailed examples of explanations.
One strong feature of this course is the frequent look under the hood in the bytecode of classes. Bytecodes are the compiled code that the java compiler "javac" provides, which sometimes reveal the hidden extra codes that javac adds to accomplish a task. For example, in the most recent version of JDK (java development kit), String concatenation always translates into creating a StringBuilder object behind the scene and calling its "append" method. Understanding such behind the scene concepts will enable you to truly master the Java language and write efficient codes.
The topics discussed in this course are:
Section 1: Getting Started with Java
In this section, I introduce the dev dot java website and discuss concepts such as "JAVA_HOME" and "CLASSPATH" environment variables. The concept of CLASSPATH will be discussed in more detail later in section 9 when I discuss the concept of java "packages".
Section 2: Primitives and Literals
This section is the absolute beginner's introduction to Java language features. Java language supports raw primitives and also provides wrapper classes (also called Boxed primitives). I discuss all of the supported primitives such as byte, short, int, long, float, double.
Section 3: Arrays
This section is dedicated to the built-in array construct in java. Java language allows primitive arrays and object arrays. An array can be directly initialized when it is declared. User-defined classes cannot extend built-in arrays.
Section 4: Local Variable Type Inference
This section is a brief introduction to the "var" identifier that was introduced in the recent versions of java. "var" allows the compiler to infer the type of local variables without the need for the developer to intervene.
Section 5: Operators in Java
This section introduces the core concept of operators that the java programming language supports. Math operators such as "addition +", "subtraction -", and "modulus %" are discussed in detail. The important concept of "operator overloading" is also discussed.
Section 6: Expressions and Statements
This section briefly presents a discussion on what constitutes an expression and a statement in java. Expressions are formed from operators and operands. Statements consist of one or more expressions and are always terminated by the semicolon ";".
Section 7: Control flow statements
This is an important section that discusses the control flow statements such as "if", "if else", "while" loop, "for" loop, "switch expression" and "switch statement". The behind the scene bytecode is also reviewed for each control flow construct.
Section 8: Intro to Object-Oriented Programming
This section is the introduction to the main concepts of object-oriented programming. Java language was developed with these concepts in mind and relies on the "inheritance", "abstraction", and "interfaces". Every "class" definition in java implicitly inherits from the "Object" class that exists inside the "java.lang" package. The idea of organizing the java project into packages and fully-qualified-name of the types is discussed in great detail.
Section 9: Classes and Objects
This section puts the general concepts of object-oriented programming in the context of Java programming (syntax) and the unique features that Java provides. We discuss how java handles inheritance, polymorphism, encapsulation, and the difference between the static and non-static states of objects.
Section 10: Advanced Topics on Classes and Objects
This section dives deeper into the features of classes and objects that Java programming provides.
Section 11: Introduction to Java Native Interface
This section is an introduction to the foreign function interface (FFI) that the java development kit provides. JNI is considered by some as a difficult topic and is rarely discussed in lectures and courses. This chapter assumes the student has some knowledge of C++ programming and how to compile ".cpp" and ".h" files.
Section 12: Introduction to Effective Java
This section introduces the most important book titled "Effective Java" that every java developer must have. Each lecture corresponds to an item of best practices of java programming that is discussed in the book.
Section 13: Miscellaneous Topics
This section provides additional insights about the java programming language or the tools that are directly or indirectly related to java programming. Tools such as GraalVM's native image and Jupyter notebooks are discussed.