Difference between revisions of "Object-Oriented Concepts and Constructs"

From Sinfronteras
Jump to: navigation, search
(Configure the in-use Java version - Java Alternatives)
 
Line 1: Line 1:
 
+
{{Sidebar}}
 
<br />
 
<br />
 
==Java==
 
==Java==

Latest revision as of 23:02, 27 March 2021




Contents

Java


Online Java Compiler

These ones supports many languages:



Installation

https://linuxize.com/post/install-java-on-ubuntu-18-04/

We have 2 options when intalling Java:

  • OpenJDK
  • Oracle JDK



Installing OpenJDK

https://linuxize.com/post/install-java-on-ubuntu-18-04/

  • Installing the Default OpenJDK:

At the time of writing these notes, the Default OpenJDK was version 11. You can verify the Default OpenJDK with:

sudo apt policy default-jdk


To install it:

sudo apt update
sudo apt install default-jdk


Verify the installation:

java  -version
javac -version



  • Installing OpenJDK 8

Java 8 is still the most widely-used version of Java. If your application requires Java 8.

sudo apt update
sudo apt install openjdk-8-jdk



Oracle Java Development Kit (Oracle JDK)

https://en.wikipedia.org/wiki/Java_Development_Kit

https://www.oracle.com/technetwork/java/javase/overview/index.html

Es apropiado instalar Oracle JDK. Para GUI Programming, por ejemplo, se necesitan librerías que se encuentran en Oracle JDK.

Hay diferentes Edition:

  • Java Platform, Standard Edition (Java SE) (ésta es la que generalmente necesitamos)
  • Java Platform, Enterprise Edition (Java EE)
  • Java Platform, Micro Edition (Java ME)
  • ...



  • Installing Oracle JDK 11 or 13

https://linuxize.com/post/install-java-on-ubuntu-18-04/

http://ubuntuhandbook.org/index.php/2019/10/how-to-install-oracle-java-13-in-ubuntu-18-04-16-04-19-04/



  • Installing Oracle JDK 8

En una ocasion, al instalar java-10-oracle la instalación de NetBeans no funcionó correctamente. Esto creo que se debía a que Java-10-oracle era muy reciente para la fecha. Fue por tanto necesario instalar java-8-oracle y configurar la ruta del JDK editando el archivo /usr/local/netbeans-8.2/etc/netbeans.conf


También, cuando instalé Android Studio fue necesario Oracle JDK 8 porque versiónes más recientes no eran correnctamente soportadas por Android Studio. En esta ocasión la instalación de Oracle JDK 8 se tuve que realizar manualmente porque ya no está disponible en los repositorioes. How to install JDK 8 en Ubuntu: https://java.tutorials24x7.com/blog/how-to-install-java-8-on-ubuntu



Check your installed-in-use java version

java  -version
javac -version


The following command should tell you what is currently providing the Java virtual machine (java) and the Java compiler (javac): https://askubuntu.com/questions/150057/how-can-i-tell-what-version-of-java-i-have-installed

file /etc/alternatives/java /etc/alternatives/javac



Check ALL java versions installed

https://phoenixnap.com/kb/check-java-version-linux

There are several ways:

update-alternatives --list java


whereis java


sudo apt list --installed
sudo apt list --installed | grep -i jdk   
sudo apt list --installed | grep -i openjdk

For some reason, the «| grep» was not working in combination with apt. So I had to to «sudo apt list --installed > file.txt» and then use grep.



Configure the in-use Java version - Java Alternatives

https://linuxize.com/post/install-java-on-ubuntu-18-04/

https://superuser.com/questions/569633/what-is-command-to-see-all-java-versions-installed-on-linux

(base) adelo@adelo-laptop:~$ sudo update-alternatives --config javac
There are 2 choices for the alternative javac (providing /usr/bin/javac).

  Selection    Path                                          Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-11-openjdk-amd64/bin/javac   1111      auto mode      # Ésta es la versión «Default OpenJDK»
  1            /usr/java/jdk1.8.0_221/bin/javac               1         manual mode    # Ésta es la versión «Oracle JDK 8»
  2            /usr/lib/jvm/java-11-openjdk-amd64/bin/javac   1111      manual mode

Press <enter> to keep the current choice[*], or type selection number:


Aquí también se explica un método para configurar Java Alternatives: https://java.tutorials24x7.com/blog/how-to-install-java-8-on-ubuntu



IDE for Java


Eclipse


Installing Eclipse

Para estar seguro de que estamos instalando la última versión, es apropiado descargar el paquete desde la página oficial, y no instalar la versión que se encuentra en los repositorios de Ubuntu a través de apt-get (pues estar versiones generalmente están desactualizadas).

Página oficial de Eclipse: http://www.eclipse.org/downloads/

En la siguiente página se explica como instalar eclipse en Ubuntu 16.04: http://ubuntuhandbook.org/index.php/2016/01/how-to-install-the-latest-eclipse-in-ubuntu-16-04-15-10/

Para instalarlo hay que simplemente ejecutar el instalador y seguir las instrucciones (como si se tratara de una instalación en Windows).

Luego, para agregar el ejecutable a la lista de comandos, he agregado la siguiente línea en el .bashrc:

PATH=$PATH:/home/adelo/1-system/.1-conf-system/1-archivos_programas-ubuntu/eclipse/java-photon/eclipse:



Combinaciones de teclas
  • Para que coloque los import (luego de haber ingresado un comando que necesite una librería en particular): Ctrl Shif o
  • Run: Ctrl 11
  • Comentar: Ctrl 7
  • Rastrea la variable seleccionada: CTRL k



NetBeans

https://netbeans.org/

https://en.wikipedia.org/wiki/NetBeans



Installing NetBeans on Ubuntu 18.04

https://www.itzgeek.com/how-tos/linux/ubuntu-how-tos/how-to-install-netbeans-ide-on-ubuntu-18-04-ubuntu-17-10.html

Se puede descargar NetBeans manualmente de la página oficial: https://netbeans.org/downloads/

Si se descarba el Binaries, ninguna instalación será necesaria, basta con ejecutar el binario:

netbeans/bin/netbeans

Con java-10-oracle la instalación no funcionó correctamente. Fue por tanto necesario instalar java-8-oracle y configurar la ruta del JDK editando el archivo /usr/local/netbeans-8.2/etc/netbeans.conf



Installing NetBeans on Windows 10
  • Descargar NetBeans de la página oficial: https://netbeans.org/downloads/
  • Cuando instalé NetBeans, éste detectó automáticamente la ruta del JDK - JDK for the NetBeans IDE:
C:\Program Files\Java\jdk1.8.0_181
  • Debido a que instalé la versión que tiene todos los componentes, se instaló también el GlassFish Server Open Source Edition. No sé para que es sirve y si sea apropiado instalarlo.



The Darcula plugin

In NetBeans IDE 8.2 you can now go to:

  • Tools > Plugins > Available Plugins > and install the Darcula LAF for NetBeans plugin directly from there.
  • En las versiones 9 y 10 y 11 el Plugin no se encuentra disponible por defecto. Es entonces necesario adicionarlo a la lista de "Available Plugins" de la siguiente forma:
Netbeans 9 and 10: https://stackoverflow.com/questions/52688439/changing-theme-in-apache-netbeans-9-0
Netbeans 11: https://www.youtube.com/watch?v=HuzFUuww_f0



Using Java


Writing and Running a Java code

You can use your favorite Text Editor or IDE to write your Python code:

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


Using an IDE:

  • You can run the program using the GUI options available in your IDE; which will usually compile, run and show the result in the IDE console.


Through the terminal:

  • To compile the file, open your terminal and type:
javac filename.java
  • To run the generated .class file, use:
java filename



Jar File

A Jar File (acronym for Java Archive) is format used for archiving java files (merging several java files into one)

The Jar File, provides a method to package our software to give it to the users.

The Jar File can be Runnable. That is, when we double click it, our program will run.


A typical extension to files that we have always seen when working in a Windows environment is the .exe file extension. These files are a single binary executable file that when double clicked will open the program for the user.

In the Java world however things are a little different. There is no native .exe file in Java and we must use the .jar file extension instead. A jar file works exactly the same as a .exe file and when double clicked will run the program.

Jar files come in two different varieties:

  • Simple archive folder
  • Runnable archive folder

A jar file is an acronym for Java Archive. Simple archive folder is a filetype similar to that of the .zip extension. If we want, we can open up a jar file using a program such as WinZip or WinRar and check the contents inside of the jar.

The second variant of this is the ​runnable archive folder​. This type of file is exactly the same as the archive folder, just with one additional file. This extra file is used to define what happens when the user double clicks on the icon. In our case, we will point to the main method in our class file that we want to run. This will kick start the program to run when it is double clicked.



Creating a Jar

Open up your Eclipse and navigate to the project you are currently working on. Note this will only work correctly with an application that has a GUI for the user to see. In this case the project we are looking at is called Sample Program 1.

  • Right click on the project name, and a menu will open.
  • In the menu that opens, click on the Export button.
  • In the window that opens you will see that two different types of JAR file are available:
    • If you wanted to simply package your project to give to someone, you could use the JAR file.
    • In our case, we are interested in the Runnable JAR file, so we will click on this option and then click Next.
  • You will then be passed to a second window where you will be able to specify the details for the runnable Jar file you are about to create:
    • The first of these is the launch configuration. This is the most important step to ensure that your Jar file will open the project when it is double clicked.
      • Select the name of the class you want to run, inside of the project that you have been working on. In this case, you can see that the Main class is selected which is inside of the project titled SampleProgram1 that we are working in.
    • The second step is then to select a location where we would like to export the Jar file to.
    • After you have finished, click Finish at the bottom of the page.
  • A small warning message may pop up, but this is ok. Click Ok to ignore this message.



Include images into the jar

https://coderanch.com/t/343401/java/pictures-loaded-executable-jar-file

To make sure that images used in the GUI are shown in the .jar, the images in the code have to be manages this way:


    .
    .
    -
    private void setAnimalPanel() {
        animalPanel = new JPanel(null);
        animalPanel.setLayout(null);
        animalPanel.setBorder(BorderFactory.createTitledBorder(null, "Animals: ", 0, 0, new Font("PLAIN", Font.BOLD, MainFrame.xCoordinate(12))));
        animalPanel.setBounds(MainFrame.xCoordinate(220), MainFrame.yCoordinate(70), MainFrame.xCoordinate(200), MainFrame.yCoordinate(185));
        
        JLabel animalImage = new JLabel();
        ImageIcon imgA = new ImageIcon(this.getClass().getResource("/images/animals.png"));
        
        Image aImg = imgA.getImage();
        Image newImgA = aImg.getScaledInstance(MainFrame.xCoordinate(90), MainFrame.yCoordinate(90), Image.SCALE_SMOOTH);
        ImageIcon newIconA = new ImageIcon(newImgA);
        animalImage.setIcon(newIconA);
        animalImage.setPreferredSize(new Dimension(MainFrame.xCoordinate(90), MainFrame.yCoordinate(90)));
        animalImage.setBounds(MainFrame.xCoordinate(0), MainFrame.yCoordinate(30), MainFrame.xCoordinate(100), MainFrame.yCoordinate(100));
        animalPanel.add(animalImage);
    }
    .
    .
    -


See how we did it in the project CCTZoo



Exploring the Jar File

Now that we have created the Jar file. If we double click on the file our program will run. However if we want, we can take a look inside of the Jar file. This is easily done by right clicking on the Jar file that we have created and clicking “Open with WinRAR” or whichever program you currently have installed on your system for viewing Zip files.

After WinRAR has opened you will be able to see the contents of the Jar file. In this case you can see the class file from the project that we have been developing. In addition to this, you will see an additional folder titled META-INF. This is the folder where all of the configuration for the Jar file are held. We will go into this folder and take a look around.

Inside of this folder, you will see a file titled MANIFEST.MF. This is the main configuration file for the Jar file we have created. If we open up this file, we can see the details of what is called when we double click on the Jar file to view it.

There is very little content that is needed to make the Jar file run. Inside of this file, you can see that the Main-Class attribute is set to the name of the class file that we want to run when the Jar is double clicked. In the case of this project, the class file that we want to run is called Main.class, so the title Main is used as the value for this attribute. If your class was called MyProgram.class, this would be set to MyProgram.



