JVM-JRE-JDK

Last Updated on 2 anni | Published: 24/03/2024

Linguaggio Java

Java è stato creato dal «Green Team», un gruppo di ingegneri della «Sun Microsystems» coordinati dal leader James Gosling, nella prima metà degli anni novanta.

2010: Oracle acquisisce Sun, e comicia l’evoluzione del linguaggio che attualmente è uno dei più utilizzati a livello mondiale  secondo le statistiche annuali dell’ IEEE (Institute of Electrical and Electronic Engineers).

Differenze tra Linguaggi

Linguaggi Compilati

Un linguaggio compilato è un linguaggio di programmazione che richiede un processo di compilazione. Durante la compilazione, il codice sorgente scritto dall’utente viene tradotto in codice macchina (binario) specifico per una particolare architettura hardware.

  • L’utente scrive il codice sorgente in un linguaggio di programmazione specifico.
  • Il compilatore analizza e traduce il codice sorgente in codice macchina.
  • Il codice macchina viene eseguito direttamente dall’hardware.
Esempi di Linguaggi Compilati
  • C
  • C++
  • Fortran
  • Ada

Vantaggi e Svantaggi

  • Vantaggi: Solitamente offre prestazioni elevate e controllo completo sull’hardware.
  • Svantaggi: La portabilità può essere limitata poiché il codice compilato è specifico per una piattaforma hardware.

Linguaggi Interpretati

Un linguaggio interpretato è un linguaggio di programmazione che viene eseguito direttamente da un interprete senza la necessità di un passaggio di compilazione.

  • L’utente scrive il codice sorgente in un linguaggio di programmazione specifico.
  • L’interprete legge ed esegue il codice sorgente istruzione per istruzione.

Esempi di Linguaggi Interpretati

  • Python
  • JavaScript
  • Ruby
  • PHP

Vantaggi e Svantaggi

  • Vantaggi: Maggiore portabilità, facilità di sviluppo e debug.
  • Svantaggi: Solitamente offre prestazioni inferiori rispetto ai linguaggi compilati.

Java Virtual Machine (JVM)

Java è un Linguaggio di programmazione sia compilato che interpretato, infatti il codice sorgente (estensione .java) viene prima compilato (attraverso il comado javac) in un formato intermedio (bytecode .class) e successivamente interpretato dalla JVM (Java Virtual Machine) che ha il compito di iterpretare “a volo” le istruzioni bytecode in istruzioni per il processore. La JVM viene sviluppata per ogni sistema operativo. L’ ambiente di sviluppo ed esecuzione di applicazioni java è composto  da:

JVM: Java Virtual Machine che rappresenta l’ interprete dei comandi è stata sviluppata per ogni sistema operativo (Linux – Windows – Mac).

JRE: Java Runtime Environment è un ambiente che lavora in runtime, cioè durante l’esecuzione del programma, e contiene librerie, ovvero tutto il necessario per eseguire programmi scritti in Java.

JDK: Java Development Kit che contiene tutto il necessario, quindi librerie, per eseguire e compilare programmi scritti in Java.

Vantaggi della JVM

  • Portabilità: Il bytecode Java può essere eseguito su qualsiasi piattaforma supportata dalla JVM.
  • Sicurezza: La JVM fornisce un ambiente sicuro attraverso il sandboxing e la verifica del bytecode.

Caratteristiche Salienti di Java

Piattaforma Indipendente (Cross-Platform)

Java è progettato per essere eseguito su qualsiasi piattaforma hardware/software. Il codice sorgente Java viene compilato in bytecode, che può essere eseguito su una qualsiasi macchina virtuale Java (JVM), rendendo il linguaggio “write once, run anywhere” (scrivi una volta, esegui ovunque).

Orientato agli Oggetti (Object-Oriented)

Java è un linguaggio di programmazione orientato agli oggetti, che supporta concetti come incapsulamento, ereditarietà e polimorfismo, facilitando la progettazione e la modellazione di soluzioni complesse.

Sicurezza

Java è stato progettato con una forte enfasi sulla sicurezza. Fornisce un ambiente sicuro attraverso il sandboxing e la verifica del bytecode, prevenendo l’esecuzione di codice dannoso.

Robusta e Affidabile

Grazie al suo sistema di gestione delle eccezioni e al garbage collector, Java è noto per la sua robustezza e affidabilità. Queste caratteristiche contribuiscono a ridurre il numero di errori e a migliorare la stabilità delle applicazioni.

Multithreading

Java supporta la programmazione multithreading, consentendo agli sviluppatori di creare applicazioni che possono eseguire più attività contemporaneamente, migliorando l’efficienza e le prestazioni dei programmi.

