Lecture Notes 1 Overview of Object-Oriented Programming Paradigm Object-oriented programming and Java (Object-oriented programming and Java. Differences between Java and C++. Software) Object-oriented programming (OOP) is a computer programming model that organizes software design around data, or objects, rather than functions and logic. An object can be defined as a data field that has unique attributes and behavior. OOP focuses on the objects that developers want to manipulate rather than the logic required to manipulate them. This approach to programming is well-suited for programs that are large, complex and actively updated or maintained. This includes programs for manufacturing and design, as well as mobile applications; for example, OOP can be used for manufacturing system simulation software. The organization of an object-oriented program also makes the method beneficial to collaborative development, where projects are divided into groups. Additional benefits of OOP include code reusability, scalability and efficiency. The first step in OOP is to collect all of the objects a programmer wants to manipulate and identify how they relate to each other -- an exercise known as data modeling. Examples of an object can range from physical entities, such as a human being who is described by properties like name and address, to small computer programs, such as widgets. Once an object is known, it is labeled with a class of objects that defines the kind of data it contains and any logic sequences that can manipulate it. Each distinct logic sequence is known as a method. Objects can communicate with well-defined interfaces called messages. What is the structure of object-oriented programming? The structure, or building blocks, of object-oriented programming include the following: Classes are user-defined data types that act as the blueprint for individual objects, attributes and methods. Objects are instances of a class created with specifically defined data. Objects can correspond to real-world objects or an abstract entity. When class is defined initially, the description is the only object that is defined. Methods are functions that are defined inside a class that describe the behaviors of an object. Each method contained in class definitions starts with a reference to an instance object. Additionally, the subroutines contained in an object are called instance methods. Programmers use methods for reusability or keeping functionality encapsulated inside one object at a time. Attributes are defined in the class template and represent the state of an object. Objects will have data stored in the attributes field. Class attributes belong to the class itself. This image shows an example of the structure and naming in OOP. What are the main principles of OOP? Object-oriented programming is based on the following principles: Encapsulation. This principle states that all important information is contained inside an object and only select information is exposed. The implementation and state of each object are privately held inside a defined class. Other objects do not have access to this class or the authority to make changes. They are only able to call a list of public functions or methods. This characteristic of data hiding provides greater program security and avoids unintended data corruption. Abstraction. Objects only reveal internal mechanisms that are relevant for the use of other objects, hiding any unnecessary implementation code. The derived class can have its functionality extended. This concept can help developers more easily make additional changes or additions over time. Inheritance. Classes can reuse code from other classes. Relationships and subclasses between objects can be assigned, enabling developers to reuse common logic while still maintaining a unique hierarchy. This property of OOP forces a more thorough data analysis, reduces development time and ensures a higher level of accuracy. Polymorphism. Objects are designed to share behaviors and they can take on more than one form. The program will determine which meaning or usage is necessary for each execution of that object from a parent class, reducing the need to duplicate code. A child class is then created, which extends the functionality of the parent class. Polymorphism allows different types of objects to pass through the same interface. Key Differences between C++ and Java Though both the titans share the object-oriented programming nature's roots, they were never purely object-oriented because of their origin, design, and support libraries. Hence, they have their differences against a variety of aspects. 2 Java Syntax and Structure Java Basics (Simple programs. Simple data types and literals. Type casting. Basic Java operators. Example programs) UML Basics (Class Diagrams in UML) 1. **Introduction to Java** - Brief history and importance in the software development industry. - Platform independence and the JVM (Java Virtual Machine). 2. **Java Development Environment** - Setting up JDK (Java Development Kit) and IDE (Integrated Development Environment). - Writing and compiling a simple "Hello, World!" program. 3. **Java Language Basics** - Comments, identifiers, and keywords. - Data types (primitive and non-primitive). - Variables and constants. - Operators (arithmetic, relational, logical, assignment, etc.). - Control flow statements (if-else, switch, loops). 4. **Methods and Classes** - Declaring methods and calling them. - Creating classes and objects. - Class inheritance and method overriding. 5. **Exception Handling** - Handling exceptions using try-catch blocks. - Using the finally block for cleanup. 6. **Arrays and Strings** - Declaring and initializing arrays. - Working with strings and common string operations. ### Java Basics (Simple Programs, Simple Data Types and Literals, Type Casting, Basic Java Operators, Example Programs) - **Simple Programs** - Writing basic programs to demonstrate concepts like input/output, loops, conditionals, etc. - **Simple Data Types and Literals** - Explanation of primitive data types (int, float, double, char, boolean). - Using literals to represent values. - **Type Casting** - Implicit and explicit type casting (casting between primitive data types). - **Basic Java Operators** - Arithmetic operators (+, -, *, /, %). - Relational operators (>, <, >=, <=, ==, !=). - Logical operators (&&, ||, !). - Assignment operators (=, +=, -=, *=, /=, %=). - **Example Programs** - Writing example programs to illustrate the use of basic Java concepts. ### UML Basics (Class Diagrams in UML) 1. **Introduction to UML** - Overview of UML and its importance in software development. - Different types of UML diagrams and their purposes. 2. **Class Diagrams** - Understanding the components of a class diagram (class, attributes, methods, associations, etc.). - Drawing class diagrams to represent simple relationships between classes. 3. **Example Class Diagrams** - Creating class diagrams for simple real-world scenarios (e.g., modeling a library system, a student information system, etc.). 3. Setting Up Eclipse IDE for Java Development To download Java, go to https://docs.aws.amazon.com/corretto/latest/corretto-11ug/downloads-list.html This is the download site for the free Amazon Corretto version of the Java 11 - Java Development Kit (JDK). Java 11 is installed on the lab computers, and using the same version will avoid possible compatibility problems if you move files between machines. On the download page scroll down to the table of download choices, and in that table scroll down to find your computer: Click on the appropriate version for your computer, for Windows download the .msi installer, for macs download the .pkg package which contains the installer. Run the installer and accept all of the default choices during installation. After you finish installing java, you can delete the .msi or .pkg file. Downloading Eclipse Go to https://www.eclipse.org/downloads/packages/release/2021-06/r/eclipse-ide-javadevelopers This is the version of Eclipse which is installed in the labs. Use this version to avoid compatibility conflicts. Click the "Download ..." button. This takes you to a second page to download the version that matches your machine Run the downloaded installer file (on macs double click the Eclipse installer) (Be patient. At times this is slow.) Click on "Eclipse IDE for Java Developers" Check that it is using the Corretto jdk On Macs note the installation folder for later Click [INSTALL]. Accept the unsigned content warning. [Launch] Running Eclipse for the first time When you run Eclipse for the first time, it will ask you to choose a folder for your "workspace" where it will keep your files. I just accepted the default location. You also might consider putting it on you USB flash drive if you want to bring it into the lab or other USM computers. When Eclipse first starts you will see a Welcome page. To get rid of it just click on the X on the Welcome tab. Follow the instructions in Lab1 to write and run your first program and make sure everything is working. On macs move eclipse to the applications folder On macs the executable Eclipse.app is put in the installation folder that you noted during installation. Open that folder in Finder: Go > Computer > Macintosh HD > Users > ..., and drag and drop Eclipse.app into the Applications folder. 4 Fundamentals of object-oriented programming (Basic concepts. Classification of subtypes of OOP. History. Definition of OOP and its basic concepts. Difficulties of definition. Concepts. Features of implementation. Design of programs in general. Various OOP methodologies. Component programming. Prototype programming. Class-oriented programming. Performance of object programs. Criticism of OOP. Object-oriented languages) Understanding Data Types in Java The fascinating journey of Object-Oriented Programming (OOP) began in the 1960s with the groundbreaking development of the Simula programming language. Simula was a pioneer, being the first language to introduce the world to the revolutionary concept of classes and objects. This laid the crucial foundation for OOP that we know and appreciate today. However, the true potential of OOP wasn't fully realized until the 1980s, when the Smalltalk language emerged. With its innovative design, Smalltalk made OOP more accessible and versatile, leading to its widespread adoption. Since that pivotal moment, numerous programming languages have embraced OOP principles, including Java, C++, Python, and C#. In simple terms, classes are custom data types created by users. They provide a blueprint for organizing attributes and methods. Objects are created using this blueprint as a base. Classes consist of fields (attributes) and methods (behaviors). For example, in a superhero class like Iron Man, attributes could be name and suit color, while methods might be fly() and shootLaser(). Here's a basic example of how to create an Iron Man class using JavaScript: This code demonstrates the creation of an Iron Man class with name and suit color attributes, as well as fly() and shootLaser() methods. 5 Control Flow: Decision Making in Java Java control statements (Conditional if() statement. Conditional switch() statement. For() loop statement. While() loop statement. Do-while() statement. Break() and continue() labels and instructions. Example programs). Java compiler executes the code from top to bottom. The statements in the code are executed according to the order in which they appear. However, Java provides statements that can be used to control the flow of Java code. Such statements are called control flow statements. It is one of the fundamental features of Java, which provides a smooth flow of program. Java provides three types of control flow statements. 1. Decision Making statements o if statements o switch statement 2. Loop statements o do while loop o while loop o for loop o for-each loop 3. Jump statements o break statement o continue statement Decision-Making statements: As the name suggests, decision-making statements decide which statement to execute and when. Decision-making statements evaluate the Boolean expression and control the program flow depending upon the result of the condition provided. There are two types of decisionmaking statements in Java, i.e., If statement and switch statement. 1) If Statement: In Java, the "if" statement is used to evaluate a condition. The control of the program is diverted depending upon the specific condition. The condition of the If statement gives a Boolean value, either true or false. In Java, there are four types of if-statements given below. 1. Simple if statement 2. if-else statement 3. if-else-if ladder 4. Nested if-statement Let's understand the if-statements one by one. 1) Simple if statement: It is the most basic statement among all control flow statements in Java. It evaluates a Boolean expression and enables the program to enter a block of code if the expression evaluates to true. Syntax of if statement is given below. 1. if(condition) { 2. statement 1; //executes when condition is true 3. } Consider the following example in which we have used the if statement in the java code. Student.java Student.java 6 Arrays (Creating a one-dimensional array. Two-dimensional and multidimensional arrays. Character arrays. Assigning and comparing arrays. Example programs) 7 Classes and Objects (Creating classes and objects. Static elements. Accessing class members. The this keyword. Inner classes. Anonymous objects. Example programs) 8 Methods and constructors (Method overloading. Constructors. Object as an argument and result of a method. Methods of passing arguments. Example programs) Methods and Constructors in Java **1. Methods** - **Definition**: Methods in Java are blocks of code that perform a specific task. They are defined within a class and can be called to execute the code inside them. - **Syntax**: ```java returnType methodName(parameterType parameter1, parameterType parameter2, ...) { // Method body } ``` - **Example**: ```java public int add(int a, int b) { return a + b; } ``` **2. Method Overloading** - **Definition**: Method overloading is the practice of defining multiple methods in a class with the same name but different parameters. This allows methods to perform similar tasks with different inputs. - **Example**: ```java public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } ``` **3. Constructors** - **Definition**: Constructors are special methods in Java that are used to initialize objects. They have the same name as the class and do not have a return type. - **Syntax**: ```java public class ClassName { // Constructor public ClassName() { // Constructor body } } ``` - **Example**: ```java public class Person { private String name; // Constructor public Person(String name) { this.name = name; } } ``` **4. Using Objects as Arguments and Return Values** - Objects can be passed as arguments to methods and can also be returned from methods. - **Example**: ```java public class Calculator { public int add(int a, int b) { return a + b; } public Person createPerson(String name) { return new Person(name); } } ``` **5. Methods of Passing Arguments** - **Pass by Value**: In Java, arguments are passed by value, which means a copy of the argument is passed to the method. - **Pass by Reference**: Java does not support pass by reference. When an object is passed to a method, a reference to the object is passed by value. **Example Programs**: - Method Overloading: ```java public class Calculator { public int add(int a, int b) { return a + b; } public double add(double a, double b) { return a + b; } } ``` - Constructors: ```java public class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } } ``` - Using Objects as Arguments and Return Values: ```java public class Main { public static void main(String[] args) { Calculator calc = new Calculator(); int sum = calc.add(5, 10); System.out.println("Sum: " + sum); Person person = calc.createPerson("Alice"); System.out.println("Person name: " + person.getName()); } } ``` - Methods of Passing Arguments: ```java public class Main { public static void main(String[] args) { int a = 5; int b = 10; swap(a, b); System.out.println("a: " + a + ", b: " + b); } public static void swap(int x, int y) { int temp = x; x = y; y = temp; } } ``` These are the key concepts and examples related to methods and constructors in Java. 9 Inheritance and method overriding (Creating a subclass. Accessing superclass elements. Constructors and inheritance. Referencing a superclass element. Overriding methods in inheritance. Multi-level inheritance. Superclass object variables and dynamic method management. Abstract classes. Example programs) ### Inheritance and Method Overriding in Java **1. Creating a Subclass** - Inheritance in Java allows a class (subclass/child class) to inherit attributes and methods from another class (superclass/parent class). - Syntax for creating a subclass: ```java class SubClass extends SuperClass { // Subclass methods and attributes } ``` **2. Accessing Superclass Elements** - Subclasses can access public and protected members (fields and methods) of the superclass. - Example: ```java class SuperClass { public int publicField; protected int protectedField; private int privateField; } class SubClass extends SuperClass { public void accessFields() { publicField = 1; // OK protectedField = 2; // OK // privateField = 3; // Not accessible } } ``` **3. Constructors and Inheritance** - Constructors are not inherited, but a subclass can call the superclass constructor using `super()`. - Example: ```java class SuperClass { public SuperClass() { System.out.println("SuperClass constructor"); } } class SubClass extends SuperClass { public SubClass() { super(); // Call superclass constructor System.out.println("SubClass constructor"); } } ``` **4. Referencing a Superclass Element** - Use `super` keyword to reference a member of the superclass. - Example: ```java class SuperClass { public void display() { System.out.println("SuperClass display method"); } } class SubClass extends SuperClass { public void display() { super.display(); // Call superclass method System.out.println("SubClass display method"); } } ``` **5. Overriding Methods in Inheritance** - Subclasses can provide a specific implementation for a method defined in the superclass (method overriding). - Use `@Override` annotation to indicate that a method is intended to override a superclass method (optional but recommended). - Example: ```java class SuperClass { public void display() { System.out.println("SuperClass display method"); } } class SubClass extends SuperClass { @Override public void display() { System.out.println("SubClass display method"); } } ``` **6. Multi-level Inheritance** - In Java, a class can inherit from another class, which in turn can inherit from another class, creating a multi-level inheritance hierarchy. - Example: ```java class A { // Class A } class B extends A { // Class B } class C extends B { // Class C } ``` **7. Superclass Object Variables and Dynamic Method Management** - In Java, you can create an object of the superclass and assign it to a variable of the superclass type, allowing dynamic method invocation based on the actual object type. - Example: ```java SuperClass obj = new SubClass(); obj.display(); // Calls SubClass display method ``` **8. Abstract Classes** - Abstract classes in Java cannot be instantiated and may contain abstract methods (methods without a body) that must be implemented by concrete subclasses. - Example: ```java abstract class Shape { abstract void draw(); // Abstract method } class Circle extends Shape { void draw() { System.out.println("Drawing a circle"); } } ``` 10 Packages and interfaces (Packages in Java. Interfaces. Interface links. Extending interfaces) - **Definition**: A package in Java is a way to organize related classes and interfaces into a single unit, making it easier to manage and locate them. - **Creating a Package**: ```java package com.example.mypackage; ``` - **Accessing Classes from a Package**: ```java import com.example.mypackage.MyClass; ``` - **Package Scope**: Classes with no specified access modifier are accessible only within the same package (package-private or default access). ### Interfaces - **Definition**: An interface in Java is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types. - **Interface Declaration**: ```java public interface MyInterface { // interface body } ``` - **Implementing an Interface**: ```java public class MyClass implements MyInterface { // class body } ``` - **Interface Constants**: ```java public interface MyInterface { int MY_CONSTANT = 10; } ``` ### Interface Inheritance - An interface in Java can inherit from another interface using the `extends` keyword. - **Extending an Interface**: ```java public interface MySubInterface extends MySuperInterface { // interface body } ``` - **Implementing Multiple Interfaces**: ```java public class MyClass implements MyInterface1, MyInterface2 { // class body } ``` ### Example Programs **1. Package Example**: ```java package com.example.mypackage; public class MyClass { // class body } ``` **2. Interface Example**: ```java public interface Animal { void eat(); void sleep(); } public class Dog implements Animal { public void eat() { System.out.println("Dog is eating"); } public void sleep() { System.out.println("Dog is sleeping"); } } ``` **3. Interface Inheritance Example**: ```java public interface Animal { void eat(); void sleep(); } public interface Pet extends Animal { void play(); } public class Dog implements Pet { public void eat() { System.out.println("Dog is eating"); } public void sleep() { System.out.println("Dog is sleeping"); } public void play() { System.out.println("Dog is playing"); } } ``` 11 Working with text.(Objects of the String class. The toString() method. Methods for working with strings. Comparing strings. Searching for substrings and indexes. Changing text strings. StringBuffer class. Command line arguments) here are three classes for working with text data in Java: String , StringBuffer and StringBuilder . Every developer faces the first one at the very beginning of learning the language. What about the other two? What are their differences, and when is it better to use one or the other class? In general, the difference between them is small, but it's better to understand everything in practice :) String class in Java StringBuffer class in Java Java StringBuilder class String class This class is a sequence of characters. All program-defined string literals like "This is String" are instances of the String class. String has two fundamental features: it is an immutable (immutable) class this is the final class In general, the String class cannot have descendants ( final) and instances of the class cannot be modified after creation ( immutable). This gives the String class several important benefits: 1. Due to immutability, the hashcode of an instance of the String class is cached. It doesn't need to be calculated every time because the object's field values will never change after it's been created. This gives high performance when using this class as a key for HashMap. 2. The String class can be used in a multi-threaded environment without additional synchronization. 3. Another feature of the String class is that the " +" operator in Java is overloaded for it. Therefore, concatenation (addition) of strings is quite simple: public static void main(String[] args) { String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit"; System.out.println(command); // Follow the white rabbit } Under the hood, string concatenation is performed by the StringBuilder or StringBuffer class (at the discretion of the compiler) and the method append(we'll talk about these classes a little later). If we add instances of the String class with instances of other classes, the latter will be cast to a string representation: public static void main(String[] args) { Boolean b = Boolean.TRUE; String result = "b is " + b; System.out.println(result); //b is true } This is another interesting property of the String class: objects of any class can be cast to a string representation using the method toString()defined in the class Objectand inherited by all other classes. Often the toString() method on an object is called implicitly. For example, when we display something on the screen or add a String to an object of another class. The String class has one more feature. All string literals defined in Java code, such as "asdf", are cached at compile time and added to the so-called string pool. If we run the following code: String a = "Wake up, Neo"; String b = "Wake up, Neo"; System.out.println(a == b); We will see true in the console because the variables will aactually brefer to the same instance of the String class added to the string pool at compile time. That is, different instances of the class with the same value are not created, and memory is saved. Flaws: It is easy to guess that the String class is needed primarily to work with strings. But in some cases, the features of the String class listed above can turn from advantages into disadvantages. Once strings have been created in Java program code, many operations are often performed on them: translation of strings into different registers; extraction of substrings; concatenation; etc. Let's look at this code: public static void main(String[] args) { String s = " Wake up, Neo! "; s = s.toUpperCase(); s = s.trim(); System.out.println("\"" + s + "\""); } At first glance, it seems that we just translated the line "Wake up, Neo!" to uppercase, remove extra spaces from this string and wrap it in quotation marks. In fact, due to the immutability of the String class, as a result of each operation, new string instances are created, and the old ones are discarded, generating a lot of garbage. How to avoid wasted memory usage? StringBuffer class To deal with temporary garbage creation due to modifications to the String object, you can use the StringBuffer class. This is mutablea class, i.e. changeable. An object of the StringBuffer class can contain a certain set of characters, the length and value of which can be changed by calling certain methods. Let's see how this class works. To create a new object, one of its constructors is used, for example: StringBuffer() - will create an empty (containing no characters) object StringBuffer(String str) - will create an object based on the variable str (containing all the characters of str in the same sequence) Practice: StringBuffer sb = new StringBuffer(); StringBuffer sb2 = new StringBuffer("Not empty"); String concatenation via StringBuffer in Java is done using the append. In general, the method appendin the StringBuffer class is overloaded in such a way that it can accept almost any data type: public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append(new Integer(2)); sb.append("; "); sb.append(false); sb.append("; "); sb.append(Arrays.asList(1,2,3)); sb.append("; "); System.out.println(sb); // 2; false; [1, 2, 3]; } The method appendreturns the object on which it was called (like many other methods), which allows it to be called "chained". The example above could be written like this: public static void main(String[] args) { StringBuffer sb = new StringBuffer(); sb.append(new Integer(2)) .append("; ") .append(false) .append("; ") .append(Arrays.asList(1,2,3)) .append("; "); System.out.println(sb); // 2; false; [1, 2, 3]; } The StringBuffer class has a number of methods for working with strings. We list the main ones: delete(int start, int end)- deletes a substring of characters starting from position start, endingend deleteCharAt(int index)- delete character at positionindex insert(int offset, String str)- inserts a string strat position offset. The method insertis also overloaded and can take different arguments replace(int start, int end, String str)- will replace all characters from position to startposition withendstr reverse()- reverses the order of all characters substring(int start)- will return a substring starting from position start substring(int start, int end)- will return a substring starting from position startto positionend The full list of methods and constructors is in the official documentation . How do the above methods work? Let's see in practice: public static void main(String[] args) { String numbers = "0123456789"; StringBuffer sb = new StringBuffer(numbers); System.out.println(sb.substring(3)); // 3456789 System.out.println(sb.substring(4, 8)); // 4567 System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789 sb = new StringBuffer(numbers); System.out.println(sb.reverse()); // 9876543210 sb.reverse(); // Return the original order sb = new StringBuffer(numbers); System.out.println(sb.delete(5, 9)); // 012349 System.out.println(sb.deleteCharAt(1)); // 02349 System.out.println(sb.insert(1, "One")); // 0One2349 } Advantages: 1. As already mentioned, StringBuffer is a mutable class, so when working with it, there is not the same amount of garbage in memory as with String. Therefore, if there are many modifications to the strings, it is better to use StringBuffer. 2. StringBuffer is a thread safe class. Its methods are synchronized and instances can be used by multiple threads at the same time. Flaws: On the one hand, thread safety is an advantage of the class, and on the other hand, it is a disadvantage. Synchronized methods are slower than non-synchronized methods. This is where StringBuilder comes into play. Let's see what kind of Java class it is - StringBuilder, what methods it has and what its features are. StringBuilder class StringBuilder in Java is a class that represents a sequence of characters. It is very similar to StringBuffer in everything except thread safety. StringBuilder provides an API similar to StringBuffer's. Let's demonstrate this with a familiar example by replacing the variable declaration from StringBufer with StringBuilder: public static void main(String[] args) { String numbers = "0123456789"; StringBuilder sb = new StringBuilder(numbers); System.out.println(sb.substring(3)); //3456789 System.out.println(sb.substring(4, 8)); //4567 System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789 sb = new StringBuilder(numbers); System.out.println(sb.reverse()); //9876543210 sb.reverse(); // Return the original order sb = new StringBuilder(numbers); System.out.println(sb.delete(5, 9)); //012349 System.out.println(sb.deleteCharAt(1)); //02349 System.out.println(sb.insert(1, "One")); //0One2349 } The only difference is that StringBuffer is thread-safe and all its methods are synchronized, while StringBuilder is not. This is the only feature. StringBuilder in Java is faster than StringBuffer due to non-synchronization of methods. Therefore, in most cases, except for a multi-threaded environment, it is better to use StringBuilder for a Java program. 12 Handling exceptional situations Exceptional situations. Exception classes. Description of the exceptional situation. Multiple catch{} block. Nested try blocks. Artificially throwing exceptions. Throwing exceptions using methods. Checked and unchecked exceptions. Creating your own exceptions 13 Multithreaded Programming (Java Threading Model. Creating a Thread. Creating Multiple Threads. Synchronizing Threads) ### Multithreaded Programming in Java **1. Java Threading Model** - Java supports multithreading, allowing multiple threads to execute concurrently within a single program. - Threads in Java are instances of the `Thread` class or implement the `Runnable` interface. **2. Creating a Thread** - Extending the `Thread` class: ```java public class MyThread extends Thread { public void run() { // Thread logic } } MyThread thread = new MyThread(); thread.start(); // Start the thread ``` - Implementing the `Runnable` interface: ```java public class MyRunnable implements Runnable { public void run() { // Thread logic } } Thread thread = new Thread(new MyRunnable()); thread.start(); // Start the thread ``` **3. Creating Multiple Threads** - Using loops to create multiple threads: ```java for (int i = 0; i < 5; i++) { Thread thread = new Thread(new MyRunnable()); thread.start(); } ``` **4. Synchronizing Threads** - Synchronization ensures that only one thread can access a block of code at a time, preventing data corruption. - Using synchronized methods: ```java public synchronized void synchronizedMethod() { // Synchronized method logic } ``` - Using synchronized blocks: ```java public void someMethod() { synchronized (this) { // Synchronized block logic } } ``` **Example Program:** ```java public class MyRunnable implements Runnable { private int count = 0; public void run() { for (int i = 0; i < 5; i++) { increment(); System.out.println(Thread.currentThread().getName() + ": " + count); } } private synchronized void increment() { count++; } public static void main(String[] args) { MyRunnable runnable = new MyRunnable(); Thread thread1 = new Thread(runnable); Thread thread2 = new Thread(runnable); thread1.start(); thread2.start(); } } ``` In this example, two threads (`thread1` and `thread2`) are created using the same instance of `MyRunnable`. The `increment` method is synchronized to prevent concurrent access to the `count` variable, ensuring that the output is correctly incremented. 14 I/O system (Byte and character streams. Console input using the System.in object. Console input using the Scanner class. Using a dialog box. Working with files) Java brings various Streams with its I/O package that helps the user to perform all the input-output operations. These streams support all the types of objects, data-types, characters, files etc to fully execute the I/O operations. Before exploring various input and output streams lets look at 3 standard or default streams that Java has to provide which are also most common in use: 1. System.in: This is the standard input stream that is used to read characters from the keyboard or any other standard input device. 2. System.out: This is the standard output stream that is used to produce the result of a program on an output device like the computer screen. Here is a list of the various print functions that we use to output statements: print(): This method in Java is used to display a text on the console. This text is passed as the parameter to this method in the form of String. This method prints the text on the console and the cursor remains at the end of the text at the console. The next printing takes place from just here. Syntax: System.out.print(parameter); Example: // Java code to illustrate print() import java.io.*; class Demo_print { public static void main(String[] args) { // using print() // all are printed in the // same line System.out.print("GfG! "); System.out.print("GfG! "); System.out.print("GfG! "); } } Output: GfG! GfG! GfG! println(): This method in Java is also used to display a text on the console. It prints the text on the console and the cursor moves to the start of the next line at the console. The next printing takes place from the next line. Syntax: System.out.println(parameter); Example: // Java code to illustrate println() import java.io.*; class Demo_print { public static void main(String[] args) { // using println() // all are printed in the // different line System.out.println("GfG! "); System.out.println("GfG! "); System.out.println("GfG! "); } } Output: GfG! GfG! GfG! printf(): This is the easiest of all methods as this is similar to printf in C. Note that System.out.print() and System.out.println() take a single argument, but printf() may take multiple arguments. This is used to format the output in Java. Example: // A Java program to demonstrate working of printf() in Java class JavaFormatter1 { public static void main(String args[]) { int x = 100; System.out.printf( "Printing simple" + " integer: x = %d\n", x); // this will print it upto // 2 decimal places System.out.printf( "Formatted with" + " precision: PI = %.2f\n", Math.PI); float n = 5.2f; // automatically appends zero // to the rightmost part of decimal System.out.printf( "Formatted to " + "specific width: n = %.4f\n", n); n = 2324435.3f; // here number is formatted from // right margin and occupies a // width of 20 characters System.out.printf( "Formatted to " + "right margin: n = %20.4f\n", n); } } Output: Printing simple integer: x = 100 Formatted with precision: PI = 3.14 Formatted to specific width: n = 5.2000 Formatted to right margin: n = 2324435.2500 3. System.err: This is the standard error stream that is used to output all the error data that a program might throw, on a computer screen or any standard output device. This stream also uses all the 3 above-mentioned functions to output the error data: print() println() printf() 15 Creating GUI programs (Creating a simple window. Handling events. Application with a button. Basic component classes. Creating a graph of a function. Calculator. Fundamentals of creating applets) There are current three sets of Java APIs for graphics programming: AWT (Abstract Windowing Toolkit), Swing and JavaFX. 1. AWT API was introduced in JDK 1.0. Most of the AWT UI components have become obsolete and should be replaced by newer Swing UI components. 2. Swing API, a much more comprehensive set of graphics libraries that enhances the AWT, was introduced as part of Java Foundation Classes (JFC) after the release of JDK 1.1. JFC consists of Swing, Java2D, Accessibility, Internationalization, and Pluggable Look-and-Feel Support APIs. JFC has been integrated into core Java since JDK 1.2. 3. The latest JavaFX, which was integrated into JDK 8, was meant to replace Swing. JavaFX was moved out from the JDK in JDK 11, but still available as a separate module. Other than AWT/Swing/JavaFX graphics APIs provided in JDK, other organizations/vendors have also provided graphics APIs that work with Java, such as Eclipse's Standard Widget Toolkit (SWT) (used in Eclipse), Google Web Toolkit (GWT) (used in Android), 3D Graphics API such as Java bindings for OpenGL (JOGL), Java3D, and etc. Furthermore, developers have moved to use technologies such as HTML5 as the basis of webapps. You need to refer to the "JDK API documentation" for the AWT/Swing APIs (under module java.desktop) while reading this chapter. The best online reference for Graphics programming is the "Swing Tutorial" @ http://docs.oracle.com/javase/tutorial/uiswing/. For advanced 2D graphics programming, read "Java 2D Tutorial" @ http://docs.oracle.com/javase/tutorial/2d/index.html. For 3D graphics, read my 3D articles. 2. Programming GUI with AWT I shall start with the AWT before moving into Swing to give you a complete picture of Java Graphics. 2.1 AWT Packages AWT is huge! It consists of 12 packages of 370 classes (Swing is even bigger, with 18 packages of 737 classes as of JDK 8). Fortunately, only 2 packages java.awt and java.awt.event - are commonly-used. 1. The java.awt package contains the core AWT graphics classes: o GUI Component classes, such as Button, TextField, and Label. o GUI Container classes, such as Frame and Panel. o Layout managers, such as FlowLayout, BorderLayout and GridLayout. o Custom graphics classes, such as Graphics, Color and Font. 2. The java.awt.event package supports event handling: o Event classes, such as ActionEvent, MouseEvent, KeyEvent and WindowEvent, o Event Listener Interfaces, such as ActionListener, MouseListener, MouseMotionListener, KeyListener and WindowListener, o Event Listener Adapter classes, such as MouseAdapter, KeyAdapter, and WindowAdapter. AWT provides a platform-independent and device-independent interface to develop graphic programs that runs on all platforms, including Windows, macOS, and Unixes. 2.2 AWT Containers and Components There are two groups of GUI elements: 1. Component (Widget, Control): Components are elementary GUI entities, such as Button, Label, and TextField. They are also called widgets, controls in other graphics systems. 2. Container: Containers, such as Frame and Panel, are used to hold components in a specific layout (such as FlowLayout or GridLayout). A container can also hold sub-containers. In the above figure, there are three containers: a Frame and two Panels. A Frame is the toplevel container of an AWT program. A Frame has a title bar (containing an icon, a title, and the minimize/maximize/close buttons), an optional menu bar and the content display area. A Panel is a rectangular area used to group related GUI components in a certain layout. In the above figure, the top-level Frame contains two Panels. There are five components: a Label (providing description), a TextField (for users to enter text), and three Buttons (for user to trigger certain programmed actions). In a GUI program, a component must be kept (or added) in a container. You need to identify a container to hold the components. Every container has a method called add(Component c). A container (say aContainer) can invoke aContainer.add(aComponent) to add aComponent into itself. For example, Panel pnl = new Panel(); // Panel is a container Button btn = new Button("Press"); // Button is a component pnl.add(btn); // The Panel container adds a Button component GUI components are also called controls (e.g., Microsoft ActiveX Control), widgets (e.g., Eclipse's Standard Widget Toolkit, Google Web Toolkit), which allow users to interact with (or control) the application. 2.3 AWT Container Classes Top-Level Containers: Frame, Dialog and Applet Each GUI program has a top-level container. The commonly-used top-level containers in AWT are Frame, Dialog and Applet: A Frame provides the "main window" for your GUI application. It has a title bar (containing an icon, a title, the minimize, maximize/restore-down and close buttons), an optional menu bar, and the content display area. To write a GUI program, we typically start with a subclass extending from java.awt.Frame to inherit the main window as follows: import java.awt.Frame; // Using Frame class in package java.awt // A GUI program is written as a subclass of Frame - the top-level container // This subclass inherits all properties from Frame, e.g., title, icon, buttons, contentpane public class MyGUIProgram extends Frame { // private variables ...... // Constructor to setup the GUI components and event handlers public MyGUIProgram() { ...... } // The entry main() method public static void main(String[] args) { // Invoke the constructor (to setup the GUI) by allocating an instance new MyGUIProgram(); } } An AWT Dialog is a "pop-up window" used for interacting with the users. A Dialog has a title-bar (containing an icon, a title and a close button) and a content display area, as illustrated. An AWT Applet (in package java.applet) is the top-level container for an applet, which is a Java program running inside a browser. Applet is no longer supported in most of the browsers. Secondary Containers: Panel and ScrollPane Secondary containers are placed inside a top-level container or another secondary container. AWT provides these secondary containers: Panel: a rectangular box used to layout a set of related GUI components in pattern such as grid or flow. ScrollPane: provides automatic horizontal and/or vertical scrolling for a single child component. others. Hierarchy of the AWT Container Classes The hierarchy of the AWT Container classes is as follows: As illustrated, a Container has a LayoutManager to layout the components in a certain pattern, e.g., flow, grid. 2.4 AWT Component Classes AWT provides many ready-made and reusable GUI components in package java.awt. The frequently-used are: Button, TextField, Label, Checkbox, CheckboxGroup (radio buttons), List, and Choice, as illustrated below. AWT GUI Component: java.awt.Label A java.awt.Label provides a descriptive text string. Take note that System.out.println() prints to the system console, NOT to the graphics screen. You could use a Label to label another component (such as text field) to provide a text description. Check the JDK API specification for java.awt.Label.