Operators

https://www.w3schools.com/java/java_operators.asp

https://www.javatpoint.com/operators-in-java

Operator Name/Description Example Same as
Python

s2

Java JS R Python Java F R
Arithmetic Operators + + Addition x + y
- - Subtraction x - y
* * Multiplication x * y
/ / Division x / y
% % Modulus x % y
** java.util.Math Exponentiation x ** y import java.util.Math

Double result = Math.pow(number, exponent);

// Floor division x // y
++ Increment: Increases the value of a variable by 1 ++x
-- Decrement: Decreases the value of a variable by 1 --x
Assignment Operators = = x = 5
+= += x+= 3 x = x + 3
-= -= x -= 3 x = x - 3
*= *= x *= 3 x = x * 3
/= /= x /= 3 x = x / 3
%= %= x %= 3 x = x % 3
//= x //= 3 x = x // 3
**= x **= 3 x = x ** 3
&= &= x &= 3 x = x & 3
|= |= x |= 3 x = x | 3
^= ^= x ^= 3 x = x ^ 3
>>= >>= x >>= 3 x = x >> 3
<<= <<= x <<= 3 x = x << 3
Comparison Operators == == Equal x == y
!= != Not equal x != y
> > Greater than x > y
< < Less than x < y
>= >= Greater than or equal to x >= y
<= <= Less than or equal to x <= y
Logical Operators and && Logical and: Returns True if both statements are true x < 5 and x < 10 x < 5 && x < 10
or || Logical or: Returns True if one of the statements is true x < 5 or x < 4 x < 5 || x < 4
not ! Logical not: Reverse the result, returns False if the result is true not(x < 5 and x < 10) !(x < 5 && x < 10)
Identity Operators is Returns true if both variables are the same object x is y
is not Returns true if both variables are not the same object x is not y
Membership Operators in Returns True if a sequence with the specified value is present in the object x in y
not in Returns True if a sequence with the specified value is not present in the object x not in y
Bitwise Operators &
AND

Sets each bit to 1 if both bits are 1

| OR

Sets each bit to 1 if one of two bits is 1

^ XOR

Sets each bit to 1 if only one of two bits is 1

~ NOT

Inverts all the bits

<< Zero fill left shift

Shift left by pushing zeros in from the right and let the leftmost bits fall off

>> Signed right shift

Shift right by pushing copies of the leftmost bit in from the left, and let the rightmost bits fall off

Added by myself
String concatenation +
"Coucou ' + 'c\'est ' + 'nous !";
conca()
'Coucou '.concat('c\'est ', 'nous !');
join()
['Coucou ', 'c\'est ', 'nous !'].join();



Some important Methods


print


Object-Oriented Paradigm

Object-oriented programming (OOP) is a programming language paradigm structured around objects (which consists of both data and behaviors[Functions-Methods]). This is in contrast to conventional Functional programming paradigm that is structured based on actions (logic) and only loosely connects data and behaviors.


A traditional functional/procedural(*) program is structured based on actions (logic). In general, a functional program take an input data, process it and produces a result. In other words, the data, stored in variables, is passed to defined functions which perform some action and modify it or create new data. The program is centralized around the actions (logic):

  • Take input data
  • Process the data
  • Produces a result


The object-oriented paradigm allows us to structure the program as a collection of objects that consist of both data and behaviors[Functions-Methods]. So, in object-oriented programming, data and functions are tied together in an entity called object. We can said that one of the main aim of OOP is to bind together the data and the functions that operate on them so that no other part of the code can access this data except that function. These data in OOPs are known as properties and functions used to modify properties are called methods.


The object-oriented programming approach encourages:

  • Modularisation: where the application can be decomposed into modules.
  • Software re-use: where an application can be composed from existing and new modules.


Major benefits of using OOPs:

  • Encapsulation : Objects created in OOPs are able to hide certain parts of code from programmer. This prevents unintentional modification in the code which may cause unwanted outcomes.
  • Code Reuse : Objects created in OOPs can easily be reused in other programs.
  • Software Maintenance : Code written in OOPs is easy to debug and maintain.
  • Design Benefits : OOPs needs extensive design planning which certainly provide design benefits over traditional style.


For simple programming tasks, use of procedural programming style is well suited but as the program becomes complex and software architecture becomes large, object oriented programming is suitable to create modular designs and patterns. This makes it particularly useful when you create larger programs.


There are four major benefits to object-oriented programming:

  • Encapsulation: in OOP, you bundle code into a single unit where you can determine the scope of each piece of data.
  • Abstraction: by using classes, you are able to generalize your object types, simplifying your program.
  • Inheritance: because a class can inherit attributes and behaviors from another class, you are able to reuse more code.
  • Polymorphism: one class can be used to create many objects, all from the same flexible piece of code.



SOLID Principles

S Single Responsibility Principle
O Open Closed Principle
L Liskov's Substitution Principle
I Interface Segregation Principle
D Dependency Inversion Principle



Single Responsibility Principle

  • One class should have one and only one responsibility:
In other words, you should write, change and maintain a class for only one purpose.
  • If it is a Model class (MVC Pattern) then it should strictly represent only one Actor/Entity. This will give you the flexibility to make changes in future without worrying about the impacts of changes for another entity.
  • Similarly, if you are writing a service/manager class then it should contain only that part of the method calls and nothing else.



Open Closed Principle

  • Software components should be open for extension, but closed for modification:
  • It means that your classes should be designed in such a way that whenever fellow developers want to change the flow of control in specific conditions in an application, all they need to do is extend your class and override some methods and that's it.
  • If other developers are not able to design the desired behaviour due to the constraints of your class, then you should reconsider changing your class. This is not to say that anybody can change the whole logic of your class, but they should be able to override the options provided by the software in an unharmful way.
  • For example, if you take a look into any good framework like Struts or Spring, you will see that you can not change their core logic and request processing; BUT you can modify the desired application flow just by extending some classes and plugging them into configuration files.



Liskov's Substitution Principle

  • Derived types must be completely substitutable for their base types
This means that the classes a fellow developer created by extending your class should be able to fit in the application without failure. It should not break the application or should not throw fatal exceptions.



Interface Segregation Principle

This is applicable to interfaces as the single responsibility principle holds to classes. It states:

  • Clients should not be forced to implement unnecessary methods which they will not use:
    • Take an example. A developer creates an interface -Reportable- and adds two methods generateExcel() and generatedPdf(). Now, client «A» wants to use this interface but they intend to use reports only in PDF format and not in excel. Will they achieve this functionality easily?
      • NO. They will have to implement two methods,
      • So, what is the solution? Create two interfaces by breaking the existing one.
They could be PdfReportable and ExcelReportable. This will give the flexibility to the user to use only required functionality.



Dependency Inversion Principle

  • This basically means that we should use an interface to provide a layer of abstraction between high and low level classes.
    • High-level modules should not depend on low-level modules. Both should depend on abstractions.
    • Abstractions should not depend upon details. Details should depend upon abstractions.



Class vs Object vs Instance

https://alfredjava.wordpress.com/2008/07/08/class-vs-object-vs-instance/

In OO Programming, we often hear of terms like "Class", "Object" and "Instance"; but what actually is a Class / Object / Instance?

In short, An object is a software bundle of related state and behavior. A class is a blueprint or prototype from which objects are created. An instance is a single and unique unit of a class.

Example, we have a blueprint (class) represents student (object) with fields like name, age, course (class member). And we have 2 students here, Foo and Bob. So, Foo and Bob is 2 different instances of the class (Student class) that represent object (Student people).

Let me go into details...



Object

Real world objects shares 2 main characteristics, state and behavior. Human have state (name, age) and behavior (running, sleeping). Car have state (current speed, current gear) and behavior (applying brake, changing gear). Software objects are conceptually similar to real-world objects: they too consist of state and related behavior. An object stores its state in fields and exposes its behavior through methods.



Class

Class is a “template” / “blueprint” that is used to create objects. Basically, a class will consists of field, static field, method, static method and constructor. Field is used to hold the state of the class (eg: name of Student object). Method is used to represent the behavior of the class (eg: how a Student object going to stand-up). Constructor is used to create a new Instance of the Class.



Instance

An instance is a unique copy of a Class that representing an Object. When a new instance of a class is created, the JVM will allocate a room of memory for that class instance.



Otro punto de vista

Luego de leer distintos fuentes para tratar de entender los conceptos de «Class vs Object vs Instance» me ha parecido que los conceptos de «Object and Instance» no están bien diferenciados... es decir no encuentro una definición que verdaderamente me convenza de la diferencia entre estos dos conceptos.

Entonces, encontré otra fuente que plantea lo siguiente: https://www.javatpoint.com/q/3420/difference-between-instance-and-object-?

Object and Instance are the same thing in most object-oriented languages. "Instance of a class" is just how the term "object" is defined.

Every object is an instance of a class. And every instance of a class is an object. You can basically interchange these.

You have 5 apples in your basket. Each of those apples is an object of type Apple, which has some characteristics (i.e. big, round, grows on trees).

In programming terms, you can have a class called Apple, which has variables size:big, shape:round, habitat:grows on trees. To have 5 apples in your basket, you need to instantiate 5 apples. Apple apple1, Apple apple2, Apple apple3 etc....

Alternatively: Objects are the definitions of something, instances are the physical things.

No me queda clara la diferencia entre un Object y una Instance.



Interface

An interface is a reference type in Java. It is similar to class. It is a collection of abstract methods. A class implements an interface, by inheriting the abstract methods of the interface



Methods

Methods are members of a class that provide a service for an object. In other words, we use methods to add behavior to objects.



Overloaded subprograms

An overloaded subprogram is one that has the same name as another subprogram in the same referencing environment. However, every version of an overloaded subprogram has a unique protocol.

C++, Java, C#, and Ada include predefined overloaded subprograms. They allow users to write multiple versions of subprograms with the same name and different protocols. In Ada, the return type of an overloaded function can be used to disambiguate calls (thus two overloaded functions can have the same parameters)



Method Overloading

Overloading: Multiple methods with the same name but different parameter lists.

In constructors:

Item item1 = new Item();
Item milk = new Item(milk, 0.99, 3);

String x = new String();
String y = new String(Hello);

In methods:

String x = new String("Hola, cómo estás");
x.substring(2);
x.substring(2, 5);
x.indexOf("h");
x.indexOf("h", 1);



Standard Methods

Two methods that should be included in classes (Good practice to include it):

  • toString
  • equals



The toString Methodg

  • Returns data stored in an object as a String:
    • Allows the contents of an object to be displayed
    • Can format the contents whatever way you wish
    • MUST return a String*
    • MUST NOT take a parameter*
public String toString() {
    return name + ", " + day + " " + monthNames[month-1] + " " + year + ", " + address;
}

Example result:

"P. Sherman, 30 May 2003, 42 Wallaby Way, Sydney"



Variables

  • Holder for information
  • Not a fixed value, contents can be changed
  • Every variable has a type



Types of variables - classification 1

Type can be:

  • Primitive
  • Object



Primitive - Simple data type

  • E.g. int, double, char, boolean
  • Built into Java
  • Can only hold one piece of data of a specific type
  • All begin with a lowercase letter



Primitive in memory
  • Actual data is stored within variable
    • E.g. int num = 78;
Primitive in memory1.png
  • When you change a primitive variable, the value inside the variable changes:
  • E.g. int x = 12;
  • num = x;
Primitive in memory2.png



Object - Complex data type

  • Created based on classes. These can be either built into Java (E.g. Scanner, String, ArrayList) or user-defined (e.g. Item)
  • Can hold multiple pieces of data of different types
  • All begin with an uppercase letter



Object in memory
  • Variable contains a reference to the location where the data is stored.
    • E.g. Item item = new Item(“Bread”, 2.50, 1);
Object in memory1.png
  • When you change information inside an object, the value (reference) inside the variable stays the same.
  • E.g. item.setName("apple"); (Es decir, aquí estoy cambiando la data (la información que se encuentra en la dirección indicada por la variable) pero lo que en realidad es el «valor de la variable» es la referencia (la dirección que indica (o que referencia) la data)).
  • When you change an object variable, you change the reference:
Object in memory2.png