Architettura Modulare

Con l’introduzione di Java 9, è stata introdotta la modularità con il sistema di moduli Java (JPMS), che consente agli sviluppatori di organizzare il proprio codice in moduli separati, migliorando la manutenibilità e la gestione delle dipendenze.

Ricco Ecosistema

Java ha un vasto ecosistema di librerie e framework, come Spring, Hibernate e JavaFX, che facilitano lo sviluppo di applicazioni enterprise, web, desktop e mobile.

Portabilità

La portabilità è una delle principali caratteristiche di Java. Le applicazioni Java possono essere eseguite su diverse piattaforme senza la necessità di riscrivere o ri-compilare il codice sorgente.

Strumenti di Sviluppo

Java fornisce una serie di strumenti di sviluppo integrati (IDE) come Eclipse, IntelliJ IDEA e NetBeans, che aiutano gli sviluppatori a scrivere, testare e debuggare il codice in modo efficiente.

Concetti Operativi della OOP

La Programmazione Orientata agli Oggetti è un paradigma di programmazione che utilizza “oggetti” e “classi” per organizzare il codice. Ecco i concetti fondamentali della OOP:

Classe – Oggetti – Metodi

Una classe è un modello o un prototipo che definisce le proprietà e i comportamenti di un oggetto. Un oggetto è un’istanza di una classe  (concretizzazione di una classe) e rappresenta un’entità del mondo reale. I metodi corrispondono ad azioni programmate nella classe.

Incapsulamento

L’incapsulamento è il principio di nascondere i dettagli di implementazione di un oggetto e di esporre solo le operazioni rilevanti. Questo viene realizzato utilizzando modificatori di accesso come public, private e protected.

Ereditarietà

L’ereditarietà permette di creare nuove classi basate su classi esistenti, ereditando le loro proprietà e comportamenti. Questo favorisce il riutilizzo del codice e la creazione di una gerarchia tra le classi.

Polimorfismo

Il polimorfismo consente a un oggetto di apparire e comportarsi come un’ altro oggetto, permettendo di scrivere codice che lavora su una classe e di usarlo con altre classi che implementano la stessa interfaccia o estendono la stessa classe base.

Astrazione

L’astrazione è il processo di astrazione dei dettagli complessi e la focalizzazione sugli aspetti essenziali. In OOP, l’astrazione permette di creare classi astratte che definiscono metodi senza implementazione, lasciando ai sottoclassi il compito di fornire l’implementazione specifica.

Il Sistema dei Tipi

E’ una delle caratteristiche fondamentali che contribuiscono alla robustezza e alla sicurezza del linguaggio.

Il sistema dei tipi  definisce il comportamento e le operazioni che possono essere eseguite su variabili, espressioni e oggetti. In Java, ogni entità ha un tipo associato che determina le operazioni che possono essere applicate ad essa.

Tipi Primitivi

Java fornisce un insieme di tipi primitivi, che rappresentano i dati fondamentali su cui operano i programmi. Questi tipi includono:

Tipo bitRange di Valori
byte8da -128 a 127
short16da -32,768 a 32,767
int32da -2,147,483,648 a 2,147,483,647
long64da -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807
float32da circa 1.4e-45 a circa 3.4e+38
double64da circa 4.9e-324 a circa 1.8e+308
char16da 0 a 65,535 (caratteri Unicode)
boolean–true o false

Riferimenti di Tipo

Oltre ai tipi primitivi, Java supporta i riferimenti di tipo, che includono:

  • Classi
  • Interfacce
  • Array

Un riferimento di tipo non contiene direttamente i dati ma fa riferimento a un’istanza o a un array di un tipo.

Gerarchia dei Tipi e Object

In Java, tutti i tipi, sia primitivi che di riferimento, sono sottotipi di Object. Questo significa che ogni oggetto in Java eredita direttamente o indirettamente dai metodi definiti nella classe Object, come toString(), equals(), e hashCode().

Casting e Conversione dei Tipi

Java supporta il casting, che consente di convertire un tipo in un altro. Tuttavia, è importante notare che il casting tra tipi incompatibili può causare eccezioni a runtime. Java offre anche metodi per la conversione sicura tra tipi, come Integer.parseInt() per la conversione da String a int.

Generics

Con l’introduzione delle generiche in Java 5, è stato possibile parametrizzare i tipi, consentendo agli sviluppatori di scrivere codice più flessibile e sicuro. Le generiche consentono di creare classi, interfacce e metodi che possono operare su vari tipi senza dover eseguire il casting.

Classi Wrapper

