Installazione e primi passi in Java.
Java è un linguaggio di programmazione sviluppato da Sun Microsystems nel 1995.
Si tratta un linguaggio ad alto livello orientato agli oggetti e fortemente tipizzato.
Dopo averlo compilato i programmi in bytecode, questo viene eseguito su una macchina virtuale (JVM), disponibile per tutti i sistemi operativi.
Il codice scritto in Java può essere eseguito su qualsiasi sistema, al costo di una penalità di prestazioni.
brew install openjdk@17
tar -xf <nome_fiel>.tar.gz -C <destinazione>
export JAVA_HOME=<destinazione>/jdk-17.0.2.jdk/Contents/Home
e export PATH=\$JAVA_HOME/bin:\$PATH
Utilizzate il gestore dei pacchetti del vostro sistema operativo.
sudo apt install openjdk-17-jdk
sudo pacman -S jdk17-openjdk
sudo dnf install java-17-openjdk
Se si hanno installate più versioni di Java, è possibile cambiare la versione predefinita.
Modificare la variabile d'ambiente JAVA_HOME
con il percorso della nuova versione di Java.
System Properties > Environment Variables > System variables > JAVA_HOME
Bisogna modificare la variabile d'ambiente JAVA_HOME
con il percorso della nuova versione di Java.
/usr/libexec/java_home -V # mostra le versioni di Java installate
export JAVA_HOME=`/usr/libexec/java_home -v <versione>` # cambia la versione di Java a quella indicata
Per cambiare la versione di Java in maniera permanente, bisogna aggiungere una riga simile al file ~/.bash_profile
, ~/.bashrc
o ~/.zshrc
.
# ~/.bash_profile
export JAVA_HOME=`/usr/libexec/java_home -v 17`
# ~/.bashrc
export JAVA_HOME=`/usr/libexec/java_home -v 17`
# ~/.zshrc
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
# ~/.fishrc
set -x JAVA_HOME (/usr/libexec/java_home -d64 -v 17)
Vale la stessa logica di MAC per l'update della variabile d'ambiente JAVA_HOME
.
sudo update-alternatives --config java # mostra le versioni di Java installate e permette di sceglierne una
sudo update-alternatives --config javac # mostra le versioni di javac installate e permette di sceglierne una
sudo archlinux-java status # mostra le versioni di Java installate
sudo archlinux-java set java-17-openjdk # cambia la versione di Java a quella indicata
Quando viene installata, la JVM seleziona un locale predefinito.
Per visualizzare il locale corrente, utilizzare il comando:
java -XshowSettings:locale -version
Per cambiare il locale da riga di comando:
java -Duser.language=<language> -Duser.region=<region> <nome_file>.java
o direttamente nel codice:
Locale.setDefault(Locale.ITALY);
java -version
java -jar <nome_file>.jar
javac <nome_file>.java
java <nome_file>
javap <nome_file>.class
jar cf <nome_output_file>.jar <files>.class
jar cfe <nome_output_file>.jar <main_class> <files>.class
Alcuni concetti fondamentali di Java e della programmazione orientata agli oggetti.
Java è un linguaggio fortemente orientato agli oggetti.
Ogni programma può essere visto come una collezione di oggetti che interagiscono tra loro.
I design pattern ci aiutano a strutturare il codice al fine di renderlo più mantenibile e leggibile anche per progetti particolarmente complessi.
L'esecuzione di un programma Java parte da un metodo main
con una firma ben precisa che si trova nella classe indicata.
Una classe è un modello che descrive un oggetto. Un oggetto è una istanza di una classe.
Le parole chiave riservate a Java.
class StaticClass {
private static String staticVar = "I'm static";
public static void staticMethod() {
System.out.println("Static variable value: " + staticVar);
}
}
Indica metodi o variabili appartenenti alla classe e non all'oggetto.
Possono essere chiamati senza aver creato un oggetto.
Hanno accesso solo ad altri metodi o variabili statici.
final class FinalClass {
private final String FINAL_VAR = "I'm final";
public final void finalMethod() {
// FINAL_VAR = "I'm not final anymore"; // Error
System.out.println("Final variable value: " + FINAL_VAR);
}
}
Si tratta di variabili, metodi o classi che non possono essere modificati.
Variabili: Non possono essere riassegnate.
Metodi: Non possono essere sovrascritti da classi derivate.
Classi: Non possono essere estese da altre classi.
interface Interface {
public void interfaceMethod();
}
Si tratta di un insieme di metodi astratti.
Non possono contenere variabili.
abstract class AbstractClass {
public abstract void abstractMethod();
public void definedMethod() {
System.out.println("I'm defined");
}
}
Si tratta di classi che non possono essere istanziate.
Possono contenere metodi astratti: senza un corpo, ma con una firma.
class MyClass {
private int privateVar;
protected int protectedVar;
int defaultVar;
public int publicVar;
}
Servono ad indicare il livello di visibilità di una variabile, metodo o classe.
private: Accessibile solo all'interno della classe.
protected: Accessibile all'interno della classe e delle classi derivate.
default: Accessibile da tutte le classi dello stesso package.
public: Accessibile ovunque.
class BaseClass {
public void method() {
System.out.println("BaseClass method");
}
}
class DerivedClass extends BaseClass {
@Override
public void method() {
System.out.println("DerivedClass method");
}
}
Metodo sovrascritto da una classe derivata.
Il metodo deve avere la stessa firma del metodo sovrascritto.
È possibile richiamare il metodo sovrascritto con la parola chiave super.<metodo>(args)
.
class OverloadClass {
public void method() {
System.out.println("No parameters");
}
public void method(int a) {
System.out.println("One parameter");
}
public void method(int a, int b) {
System.out.println("Two parameters");
}
}
Indica che un metodo è stato definito più volte con lo stesso nome ma con parametri diversi.
Il primo programma di ogni buon informatico.
// HelloWorld.java
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
javac HelloWorld.java
java HelloWorld
Quando si lancia un programma da linea di comando, è possibile passare dei parametri che saranno poi accessibili al programma stesso sotto forma di un array di stringhe.
public static void main(String[] args) {
// ...
}
Quando viene lanciato il programma, gli argomenti che seguono il nome del programma vengono passati al metodo main nel parametro args
.
java
Calculator
1
+
2
java
: invoca la JVMCalculator
: nome della classe che contiene il metodo main1
: primo parametro (args[0])+
: secondo parametro (args[1])2
: terzo parametro (args[2])// Calculator.java
class Calculator {
private static int calculateResult(int a, int b, String op) {
switch (op) {
case "+":
return a + b;
case "-":
return a - b;
case "x":
return a * b;
case "/":
return a / b;
default:
System.err.println("Unknown operator");
System.exit(1);
return 0;
}
}
public static void main(String[] args) {
if (args.length != 3) {
System.err.println("Usage: java Calculator <a> <op> <b>");
System.err.println("<op> can be +, -, x, /");
System.exit(1);
}
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[2]);
int result = calculateResult(a, b, args[1]);
System.out.println(result);
}
}
javac Calculator.java
java Calculator 2 + 3
Il programma può interagire con l'utente stampando e leggendo i caratteri sul terminale.
Vi sono diversi modi per farlo.
In questo caso utilizzeremo la classe Scanner
.
import java.util.Random;
import java.util.Scanner;
// InverseCalculator.java
public class InverseCalculator {
private static char getRandomOp() {
Random random = new Random();
int op = random.nextInt(4);
switch (op) {
case 0:
return '+';
case 1:
return '-';
case 2:
return 'x';
case 3:
return '/';
default:
return 'e';
}
}
private static int calculateResult(int a, int b, char op) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case 'x':
return a * b;
case '/':
return a / b;
default:
return 0;
}
}
@SuppressWarnings("resource")
private static int readAnswer() {
Scanner scanner = new Scanner(System.in);
int answer = scanner.nextInt();
return answer;
}
public static void main(String[] args) {
Random random = new Random();
int a = random.nextInt(20);
int b = random.nextInt(10);
char op = getRandomOp();
int result = calculateResult(a, b, op);
System.out.print("What is " + a + " " + op + " " + b + "? ");
// int answer = Integer.parseInt(System.console().readLine());
int answer = readAnswer();
if (answer == result) {
System.out.println("Correct!");
} else {
System.out.println("Wrong!");
}
}
}
javac InverseCalculator.java
java InverseCalculator
Leggere e scrivere su file è un'altra operazione estremamente frequente in un programma.
Per leggere e scrivere su file si utilizzerà la classe FileReader
e FileWriter
.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
// WordCounter.java
public class WordCounter {
private static int readWords(String file) {
try (FileReader fileReader = new FileReader(file)) {
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
int wordCount = 0;
while ((line = bufferedReader.readLine()) != null) {
String[] words = line.split(" ");
wordCount += words.length;
}
bufferedReader.close();
return wordCount;
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
return 0;
}
public static void writeCount(String file, int count) {
try (FileWriter fileWriter = new FileWriter(file)) {
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter printWriter = new PrintWriter(bufferedWriter);
printWriter.println(count);
printWriter.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("Usage: java WordCounter <input_file> <output_file>");
System.exit(1);
}
String inputFile = args[0];
String outputFile = args[1];
int wordCount = readWords(inputFile);
writeCount(outputFile, wordCount);
}
}
javac WordCount.java
java WordCount.java input.txt output.txt