More on Objects
  • Objects consist of:
    • Fields (instance variables)
    • Constructors
    • Methods
  • When an Object is declared, it is null. The variable contains no reference.
    • If an Object is null, you cannot use any of its methods.
  • When an Object is initialised, it is created fully.
    • Constructor is called & a copy of all fields and methods are created in memory.



Types of variables - classification 2


Instance variable

Instance variables are declared in a class, but outside a method, constructor or any block.

For each instantiated object of the class, a separate copy of each instance variables is made.



Local variable

A variable created within the braces (curly brackets) of a method (any method).

A new copy of the local variable is created every time the corresponding method is run.



Parameter variable

A parameter (Method Parameters) is a variable created within the brackets of a method signature. a new copy is created every time the corresponding method is run.

public void increaseQuantity(int quant) {
    quantity = quantity + quant;
}

«quant» is a parameter variable.

Two types of parameter passing:

  • Pass by value - copy of value is sent to method
    • Used when passing primitive types as parameters
  • Pass by reference - copy of location (arrow) is sent to method
    • Used when passing objects as parameters



Variable Lifetime

  • Lifetime: How long a variable continues to exist before it is destroyed/erased from memory.
    • The lifetime of an instance variable is as long as the object it belongs to exists in memory.
    • Lifetime of a local variable is as long as its "parent" method runs.
    • Lifetime of a parameter variable is as long as its "parent" method runs.
    • Lifetime of a static variable is from the first mention of its "parent" class.



Data types

https://www.javatpoint.com/java-data-types


Java data types.png



Primitive data types

There are 8 types of primitive data types:

Data Type Default Value Size Description Example
Numeric byte 0 1 byte Stores whole numbers from -128 to 127 byte myNum = 100;

System.out.println(myNum);

short 0 2 byte Stores whole numbers from -32,768 to 32,767 short myNum = 5000;
int 0 4 byte Stores whole numbers from -2,147,483,648 to 2,147,483,647 int myNum = 100000;
long 0L 8 byte Stores whole numbers from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 long myNum = 15000000000L;
float 0.0f 4 byte Stores fractional numbers. Sufficient for storing 6 to 7 decimal digits.

The float data type can store fractional numbers from 3.4e−038 to 3.4e+038. Note that you should end the value with an "f":

float myNum = 5.75f; Scientific Numbers

A floating point number can also be a scientific number with an "e" to indicate the power of 10:


float f1 = 35e3f;

double d1 = 12E4d;

double 0.0d 8 byte Stores fractional numbers. Sufficient for storing 15 decimal digits.

The double data type can store fractional numbers from 1.7e−308 to 1.7e+308. Note that you should end the value with a "d"

double myNum = 19.99d;
Character char '\u0000' 2 byte The char data type is used to store a single character. The character must be surrounded by single quotes, like 'A' or 'c': char myGrade = 'B';


Alternatively, you can use ASCII values to display certain characters:

char a = 65, b = 66, c = 67;

Tip: A list of all ASCII values can be found at https://www.w3schools.com/charsets/ref_html_ascii.asp

Boolean boolean false 1 bit Stores true or false values boolean isJavaFun = true;



Collections

https://www.javatpoint.com/collections-in-java


Collection Description Example
Arrays class https://www.w3schools.com/java/java_arrays.asp


Arrays are used to store multiple values in a single variable.

To declare an array, define the variable type with square brackets.

Array initialisation:

String[] cars;

String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};

int[] myNum = {10, 20, 30, 40};


Access the Elements of an Array:

System.out.println(cars[0]);


Change an Array Element:

cars[0] = "Opel";


Array Length:

System.out.println(cars.length);

Loop Through an Array:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};

for (int i = 0; i < cars.length; i++) {
    System.out.println(cars[i]);
}
Loop Through an Array with For-Each:
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};

for (String i : cars) {
    System.out.println(i);
}
Multidimensional Arrays:
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };

// This is the representation of the myNumbers array.
// Notice that it doesn't have to be symmetric (rectangular)
1  2  3  4
5  6  7

int x = myNumbers[1][2];
System.out.println(x);
// Outputs: 7
ArrayList class https://www.javatpoint.com/java-arraylist


Java ArrayList class uses a dynamic array for storing the elements.


The important points about Java ArrayList class are:

  • Java ArrayList class can contain duplicate elements.
  • Java ArrayList class maintains insertion order.
  • Java ArrayList class is non synchronized.
  • Java ArrayList allows random access because array works at the index basis.
  • In Java ArrayList class, manipulation is slow because a lot of shifting needs to occur if any element is removed from the array list.
import java.util.*;

class ArrayList1{
    public static void main(String args[]){
        ArrayList<String> list=new ArrayList<String>();
        list.add("Ravi");//Adding object in arraylist
        list.add("Vijay");
        list.add("Ravi");
        list.add("Ajay");

        //Invoking arraylist object
        System.out.println(list);
    }  
}
LinkedList class https://www.javatpoint.com/java-linkedlist


Java LinkedList class uses a doubly linked list to store the elements. It provides a linked-list data structure.


The important points about Java LinkedList are:

  • Java LinkedList class can contain duplicate elements.
  • Java LinkedList class maintains insertion order.
  • Java LinkedList class is non synchronized.
  • In Java LinkedList class, manipulation is fast because no shifting needs to occur.
  • Java LinkedList class can be used as a list, stack or queue.
import java.util.*;  

public class LinkedList1{
	public static void main(String args[]){
		LinkedList<String> al=new LinkedList<String>();
		al.add("Ravi");
		al.add("Vijay");
		al.add("Ravi");
		al.add("Ajay");

		Iterator<String> itr=al.iterator();
		while(itr.hasNext()){
		System.out.println(itr.next());
	}
}
Queue Interface


PriorityQueue class

https://www.javatpoint.com/java-priorityqueue


Java Queue Interface

Java Queue interface orders the element in FIFO (First In First Out) manner. In FIFO, first element is removed first and last element is removed at last.


PriorityQueue class

The PriorityQueue class provides the facility of using queue. But it does not orders the elements in FIFO manner. It inherits AbstractQueue class.

import java.util.*;  

class TestCollection12{
	public static void main(String args[]){

		PriorityQueue<String> queue=new PriorityQueue<String>();
		queue.add("Amit");
		queue.add("Vijay");
		queue.add("Karan");
		queue.add("Jai");
		queue.add("Rahul");
		System.out.println("head:"+queue.element());
		System.out.println("head:"+queue.peek());
		System.out.println("iterating the queue elements:");
		Iterator itr=queue.iterator();

		while(itr.hasNext()){
			System.out.println(itr.next());
		}

		queue.remove();
		queue.poll();
		System.out.println("after removing two elements:");
		Iterator<String> itr2=queue.iterator();

		while(itr2.hasNext()){
			System.out.println(itr2.next());
		}	
	}
}



Modifiers and keyworkds


Access Control Modifiers

They are used to set access levels for classes, variables, methods and constructors. The four access levels are:

  • The default. No modifiers are needed: Visible to the package.
  • public: Visible to the world.
    • Anything can access/change a public variable
    • Anything can run a public method
  • protected: Visible to the package and all subclasses.
  • private: Visible to the class only.
    • Cannot be accessed outside the class in which it's defined
    • Only methods within that class can access/change a private variable
    • Only methods within that class can run a private method
    • Cannot access private variables in a different instance
    • Can only use the private modifier on variables on outer-most level of a class
      • i.e. cannot make any local variables (variables within methods) private



Non-Access Modifiers

Java provides a number of non-access modifiers to achieve many other functionality.

  • The static modifier for creating class methods and variables.
  • The final modifier for finalizing the implementations of classes, methods, and variables.
  • The abstract modifier for creating abstract classes and methods.
  • The synchronized and volatile modifiers, which are used for threads.



The static keyword

In Java, a static member is a member of a class that isn’t associated with an instance of a class. Instead, the member belongs to the class itself. As a result, you can access the static member without first creating a class instance. https://www.dummies.com/programming/java/what-is-the-static-keyword-in-java/

The static can be: https://www.javatpoint.com/static-keyword-in-java

  • Variable (also known as class variable)
  • Block
  • Method (also known as class method)
  • Nested class



Static variable

An instance variable shared by every instance of a class.

public class Item {
    private String name;
    private double price;
    private int quantity;

    private static ItemCount;
...
}

«itemCount» is a static variable, only one copy ever exists in memory.

Useful for:

  • Specific tasks needing centralized data.
    • E.g. keeping a count of the number of instances of a class created.



Static method
  • A static method belongs to the class rather than object of a class.
  • A static method can be invoked without the need for creating an instance of a class.
  • static method can access static data member and can change the value of it.
class Calculate{
  static int cube(int x){
  return x*x*x;
  }
  
  public static void main(String args[]){
  int result=Calculate.cube(5);
  System.out.println(result);
  }
}



Static nested classes

We can not declare top-level class with a static modifier, but can declare nested classes as static. See static nested class in java



Overriding

https://www.techopedia.com/definition/24010/overriding

Overriding is an object-oriented programming feature that enables a child class to provide different implementation for a method that is already defined and/or implemented in its parent class or one of its parent classes. The overriden method in the child class should have the same name, signature, and parameters as the one in its parent class.

Overriding enables handling different data types through a uniform interface. Hence, a generic method could be defined in the parent class, while each child class provides its specific implementation for this method.



The this Keyword

this is a reference to the current object - the object whose method or constructor is being called.

this is used a lot in constructors.


this avoids confusion where local variables have same name as global variables, for example:

public Person(String name1, Date dob1, String address1) {
    name = name1;
    dob = dob1;
    address = address1;
}

Vs.

public Person(String name, Date dob, String address) {
    this.name = name;
    this.dob = dob;
    this.address = address;
}


The this keyword can also be used to call a constructor of this instance of a class, e.g:

public class Rectangle {
    private int x, y;
    private int width, height;

    public Rectangle() {
        this(0, 0, 0, 0);
    }

    public Rectangle(int width, int height) {
        this(0, 0, width, height);
    }