Le classi wrapper in Java sono classi che incapsulano i tipi primitivi fornendo loro una rappresentazione oggettiva. Queste classi forniscono metodi utili per lavorare con i tipi primitivi come oggetti. Ogni tipo primitivo ha una classe wrapper corrispondente, come mostrato di seguito:

  • byte: Byte
  • short: Short
  • int: Integer
  • long: Long
  • float: Float
  • double: Double
  • char: Character
  • boolean: Boolean

Concetto di Variabile

Una variabile in un linguaggio di programmazione è un’entità che rappresenta un’area di memoria allocata per memorizzare un valore. Le variabili sono fondamentali nella programmazione perché consentono di conservare e manipolare dati durante l’esecuzione di un programma.

Definizione:

Una variabile è composta da un tipo, un nome e un valore. Il nome della variabile serve come riferimento per accedere al valore memorizzato nella memoria.

Dichiarazione

Prima di utilizzare una variabile, è necessario dichiararla specificando il suo nome e il suo tipo.

Assegnazione

Dopo aver dichiarato una variabile, è possibile assegnarle un valore utilizzando l’operatore di assegnazione =.

int numero;

String nome;

boolean coniugato;

Integer valore;

numero=100;
nome=”Giovanni“

coniugato=true;

valore=2500;

Convenzioni sulla scrittura del Codice

Determinate regole devono essere rispettate quando si scrive codice sorgente, perchè dobbiamo  pensare che scriviamo anche per altri programmatori, magari fanno parte del team oppure leggiamo codice che non abbiamo scritto noi. Le convenzioni suggerite sono le seguenti:

I Package sono le cartelle e le sottocartelle che abitualmente utilizziamo nel nostro sistema operativo. Concludiamo con le convenzioni in merito alle variabili e costanti, i nomi da utilizzare possono essere alfanumerici e non devono contenere caratteri accentati, segni di puntegiatura ed il carattere underscore ( _ ), inoltre un nome di variabile in maiuscolo è diverso dallo stesso scritto in minuscolo, risultano essere due variabili diverse proprio perche Java è Key Sensitive.

Gli Operatori

In Java, gli operatori sono simboli speciali che vengono utilizzati per eseguire operazioni specifiche su operandi (variabili o valori). Ad esempio, l’operatore + viene utilizzato per sommare due numeri, mentre l’operatore == viene utilizzato per verificare l’uguaglianza tra due valori.

Ecco alcuni degli operatori più comuni in Java:

Aritmetica:

+, –, *, /, % (modulo ritorna 0 se non da resto ad esempio 10%2)

Assegnazione:

=, +=, -=, *=, /=, %=

Comparazione:

==, !=, >, <, >=, <=

Incremento/Decremento:

++ oppure — (++x  –x  x++  x–)

Logici:

&&, ||, !

Condizionali: ?:

  • In Java, gli operatori condizionali sono utilizzati per eseguire determinate azioni a seconda del valore di una condizione. La sintassi per utilizzare questo operatore è la seguente: condizione ? val1 : val2, quindi un esempio pratico potrebbe essere il seguente codice:

int k=11;   boolean x=k%2==0 ? true : false; 

Il valore della variabile x dipende dalla condizione, in questo caso se la condizione è vera si assegna true ad x altrimenti false .

Instanceof:

  • per verificare se un oggetto è un’istanza di una determinata classe o interfaccia.

Casting in Java

Il casting in Java avviene quando si assegna un tipo di valore primitivo ad una variabile di altro tipo, ad esempio assegnare un valore decimale ad una variabile di tipo intero (int val=12.5).

CASTING ALLARGATO

Questo accade automaticamente quando si assegna un tipo più piccolo ad un tipo più grande, lo si può notare tra primitivi double e int, vedi tabella dei primitivi: (int x=10; double valore = x)

CASTING RESTRINGENTE

Questo non è automatico e si verifica quando è il contrario dell’ esempio precedente, un tipo più grande in un tipo più piccolo. In questo caso manualmente si inserisce il tipo tra parentesi tonde davanti al valore:

int x = (int)20.45;

questo comporta la perdita del decimale e quindi x sarà uguale a 20)

Java e le Classi di Sistema

Negli articoli precedenti si è fatto cenno alla JRE ovvero Java Runtime Environment inclusa nel pacchetto di installazione Java che fornisce anche diverse librerie di integrazione per assistere gli sviluppatori, infatti include pacchetti java.lang e java.utils fondamentali per la progettazione di applicazioni.

Classe Math

La classe java.lang.Math serve per fare calcoli matematici i cui metodi sono tutte le funzioni matematiche calcolabili tra cui:

I valori assoluti di valori double, float, int e long:
  • static double abs(double a)
  • static float abs(float a)
  • static int abs(int a)
  • static long abs(long a)
