Unitat Didàctica 1:
En aquesta unitat aprendràs:
IO.println()var i constants final? :switchIO.readln()El HelloWorld!™️ es el clàssic primer programa que veu tot programador. Aquí el tens en Java 26:
void main() {
IO.println("Hola, Món!");
}
Observa la sintaxi:
void main() és el punt on la màquina comença a executar el teu programa.{ ... } delimiten el cos d'ordres que formen el programa.IO.println(...) indica a l'ordinador que mostri un text a la pantalla i salti a la línia següent.;).Un literal és un valor fix que apareix directament escrit al codi font del programa. La màquina distingeix diferents tipus de dades segons la seva naturalesa:
Són números sense part decimal. Poden ser positius o negatius. Per millorar la llegibilitat de nombres llargs, Java permet fer servir guions baixos (_):
println(42);
println(-17);
println(1_000_000); // Un milió
S'escriuen amb un punt (.) com a separador decimal (no amb una coma):
println(3.14159);
println(-0.5);
Qualsevol seqüència de caràcters envoltada entre cometes dobles ("..."):
println("Benvinguts al curs de programació!");
println("El resultat és: " + 10); // L'operador + concatena textos
Un sol caràcter envoltat entre cometes simples ('...'):
println('A');
println('9');
Només poden tenir dos valors: true o false. Són la base per a prendre decisions:
println(true);
println(false);
Per recordar dades que necessitarem més endavant, reservem un espai a la memòria RAM i li donem un nom. Aquest espai s'anomena variable.
int edat = 20;
double pes = 68.5;
boolean teCarnet = true;
char lletra = 'A';
String nom = "Laura";
Inferència de tipus amb var:
En Java modern podem utilitzar la paraula clau var quan inicialitzem la variable immediatament. El compilador dedueix el tipus automàticament:
var edat = 20; // El compilador dedueix que és un int
var pes = 68.5; // El compilador dedueix que és un double
var teCarnet = true; // El compilador dedueix que és un boolean
var lletra = 'A'; // El compilador dedueix que és un char
var nom = "Laura"; // El compilador dedueix que és un String
Un operador és un símbol especial que indica a l'ordinador que realitzi una operació matemàtica, relacional o lògica sobre un o diversos valors, anomenats operands.
La combinació d'operadors, variables i literals s'anomena expressió. Tota expressió, en avaluar-se, produeix un únic valor d'un tipus concret.
Són els operadors matemàtics bàsics per realitzar càlculs numèrics:
+ : Suma- : Resta* : Multiplicació/ : Divisió% : Mòdul o residu de la divisió enteraPrecedència aritmètica: Igual que a les matemàtiques escolars, *, / i % tenen prioritat respecte a + i -. Pots fer servir parèntesis ( ) per forçar o clarificar l'ordre d'avaluació:
int r1 = 2 + 3 * 4; // Dóna 14 (primer 3 * 4 = 12, després + 2)
int r2 = (2 + 3) * 4; // Dóna 20 (primer 2 + 3 = 5, després * 4)
Tipus dels operands i divisió entera:
El tipus del resultat depèn del tipus dels operands utilitzats:
int), el resultat és obligatòriament un int. A la divisió, es descarta la part decimal (es trunca cap a zero).float o double), el resultat es promociona automàticament a decimal.
println(7 / 2); // 3 (divisió entera: es descarta el .5!)
println(7.0 / 2); // 3.5 (com que 7.0 és double, el resultat és double)
println(7 / 2.0); // 3.5
println(7 % 2); // 1 (el residu de dividir 7 entre 2: 7 = 3 * 2 + 1)
Ús de suma i resta amb cadenes (String) i caràcters (char):
Concatenació amb String: Quan l'operador + s'utilitza i un dels operands és un text,
Java no suma matemàticament, sinó que concatena (uneix) les dades en una nova cadena de text (String):
String salutacio = "Hola, " + "Joan!"; // "Hola, Joan!"
String missatge = "Tens " + 3 + " missatges"; // "Tens 3 missatges"
// Atenció a l'ordre d'avaluació (d'esquerra a dreta):
println("Punts: " + 5 + 3); // "Punts: 53" (concatena "Punts: 5" i després "3")
println("Punts: " + (5 + 3)); // "Punts: 8" (primer suma matemàtica dels parèntesis)
Aritmètica amb caràcters (char): A Java, els caràcters s'emmagatzemen a la memòria
amb el seu codi numèric Unicode/ASCII (per exemple, 'A' és 65, 'B' és 66, i 'a' és 97).
Per tant, es poden sumar i restar amb nombres o entre ells:
char lletra = 'A';
int codi = lletra + 1; // 66 (el codi numèric de 'B')
char seguent = (char) (lletra + 1); // 'B' (fent càsting explícit a char)
// Calcular la distància o desplaçament entre lletres:
int distancia = 'e' - 'a'; // 4 (perquè 'e' està 4 posicions després de 'a')
Operadors d'assignació composta (+=, -=, *=, /=, %=):
Són una drecera molt habitual per modificar el valor d'una variable i reassignar el resultat a ella mateixa en un sol pas:
int punts = 10;
punts += 5; // Equivalent a: punts = punts + 5; (ara val 15)
punts -= 3; // Equivalent a: punts = punts - 3; (ara val 12)
punts *= 2; // Equivalent a: punts = punts * 2; (ara val 24)
punts /= 4; // Equivalent a: punts = punts / 4; (ara val 6)
punts %= 5; // Equivalent a: punts = punts % 5; (ara val 1)
Operadors unaris d'increment i decrement (++, --):
Permeten sumar o restar 1 a una variable numèrica de manera ràpida. S'escriuen després del nom de la variable (post-increment i post-decrement):
x++ : Incrementa el valor de la variable en 1 (equivalent a x = x + 1).x-- : Decrementa el valor de la variable en 1 (equivalent a x = x - 1).
int vides = 3;
vides++; // vides passa a valdre 4
vides--; // vides torna a valdre 3
Permeten comparar dos valors entre si. El resultat d'una comparació és SEMPRE un valor booleà (boolean: true o false):
== : Igual a!= : Diferent de< : Menor que> : Major que<= : Menor o igual que>= : Major o igual que
int edat = 18;
boolean esMajor = edat >= 18; // true
boolean esMenor = edat < 18; // false
boolean teDivuit = edat == 18; // true
boolean noTeVint = edat != 20; // true
// Els caràcters també es comparen pel seu ordre alfabètic/Unicode:
boolean ordre = 'a' < 'b'; // true (97 < 98)
Molt important: Com es comparen les cadenes de text (String)?
L'operador == en cadenes de text no compara el text contingut, sinó si les dues variables apunten exactament a la mateixa referència física a la memòria RAM. Si compares cadenes amb ==, el teu programa tindrà errors imprevisibles!
Per comparar el contingut d'un text cal utilitzar sempre el mètode .equals() o .equalsIgnoreCase():
String clauIntroduida = "admin";
String clauCorrecta = "admin";
// CORRECTE: Compara els caràcters del text
boolean accioPermesa = clauIntroduida.equals(clauCorrecta); // true
// Per comparar sense distingir majúscules de minúscules:
boolean coincideix = "java".equalsIgnoreCase("JAVA"); // true
// INCORRECTE per a Strings:
// boolean fallara = (clauIntroduida == clauCorrecta); // NO utilitzar per comparar contingut!
A diferència dels aritmètics i relacionals (que ja coneixes de les matemàtiques bàsiques), els operadors lògics són nous per a molts estudiants. S'utilitzen per combinar múltiples condicions o invertir-ne el resultat. Els seus operands han de ser de tipus boolean i retornen sempre un boolean:
&& (AND lògic / conjunció "I"):
Retorna true únicament si TOTS DOS operands són true. Si un d'ells (o tots dos) és false, el resultat final és false.
Exemple de la vida quotidiana: "Per conduir legalment cal tenir 18 anys o més I tenir el carnet vigent".
int edat = 20;
boolean teCarnet = true;
boolean potConduir = (edat >= 18) && teCarnet; // true (ambdues condicions són certes)
|| (OR lògic / disjunció "O"):
Retorna true si ALMENYS UN dels operands és true (o si tots dos ho són). Només retorna false quan tots dos operands són falsos.
Exemple de la vida quotidiana: "Tens descompte al transport si ets menor de 25 anys O si ets pensionista".
int edat = 22;
boolean esPensionista = false;
boolean teDescompte = (edat < 25) || esPensionista; // true (la primera condició és certa)
! (NOT lògic / negació):
És un operador unari que inverteix el valor de la condició: converteix true en false, i false en true.
Exemple de la vida quotidiana: "Si NO està plovent, sortirem a córrer".
boolean plou = false;
boolean sortimACorrer = !plou; // true
Avaluació en curtcircuit (Short-circuit Evaluation):
Java optimitza l'avaluació d'expressions lògiques d'esquerra a dreta i s'atura tan bon punt el resultat final ja és segur:
A && B: si A és false, el resultat serà fals amb total certesa; per tant, Java mai no arriba a avaluar B.A || B: si A és true, el resultat serà cert amb total certesa; per tant, Java tampoc no avalua B.Això és clau per escriure condicions segures, com ara evitar divisions per zero:
int divisor = 0;
// Com que (divisor != 0) és false, Java NO avalua la divisió i no es produeix cap error ArithmeticException:
boolean divisioSegura = (divisor != 0) && (100 / divisor > 2); // false (sense errors)
Precedència entre operadors lògics:
Si s'escriuen diversos operadors lògics seguits sense parèntesis, l'ordre d'avaluació és:
! (Negació: màxima prioritat)&& (AND: té prioritat sobre l'OR, equivalent a la multiplicació)|| (OR: menor prioritat, equivalent a la suma)
// L'expressió:
boolean res = true || false && false;
// S'avalua com: true || (false && false) -> true || false -> true!
// Si vols forçar que s'avaluï primer l'OR, utilitza parèntesis: (true || false) && false -> false
Als programes reals és habitual combinar operadors aritmètics, de comparació i lògics en una única expressió. Java resol cada part seguint una jerarquia de precedència estricta:
int edat = 19;
double notaMitjana = 8.5;
double ingressosFamiliars = 14_000.0;
boolean teExpedientDisciplinari = false;
// Comprovació de beca universitària:
boolean teBeca = edat <= 25 && (notaMitjana >= 8.0 || ingressosFamiliars < 15_000.0) && !teExpedientDisciplinari;
println("Té dret a beca? " + teBeca); // true
Jerarquia de precedència general en Java (de major a menor prioritat):
( ): Màxima prioritat absoluta. Utilitza'ls sempre per garantir l'ordre desitjat i facilitar la lectura del codi!++, --, !, (càsting)*, /, %+, - (i concatenació de text +)<, >, <=, >===, !=&&||? : i Expressions switch=, +=, -=, *=, /=, %= (prioritat mínima)? :)L'operador ternari és una construcció concisa i elegant que permet escollir entre dos valors possibles segons una condició booleana. És l'únic operador del llenguatge que compta amb tres operands:
condicio ? valor_si_cert : valor_si_fals
Com funciona?
condicio (que ha de resultar en un boolean: true o false).true, l'operador retorna el resultat de l'expressió situada abans dels dos punts (:).false, l'operador retorna el resultat de l'expressió situada després dels dos punts.Tipus de retorn: Les dues branques (valor cert i valor fals) han de retornar valors de tipus compatibles entre si (per exemple, ambdues cadenes String o ambdues valors numèrics):
// Exemple 1: Aprovat o suspès segons la qualificació
int nota = 7;
String resultat = (nota >= 5) ? "Aprovat" : "Suspès";
println(resultat); // Imprimeix: Aprovat
// Exemple 2: Determinar el màxim de dos nombres
int num1 = 45;
int num2 = 78;
int maxim = (num1 > num2) ? num1 : num2; // valdrà 78
// Exemple 3: Pluralització gramatical de missatges
int fitxersTrobats = 1;
println("S'ha trobat " + fitxersTrobats + (fitxersTrobats == 1 ? " fitxer" : " fitxers"));
Mentre que l'operador ternari (? :) és ideal per escollir entre dos valors segons una condició booleana, les expressions switch permeten avaluar un valor i seleccionar el resultat corresponent entre múltiples opcions possibles d'una forma molt neta, segura i directa.
A diferència de les estructures tradicionals, una expressió switch:
->) a cada cas, sense necessitat d'escriure break (evitant errors de caiguda accidental).case 1, 2, 3 ->).default.
// Exemple 1: Obtenir el tipus de jornada segons el dia de la setmana
int dia = 3;
String tipusJornada = switch (dia) {
case 1, 2, 3, 4, 5 -> "Dia feiner";
case 6, 7 -> "Cap de setmana";
default -> "Número de dia incorrecte";
};
println(tipusJornada); // Imprimeix: Dia feiner
// Exemple 2: Determinar l'estació de l'any a partir del mes
int mes = 4;
String estacio = switch (mes) {
case 12, 1, 2 -> "Hivern";
case 3, 4, 5 -> "Primavera";
case 6, 7, 8 -> "Estiu";
case 9, 10, 11 -> "Tardor";
default -> "Mes desconegut";
};
println("L'estació és: " + estacio); // L'estació és: Primavera
// Exemple 3: Assignació d'un descompte basat en un codi de text
String codiClient = "VIP";
double descompte = switch (codiClient) {
case "VIP" -> 0.20; // 20%
case "PREMIUM" -> 0.15; // 15%
case "STANDARD" -> 0.05; // 5%
default -> 0.0;
};
Quan treballem amb dades, molt sovint necessitem transformar un valor d'un tipus a un altre. En Java hem de distingir dos escenaris clarament diferenciats segons la naturalesa de les dades:
int i double).String).Quan convertim entre tipus numèrics primitius, trobem dues situacions:
Conversió implícita (automàtica o promoció): Es produeix en passar d'un tipus més petit o estret a un de més gran o ample (per exemple, de int a double). Com que el tipus destí té més capacitat de bits, no hi ha cap perill de pèrdua d'informació i Java ho fa automàticament:
int a = 10;
double b = a; // Correcte i automàtic: b valdrà 10.0
Càsting explícit: Es produeix en voler passar d'un tipus més gran a un de més petit (per exemple, de double a int). Com que hi pot haver pèrdua de precisió o desbordament, el compilador ens obliga a indicar el tipus destí explícitament entre parèntesis (tipus):
double preu = 9.99;
int partEntera = (int) preu; // partEntera valdrà 9 (es trunquen els decimals, no s'arrodoneix)
Què passa si tenim el text "42" i volem tractar-lo com a nombre? Un String NO és un tipus primitiu numèric, sinó una seqüència de caràcters de text emmagatzemada com a objecte. Per tant, no és possible fer un càsting directe:
// int num = (int) "42"; // ERROR DE COMPILACIÓ: Tipus incompatibles (inconvertible types)
Per obtenir el valor numèric real a partir dels caràcters d'un text cal interpretar o analitzar el text símbol a símbol. Aquest procés s'anomena en informàtica parsing. Java proporciona funcions estàndard per fer aquest procés:
Integer.parseInt(text) : Analitza el text i en retorna el valor enter (int).Double.parseDouble(text) : Analitza el text i en retorna el valor decimal (double).
String textEdat = "25";
int edat = Integer.parseInt(textEdat); // Ara edat és un int que val 25
String textPreu = "19.95";
double preu = Double.parseDouble(textPreu); // Ara preu és un double que val 19.95
Compte amb el contingut del text!
Si el text que passem a Integer.parseInt() o Double.parseDouble() no és un número vàlid (per exemple, conté lletres com "hola" o caràcters invàlids), el programa s'aturarà amb un error en temps d'execució (NumberFormatException) perquè la màquina no pot interpretar caràcters no numèrics com a xifres.
Fins ara, els nostres programes només mostraven informació fixa amb println(). Però els programes reals són interactius: demanen dades a l'usuari a través de la consola i calculen respostes segons el que aquest introdueixi.
En Java 26 podem llegir el que l'usuari escriu pel teclat mitjançant la instrucció IO.readln():
void main() {
String nom = IO.readln("Com et dius? ");
println("Hola, " + nom + "! Benvingut/da al curs de programació.");
}
Com funciona IO.readln()?
IO.readln() retorna SEMPRE un text (String). Encara que l'usuari escrigui un número com el 42, la màquina rep la cadena "42".Com que el que l'usuari escriu és sempre un String, si intentem fer operacions matemàtiques directament amb l'operador +, Java concatenarà el text en lloc de sumar-lo:
String edatText = IO.readln("Quina edat tens? "); // L'usuari escriu 20
println("L'any que ve tindràs: " + (edatText + 1)); // Imprimirà "201", NO 21!
Per poder operar amb nombres introduïts per l'usuari, apliquem el que hem après a la secció anterior: fem servir el parsing (Integer.parseInt() o Double.parseDouble()) sobre el text llegit:
void main() {
// Demanem un enter i fem el parsing directament:
int n1 = Integer.parseInt(IO.readln("Introdueix el primer número enter: "));
// Demanem un decimal:
double n2 = Double.parseDouble(IO.readln("Introdueix el segon número decimal: "));
// Ja podem operar matemàticament amb n1 i n2!
println("Suma: " + (n1 + n2));
println("Resta: " + (n1 - n2));
println("Multiplicació: " + (n1 * n2));
println("Divisió: " + (n1 / n2));
println("Residu: " + (n1 % n2));
}
Posa a prova el que has après completant els qüestionaris interactius auto-avaluables i els reptes de programació.