    public Rectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
}


Here is given the 6 usage of java this keyword: (https://www.javatpoint.com/this-keyword)

  • this can be used to refer current class instance variable.
  • this can be used to invoke current class method (implicitly)
  • this() can be used to invoke current class constructor.
  • this can be passed as an argument in the method call.
  • this can be passed as argument in the constructor call.
  • this can be used to return the current class instance from the method.



Four fundamental OOP concepts

https://stackify.com/oops-concepts-in-java/



Abstraction

https://stackify.com/oop-concept-abstraction/

Abstraction is a key concept in programming. In particular, it is one of the 4 fundamental concepts of object-oriented programming (OOP) languages. Its main goal is to handle complexity by hiding unnecessary details from the user. That enables the user to implement more complex logic on top of the provided abstraction without understanding or even thinking about all the hidden complexity.



Abstraction in the real world

I'm a coffee addict. So, when I wake up in the morning, I go into my kitchen, switch on the coffee machine and make coffee. Sounds familiar?

Making coffee with a coffee machine is a good example of abstraction:

  • You need to know how to use your coffee machine to make coffee.
You need to provide water and coffee beans,
Switch the machine on,
Select the kind of coffee you want to get ...


  • The thing you don't need to know is how the coffee machine is working internally to brew a fresh cup of delicious coffee:
You don't need to know how the coffee machine heat the water,
You don't need to know the ideal temperature of the water,
Neither the amount of ground coffee you need to use.


Someone else worried about all these details and created a coffee machine that now acts as an abstraction of the coffee making process and hides all these details. You just interact with a simple interface that doesn't require any knowledge about the internal implementation.


We can use the same concept in programming and specially in object-oriented programming languages...


Another good example of abstraction, is any Software or Application. Let's consider an Email Service Application (Gmail, for example)...



Abstraction in Programming

Abstraction is a concept much more easier than it seams to be. Every time that we create a Function or an Object, we are probably implementing abstraction. If this Function or Object can be re-used in another part of the code or even in another program to perform a particular task, our Function or Object will be acting as an abstraction of the task that is performing; just like the coffee machine of our previous example acts as an abstraction of the coffee making process by hiding all the complex details.


Two fundamental abstraction facilities:

  • Process abstraction:
Nearly all programming languages support process abstraction with subprograms (functions, for example)
  • Data abstraction:
Nearly all programming languages designed since 1980 support data abstraction (objects).




Abstraction in OOP

Objects in an OOP language provide an abstraction that hides the internal implementation details. Similar to the coffee machine in your kitchen, you just need to know which methods of the object are available to call and which input parameters are needed to trigger a specific operation. But you don't need to understand how this method is implemented and which kinds of actions it has to perform to create the expected result.

Let's implement the coffee machine example in Java. You do the same in any other object-oriented programming language. The syntax might be a little bit different, but the general concept is the same.



Abstract methods and classes in Java

https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

An abstract class is a class that is declared abstract; it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this:

abstract void moveTo(double deltaX, double deltaY);


If a class includes abstract methods, then the class itself must be declared abstract:

public abstract class GraphicObject {
   // declare fields
   // declare nonabstract methods
   abstract void draw();
}


When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract.



Interfaces in Java

https://docs.oracle.com/javase/tutorial/java/IandI/createinterface.html



Abstract Classes Compared to Interfaces

https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html



Abstraction code example - Use abstraction to implement a coffee machine



Abstract Class

A class which contains the abstract keyword in its declaration is known as abstract class.

  • Abstract classes may or may not contain abstract methods ie., methods without a body.
    • Un «abstract method» is un método que sólo está declarado. No contiene más nada: public void get();
  • But, if a class has at least one abstract method, then the class must be declared abstract.
  • If a class is declared abstract it cannot be instantiated.
  • To use an abstract class you have to inherit it from another class, provide implementations to the abstract methods in it.
  • If you inherit an abstract class you have to provide implementations to all the abstract methods in it.

Example:

package atest1;

public abstract class Employee {
    
    private String name;
    private String address;
    private int    number;
    
    public Employee(String name, String address, int number){
        System.out.println("Constructing an Employee");
        this.name    = name;
        this.address = address;
        this.number  = number;
    }
    
    public double computePay(){
        System.out.println("Inside Employee computePay");
        return 0.0;
    }
    
    public void mailCheck(){
        System.out.println("Mailing a check to " + this.name + " " + this.address);
    }
    
    public String toString(){
        return name + " " + address + " " + number;
    }
    
    public String getName(){
        return name;
    }
    
    public String getAddress(){
        return address;
    }
    
    public void setAddress(String newAddress){
        address = newAddress;
    }
    
    public int getNumber(){
        return number;
    }
            
}

You can observe that except abstract methods the Employee class is same as normal class in Java. The class is now abstract, but it still has three fields, seven methods, and one constructor.

Now you can try to instantiate the Employee class as shown below:

package atest1_abstract_class;

public class AbstractDemo {
    
    public static void main(String [] args){
        // Following is not allowed and would raise the error:
        // Employee.java:46: Employee is abstract; cannot be instantiated
        // Employee e = new Employee("George W.", "Houston, TX", 43);
        
        // Esto no s'e que es. Netbeans me da la opci'on de instanciar esta abstract class as'i:
        Employee e = new Employee("George W.", "Houston, TX", 43) {};
        
        System.out.println("\n Call mailCheck using Employee reference:");
        e.mailCheck();
        
    }
    
}

When you compile the above class, it gives you the following error:

Employee.java:46: Employee is abstract; cannot be instantiated
    Employee e = new Employee("George W.", "Houston, TX", 43);



Inheriting the Abstract Class

We can inherit the properties of Employee class just like concrete class as shown below:

package atest1_abstract_class;

public class Salary extends Employee{
    
    private double salary;
    
    public Salary(String name, String address, int number, double salary){
        super(name, address, number);
        setSalary(salary);
    }
    
    public void mailCheck(){
        System.out.println("Within mailCheck of Salary class ");
        System.out.println("Mailing check to " + getName() + " with salary " + salary);
    }
    
    public double getSalary(){
        return salary;
    }
    
    public void setSalary(double newSalary){
        if(newSalary >= 0.0){
            salary = newSalary;
        }
    }
    
    public double computePay(){
        System.out.println("Computing salary pay for " + getName());
        return salary/52;
    }
}

Here, you cannot instantiate the Employee class, but you can instantiate the Salary Class, and using this instance you can access the all the three fields and seven methods of Employee class as shown below.

package atest1_abstract_class;

public class AbstractDemo {
    
    public static void main(String [] args){  
        Salary   s  = new Salary("Joe Bloggs", "Dublin 10", 3, 3600.00);
        Employee e2 = new Salary("John Adams", "Dublin 12", 2, 2400.00);
        
        System.out.println("\nCall mailCheck using Salary reference:");
        s.mailCheck();
        
        System.out.println("\nCall mailCheck using Employee reference--");
        e.mailCheck();
        
    }
    
}

This produces the following result:

Constructing an Employee
Constructing an Employee

Call mailCheck using Salary reference:
Within mail Check of Salary class
Mailing check to Joe Bloggs with salary 3600.0

Call mail Check using Employee reference:
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.00



Abstract Methods

If you want a class to contain a particular method but you want the actual implementation of that method to be determined by child classes, you can declare the method in the parent class as abstract.

  • Abstract keyword is used to declare the method as abstract.
  • You have to place the abstract keyword before the method name in the method declaration.
  • An abstract method contains a method signature, but no method body.
public abstract class Employee{

    private String name;
    private String address;
    private int number;

    public abstract double computePay();

    // Remainder of class definition

}

Declaring a method as abstract has two consequences:

  • The class containing it must be declared as abstract.
  • Any class inheriting the current class must either override the abstract method or declare itself as abstract.

Suppose Salary class inherits the Employee class, then it should implement the computePay() method as shown below:

public class Salary extends Employee {
    private double salary;
    public double computePay() {
        System.out.println("Computing salary pay for " + getName());
        return salary/52;
    }

    // Remainder of class definition

}



Encapsulation

https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)

https://www.tutorialspoint.com/java/java_encapsulation.htm

https://www.csee.umbc.edu/courses/331/spring11/notes/11/pl9ch11.pdf

https://www.chegg.com/homework-help/concepts-of-programming-languages-10th-edition-chapter-11-problem-15ps-solution-9780133072518


In object oriented programming languages, encapsulation refers to one of two related but distinct notions, and sometimes to the combination of both:

  • Encapsulation is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit (e.g., a class in Java). It is the mechanism that binds together the code and the data it manipulates.
  • Encapsulation is a mechanism for restricting direct access to some of the object's components. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding.
To achieve encapsulation this:
Declare the variables of a class as private.
Provide public setter and getter methods to modify and view the variables values.


Some programming language researchers and academics use the first meaning alone or in combination with the second as a distinguishing feature of object-oriented programming.

In many object-oriented languages, components are not hidden automatically and this can be overridden; thus, information hiding is defined as a separate notion by those who prefer the first definition.

The features of encapsulation are supported using classes in most object-oriented languages, although other alternatives also exist.


Naming encapsulation:

There is another kind of encapsulation that is necessary for constructing large programs and it is known as Naming encapsulation. Large programs are developed by more than one developer. So there is a chance of naming problems. It means different variables can have the same name. Naming encapsulation defines names scopes that assist in avoiding the name conflicts. For example, each library can create its own naming encapsulation to prevent its names from conflicting with the names defined in other libraries or in client code. Each logical part of a software system can create a naming encapsulation with the same purpose.


TestEncapsulation.java
package zpruebas;

public class ZPruebas{
    
    private String id;
    private String name;
    private int    age;
    
    
    // Setter methods
    public void setId(String newId){
        id = newId;
    }
    
    public void setName(String newName){
        name = newName;
    }
    
    public void setAge(int newAge){
        age = newAge;
    }
    
    
    // Getter methods
    public String getId(){
        return id;
    }
    
    public String getName(){
        return name;
    }
    
    public int getAge(){
        return age;
    }
        
}

The public setXXX() and getXXX() methods are the access points of the instance variables of the TestEncapsulation class. Normally, these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters.

The variables of the EncapTest class can be accessed as below:

/* File name : RunEncap.java */

public class RunEncapsulation{
    public static void main(String args[]){
        TestEncapsulation encap = new TestEncapsulation();
        encap.setId("12343");
        encap.setName("James");
        encap.setAge(20);
        
        System.out.println("ID: "+encap.getId()+". Name: "+encap.getName()+". Age: "+encap.getAge());
    }
}

This would produce the following result:

ID: 12343. Name: James. Age: 20

Benefits of Encapsulation:

  • The fields of a class can be made read-only or write-only.
  • A class can have total control over what is stored in its fields.
  • The users of a class do not know how the class stores its data. A class can change the data type of a field and users of the class do not need to change any of their code.



Inheritance

Inheritance can be defined as the process where one class acquires the properties and behavior (methods and fields) of another class.

Inheritance enables code reusability as well as adding new features to the existing code.

  • superclass (base class, parent class): The class whose properties are inherited.
  • subclass (derived class, child class): The class which inherits the properties of other.



Types of inheritance

Types of inheritance


Single inheritance enables a derived class to inherit properties and behavior from only a single parent class.


Multiple inheritance enables a class can inherit characteristics and features from more than one parent class.


A very important fact to remember is that Java does not support multiple inheritance. This means that a class cannot extend more than one class. Therefore following is illegal:

public class extends Animal, Mammal{} // Illegal in Java


However, a class can implement one or more interfaces. This has made Java get rid of the impossibility of multiple inheritance.



Inheritance in Java


Extends keyword

extends is the keyword used to inherit the properties of a class. With use of the extends keyword the subclasses will be able to inherit all the properties of the superclass except for the private properties of the superclass.

Example:

class Super{
    ...
    ...
}


class Sub extends Super{
    ...
    ...
}


Calculation.java
package calculation;

class Calculation {
    int z;
    
    public void addition(int x, int y){
        z=x+y;
        System.out.println("The sum of the given numbers:"+z);
    }
    
    public void substraction(int x,int y){
        z=x-y;
        System.out.println("The difference between the given numbers:"+z);
    }
}


MyCalculation.java
package calculation;

public class MyCalculation extends Calculation{
    
    public void multiplication(int x, int y){
        z = x*y;
        System.out.println("The product of the given numbers is: "+z);
    }
    
    public static void main(String args[]){
        int a=20, b=10;
        MyCalculation demo = new MyCalculation();
        demo.addition(a,b);
        demo.substraction(a, b);
        demo.multiplication(a, b);
    }
}


Using extends keyword, My_Calculation inherits the methods addition() and Subtraction() from Calculation class.

You can instantiate the class as given below as well. But using the superclass reference variable ( cal in this case ) you cannot call the method multiplication(), which belongs to the subclass My_Calculation:


Calculation cal = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);


A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.



The super keyword

The super keyword is similar to this keyword. The following are the scenarios where the super keyword is used.

  • It is used to differentiate the members of superclass from the members of subclass, if they have same names.
  • It is used to invoke the superclass constructor from subclass.



Differentiating the members

If a class is inheriting the properties of another class, and if the members of the superclass have the same names as the sub class, to differentiate these variables we use super keyword as shown below.

super.variable
super.method();


Sample Code

In the given program you have two classes namely Sub_class and Super_class, both have a method named display() with different implementations, and a variable named num with different values.


package btest2_the_super_keyword;

class Super_class{
    int num=20;

    //display method of superclass
    public void display(){
        System.out.println("This is the display method of superclass");
    }
}


package btest2_the_super_keyword;

public class Sub_class extends Super_class {
    int num=10;
    
    //display method of sub class
    public void display(){
        System.out.println("This is the display method of subclass");
    }
    
    public void my_method(){
        //Instantiating subclass
        Sub_class sub=new Sub_class();
        
        //Invoking the display() method of sub class
        sub.display();
        
        //Invoking the display() method of superclass
        super.display();
        
        //printing the value of variable num of subclass
        System.out.println("value of the variable named num in sub class:"+ sub.num);
        
        //printing the value of variable num of superclass
        System.out.println("value of the variable named num in super class:"+ super.num);
        
    }

    public static void main(String args[]){
        Sub_class obj = new Sub_class();
        obj.my_method();
    }
    
}



Invoking Superclass constructor

If a class is inheriting the properties of another class, the subclass automatically acquires the default constructor of the super class. But if you want to call a parameterized constructor of the super class, you need to use the super keyword as shown below.


super(values);
class SuperClass{
    
    int age;
    
    SuperClass(int age){
        this.age=age;
    }
    
    public void getAge(){
        System.out.println("The value of the variable named age in super class is: " +age);
    }
}


public class SubClass extends SuperClass {
    
    SubClass(int age){
        super(age);
    }
    
    public static void main(String argd[]){
        SubClass s = new SubClass(24);
        s.getAge();
    }
    
}



C++ Inheritance

https://www.w3schools.com/cpp/cpp_inheritance.asp

https://www.tutorialspoint.com/cplusplus/cpp_interfaces.htm



Polymorphism

Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.

Any Java object that can pass more than one IS-A test is considered to be polymorphic. In Java, all Java objects are polymorphic since any object will pass the IS-A test for their own type and for the class Object.

It is important to know that the only possible way to access an object is through a reference variable. A reference variable can be of only one type. Once declared, the type of a reference variable cannot be changed.

The reference variable can be reassigned to other objects provided that it is not declared final. The type of the reference variable would determine the methods that it can invoke on the object.

Let us look at an example:

public interface Vegetarian{}

public class Animal{}

public class Deer extends Animal implements Vegetarian{}

The Deer class is considered to be polymorphic since this has multiple inheritance. The following are true for the above example:

  • A Deer IS-A Animal
  • A Deer IS-A Vegetarian
  • A Deer IS-A Deer
  • A Deer IS-A Object

When we apply the reference variable facts to a Deer object reference, the following declarations are legal:

Deer d = new Deer();

Animal a = d;

Vegetarian v = d;

Object o = d;

All the reference variables d,a,v,o refer to the same Deer object in the heap.



Virtual Methods

The behaviour of overridden methods in Java allows you to take advantage of polymorphism when designing your classes.

Method overriding, where a child class can override a method in its parent. An overridden method is essentially hidden in the parent class, and is not invoked unless the child class uses the super keyword within the overriding method.

package virtualmethods;

public class Employee {
    
    private String name;
    private String address;
    private int    number; 
    
    public Employee(String name, String address, int number) { 
        System.out.println("Constructing an Employee"); 
        this.name    = name; 
        this.address = address; 
        this.number  = number; 
    } 
    
    public void mailCheck() { 
        System.out.println("Mailing a check to "+ this.name + " "+ this.address);
    }
    
    public String toString() { 
        return name + " " + address + " " + number; 
    } 
    
    public String getName() { 
        return name; 
    } 
    
    public String getAddress() { 
        return address; 
    } 
    
    public void setAddress(String newAddress) {
        address = newAddress; 
    } 
    
    public int getNumber() {
        return number; 
    }
    
}
package virtualmethods;

public class Salary extends Employee {
    
    private double salary;
    
    public Salary(String name, String address, int number, double salary) { 
        super(name, address, number);
        setSalary(salary);
    } 
    
    public void mailCheck() {
        System.out.println("Within mailCheck of Salary class ");
        System.out.println("Mailing check to "+getName()+ " with salary "+salary);
    }
    
    public double getSalary() {
        return salary;
    }
    
    public void setSalary(double newSalary){
        if(newSalary >= 0.0){
            salary = newSalary;
        }
    }
    
    public double computePay(){
        System.out.println("Computing salary pay for " + getName());
        return salary/52;
    }
    
}
package virtualmethods;

public class VirtualDemo {
    public static void main(String [] args){
        
        Salary   s = new Salary("Joe Bloggs", "Dublin 10", 3, 3600.00);
        Employee e = new Salary("John Adams", "Dublin 12", 2, 2400.00);
        
        System.out.println("\nCall mailCheck using Salary reference:");        
        s.mailCheck();
        
        System.out.println("\nCall mailCheck using Employee reference:");
        e.mailCheck();
        
    }
    
}

This would produce the following result:

Constructing an Employee
Constructing an Employee

Call mailCheck using Salary reference:
Within mailCheck of Salary class 
Mailing check to Joe Bloggs with salary 3600.0

Call mailCheck using Employee reference:
Mailing a check to John Adams Dublin 12

Here, we instantiate two Salary objects . one using a Salary reference s, and the other using an Employee reference e. While invoking s.mailCheck() the compiler sees mailCheck() in the Salary class at compile time, and the JVM invokes mailCheck() in the Salary class at run time.

Invoking mailCheck() on e is quite different because e is an Employee reference. When the compiler sees e.mailCheck(), the compiler sees the mailCheck() method in the Employee class.

Here, at compile time, the compiler used mailCheck() in Employee to validate this statement. At run time, however, the JVM invokes mailCheck() in the Salary class.

This behavior is referred to as virtual method invocation, and the methods are referred to as virtual methods. All methods in Java behave in this manner, whereby an overridden method is invoked at run time, no matter what data type the reference is, which was used in the source code at compile time.



IS-A relationship

IS-A is a way of saying : This object is a type of that object.

public class Animal{

}

public class Mammal extends Animal{

}

public class Reptile extends Animal{

}

public class Dog extends Mammal{
    public static void main(String args[]){
        Animal a = new Animal();
        Mammal m = new Mammal();
        Dog    d = new Dog();

        System.out.println(m instanceof Animal); // true
        System.out.println(d instanceof Mammal); // true
        System.out.println(d instanceof Animal); // true
    }

}

The following are true:

  • Animal is the superclass of Mammal class.
  • Animal is the superclass of Reptile class.
  • Mammal and Reptile are subclasses of Animal class.
  • Dog is the subclass of both Mammal and Animal classes.

Now, if we consider the IS-A relationship, we can say:

  • Mammal IS-A Animal
  • Reptile IS-A Animal
  • Dog IS-A Mammal
  • Therefore : Dog IS-A Animal as well



HAS-A relationship

These relationships are mainly based on the usage. This determines whether a certain class HAS-A certain thing. This relationship helps to reduce duplication of code as well as bugs.

public class Vehicle{} 

public class Speed{} 

public class Van extends Vehicle{
    private Speed sp;
}

This shows that class Van HAS-A Speed. By having a separate class for Speed, we do not have to put the entire code that belongs to speed inside the Van class. We also can reuse the Speed class in multiple applications.



Composition

This is an excellent example to understand composition: https://refactoring.guru/design-patterns/decorator



Nested classes

Java allows us to define a class within another class. Such a class is called a nested class. The class which enclosed nested class is known as Outer class. In java, we can not make Top level class static. Only nested classes can be static.

class OuterClass {
    ...
    class NestedClass {
        ...
    }
}


Compelling reasons for using nested classes include the following:

  • It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Thus, having that functionality contained within a nested class will increase readability and reduce clutter.
  • It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
Another very important advantage of having nested classes, is the fact that nested classes will be able to access all the class members of their enclosing top-level-class (including the private member methods and variables). This is a more efficient way than the traditional way of accessing the non-private members using an object instance. A noticeable advantage of this feature can be seen when developing event-based applications, where action and event listeners can be defined as nested classes rather than having them as separate individual top-level-classes.
  • It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.
  • A difference or an advantage nested classes possess over subclasses, is that subclasses can't access private members (unless they are declared as protected) while nested classes can.


Nested classes in java can be classified into the following types:

  • non-static nested classes
  • static nested classes

Following are major differences between static nested class and non-static nested class. Non-static nested class is also called Inner Class. https://www.geeksforgeeks.org/static-class-in-java/

  • Nested static class doesn’t need reference of Outer class, but Non-static nested class or Inner class requires Outer class reference.
  • Inner class(or non-static nested class) can access both static and non-static members of Outer class. A static class cannot access non-static members of the Outer class. It can access only static members of Outer class.
  • An instance of Inner class cannot be created without an instance of outer class and an Inner class can reference data and methods defined in Outer class in which it nests, so we don’t need to pass reference of an object to the constructor of the Inner class. For this reason Inner classes can make program simple and concise.



Non-static nested classes

En muchas fuentes se habla de Inner class(or non-static nested class). Como si fuesen sinónomos. En todo caso una Inner class es una no-static nested class.

Non-static nested classes are defined within the top-level-classes and they are bound by the scope of their enclosing class. non-static nested classes can have direct access into all of the members (event the private ones) of their enclosing class. On the other hand, the enclosing class doesn't have any access to the members of the enclosed nested class. It is also worth to mention that nested classes (in general) can be defined from within any block inside a top-level-class, that could be a method block or even a control statement target block (such as if, for or while). There are two flavours of non-static nested classes:

  • Inner Classes
  • Anonymous Classes



Inner Classes

These are the most widely used type of nested classes, the following code excerpt shows:

  • How to define a an inner class within a normal top-level-class
  • How easily the private members of the enclosing class can be accessed by the nested class
  • How to obtain an instance of the inner class from within the enclosing class



Anonymous Classes


static nested classes


Example

package nestedclasses;

public class OuterClass {
    
    private int private_member_variable = 100;
    
    // // no-static (Inner) nested class
    public class InnerClass {
        public void printPrivateVariable() {
            // Se debe notar como se puede acceder directamente a la Instance variable of the OuterClass
            // Esto se puede hacer porque es un no-static:
            System.out.println(private_member_variable);
        }
    }
    
    // You can do a method responsible of running the Method inside the Inner class
    // This is a way to call the Method inside the Inner class from another class.
    // Sim embargo, no es la 'unica forma de hacerlo.
    // En la TestClass se muestran otra de hacerlo.
    public void callInnerClassMethod() {
        InnerClass innerClass = new InnerClass();
        innerClass.printPrivateVariable();
    }
    
    
    // // static nested class
    public static class StaticNestedClass {
        public void printPrivateVariables() {
            // Se debe notar que en este caso, NO se puede acceder directamente a la Instance variable of the OuterClass,
            // We first need to create an Instance of the OuterClass to be able to access its Instance variables
            OuterClass outerclass = new OuterClass();
            System.out.println(outerclass.private_member_variable);
        }
    }
    
}

The following code explains how an instance of a Nested class can be obtained from code outside their enclosing class:

package nestedclasses;

public class TestClass {

    public static void main(String args[]) {

        // // no-static (Inner) nested class
        
        // If we use the method we created in the OuterClass that is responsible of running the Method inside the Inner class,
        // we can run the method inside the Inner class this way:
        OuterClass outerclass = new OuterClass();
        outerclass.callInnerClassMethod();

        // If we want to run the method directly form an instance of the Inner class,
        // here is how an instance of the Inner class can be obtained from code outside their enclosing class or from a static method:
        // Note que debido a que la clase es no-static, debemos utilizar la Instance of the OuterClass Class to access
        // the «new» method that allows to instantiate the class.
        OuterClass.InnerClass innerclass = outerclass.new InnerClass();
        innerclass.printPrivateVariable();


        // // static nested class
        
        // Here is how an instance of the Static Nested Class can be obtained.
        // Note que debido a que la clase es static, no necesitamos una Instance of the OuterClass to access the «new» method.
        OuterClass.StaticNestedClass staticnestedclass = new OuterClass.StaticNestedClass();
        staticnestedclass.printPrivateVariables();
        
    }
    
}



Upcasting - Downcasting

http://www.codejava.net/java-core/the-java-language/what-is-upcasting-and-downcasting-in-java

Java permits an object of a subclass type to be treated as an object of any superclass type.

In this sense, Upcasting is casting a subtype to a supertype, upward to the inheritance tree. In the other hand, Downcasting is casting to a subtype, downward to the inheritance tree

Upcasting-Downcasting



UpCasting

Upcasting is casting a subtype to a supertype, upward to the inheritance tree. Let’s see an example:

Dog    dog  = new Dog();
Animal anim = (Animal) dog;
anim.eat();



Upcasting during method calling

We need upcasting when we want to write general code that deals with only the supertype. Consider the following class:

public class AnimalTrainer {
    public void teach(Animal anim) {
        anim.move();
        anim.eat();
    }
}

Here, the teach() method can accept any object which is subtype of Animal. So objects of type Dog and Cat will be upcasted to Animal when they are passed into this method:

Dog dog = new Dog();
Cat cat = new Cat();
 
AnimalTrainer trainer = new AnimalTrainer();
trainer.teach(dog);  // Upcasting is done automatically by Java
trainer.teach(cat);  // Upcasting is done automatically by Java