Massimi e minimi tra valori double, float, int e long
  • static double max(double a, double b)
  • static float max(float a, float b)
  • static int max(int a, int b)
  • static long max(long a, long b)
  • static double min(double a, double b)
  • static float min(float a, float b)
  • static int min(int a, int b)
  • static long min(long a, long b)
Numeri pseudocasuali
  • static double random() – spara un numero casuale tra 0 e 1

Classe Scanner

Classe molto utilizzata negli esercizi di java, risiede nel package java.util e rappresenta una soluzione molto semplice per realizzare un input da un stream come la tastiera. I metodi di questa classe sono in grado di individuare ed interpretare i tipi primitivi e le stringhe ed i suoi costruttori permettono di ottenere un oggetto di tipo Scanner partendo da oggetti di altri tipi:

InputStrem

Utile quando bisogna leggere da tastiera (l’ oggetto System.in è di tipo InputStream)

String

Utile quando è necessario procurarsi input da una stringa

File

Utile quando l’ input proviene da file di testo.

Possiamo utilizzare questa classe per leggere caratteri da tastiera, includendola nel progetto attraverso l’ istanza:

Scanner in = new Scanner(System.in);

Tra i metodi dell’ oggetto c’è anche nextLine() che legge una stringa da tastiera restituendola al chiamante.

String s = in.nextLine();

Tra i metodi della classe Scanner possiamo menzionare anche:

nextInt()

legge il token successivo interpretandolo come un numero intero e lo restituisce al chiamante, o lancia un eccezione di tipo InputMismatchException se il token non è un intero.

nextDouble()

legge il token successivo interpretandolo come un numero reale e lo restituisce al chiamante, o lancia un eccezione di tipo InputMismatchException se il token non è un reale.

next()

legge il successivo token senza delimitatori e lo restituisce al chiamante

hashNext()

restituisce vero se in input è disponibile un ulteriore token, falso altrimenti.

hashNextInt()

restituisce vero se il prossimo token può essere interpretato come un numero intero, falso altrimenti.

Classe System

La classe System in Java è una classe predefinita che fornisce un insieme di metodi e variabili utili per interagire con il sistema in cui viene eseguito un’applicazione Java. È parte del package java.lang e non necessita di essere importata esplicitamente perché è automaticamente disponibile in ogni programma Java.

Alcuni dei metodi e delle variabili più utilizzati della classe System includono:

  1. out: È un oggetto della classe PrintStream utilizzato per l’output standard. È un flusso di output per scrivere dati in output, come testo, su console o su altri dispositivi di output.
  2. in: È un oggetto della classe InputStream utilizzato per l’input standard. È un flusso di input per leggere dati in input, come testo o altri tipi di dati, da console o da altri dispositivi di input.
  3. err: È un oggetto della classe PrintStream utilizzato per l’output degli errori standard. È un flusso di output separato da out, utilizzato per scrivere messaggi di errore su console o su altri dispositivi di output.

Uno dei metodi più utilizzati dell’oggetto out è println(). Questo metodo viene utilizzato per stampare una riga di testo seguita da un carattere di nuova riga sul dispositivo di output standard.

System.out.println(“Ciao, mondo!“);

Compilare ed Eseguire da Console

Una delle prime cose da imparare quando si inizia a programmare in Java è come creare un progetto base che includa una classe con un metodo main(), il punto di ingresso per l’esecuzione del programma.

Il main() è  il metodo che la JVM (Java Virtual Machine) cerca per avviare l’esecuzione del programma. Ogni applicazione Java deve avere almeno una classe con un metodo main().

Per creare un primo progetto Java è sufficiente utilizzare un editor di testo (come Notepad, Visual Studio Code, IntelliJ IDEA, ecc.) e creare un nuovo file chiamato MioProgetto.java. All’interno di questo file, creare una nuova classe chiamata MioProgetto. All’interno della classe MioPrimoProgetto, aggiungi un metodo main().

All’interno del metodo main(), ad esempio, possiamo stampare un messaggio di benvenuto sulla console.

public class MioProgetto {
     public static void main(String[] args) {
          System.out.println(“Benvenuto !!”);
     }
}

Una volta scritto il codice, aprire il Prompt dei comandi o il Terminale, navigare nella directory in cui si trova il file MioProgetto.java ed eseguire la compilazione:

javac MioProgetto.java

Se non ci sono errori, questo comando creerà un file MioProgetto.class, che è il file bytecode eseguibile dalla JVM.

java MioProgetto

Nel prossimo articolo utilizzeremo l’ IDE Eclipse, ambiente di sviluppo, per creare progetti Java Standard Edition ed apprendere le basi mediante con esempi mirati, oltre che ……..

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *