i dati sono strutturati differentemente, quindi si chiamano oggetti, caratterizzati da
stato → serie di variabili (attributi) che caratterizzano l’oggetto
comportamenti (metodi) che agiscono sullo stato dell’oggetto modificandolo o ispezionandolo
VANTAGGIO = INCAPSULAMENTO = modificare lo stato di un oggetto per mezzo dei suoi attributi
ogni oggetto incapsula al suo interno sia i dati (nella forma di attributi o variabili) che le funzioni (nella forma di metodi) che operano su questi dati. Sono intoccabili dall’esterno, e li creo ioo!!
ESEMPIO PRATICO
1. Definizione della Classe Auto
public class Auto {
// Attributi (variabili di istanza)
private String modello; // Modello dell'auto
private String colore; // Colore dell'auto
private int velocita; // Velocità dell'auto
// Costruttore della classe
public Auto(String modello, String colore) {
this.modello = modello;
this.colore = colore;
this.velocita = 0; // Inizializza la velocità a 0
}
// Metodo per accelerare
public void accelera(int incremento) {
velocita += incremento; // Aumenta la velocità
System.out.println("L'auto accelera a " + velocita + " km/h");
}
// Metodo per frenare
public void frena(int decremento) {
velocita -= decremento; // Diminuisce la velocità
if (velocita < 0) {
velocita = 0; // Assicura che la velocità non sia negativa
}
System.out.println("L'auto frena a " + velocita + " km/h");
}
// Metodo per ottenere il modello dell'auto
public String getModello() {
return modello; // Restituisce il modello
}
// Metodo per ottenere il colore dell'auto
public String getColore() {
return colore; // Restituisce il colore
}
}
2. Utilizzo della Classe Auto
public class Main {
public static void main(String[] args) {
// Creazione di un oggetto Auto
Auto miaAuto = new Auto("Fiat 500", "Rosso");
// Chiamata ai metodi dell'oggetto
miaAuto.accelera(50); // L'auto accelera a 50 km/h
miaAuto.frena(20); // L'auto frena a 30 km/h
// Accesso agli attributi tramite i metodi
System.out.println("Modello: " + miaAuto.getModello()); // Modello: Fiat 500
System.out.println("Colore: " + miaAuto.getColore()); // Colore: Rosso
}
}
Ha creato l’oggetto auto, definito degli attributi (modello, colore, velocità) e definito dei metodi (accelerare, frenare, visualizza modello, visualizza colore) → attributi e metodi costituiscono la classe.
Quindi decido io oggetto, attributi e metodi secondo le mie necessità!!!
Tutti gli oggetti della stessa classe hanno stessi metodi e stato.
Prima di creare e utilizzare l’oggetto devo definire la classe, ovvero il tipo di dato in cui il mio oggetto può rientrare.
Quindi in ordine abbiamo:
definisco la classe
stato → attributi (variabili)
metodi (operazioni sulle variabili)
creo e utilizzo degli oggetti
CASO SPECIFICO
Classi prive di stato e contenenti solo metodi → si applicano solo a dei parametro
PRIMI APPUNTI SINTATTICI (molto generico)
il programma va scritto dentro il metodo main, contenuto nella classe Main. Per convenzione il metodo inizia per minuscola e la classe per maiuscola
le classi iniziano con la lettera maiuscola
public class Main {
public static void main(String[] args){
//...convenuto...
}
}
PACKAGE
insieme di classi, interfacce e sotto-package
per convenzione hanno lo stesso nome della cartella in cui si trova il file
ora non mi serve
IMPORT
utilizzare le classi di un pacchetto senza dover specificare il package corrispondente ogni volta.
non posso fare import di 2 classi con stesso nome
ESEMPI:
COMPILAZIONE
compilare = creare eseguibili = file che saranno letti dalla macchina per eseguire il programma
java compila in bytecode per permettere a qualsiasi computer di eseguire il programma. Infatti il btyecode può essere tradotto da qs pc grazie ad una virtual machine che si occupa di tradurlo in linguaggio macchina (quello specifico del pc in cui esso si trova)
2 TIPI DI VARIABILI (nello stack)
primitivi
generati sullo stack
Esempi: int, char, double, boolean, etc.
riferimento
L'heap è la parte della memoria in cui vengono allocate le istanze delle classi, cioè gli oggetti
gli oggetti non sono generati sullo stack, nello stack hanno solo un riferimento (puntatore) che indica la loro posizione nell’heap
Esempi: ArrayList e nome delle classi
dato i un riferimento a array (nota che in Java se stampi il riferimento esce l’indirizzo di memoria, non il contenuto dell’oggetto puntato)
OGGGETI MUTABILI E IMMUTABILI
MUTABILITA’: Un oggetto è mutabile se i suoi campi possono essere modificati dopo che l'oggetto è stato creato. Questo può accadere in vari modi, come la presenza di metodi che modificano lo stato (metodi setter) o la modifica diretta degli attributi.
IMMUTABILITA’: Un oggetto è immutabile se il suo stato interno non può essere modificato dopo che l'oggetto è stato creato. Per creare oggetti immutabili, in genere segui queste regole:
Tutti i campi devono essere privati e final.
Non devono esserci metodi setter o altri metodi che modificano i campi interni.
STACK VS HEAP
Stack: struttura di memoria di tipo LIFO (Last In, First Out), dove gli elementi vengono aggiunti e rimossi in ordine inverso rispetto a come sono stati aggiunti.
allocazione statica: la dimensione delle variabili deve essere nota a tempo di compilazione.
quando una funzione termina, tutte le variabili locali vengono automaticamente rimosse.
Heap: struttura di memoria utilizzata per l'allocazione dinamica della memoria
allocazione dinamica: la memoria nell'heap può essere allocata e liberata in qualsiasi momento durante l'esecuzione del programma.
utilizzato per allocare memoria per oggetti e dati che devono persistere oltre la vita della funzione che li ha creati
Per completezza ho definito una classe con tutte le sue proprietà ma mi concentro sugli attributi
public class Auto {
private String modello;
private String colore;
// Costruttore
public Auto(String modello, String colore) {
this.modello = modello; // Inizializza l'attributo colore
this.colore = colore; // Inizializza l'attributo colore
}
// Metodi
public void mostraDettagli() {
System.out.println("Modello: " + modello + ", Colore: " + colore);
}
}
modificatori di accessi: public / private parole chiave utilizzate per controllare l'accesso ai membri di una classe (attributi e metodi)
private = esempio di incapsulamento
ES. private String colore; : significa che l'attributo colore è accessibile solo all'interno della classe Auto
costruttore → metodo speciale utilizzato per inizializzare gli attributi (costruttore pk appunto lo userè per costruire un oggetto)
(specifica anche in che sequenza scrvere i parametri di un oggetto, in base all’attributo)
Parametri→ sono variabili che vengono dichiarate all'interno delle parentesi di un metodo (o di un costruttore). Quando il costruttore viene chiamato per creare un nuovo oggetto, i valori forniti durante questa chiamata vengono passati ai parametri → come le funzioni
Attributi → con private ho specificato il tipo di accesso e creato l’etichetta, invece nel costruttore assegno un parametro ad un attributo
non puoi assegnare più parametri a un singolo attributo
this.modello = modello;
traduzione: this."attributo" = "parametro";
this. è usato per distinguere l’attributo dal parametro quando corrispondono
GESTIONE DELLA MEMORIA
Attributo: alloca memoria solo nel momento in cui creo un oggetto in cui lo uso
Parametro; alloca memoria solo quando gli assegno un valore, non appena il metodo smette di essere utilizzato la memoria del parametro è deallocata
Oggetti: Quando crei un oggetto di una classe, l'intera istanza dell'oggetto alloca memoria per tutti gli attributi definiti nella classe. Gli oggetti sono allocati nell'heap.
Ogni volta che crei un oggetto utilizzando new, stai allocando memoria per tutti gli attributi di quell'oggetto.
l’invocazione di un metodo può essere realizzato pure a partire da un altra chiamata a un metodo [riassuntivamente indicata con f(x)] che chiama un oggetto e tra i parametri posso avere altre chiamate di metodo [g(x)]
static = il metodo è definito su una classe (metodo di classe)
definisco il tipo del valore di ritorno
void se non ritorna nulla
parametri formali pk i nomi devono essere accompagnati dal loro tipo di dato
OVERLOADING
💡
dichiarare più metodi con lo stesso nome e diversi parametri → ad esempio valueOf(ammette interi e stringhe)
serve per essere pratici semanticamente anche cambiando i parametri (cambiare nome ogni volta non è efficace)
la chiamata è riferita al secondo caso per inferenza
CONVERSIONI IMPLICITE (O CASTING IMPLICITO)
(somma tra 2 tipi uguali ovviamente) Java sa che può convertire int in double (equivalente di float in go) senza perdita di dati in alcuno scenario possibile, quindi lo fa in automatico
SE INVECE APPLICO IL CONCETTO CON LA CHIAMATA AL METODO SOMMA?
Anche in questo caso fa la conversione implicita
Notare che Java permette di definire la chiamata ad un metodo (somma) limitandosi al solo nome (quindi poteva escludere Prova), nel momento in cui metodo e chiamata stanno nella stessa classe.
Notare che ciò è possibile pk il valore di ritorno del secondo metodo è un double, altrimenti avrei perdita di dati
RICORDA: il nome del metodo lo decido io, come le classe. Il primo inizia con la minuscola, il secondo con la maiuscola
qui non ci sono conversioni implicite possibili
AMBIGUO: in una situazione in cui gli vanno bene molteplici conversioni implicite, lui non può fare nulla
COLLEZIONI P.1 e COME DEFINIRE UN OGGETTO
COLLEZIONE = oggetto che rappresenta un insieme di elementi.
Equivalente di array e slice in Go
COME DEFINIRE UN OGGETTO: classe oggetto = new classe()
new è necessario se vuoi creare un oggetto di predefinito senza immediatamente inizializzarlo con valori, altrimenti puoi mettere i valori direttamente
per gli oggetti personalizzati devi usare new
CASO PARTICOLARE
Nelle collezioni posso mettere qualunque tipo di dato
il metodo get mi specifica il valore all’interno di una collezione specificando il l’indice
ERRORE: assegnare il valore del metodo get alla variabile i di tipo int non ha senso, pk Arraylist è generico ed io non specifico il tipo di ogni cella, quindi Java non conoscendo il tipo da ad ogni cella il tipo object. Altrimenti faccio la conversione (casting esplicito)
NOTARE: che ArrayList è una classe regolare e lo capisco pk prima di utilizzare un suo metodo ho definito in oggetto (in quanto le classi statiche richiedono sintatticamente un oggetto (su cui agiranno), tra metodo e classe).
MA SE POSSO INVENTARE IL NOME DELLE CLASSI (come gli oggetti) A COSA SERVE Arraylist?
QUESTO NON SI PUO’ FARE
stesso indice, 2 variabili di differente tipo: compila ma non esegue (scrive ClassastExeption)
COLLEZIONE GENERICA: Arraylist
COLLEZIONE SPECIFICA: Arraylist<String>
SINTESI
COLLEZIONI P.2
LE COLLEZIONI SONO DI OGGETTI, NON DI PRIMITIVI (pk sono classi)
ci sono tipi riferimento (nella stack) che si riferiscono per praticità ai loro oggetti corrispondenti (nella heap). Quindi anche se int è primitivo posso inserirlo in una collezione come collezione grazie al suo corrispondente tipo oggetto (nella heap)
ogni tipo nella stack ha un corrispondente tipo nella heap (definito con la maiuscola)
wrapping è il processo con cui converto una variabile primitita nel suo corrispondente oggetto
Il metodo Integer.valueOf(int i) è un metodo statico della classe Integer che restituisce un oggetto Integer rappresentante il valore del tipo primitivo int fornito come argomento.
SINTESI
Wrappin statico sopra → pk avvolgo il primitivo e lo metto nella heap
Unwrapping dinamico sotto
SORPRESA
Le versioni recenti di Java fanno il Boxing/Autoboxing
capacità di fare Wrapping/Unwrapping in automatico con una semplice equivalenza tra 2 valori di tipo di cui uno è il tipo riferimento dell’altro
mi permette anche di inserire un primitivo in una collezione (e viceversa)
OPERATORI LOGICI
se io comparo 2 oggetti, comparo i rispettivi riferimenti. Quindi se comparo 2 oggetti pur con stesso nome saranno diversi pk hanno diversi riferimenti.
per comparare 2 oggetti uso il metodo equals
I/O SU TERMINALE JAVA
DEFINIRE UNO SCANNER AGGANCIATO ALL’INPUT
Scanner classe
s = oggetto
tra parentesi metto qc a cui agganciarsi → standard input utilizzando la classe System col suo attributo in
s.hasNext = per vedere se c’è una striga (boeleano)
s.Next = ritorna la stringa
ESEMPIO CON CICLO WHILE (fintanto che)
VARIANTE CON INT
In questo caso da errore pk s è una stringa
COMPENDIO spiegato parzialmente
Caratteristiche 1° Frammento
Blocchi di Istruzione: Ogni condizione if, else if e else utilizza le parentesi graffe {} per racchiudere le istruzioni da eseguire. Anche se in questo caso ci sono solo singole istruzioni, l'uso delle parentesi graffe rende il codice più chiaro e permette di aggiungere facilmente più istruzioni in futuro, senza dover modificare la struttura.
Facilità di Espansione: Se in futuro desiderassi aggiungere più istruzioni a una delle condizioni, puoi farlo senza preoccuparti di dover inserire le parentesi graffe, il che può rendere il codice più leggibile.
Caratteristiche 2° Frammento
Senza Blocchi di Istruzione: In questo caso, le istruzioni all'interno delle condizioni if, else if e else non utilizzano le parentesi graffe. Ciò è consentito in Java, ma applica una regola secondo la quale se un blocco di codice ha solo una singola istruzione, le parentesi graffe non sono necessarie.
Compactness: Questo codice è più compatto e può sembrare più facile da leggere per chi preferisce meno righe di codice. Tuttavia, potrebbe risultare più difficile da mantenere se in futuro si desidera aggiungere più istruzioni alle condizioni.