As Upcasting is done automatically, The teach method can have what ever Animal or it's subclass as an argument.



Downcasting

Downcasting is casting to a subtype, downward to the inheritance tree. Let’s see an example:

Animal anim = new Cat();
Cat cat = (Cat) anim;

Here, we cast the Animal type to the Cat type. As Cat is subclass of Animal, this casting is called downcasting.

Unlike upcasting, downcasting can fail if the actual object type is not the target object type. For example:

Animal anim = new Cat();
Dog dog = (Dog) anim;

This will throw a ClassCastException because the actual object type is Cat. And a Cat is not a Dog so we cannot cast it to a Dog.

The Java language provides the instanceof keyword to check type of an object before casting. For example:

if (anim instanceof Cat) {
    Cat cat = (Cat) anim;
    cat.meow();
} else if (anim instanceof Dog) {
    Dog dog = (Dog) anim;
    dog.bark();
}

So if you are not sure about the original object type, use the instanceof operator to check the type before casting. This eliminates the risk of a ClassCastException thrown.

Downcasting is used more frequently than upcasting. Use downcasting when we want to access specific behaviors of a subtype.

Consider the following example:

public class AnimalTrainer {
    public void teach(Animal anim) {
        // do animal-things
        anim.move();
        anim.eat();
 
        // if there's a dog, tell it barks
        if (anim instanceof Dog) {
            Dog dog = (Dog) anim;
            dog.bark();
        }
    }
}

Here, in the teach() method, we check if there is an instance of a Dog object passed in, downcast it to the Dog type and invoke its specific method, bark().



Using polymorphism

Cats can't purr, while being labelled something else:

  • If you upcast an object, it will lose all it's properties, which were inherited from below it's current position.
  • For example, if you cast a Cat to an Animal, it will lose properties inherited from Mammal and Cat. That data will not be lost, you just can't use it, until you downcast the object to the right level.
  • Why is it like that? If you have a group of Animals, then you can't be sure which ones can meow() and which ones can bark(). That is why you can't make Animal do things, that are only specific for Dogs or Cats
Cats can't purr, while being labelled something else


However the problem above is not an obstacle if you choose to use polymorphism. Polymorphism uses automatic downcast during method calls.

Polymorphism uses automatic downcast during method calls.



Remember

  • Casting does not change the actual object type. Only the reference type gets changed.
    • For example, if you create a Cat and upcast it to Animal, then the object doesn't stop from being a Cat. It's still a Cat, but it's just treated as any other Animal and it's Cat properties are hidden until it's downcasted to a Cat again.
  • Upcasting is always safe and never fails.
  • Downcasting can risk throwing a ClassCastException, so the instanceof operator is used to check type before casting.
  • Upcasting is done automatically (it's also legal to do manually), while downcasting must be manually done by the programmer.
    • Why is it, that upcasting is automatic, but downcasting must be manual? Because as explained above, Upcasting can never fail. But if you have a group of different Animals and want to downcast them all to a Cat, then there's a chance, that some of these Animals are actually Dogs, and process fails, by throwing a ClassCastException
Casting does not change the actual object type



Example

public class Animal {
    
    int health = 100;
    
    public static void stroke(Animal a) {
        System.out.println("you stroke the "+a);
    }

}
public class Mammal extends Animal {}
public class Cat extends Mammal {}
public class Dog extends Mammal {}
public class Test {
    
    public static void main(String[] args) {
        Cat c = new Cat();
        System.out.println(c.health);
        
        Dog d = new Dog();
        System.out.println(d.health);
        
        
        // // Upcasting
        Mammal m = c;           // Although there's no need to for programmer to upcast manually, it's legal to do so:
                                // Mammal m = (Mammal) new cat();
                                
        System.out.println(c);  // This print:               upcastingdowncasting.Cat@15db9742                               
        System.out.println(m);  // This will print the same: upcastingdowncasting.Cat@15db9742
                                // As you can see, Casting does not change the actual object type
                                // Cat is still exactly the same Cat after upcasting.
                                // It didn't change to a Mammal, it's just being labelled Mammal right now.
                                // This is allowed, because Cat is a Mammal.
        
                                        
        // // Downcasting
        if(m instanceof Cat){   // testing if the Animal is a Cat
            System.out.println("It's a Cat! Now I can downcast it to a Cat, without a fear of failure.");
            Cat c1 = (Cat)m;    // Manual downcasting back to a Cat
        }
        
        // The following code will compile, but throws "java.lang.ClassCastException: Mammal cannot be cast to Cat" exception during runTime,
        // because I’m trying to cast a Mammal, which is not a Cat, to a Cat.
        Mammal m1 = new Mammal();
        Cat    c2 = (Cat)m1;                        
                                
    }
    
}



I really need to make a Dog out of my Cat

Well, you can't do it by casting. However, objects are nothing else, but few methods and fields. That means, you can make a new dog out of your Cat's data.

Cat class:

class Cat extends Mammal {
    Color furColor;
    int numberOfLives;
    int speed;
    int balance;
    int kittens = 0;

    Cat(Color f, int n, int s, int b) {
        this.furColor = f;
        this.numberOfLives = n;
        this.speed = s;
        this.balance = b;
    }
}

Dog class:

class Dog extends Mammal {
    Color furColor;
    int speed;
    int barkVolume;
    int puppies = 0;
    Dog(Color f, int n, int s, int b) {
        this.furColor = f;
        this.speed = s;
        this.barkVolume = b;
    }
}

You want to make a Dog out of the Cat. All you need to do, is, place a method inside of the Cat class, that converts the fields and returns a new Dog based on that:

public Dog toDog(int barkVolume){
    Dog d = new Dog(furColor, speed, barkVolume);
    d.puppies = kittens;
    return d;
}

As you can see, they don't match that well, so some fields were inconvertible, and some data had to be made from scratch. Notice, that:

  • numberOfLives and Balance were not converted, and
  • barkVolume was completely new data.
  • If you have 2 Classes, that match perfectly, then hurray, but it rarely happens.

Conversion can now be called from where ever you need:

Cat c = new Cat(Color.black, 9, 20, 40);
Dog d = c.toDog(50);



Errors and Exceptions


Errors

Multiple types of error within Java:

  • Syntax errors
  • Logic errors
  • Runtime errors



Syntax errors

  • Types
  • Misspellings
  • Trying to use a class that doesn't exist
  • Trying to pass the wrong parameters to a method


  • Caught by the compiler/IDE
    • Program won't compile with syntax errors present



Logic errors

  • Occur when the program doesn't do what it's intended to do. E.g.
    • Loop printing out contents of an array doesn't display the last element.
    • Searching for the minimum element actually finds the maximum


  • Programs can be compiled with logic errors present.



Runtime errors

  • Errors that can happen while the program is running.
  • Caused by the program trying to do something impossible. E.g.
    • Trying to access a slot in an array that doesn't exist.
    • Trying to save a piece of text as a number.
    • Trying to open a file that doesn't exist.


  • This kind of error can result in the program crashing.
  • Runtime errors are said to cause exceptions (Se dice que los errores de tiempo de ejecución causan excepciones).



Exceptions

  • Error that occurs during the runtime of a program.
  • When an exception occurs, it is said to be thrown.
  • Some examples of causes of exceptions were already given above as runtime errors.
    • E.g. Trying to access a file that does not exist would be an IOException.
  • Exceptions cause the program to terminate abnormally & may cause major issues.
    • Example: Transferring money from one account to another: If exception occurs AFTER money is withdrawn from account A but BEFORE money is lodged to account B, money would be lost.



Exception object

  • When an exception occurs, an Exception object is created (Similar to an Event object when an event occurs in a GUI)
  • All Exceptions inherit from the Throwable class.
  • The Exception object created is a specific type, depending on what error occurs. E.g:
    • IOException for input/output error.
    • ArrayIndexOutOfBoundsException for trying to access a slot outside the end of an array.
  • Exception object contains information about the exception that occurred. For an Exception called e:
    • e.printStackTrace() - prints out the sequence of events/method calls leading up to the exception.
    • e.getMessage() - returns a detailed message of the exception.
    • e.toString() - returns the full details of the exception that occurred.
  • You can also write your own Exception classes by extending the Throwable class or any of its subclasses.

The Exception Hierarchy:

The Exception Hierarchy



Checked exception

Any exception that is a subclass of Exception and is not a subclass of RuntimeException. In practical terms, checked exceptions are exceptions that should be anticipated to be handled.

  • Examples:
    • When working with files, you should anticipate the situation where the file isn't present, a FileNotFoundException.
    • IOException
      • FileNotFoundException
      • EOFException
    • SQLException



Unchecked exception

Any exception that is a subclass of RuntimeException.

  • Usually caused by logic/coding issues within the program – these cannot be recovered from.
  • Certain types are caused by user carelessness & can be recovered from.
  • Examples:
    • IndexOutOfBoundsException
      • ArrayIndexOutOfBoundsException
      • StringIndexOutOfBoundsException
    • ClassCastException
    • InputMismatchException
    • NumberFormatException



Handling/Dealing with exceptions

Java exception-handling model is based on 3 operations:

  • Operations involved in dealing with exceptions:
1. Declaring an exception to be thrown - (exception propagation) (pass the buck).
2. Catching an exception - handle it yourself.
  • Operations involved in causing exceptions:
3. Deliberately throwing an exception.


When a checked exception could possibly occur within a piece of code, it must be either:

  • declared to be thrown or
  • caught.

If you do not use one of the two operations to deal with the exception, your code will not compile.



Declaring an exception to be thrown
  • What is declaring an exception?
    • Marking a method as a possible source of a specific type of exception.
  • Done using the throws keyword in the method signature:
    • public void myMethod() throws IOException
    • If multiple exception types are possible, list them after throws, separated by commas.
  • What does it mean?
    • If a method contains a checked exception and you do not want to deal with it in that method, you can declare that it may throw that exception.
    • Whatever calls that method would then also have to handle the exception in some way – exception propagation.
      • Passing the buck!!!
//Method to get the sum of numbers input from a file
public void computeSum() throws IOException{  // Declares this method might throw an IOException
    boolean done = false;
    String filename = "testdata.txt";
    BufferedReader reader = new BufferedReader(new FileReader(filename));
    while (!done) {
        String input = reader.readLine();
        if (input != null) {
            int value = Integer.parseInt(input);
            sum = sum + value;
            System.out.println("value is " + value );
        }
        else {
            done = true;
        }
    }
    reader.close();
}



Catching an Exception

Done using try-catch blocks:

try{
    // Code that could cause an exception
}catch(Exception e){
    // code to run if the exception occurs
}
  • Use this approach when dealing with exceptions within main methods and event handlers.


  • try{} Any code that could possibly cause an exception goes within a try{} block
    • This is the code that will always attempt to run.
  • catch{} The code that should run if something goes wrong goes within a catch{} block
    • This is the code that will run only if the specified exception occurs.
    • Catch block code lets the program to recover from the exception.
    • Code continues on from after the catch block.
    • Catching an exception in this manner means that the program will not crash.


  • Sequence of events:
    • When an exception occurs, the program jumps straight from where it happened into the appropriate catch block.
Catching Exceptions
public class IntegerInput {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        boolean repeat = true;
        while (repeat == true) {
            try {
                System.out.print("Enter an integer: ");
                int number = scanner.nextInt();
                System.out.println("The number entered is " + number);
                repeat = false;
            }
            catch (InputMismatchException ex) {
                System.out.println("Try again. (Incorrect input: an integer is required)");
                scanner.nextLine(); // discard current line and move on to next line
            }
        }
    }
}



Passing Object References

Ahora que nuestro programa está formado por diferentes archivos (diferentes class), veremos que en ocasiones, cuando creamos una «instance» de una class (Ej: «BasicShowData.java») dentro de, por ejemplo, «BasicLogin.java», podría ser necesario que «BasicShowData.java» colecte información de «BasicLogin.java». To do this, we will pass a reference across from the BasicLogin.java page to the «BasicShowData.java» page that will allow us to call back to the «BasicLogin.java» and access any variables or methods that it may have.

Note que inside «», when we click the "Login" button, the actionListener method is then called and the BasicShowData class is just being created. Instead of just creating the «BasicShowData()» class, we are going to pass a reference to «this» current class that we are in (BasicLogin.java class). En otras palabras, cuando en «BasicLogin.java» creamos la instance de «BasicShowData()» vamos a pasar una referencia de la clase donde estamos («BasicLogin.java») a través de «this»:

In BasicLogin.java:

BasicShowData d = new BasicShowData(this);

Now, in the «BasicShowData class», we must change the default constructor to catch «this» reference:

public BasicShowData(BasicLogin ref) {

De esta forma, la instancia de «BasicShowData class» puede acceder to all the variables and fields of the current class («BasicLogin.java»).

PassingObjectReferences/src/BasicLogin.java
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;

public class BasicLogin extends JFrame implements ActionListener{
	JTextField username = null;
	JTextField password = null;
	
	public BasicLogin(){
		
		setSize(300,300);
		setVisible(true);
		
		this.setLayout(new GridLayout(3,2));
		
		JLabel un = new JLabel("Username");
		this.add(un);
		
		username = new JTextField(20);
		this.add(username);
		
		JLabel pw = new JLabel("Password");
		this.add(pw);
		password = new JTextField(20);
		this.add(password);
		
		JButton button = new JButton("Login!");
		button.addActionListener(this);
		this.add(button);
		
		validate();
		repaint();
	}
	public static void main(String[] args){
		
		new BasicLogin();

	}
	@Override
	public void actionPerformed(ActionEvent arg0){
		// TODO Auto-generated method stub
		BasicShowData d = new BasicShowData(this);
	}

}


PassingObjectReferences/src/BasicShowData.java
import javax.swing.JFrame;
import javax.swing.JLabel;

public class BasicShowData extends JFrame {

	public BasicShowData(BasicLogin ref) {
		
		String username = ref.username.getText();
		
		setSize(300,300);
		
		setVisible(true);
		
		JLabel tx = new JLabel("They logged in as: " + username);
		this.add(tx);
	}
}



Generics in Java

https://www.tutorialspoint.com/java/java_generics.htm

https://www.geeksforgeeks.org/generics-in-java/



Connecting to a MySQL database using Java

La conección a la base de datos MySQL la haremos a través de Connector/J. Esta librería no se encuentra por defecto en las librerías de Java y debemos por lo tanto agregarla a nuestro proyecto Java.

Entonces, para realizar la conección debemos:

  1. Crear la base de datos MySQL a la cual queremos conectarnos
  2. Create an Eclipse Java project
  3. Agregar la librería externa Connector/J a nuestro proyecto
  4. Creación de la Clase Java en donde se hará la conexión



Creating a MySQL database

Luego de haber instalado y configurado MySQL (Instalación de MySQL) debemos crear la base de datos a la cual queremos conectarnos con Java. Para más detalles ver Database#MySQL

En este caso vamos a crear la base de datos "graham" y la tabla "samplelogin".

CREATE DATABASE graham;

USE graham;

CREATE TABLE samplelogin(
   id	 	INT(10)		NOT NULL AUTO_INCREMENT,
   username 	VARCHAR(15)	NOT NULL,
   password 	VARCHAR(15)	NOT NULL,
   PRIMARY KEY(id)
);

INSERT INTO samplelogin VALUES('001','Adelo Vieira','a2930');
INSERT INTO samplelogin VALUES('002','Rachel Smith','r1039');



Creating an Eclipse Java Project to use Connector/J

Before we make a connection to the database we first must create a new Eclipse project.

Creación de un proyecto Java en Eclipse:

  • File > New > Java Project: enter Project name
    • Esto creará una carpeta con el nombre del proyecto y dentro de ésta la carpeta srs
    • ...



Agregar la librería externa Connector/J a nuestro proyecto


Connector/J

MySQL Connector/J (Desarrollado por MySQL) is the official JDBC driver for MySQL (MySQL is now owned by Oracle Corporation).

We will need this additional library to allow us to make a connection from Java to the MySQL database. Java does not come with this library by default so we need to include this ourselves.

Para descargar Connector/J: https://dev.mysql.com/downloads/connector/j/

You will then be brought to a page where you will be asked if you would like to signup or login. This step is not needed, at the end of the page you will see a link that says "No thanks, just start my download". Click this link to skip ahead and begin the download.

Inside this folder you will see lots of different files, but we only need one file from this folder. The file we are interested in is the mysql-connector-java-5.1.44-bin.jar file. This is a single jar file that contains all the compiled source code we need to connect to a database.



Making a reference to Connector/J

  • Now that we have a new project, we can begin the process of adding the new library into the eclipse project. Right click on the project name and click "Properties". This will open a window showing you all of the project specific settings for the application you are developing.
  • Inside the properties dialog that opens, click on the Java Build Path option.
  • Once you have opened the Java Build Path option, next click the Libraries tab. This will show you a list of additional libraries you have already referenced. But because this is a new project, you will not see any libraries yet!
  • On the right hand side of this window click "Add External Jar" and a dialog window will open. Use this window to locate the mysql-connector-java-5.1.44-bin.jar file that you extracted earlier.
  • After you have found the jar file, you will see a new entry will be made under the libraries tab. This is telling you that when you go to compile the software you are building, it will also look for the .jar file you have just pointed to.
  • Click Ok to finish this step.
  • When you have finished making a reference to the library you will see that inside of your project under the Referenced Libraries menu, there will be a reference to the JAR file that you just pointed to in the previous step. You are now ready to start adding some code into your project to connect to the database.



Creación de la Clase Java en donde se hará la conexión

Luego de haber creado el proyecto Java, debemos crear una clase de la siguiente forma:

  • src folder (clic d) > New > Class: enter name and Click OK!

One thing to keep in mind when working with this code is that it is tempting to allow Eclipse to automatically settle of the imports for you. This can cause issues however, because some libraries in Java have the same name as the ones inside the Connector/J library. To prevent any problems, manually add the imports yourself to the top of your program:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

All of the code that we are working on is inside of a try catch statement as we do not know for sure what may happen to the database connection. If the database connection suddenly dropped it would crash our program. To prevent this, we can use a try catch statement and catch the error if anything goes wrong and allow our program to fail gracefully rather than come to a complete crash from an error.


La conexión con la base de datos la haremos a través de DriverManager.getConnection, método que se encuentra en la Librería Connector/J.

MyDBConnection.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MyDBConnection{
	
	public MyDBConnection() throws SQLException{
		
		// La conexi'on con la base de datos se hace a trav'es de esta orden:
           	Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/graham?"
    					             	       +"user=root&password=a1640774200");
		
		// Luego de establecer la conexi'on podemos realizar un query sobre la base de datos:
        	Statement stmt = conn.createStatement();
        	ResultSet rs = stmt.executeQuery("select * from samplelogin;");
			
	}

}

En el ejemplo anterior hemos realizado la conexión con la base de datos SQL «graham» y hemos almacenado el resultado de la query en la variable rs. Sin embago, no hemos desplegado el resultado de la query ni hemos hecho nada útil con ella. A continuación se muestran algunas clases que conectan con la base de datos y muestran ejemplos más elaborados.



Creación de la clase ShowingData.java

ShowingData.java
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JTextField;


public class ShowingData extends JFrame  {
	
    public ShowingData(){
    
    	setSize(500,500);
    	setVisible(true);
    	
    	Connection conn = null;
    	Statement stmt = null;
    	ResultSet rs = null;
    	
    	try {
    	    // La conexi'on con la base de datos se hace a trav'es de esta orden:
    	    conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/graham?"
    	    				        +"user=root&password=a1640774200");

    	    // Luego de establecer la conexi'on podemos realizar un query sobre la base de datos:
    	    stmt = conn.createStatement();
    	    rs = stmt.executeQuery("select * from samplelogin;");

    	    // El reultado del query se encuentra en el objeto "rs" creado arriba.
    	    // Ahora queremos desplegar la data almacenada en "rs".
    	    // En este ejemplo vamos a desplegar la data en un JTable.
    	    
    	    // Lo primero que hay que hacer es crear una variable de tipo String (una matriz en este caso)
    	    // El n'umero de columnas debe, por supuesto, ser igual al n'umero de columnas de la tabla
    	    // almacenada en "rs". El n'umero de filas debe ser igual o mayor al n'umero de filas de la tabla.
     	    String[][] data = new String[100][3];
     	    
     	    // Ahora vamos a ingresar la data que se encuentra en el objeto "rs" a la matriz "data" creada arriba.
     	    // Para esto vamos a realizar un ciclo que va a recorrer el objeto "rs" e ingresar los valores a "data"
    	    int counter = 0;
    	    while(rs.next()){
    	    	String id = rs.getString("id");      
    	       
    	    	data[counter][0] = id;
    	      
    	        String un = rs.getString("username");
    	    	data[counter][1] = un;    	      
    	        
    	        String pw = rs.getString("password");
    	    	data[counter][2] = pw;
    	        
    	        counter = counter+ 1;
    	    }
    	    
    	    // Ahora que ya tenemos la data almacenada en la matriz "data", podemos desplegarla en una JTable.
    	    // S'ólo debemos antes crear un vector String que contenga el nombre de las columnas:
    	    String[] colNames = {"id" , "username" , "password"};
    	    
    	    // Ahora s'i podemos desplegar la data correctamente en el JTable:
    	    JTable table = new JTable(data , colNames);
    	    
    	    // Tenemos tambi'en que agregamos un JScrollPane a nuestra tabla para poder desplazarnos en ella:
    	    JScrollPane sr = new JScrollPane(table);
    	    
    	    // Por 'ultimo, agregamos nuestra Jtable al JFrame:
    	    this.add(sr);
    	        
    	} 
    	
    	// Handle any errors:
    	catch (SQLException ex) {
    	    System.out.println("SQLException: " + ex.getMessage());
    	    System.out.println("SQLState: " + ex.getSQLState());
    	    System.out.println("VendorError: " + ex.getErrorCode());
    	}
    	
    	
    }
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub
			new ShowingData();
	}

}



Creación de la clase Register.java

En este caso vamos a crear la clase Register.java, la cual permite ingresar datos a una base de datos MySQL utilizando la librería Connector/J.

Register.java
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;


public class Register extends JFrame implements ActionListener{
	
	// make the fields global so we can see them!!
	JTextField username = null;
	JTextField password = null;
	
	public Register(){		

		setSize(400,400);
		setVisible(true);
		this.setLayout(new GridLayout(3,1));

		JLabel un = new JLabel("Username:");
		this.add(un);
		username = new JTextField(20);
		this.add(username);
		
		JLabel pw = new JLabel("Password:");
		this.add(pw);
		password = new JTextField(20);
		this.add(password);
		
		JButton register = new JButton("Register");
		
		register.addActionListener(this);
		
		this.add(register);
		
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Register();
	}
	
	public void registerNewUser(){
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
		}
		
		catch(Exception e ){}
		
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		
		try {
			// En esta linea debemos ajustar: 
			// El IP (127.0.0.1 si es localhost) y el Port (generalmente el 3306) en donde corre MySQL.
			// El nombre de la base de datos a la cual queremos conectarnos: graham en nuestro ej.
			// El usuario y la clave de MySQL.
			conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/graham?user=root&password=a1640774200");
	    	
			// Do something with the Connection
			stmt = conn.createStatement();
			
			// or alternatively, if you don't know ahead of time that
			// the query will be a SELECT...
			String un = username.getText();
			String pw = password.getText();
			
			// En esta linea debemos ajustar el nombre de la base de datos y la tabla
			// en donde queremos agragar datos. En nuestro ejemplo: graham, samplelogin.
			if (stmt.execute("INSERT INTO `graham`.`samplelogin` (`username`, `password`) VALUES ('"+un+"', '"+pw+"');")) {
			}
		}
		
		// loop over results
		catch (SQLException ex) {
			// handle any errors
			System.out.println("SQLException: " + ex.getMessage());
			System.out.println("SQLState: " + ex.getSQLState());
			System.out.println("VendorError: " + ex.getErrorCode());
		}
	}
	
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		registerNewUser();
	}
}



Threads

La siguiente es la referencia colocada por el Prof. para este tema: https://docs.oracle.com/javase/tutorial/essential/concurrency/

Threads are used to allow our program to do more than one thing at any one time.

We picture a process which has two tasks that aren't necessarily dependent on each other. They can occur at the same time, each handled by a "thread"

  • Thread.jpg
  • Java thread.png

So, a process (think program) can contain a number of different threads. As the program is running, the processor switches between each of the threads allowing each of them to have some CPU time to run.

For dual (or more) core machines, each thread can be executed on a separate core, so no switching is neceessary. The threads truly run concurrently.

In the previous picture you can also see that Thread number 2 has died off and thread 1 continued on. This is ok.

Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.

Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files.

Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. From the programmer’s point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads



The difficulty with threads

  • Threads can be difficult to work with because their behavior can be unpredictable.
  • The order in which they are running may change unless synchronized.



Some methods available in the Thread class

// Changes the name of this thread to be equal to the argument name.
setName(String name) 

// Changes the priority of this thread. Valid values are 1 through 10.
setPriority(int newPriority)

// Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds
sleep(long millis)

// Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
start()

// Causes the current thread to block (pause) until the specified thread terminates.
Thread.join()

// Causes the current thread to block until the specified thread terminates or the specified number of milliseconds passes
Thread.join(long millis)



Creating Threads

We'll see that (just like everything in Java) a thread is just an object. We can create them, use them, etc...

When we want to create threads, two options are available to us:

  • Extend the thread class, or
  • We can implement the Runnable interface


Extend the thread class:

By doing like this we have access to all the methods in the thread class.

We need to extend the thread class and add a run method (Instead of a main method, threads run the run() method):

MyThread.java:
public class MyThread extends Thread {

	public void run(){
		// This is the code that is executed when the thread is started
		// Este es s'olo un c'odigo ejemplo. Aqu'i podr'ia haber cualquier c'odigo
		for (int i=0 ; i < 100000000 ; i++){
			System.out.println(this.getName() + ": " + i);
			
		}
		
	}
	
}

Then, when we want to use our thread (in our standard class: MyProgram.java in our example), we create an instance of the thread, then start it.

MyThread t = new MyThread();
t.start();


Implement the Runnable interface:

To do this we just start by making a regular class, but implement the runnable interface.

After this, we need to add a run() method to the class (Instead of a main method, threads run the run() method):

MyRunnable.java
public class MyRunnable implements Runnable {
	
	public void run(){
		
		for (int i=0 ; i < 100000000 ; i++){
			System.out.println("My Tread implementing the Runnable interface: " + i);
			
		}
		
	}
	
}


Then, in our standard class (MyProgram.java in our example), when we want to use our thread, we just need to create an instance of the thread in case we extended the thread class (as we said above), then start it. However, if we implemented the Runnable interface:

  • We need to create an instance of the Runnable Tread we created:
MyRunnable r = new MyRunnable();
  • After this, we need to create a Thread object and pass the Runnable Tread object we created to it, and then start it:
Thread tr = new Thread(r);
tr.start();


Whatever code is inside the run method will be executed when the thread is started.

For instance, if we would like the thread to sleep for a certain amount of time, we can call:

try{ 
     myThread.sleep(10000);
}catch (InterruptedException e){
     e.printStackTrace();
}


A continuación («MyProgram.java») es la «standad class» en donde vamos a utilizar las «Threads» («MyThread.java» and «MyRunnable.java») creadas arriba:

MyProgram.java:
import javax.swing.JFrame;

public class MyProgram extends JFrame{
	
	public MyProgram(){

		setSize(500,500);
		setVisible(true);
		
//		Object created extending the thread class:
		MyThread t = new MyThread();
		t.setName("t1");
		t.setPriority(10);
		t.start();

//		Object created implementing the runnable interface:		
		MyRunnable r = new MyRunnable();
		Thread tr = new Thread(r);
		tr.start();
		
	}
	public static void main(String[] args) {
		new MyProgram();
	}

}

En el ejemplo anterior hemos creado un JFrame que cuando se abre se ejecuta también el Thread.

Cuando se ejecuta MyProgram.java se debe notar que la ejecución no sigue el orden del código. Es decir, en nuestro ejemplo nuestras Threads sólo imprimen un valores en pantalla. Note que no necesariamente se debe terminar la impresión de todos los valores de la primera Thread en el código antes de comenzar la segunda. Esta característica impredecible de las Threads fue mencionada en The difficulty with threads

A continuación se muestra un ejemplo un poquito más elaborado en el cual la Thread se ejecuta una vez que se hace clic en un botón desplegado en el JFrame. Para esto se implementa el ActionListener

GUIThread.java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;

public class GUIThread extends JFrame implements ActionListener{

	public GUIThread(){
		
		setSize(300,300);
		setVisible(true);
		
		JButton btn = new JButton("Button");
		btn.addActionListener(this);
		this.add(btn);
		
	}
	
	public static void main(String[] args) {
	    // TODO Auto-generated method stub
            new GUIThread();
	}
	
	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
		System.out.println("Button");
		
		MyThread x = new MyThread();
		x.start();
			
	}

}



Daemon thread

Daemon thread in Java are those thread which runs in background and mostly created by JVM* for performing background task like Garbage collection and other house keeping tasks. Difference between Daemon and Non Daemon(User Threads) is also an interesting multi-threading interview question, which asked mostly on fresher level java interviews.

(*) A Java virtual machine (JVM) is an abstract computing machine that enables a computer to run a Java program.

  • In one line main difference between daemon thread and user thread is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish the execution. As soon as last non daemon thread finished JVM terminates no matter how many Daemon thread exist or running inside JVM.
  • Another difference between daemon thread and user thread is that Daemon Thread are treated differently than User Thread when JVM terminates, finally blocks are not called, Stacks are not unwounded and JVM just exits.
  • Thread inherits its daemon nature from the Thread which creates it (i.e. parent Thread). If the main thread is a non daemon thread, any other thread created from it will remain non-daemon until explicitly made daemon by calling setDaemon(true).
  • Thread.setDaemon(true) makes a Thread daemon but it can only be called before starting Thread in Java. It will throw IllegalThreadStateException if corresponding Thread is already started and running.
  • Daemon Threads are suitable for doing background jobs like housekeeping, Though I have yet to use it for any practical purpose in application code. Let us know if you have used daemon thread in your java application for any practical purpose.



Ejemplos clásicos para comprender el concepto de Thread

Los siguientes problemas fueron abordados por el Prof. para explicar el concepto the Thread.



Dining philosophers problem

https://en.wikipedia.org/wiki/Dining_philosophers_problem



Atomicity (database systems)

https://en.wikipedia.org/wiki/Atomicity_(database_systems)



Serialization

https://www.javatpoint.com/serialization-in-java http://www.baeldung.com/java-serialization https://docs.oracle.com/javase/tutorial/jndi/objects/serial.html https://www.tutorialspoint.com/java/java_serialization.htm


Serialization is the conversion of an object (the state of an object) to a series of bytes (a byte stream), so that the object can be easily saved to persistent storage or streamed across a communication link (transferred over a network). The byte stream can then be deserialized - converted into a replica of the original object.

Más concisamente podríamos decir que:

  • Serialization is a mechanism of writing the state of an object into a byte stream.
  • Deserialization is the process of reconstructing the object from the serialized state. It is the reverse operation of serialization.



Advantage of Java Serialization

It is mainly used to travel object's state on the network (known as marshaling). https://www.javatpoint.com/serialization-in-java



java.io.Serializable interface

Classes that are eligible for serialization need to implement a special marker interface: Serializable

Serializable is a marker interface (has no data member and method). It is used to "mark" java classes so that objects of these classes may get certain capability. It must be implemented by the class whose object you want to persist. https://www.javatpoint.com/serialization-in-java

Let's see the example given below:

package serialization;

import java.io.Serializable;  

public class Student implements Serializable {
    int id;
    String name;
    
    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }
    
}

In the above example, Student class implements Serializable interface. Now its objects can be converted into stream.



ObjectOutputStream class

The ObjectOutputStream class is used to write primitive data types and Java objects to an OutputStream. Only objects that support the java.io.Serializable interface can be written to streams.



Constructor

public ObjectOutputStream(OutputStream out) throws IOException {}  // creates an ObjectOutputStream that writes to the specified OutputStream



Important Methods

public final void writeObject(Object obj) throws IOException {}  // writes the specified object to the ObjectOutputStream.
public void flush() throws IOException {}  // flushes the current output stream.
public void close() throws IOException {}  // closes the current output stream.



Example Serialization

In this example, we are going to serialize the object of Student class. The writeObject() method of ObjectOutputStream class provides the functionality to serialize the object. We are saving the state of the object in the file named f.txt.

package serialization;

import java.io.*;  

class Serialize{
    
    public static void main(String args[]) throws Exception {
        
        Student s1 =new Student(211,"Adelo");  

        FileOutputStream   fout = new FileOutputStream("f.txt");
        ObjectOutputStream out  = new ObjectOutputStream(fout);

        out.writeObject(s1);  
        out.flush();  
        
        System.out.println("Success");  
        
    }
    
}



ObjectInputStream class

An ObjectInputStream deserializes objects and primitive data written using an ObjectOutputStream.



Constructor

public ObjectInputStream(InputStream in) throws IOException {}  // creates an ObjectInputStream that reads from the specified InputStream



Important Methods

public final Object readObject() throws IOException, ClassNotFoundException{}  // reads an object from the input stream
public void close() throws IOException {}  // closes ObjectInputStream



Example of Deserialization

package serialization;

import java.io.*;  

class Deserialize {
    
    public static void main(String args[])throws Exception {
        
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("f.txt"));
        
        Student s = (Student)in.readObject();
        
        System.out.println(s.id+" "+s.name);
        
        in.close();
        
    }
    
}



Serialization with Inheritance (IS-A Relationship)

If a class implements serializable then all its sub classes will also be serializable. Let's see the example given below:

package serialization_with_inheritance;

import java.io.Serializable;

class Person implements Serializable {

    int id;
    String name;
    
    Person(int id, String name) {
        this.id   = id;
        this.name = name;
        
    }
    
}
package serialization_with_inheritance;

class Student extends Person {
    
    String course;
    int    fee;
    
    public Student(int id, String name, String course, int fee) {
        super(id, name);
        
        this.course = course;
        this.fee    = fee;
        
    }
    
}

Now you can serialize the Student class object that extends the Person class which is Serializable. Parent class properties are inherited to subclasses so if parent class is Serializable, subclass would also be.



Serialization with Aggregation (HAS-A Relationship)

If a class has a reference of another class, all the references must be Serializable otherwise serialization process will not be performed. In such case, NotSerializableException is thrown at runtime.

package serialization_with_aggregation;

class Address{
    
    String addressLine,city,state;

    public Address(String addressLine, String city, String state) {

        this.addressLine = addressLine;
        this.city        = city;
        this.state       = state;

    }

}
package serialization_with_aggregation;

import java.io.Serializable;

public class Student implements Serializable {
    int     id;
    String  name;
    Address address;  // HAS-A
    
    public Student(int id, String name) {
        this.id   = id;
        this.name = name;
    }
}

Since Address is not Serializable, you can not serialize the instance of Student class.



Serialization with static data member

If there is any static data member in a class, it will not be serialized because static is the part of class not object.

package serialization_with_static_data_member;

import java.io.Serializable;

class Employee implements Serializable {
    int           id;
    String        name;
    static String company = "SSS IT Pvt Ltd";  // It won't be serialized because is a static member
    
    public Employee(int id, String name) {
        this.id   = id;
        this.name = name;
    }
}



Serialization with array or collection

Rule: In case of array or collection, all the objects of array or collection must be serializable. If any object is not serialiizable, serialization will be failed.



Externalizable in java

The Externalizable interface provides the facility of writing the state of an object into a byte stream in compress format. It is not a marker interface.

The Externalizable interface provides two methods:

public void writeExternal(ObjectOutput out) throws IOException
public void readExternal(ObjectInput in) throws IOException



Java Transient Keyword

If you don't want to serialize any data member of a class, you can mark it as transient. Visit next page for more details: https://www.javatpoint.com/transient-keyword



==Object Orientation with Design Patterns



Java GUI Programming


Retrieved from "http://wiki.sinfronteras.ws/index.php?title=Object-Oriented_Concepts_and_Constructs&oldid=23311"