Un programa és, en essència, dades que es transformen. Les variables són els recipients on deses aquestes dades i els tipus són les regles que determinen què cap en cada recipient i quines operacions hi tenen sentit. En Java aquestes regles es comproven abans d'executar res, i això converteix el sistema de tipus en la teva primera xarxa de seguretat: molt del que en altres llenguatges peta en producció, aquí ni tan sols compila. En aquesta lliçó aprendràs els vuit tipus primitius, la diferència crucial entre primitius i referències, el comportament especial de String, les conversions de tipus, les constants i la inferència amb var. En acabar hauràs modelat amb variables el primer llibre del catàleg de BiblioTech.
Contingut
- Declaració, inicialització i assignació
- Els vuit tipus primitius
- Literals: com s'escriuen els valors
- Primitius davant de referències: què desa cada variable
String: el tipus especial- Conversions de tipus
- Embolcalls, autoboxing i conversió des de text
finali constants- Inferència de tipus amb
var - Modelant un llibre de BiblioTech
- Errors Habituals i Consells
- Exercicis
- Declaració, inicialització i assignació
Tres operacions que convé distingir des del principi:
int anyPublicacio; // 1. DECLARACIO: reservem el nom i fixem el tipus
anyPublicacio = 2018; // 2. ASSIGNACIO: li donem un valor
int diesRetard = 12; // 3. DECLARACIO + INICIALITZACIO en una sola linia- Declarar és anunciar al compilador: "existirà una variable anomenada
anyPublicacioque contindrà enters". A partir d'aquí, el compilador vigila que no hi fiquis cap altra cosa. - Inicialitzar és donar-li el seu primer valor.
- Assignar és donar-li un valor (el primer o qualsevol altre de posterior). El símbol
=no significa igualtat matemàtica, sinó "desa el de la dreta a la variable de l'esquerra".
Una regla que Java imposa i que convé celebrar: no pots llegir una variable local abans d'assignar-li un valor.
int diesRetard;
System.out.println(diesRetard); // ERROR de compilacio: variable diesRetard might not have been initializedAltres llenguatges et retornarien brossa o undefined; Java es nega a compilar. Això elimina tota una família d'errors subtils.
Pots declarar diverses variables del mateix tipus en una línia, encara que per llegibilitat es prefereix una per línia:
- Els vuit tipus primitius
Java té exactament vuit tipus primitius. No són objectes: són valors purs que la JVM manipula de manera directa i eficient.
| Tipus | Categoria | Mida | Rang | Valor per defecte | Ús típic |
|---|---|---|---|---|---|
byte |
Enter | 8 bits | −128 a 127 | 0 |
Dades binàries, estalvi de memòria |
short |
Enter | 16 bits | −32.768 a 32.767 | 0 |
Poc utilitzat |
int |
Enter | 32 bits | −2.147.483.648 a 2.147.483.647 | 0 |
L'enter per defecte |
long |
Enter | 64 bits | ±9,22 × 10¹⁸ | 0L |
Marques de temps, identificadors, xifres grans |
float |
Decimal | 32 bits | ~7 dígits significatius | 0.0f |
Poc utilitzat; precisió insuficient |
double |
Decimal | 64 bits | ~15 dígits significatius | 0.0d |
El decimal per defecte |
char |
Caràcter | 16 bits | 0 a 65.535 (un caràcter Unicode) | ' ' |
Un únic caràcter |
boolean |
Lògic | Depèn de la JVM | true o false |
false |
Condicions, banderes |
Notes importants sobre aquesta taula:
- La columna "valor per defecte" només s'aplica als camps d'una classe (mòdul 3), no a les variables locals dins de
main, que com acabem de veure s'han d'inicialitzar explícitament. - A la pràctica faràs servir
int,double,booleanicharel 95 % del temps.byte,shortifloatsón casos especials. longés imprescindible quanintes queda curt. El límit d'int(uns 2.147 milions) sembla enorme fins que comptes mil·lisegons: el nombre de mil·lisegons des del 1970 va desbordarintel 1970 + 24 dies.charno és unStringd'un caràcter: s'escriu amb cometes simples ('A') i és un tipus numèric per sota.booleanen Java no és un número. No existeix l'equivalència "0 és fals, 1 és cert" de C:if (1)no compila.
byte codiSeccio = 3; // seccions de la biblioteca: 1..12
short exemplarsTotals = 850; // llibres al cataleg de Nexus Software
int anyPublicacio = 2018;
long identificadorPrestec = 100000000045L; // la L es obligatoria: no cap en un int
float pesLlibreKg = 0.68f; // la f es obligatoria
double multa = 3.75;
char inicialSeccio = 'J'; // cometes SIMPLES
boolean disponible = true;
- Literals: com s'escriuen els valors
Un literal és un valor escrit directament al codi. Java admet diverses notacions:
Literals enters
int decimal = 2018; // base 10, el normal
int hexadecimal = 0x7E2; // base 16, prefix 0x -> 2018
int binari = 0b11111100010; // base 2, prefix 0b -> 2018 (des de Java 7)
int octal = 03742; // base 8, prefix 0 -> 2018 (evitar: confon)
long codiLlarg = 9788498750102L; // sufix L obligatori si supera el rang d'intCompte amb l'octal: int x = 010; val 8, no pas 10. És una font clàssica d'errors; evita els zeros a l'esquerra.
Guions baixos com a separadors
Des de Java 7 pots fer servir _ per fer llegibles els números llargs. El compilador els ignora completament:
int pressupostAnual = 1_250_000; // es llegeix molt millor que 1250000
long isbnNumeric = 978_000_000_0001L;
int mascara = 0b1010_0101_1100_0011;Restriccions: no poden anar al principi, al final, ni al costat del punt decimal.
Literals decimals
double multa = 3.75;
double tarifa = 0.25d; // la d es opcional: double es el tipus per defecte
float pes = 0.68f; // la f SI que es obligatoria
double notacioCientifica = 1.5e3; // 1500.0Regla que causa molts errors: un literal decimal sense sufix és double. Per això float pes = 0.68; no compila: estàs intentant ficar un double dins d'un float, que és més petit. Cal escriure 0.68f.
Literals de caràcter i booleans
char lletra = 'J';
char codi = 74; // char es numeric per sota: 74 es la 'J' en Unicode
char salt = '\n'; // sequencia d'escapada
boolean disponible = true;
boolean prestat = false;Seqüències d'escapada més utilitzades:
| Seqüència | Significat |
|---|---|
\n |
Salt de línia |
\t |
Tabulador |
\" |
Cometa doble dins d'un String |
\' |
Cometa simple dins d'un char |
\\ |
Barra invertida |
- Primitius davant de referències: què desa cada variable
Aquesta és una de les idees més importants del mòdul, i la que explica molts comportaments que d'una altra manera semblen arbitraris.
Java divideix els tipus en dues famílies:
- Tipus primitius (els vuit anteriors): la variable conté el valor directament.
- Tipus per referència (
String, arrays, i totes les classes): la variable conté una referència (una adreça) a un objecte que viu en una altra zona de memòria.
La memòria d'un programa Java s'organitza, de manera simplificada, en dues zones:
- La pila (stack): ràpida i petita, desa les variables locals dels mètodes.
- El monticle (heap): gran, desa els objectes. És on actua el recol·lector de brossa.
flowchart LR
subgraph Pila["Pila (variables locals de main)"]
A["anyPublicacio<br/><b>2018</b>"]
B["disponible<br/><b>true</b>"]
C["titol<br/><b>ref → #a1b2</b>"]
D["autor<br/><b>ref → #c3d4</b>"]
end
subgraph Heap["Monticle (objectes)"]
E["#a1b2<br/>String: 'Java Eficac'"]
F["#c3d4<br/>String: 'Joshua Bloch'"]
end
C --> E
D --> F
Fixa't en la diferència: anyPublicacio és 2018; titol no és el text, sinó una fletxa que hi apunta.
Conseqüències pràctiques immediates:
// Amb primitius: es copia el VALOR
int diesA = 12;
int diesB = diesA; // diesB rep una copia del numero
diesA = 20;
System.out.println(diesB); // 12 -> diesB no s'ha vist afectada
// Amb referencies: es copia la REFERENCIA
String titolA = "Java Eficac";
String titolB = titolA; // totes dues apunten al MATEIX objecteUna variable de referència pot valer, a més, null, que significa "no apunta a cap objecte". Els primitius no poden ser mai null.
String editorial = null; // valid: la referencia no apunta a res
// int pagines = null; // ERROR: un int sempre te un numeroIntentar fer servir una referència null produeix l'error d'execució més famós de Java, NullPointerException. El tractaràs formalment al mòdul 6.
String: el tipus especial
String: el tipus especialString no és un primitiu, és una classe. Però rep un tracte tan privilegiat del llenguatge que es comporta a mig camí.
Creació
String titol = "Java Eficac"; // forma normal, amb literal
String autor = new String("Joshua Bloch"); // funciona, pero NO es fa servirString és l'única classe que es pot crear amb un literal, sense new. Fer servir new String(...) és un antipatró: crea un objecte extra sense cap avantatge.
Immutabilitat
Un String no es pot modificar mai. Tots els mètodes que "canvien" una cadena retornen en realitat una cadena nova:
String titol = "Java Eficac";
titol.toUpperCase(); // calcula "JAVA EFICAC"... i el llenca
System.out.println(titol); // continua imprimint "Java Eficac"
titol = titol.toUpperCase(); // CORRECTE: desem el resultat
System.out.println(titol); // "JAVA EFICAC"Aquest és un dels errors més freqüents de qui comença. Si un mètode de String no sembla fer res, gairebé segur que has oblidat desar-ne el resultat.
Per què són immutables? Per seguretat (una cadena no pot canviar sota els teus peus), per eficiència (permet compartir cadenes idèntiques al pool de cadenes) i perquè les fa segures entre fils sense cap cost (mòdul 8).
Concatenació
String titol = "Java Eficac";
int anyPublicacio = 2018;
String fitxa = titol + " (" + anyPublicacio + ")";
System.out.println(fitxa); // Java Eficac (2018)L'operador + concatena. Quan un dels operands és un String, Java converteix automàticament l'altre a text. Això també significa que "Total: " + 2 + 3 produeix "Total: 23" i no "Total: 5": s'avalua d'esquerra a dreta, i tan bon punt hi ha un String tota la resta s'hi enganxa com a text. Es corregeix amb parèntesis: "Total: " + (2 + 3).
Mètodes essencials
Partim de:
| Mètode | Què fa | Exemple | Resultat |
|---|---|---|---|
length() |
Nombre de caràcters | "Java Eficac".length() |
11 |
trim() |
Elimina espais dels extrems | titol.trim() |
"Java Eficac" |
strip() |
Com trim però Unicode-aware (Java 11+) |
titol.strip() |
"Java Eficac" |
toUpperCase() |
Tot a majúscules | "java".toUpperCase() |
"JAVA" |
toLowerCase() |
Tot a minúscules | "JAVA".toLowerCase() |
"java" |
substring(i) |
Des de l'índex i fins al final |
"Java Eficac".substring(5) |
"Eficac" |
substring(i, j) |
De l'índex i al j (sense incloure j) |
"Java Eficac".substring(0, 4) |
"Java" |
equals(altre) |
Contingut idèntic? | "java".equals("Java") |
false |
equalsIgnoreCase(altre) |
Idèntic ignorant majúscules | "java".equalsIgnoreCase("Java") |
true |
isEmpty() |
Longitud zero? | "".isEmpty() |
true |
isBlank() |
Buida o només espais? (Java 11+) | " ".isBlank() |
true |
contains(txt) |
Conté aquest fragment? | "Java Eficac".contains("Efi") |
true |
replace(a, b) |
Substitueix | "Java".replace('a', 'o') |
"Jovo" |
charAt(i) |
Caràcter a la posició i |
"Java".charAt(0) |
'J' |
indexOf(txt) |
Posició de la primera aparició (−1 si no hi és) | "Java Eficac".indexOf("E") |
5 |
Els índexs comencen en 0, i substring(i, j) inclou i però exclou j. És la convenció de tot Java; interioritza-la ja.
Exemple aplicat a BiblioTech:
String isbn = "978-0000000001";
System.out.println("ISBN complet: " + isbn);
System.out.println("Prefix GS1: " + isbn.substring(0, 3)); // "978"
System.out.println("Codi: " + isbn.substring(4)); // "0000000001"
System.out.println("Longitud: " + isbn.length()); // 14Text blocks (Java 15+)
Per a textos de diverses línies existeix una sintaxi amb triple cometa que evita els \n i les concatenacions:
String capcalera = """
============================================
BiblioTech - Nexus Software
Sistema de gestio de la biblioteca
============================================
""";
System.out.println(capcalera);Detalls: la triple cometa d'obertura ha d'anar seguida d'un salt de línia, i el sagnat es calcula respecte a la línia de tancament, de manera que pots sagnar el bloc dins del codi sense que aquells espais apareguin a la sortida. És enormement còmode per a menús, plantilles o fragments de JSON i SQL.
- Conversions de tipus
Quan barreges tipus numèrics, Java aplica regles estrictes.
Conversió eixamplant (widening): automàtica
Va d'un tipus petit a un de més gran. No es perd informació, així que Java la fa sola:
int diesRetard = 12;
double diesComDecimal = diesRetard; // automatic: 12.0
System.out.println(diesComDecimal); // 12.0Això explica per què 12 * 0.25 dona 3.0: l'int es converteix a double abans de multiplicar.
Conversió estrenyent (narrowing): requereix cast explícit
Va d'un tipus gran a un de més petit. Pot perdre informació, així que Java t'obliga a demanar-la explícitament amb un cast, que és la teva signatura de "sé el que faig":
double multaExacta = 3.75;
int multaEntera = (int) multaExacta; // cast obligatori
System.out.println(multaEntera); // 3 <- es TRUNCA, no s'arrodoneixPunts crítics:
- El cast a enter trunca, no arrodoneix.
(int) 3.99és3. Per arrodonir es fa servirMath.round(3.99), que dona4. - Si el valor no hi cap, el resultat és brossa silenciosa:
int gran = 200;
byte petit = (byte) gran;
System.out.println(petit); // -56 <- desbordament silenciosAquí no hi ha error ni avís: el compilador assumeix que sabies què feies. Per això els casts s'han de fer servir amb coneixement de causa.
Promoció en expressions
En una operació entre tipus diferents, Java promociona al més gran dels dos:
int diesRetard = 12;
double tarifa = 0.25;
double multa = diesRetard * tarifa; // int es promociona a double -> 3.0I el parany clàssic, que veurem a fons a la lliçó d'operadors:
La divisió es fa entre enters (donant 2) i només després es converteix a double. La solució és forçar-ho abans: (double) total / parts.
- Embolcalls, autoboxing i conversió des de text
Cada primitiu té una classe embolcall (wrapper) que el representa com a objecte:
| Primitiu | Embolcall |
|---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
Per a què serveixen? Per dos motius:
- Les col·leccions (mòdul 5) només admeten objectes, no primitius. No pots tenir una llista d'
int, però sí d'Integer. - Poden ser
null, cosa que permet representar "sense valor" (un any de publicació desconegut, per exemple).
Autoboxing i unboxing
Des de Java 5, la conversió entre primitiu i embolcall és automàtica:
Integer anyObjecte = 2018; // autoboxing: int -> Integer
int anyPrimitiu = anyObjecte; // unboxing: Integer -> intÉs còmode, però té dos costos que convé conèixer: consumeix més memòria i, sobretot, un unboxing sobre una referència null llança NullPointerException. Regla pràctica: fes servir primitius llevat que necessitis null o una col·lecció.
Mètodes estàtics útils dels embolcalls
Aquí hi ha la seva utilitat més immediata en aquest mòdul: convertir text a número. Recorda que els arguments de línia d'ordres i el que es llegeix per consola arriben sempre com a String.
String textAny = "2018";
int anyPublicacio = Integer.parseInt(textAny); // 2018 com a numero
String textMulta = "3.75";
double multa = Double.parseDouble(textMulta); // 3.75 com a numero
// Constants utils
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
// Conversio inversa: numero -> text
String comText = String.valueOf(2018);Si el text no representa un número vàlid (Integer.parseInt("dos mil")), el programa falla en execució amb NumberFormatException. Com capturar i tractar aquesta fallada s'estudia al mòdul 6; de moment n'hi ha prou amb saber que existeix i amb introduir dades correctes.
final i constants
final i constantsLa paraula final aplicada a una variable significa que el seu valor no pot canviar després d'assignar-se:
final double TARIFA_DIARIA = 0.25;
TARIFA_DIARIA = 0.30; // ERROR de compilacio: cannot assign a value to final variablePer què fer-les servir:
- Comuniquen intenció. Qui llegeix el codi sap que aquell valor és una regla de negoci, no una dada variable.
- Eviten errors. Un valor que no ha de canviar, no pot canviar per accident.
- Eliminen els "números màgics". Comparar un
0.25escampat per vint llocs amb una únicaTARIFA_DIARIAés la diferència entre poder canviar la tarifa en un minut o en una tarda.
Les constants s'escriuen en MAJUSCULES_AMB_GUIO_BAIX, com vam veure a la lliçó anterior:
final double TARIFA_DIARIA = 0.25; // euros per dia de retard
final int DIES_PRESTEC = 15; // durada estandard del prestec
final double MULTA_MAXIMA = 20.0; // sostre de multa per prestec
final String NOM_EMPRESA = "Nexus Software";Un matís important per a més endavant: en una variable de referència, final impedeix reassignar la referència, no modificar l'objecte apuntat. Amb String no es nota perquè són immutables, però amb objectes mutables (mòdul 3) sí.
- Inferència de tipus amb
var
varDes de Java 10 pots ometre el tipus d'una variable local i deixar que el compilador el dedueixi del valor assignat:
var titol = "Java Eficac"; // el compilador infereix String
var anyPublicacio = 2018; // infereix int
var multa = 3.75; // infereix double
var disponible = true; // infereix booleanÉs crucial entendre que var no converteix Java en un llenguatge de tipatge dinàmic. El tipus es fixa en compilació i és tan estricte com sempre:
Quan sí i quan no
| Situació | Recomanació | Exemple |
|---|---|---|
| El tipus és evident pel valor | Fes servir var |
var scanner = new Scanner(System.in); |
| El tipus és llarg i repetitiu | Fes servir var |
var cataleg = new HashMap<String, Llibre>(); |
| El tipus no es dedueix llegint | Evita var |
var resultat = processar(dades); |
| Vols un tipus concret diferent de l'inferit | No facis servir var |
double tarifa = 1; (amb var seria int) |
| Literals numèrics simples | Discutible; el tipus explícit sol ser més clar | int diesRetard = 12; |
Restriccions de var:
- Només per a variables locals (dins de mètodes). No val per a camps de classe ni paràmetres.
- Obliga a inicialitzar a la mateixa línia:
var x;no compila. - No admet
nullcom a valor inicial:var x = null;no compila, perquè no hi ha tipus a inferir.
Aquest curs fa servir tipus explícits al mòdul 1 (perquè vegis sempre quin tipus hi ha en joc) i var a partir del mòdul 5, on els tipus genèrics el fan realment útil.
- Modelant un llibre de BiblioTech
Apliquem tot el que hem après. El catàleg de Nexus Software necessita registrar, per a cada llibre: títol, autor, ISBN, any de publicació i disponibilitat. Amb el que saps avui, això es tradueix en variables soltes:
public class CatalegBiblioTech {
public static void main(String[] args) {
// --- Constants de negoci de BiblioTech ---
final String NOM_EMPRESA = "Nexus Software";
final double TARIFA_DIARIA = 0.25; // euros per dia de retard
final int DIES_PRESTEC = 15; // durada estandard del prestec
// --- Dades del primer llibre del cataleg ---
String titol = "Java Eficac";
String autor = "Joshua Bloch";
String isbn = "978-0000000001";
int anyPublicacio = 2018;
boolean disponible = true;
// --- Dades d'un prestec en curs ---
String empleat = "Marta Ruiz";
int diesTranscorreguts = 27;
int diesRetard = diesTranscorreguts - DIES_PRESTEC; // 12
double multa = diesRetard * TARIFA_DIARIA; // int * double -> double
// --- Sortida ---
System.out.println("=== " + NOM_EMPRESA + " - BiblioTech ===");
System.out.println();
System.out.println("Titol: " + titol);
System.out.println("Autor: " + autor);
System.out.println("ISBN: " + isbn);
System.out.println("Publicacio: " + anyPublicacio);
System.out.println("Disponible: " + disponible);
System.out.println();
System.out.println("Prestat a: " + empleat);
System.out.println("Dies de retard: " + diesRetard);
System.out.println("Multa acumulada: " + multa + " EUR");
}
}Sortida:
=== Nexus Software - BiblioTech === Titol: Java Eficac Autor: Joshua Bloch ISBN: 978-0000000001 Publicacio: 2018 Disponible: true Prestat a: Marta Ruiz Dies de retard: 12 Multa acumulada: 3.0 EUR
La limitació que ja es nota
Aquest enfocament funciona per a un llibre. Però Nexus Software en té centenars. Amb variables soltes necessitaries titol1, titol2, titol3… i res no garantiria que autor2 correspon realment a titol2. Les dades que formen una unitat conceptual estan escampades.
Aquesta és exactament la mancança que resol la programació orientada a objectes: al mòdul 3 crearàs una classe Llibre que agrupi aquestes cinc variables en un únic tipus, i al mòdul 5 desaràs centenars d'aquests objectes en una col·lecció. Fixa't que els noms que estàs fent servir ara (titol, autor, isbn, anyPublicacio, disponible) seran literalment els camps d'aquella classe. N'estàs posant la base.
Errors Habituals i Consells
- Oblidar desar el resultat d'un mètode de
String.titol.toUpperCase();no canvia res. Ha de sertitol = titol.toUpperCase();. float x = 3.75;no compila. Els literals decimals sóndouble; cal escriure3.75f.long x = 10000000000;no compila. El literal s'interpreta com ainti desborda. Cal escriure10000000000L.- Confondre
'A'amb"A". Cometes simples éschar, dobles ésString. No són intercanviables. - Esperar que
(int) 3.99sigui 4. El cast trunca. Per arrodonir,Math.round(). - Fer servir
==per compararString. Compara referències, no contingut. Es fa servirequals(). És tan important que la lliçó següent hi dedica un apartat sencer. - Declarar variables sense inicialitzar i llegir-les. El compilador ho impedeix en variables locals; agraeix-ho.
- Abusar de
var.var resultat = calcular();obliga el lector a anar a buscar la signatura del mètode. Fes-lo servir només quan el tipus sigui evident. - Consell: declara
finaltot allò que no hagi de canviar. És gratis i converteix un error potencial en un error de compilació. - Consell: fes servir noms que diguin què conté la variable, no de quin tipus és.
diesRetardés millor quenumeroEnter1. - Consell: quan dubtis d'un mètode de
String, obre'l a JShell i prova'l. Cinc segons davant de deu minuts de suposicions.
Exercicis
Exercici 1: Predir la sortida
Sense executar el codi, escriu què imprimeix cada línia i justifica per què. Després comprova-ho a JShell o compilant-lo.
public class ProvaTipus {
public static void main(String[] args) {
int a = 7;
int b = 2;
System.out.println(a / b);
System.out.println((double) a / b);
System.out.println((int) 3.99);
System.out.println(Math.round(3.99));
String titol = "Java Eficac";
titol.toUpperCase();
System.out.println(titol);
System.out.println(titol.substring(0, 4));
System.out.println(titol.length());
System.out.println("Total: " + 2 + 3);
System.out.println("Total: " + (2 + 3));
byte petit = (byte) 300;
System.out.println(petit);
}
}Exercici 2: Fitxa completa d'un llibre
Escriu la classe FitxaCompleta que declari les variables necessàries per al llibre "Patrons de Disseny" (ISBN 978-0000000002, any 1994, autor "Erich Gamma i altres", disponible) i calculi i mostri:
- Els anys d'antiguitat del llibre respecte al 2026.
- L'ISBN sense el prefix
978-. - El títol en majúscules.
- Si el títol té més de 10 caràcters (fes servir una variable
booleani calcula'n el valor amb una comparació, senseif).
Fes servir constants final on correspongui i respecta les convencions de nomenclatura.
Exercici 3: Corregir els errors de tipus
El codi següent té sis errors de compilació relacionats amb tipus. Troba'ls, explica cadascun i escriu-ne la versió corregida.
public class ErrorsTipus {
public static void main(String[] args) {
float tarifaDiaria = 0.25;
long identificador = 100000000045;
char seccio = "J";
int multa = 3.75;
final int DIES_PRESTEC = 15;
DIES_PRESTEC = 20;
int pagines;
System.out.println(pagines);
}
}Solucions
Solució 1
Justificació línia a línia:
a / b→3. Tots dos sónint, així que es fa divisió entera: el resultat 3,5 es trunca a 3. És l'error més clàssic de Java.(double) a / b→3.5. El cast s'aplica aaabans de dividir, així que l'operació és7.0 / 2i per promoció dona3.5.(int) 3.99→3. El cast a enter trunca la part decimal; no arrodoneix.Math.round(3.99)→4. Aquest sí que arrodoneix a l'enter més proper.titol→Java Eficac.toUpperCase()retorna una cadena nova que es descarta, perquè no s'ha assignat. ElsStringsón immutables.substring(0, 4)→Java. Des de l'índex 0 inclòs fins al 4 exclòs: caràcters 0, 1, 2 i 3.length()→11. "Java Eficac" té 4 + 1 espai + 6 = 11 caràcters."Total: " + 2 + 3→Total: 23. S'avalua d'esquerra a dreta:"Total: " + 2dona"Total: 2", i a aquella cadena s'hi enganxa el 3."Total: " + (2 + 3)→Total: 5. Els parèntesis forcen la suma numèrica primer.(byte) 300→44. Unbytenomés arriba a 127. El valor desborda i es conserven únicament els 8 bits baixos de 300 (100101100→00101100= 44). No hi ha cap avís: és una pèrdua silenciosa.
Solució 2
public class FitxaCompleta {
public static void main(String[] args) {
// Constants: valors que no canvien durant l'execucio
final String NOM_EMPRESA = "Nexus Software";
final int ANY_ACTUAL = 2026;
final int LONGITUD_TITOL_LLARG = 10;
final String PREFIX_ISBN = "978-";
// Dades del llibre
String titol = "Patrons de Disseny";
String autor = "Erich Gamma i altres";
String isbn = "978-0000000002";
int anyPublicacio = 1994;
boolean disponible = true;
// 1. Antiguitat: resta d'enters
int antiguitat = ANY_ACTUAL - anyPublicacio;
// 2. ISBN sense prefix. PREFIX_ISBN.length() val 4, aixi que
// substring(4) retorna tot a partir del cinque caracter.
String isbnSensePrefix = isbn.substring(PREFIX_ISBN.length());
// 3. Titol en majuscules. Desem el resultat: els String son immutables.
String titolMajuscules = titol.toUpperCase();
// 4. Una comparacio produeix directament un boolean, sense necessitat d'if.
boolean titolLlarg = titol.length() > LONGITUD_TITOL_LLARG;
// --- Sortida ---
System.out.println("=== " + NOM_EMPRESA + " - BiblioTech ===");
System.out.println("Titol: " + titol);
System.out.println("Autor: " + autor);
System.out.println("ISBN: " + isbn);
System.out.println("Publicacio: " + anyPublicacio);
System.out.println("Disponible: " + disponible);
System.out.println("Antiguitat: " + antiguitat + " anys");
System.out.println("ISBN sense prefix: " + isbnSensePrefix);
System.out.println("Titol majuscules: " + titolMajuscules);
System.out.println("Titol llarg: " + titolLlarg);
}
}Sortida:
=== Nexus Software - BiblioTech === Titol: Patrons de Disseny Autor: Erich Gamma i altres ISBN: 978-0000000002 Publicacio: 1994 Disponible: true Antiguitat: 32 anys ISBN sense prefix: 0000000002 Titol majuscules: PATRONS DE DISSENY Titol llarg: true
La idea clau del punt 4: una comparació com ara titol.length() > 10 és una expressió booleana. No cal cap if per obtenir true o false; l'if serveix per decidir què fer amb aquest valor, i això arriba al mòdul 2.
Solució 3
Els sis errors:
float tarifaDiaria = 0.25;— el literal0.25ésdouble; no cap en unfloatsense sufix. Solució:0.25f(o millor, fer servirdouble).long identificador = 100000000045;— el literal s'interpreta com ainti en desborda el rang. Falta el sufixL.char seccio = "J";— les cometes dobles creen unString. Uncharnecessita cometes simples:'J'.int multa = 3.75;— assignar undoublea unintés una conversió estrenyent i requereix cast explícit (o, millor, declararmultacom adouble, que és el correcte per a diners).DIES_PRESTEC = 20;— la variable ésfinal; no es pot reassignar.System.out.println(pagines);—paginess'ha declarat però no s'ha inicialitzat mai, i les variables locals han de tenir valor abans de llegir-se.
Versió corregida:
public class ErrorsTipus {
public static void main(String[] args) {
double tarifaDiaria = 0.25; // 1. double es el tipus natural per a decimals
long identificador = 100000000045L; // 2. sufix L per a literals long
char seccio = 'J'; // 3. cometes simples per a char
double multa = 3.75; // 4. l'import es decimal, no enter
final int DIES_PRESTEC = 15; // 5. constant: s'assigna una sola vegada
int pagines = 416; // 6. inicialitzada abans de fer-se servir
System.out.println("Tarifa diaria: " + tarifaDiaria);
System.out.println("Identificador: " + identificador);
System.out.println("Seccio: " + seccio);
System.out.println("Multa: " + multa);
System.out.println("Dies prestec: " + DIES_PRESTEC);
System.out.println("Pagines: " + pagines);
}
}Conclusió
Ja saps declarar, inicialitzar i assignar variables; coneixes els vuit tipus primitius amb els seus rangs i quins faràs servir de debò; escrius literals en qualsevol base i amb sufixos correctes; distingeixes els primitius (que desen el valor) de les referències (que desen una fletxa al monticle); domines String, la seva immutabilitat i els seus mètodes essencials, inclosos els text blocks; converteixes entre tipus entenent quan la conversió és automàtica i quan trunca; fas servir embolcalls i Integer.parseInt per transformar text en número; protegeixes les teves regles de negoci amb final; i saps quan var ajuda i quan fa nosa. Amb tot això has modelat el primer llibre de BiblioTech.
A la lliçó següent, Operadors, posarem aquestes dades en moviment: aritmètica (inclòs el parany de la divisió entera i el mòdul), assignació composta, increment i decrement, comparacions, operadors lògics amb avaluació de curtcircuit, l'operador ternari, operacions a nivell de bit, precedència, i l'error clàssic de comparar cadenes amb == en comptes d'equals. El fil conductor serà el càlcul de la multa per retard d'un préstec de BiblioTech.
Curs de Programació en Java
Mòdul 1: Introducció a Java
- Introducció a Java
- Configuració de l'entorn de desenvolupament
- Sintaxi i estructura bàsica
- Variables i tipus de dades
- Operadors
- Entrada i sortida per consola
- El teu primer programa complet: BiblioTech
Mòdul 2: Flux de control
- Sentències condicionals
- Bucles
- Sentències switch
- Break i continue
- Depuració i traces d'execució
- Projecte: menú interactiu de BiblioTech
Mòdul 3: Programació orientada a objectes
- Introducció a la POO
- Classes i objectes
- Mètodes
- Constructors
- Herència
- Polimorfisme
- Encapsulament
- Abstracció
- La classe Object: equals, hashCode i toString
Mòdul 4: Programació orientada a objectes avançada
- Interfícies
- Classes abstractes
- Classes internes
- Classes anònimes
- Expressions lambda
- Interfícies funcionals i referències a mètodes
- Enumeracions i registres
Mòdul 5: Estructures de dades i col·leccions
- Arrays
- El framework de col·leccions
- ArrayList
- LinkedList
- HashMap
- HashSet
- Cua i Deque
- Pila
- Ordenació i cerca en col·leccions
Mòdul 6: Gestió d'excepcions
- Introducció a les excepcions
- Bloc try-catch
- Throw i throws
- Excepcions personalitzades
- Bloc finally
- Try-with-resources i AutoCloseable
- Estratègies de gestió d'errors i logging
Mòdul 7: Entrada/sortida de fitxers
- Lectura de fitxers
- Escriptura de fitxers
- Fluxos de fitxers
- BufferedReader i BufferedWriter
- Serialització
- L'API NIO.2: Path i Files
- Formats d'intercanvi: CSV i Properties
Mòdul 8: Multifil i concurrència
- Introducció al multifil
- Creació de fils
- Cicle de vida d'un fil
- Sincronització
- Utilitats de concurrència
- Col·leccions concurrents i variables atòmiques
- Tasques asíncrones amb CompletableFuture
Mòdul 9: Xarxes
- Introducció a les xarxes
- Sockets
- ServerSocket
- DatagramSocket i DatagramPacket
- URL i HttpURLConnection
- El client HTTP modern
Mòdul 10: Temes avançats
- Genèrics
- Anotacions
- Reflexió
- Característiques de Java 8: Streams i Optional
- Dates i hores amb java.time
- Java 9 i més enllà
- Memòria, recol·lecció de brossa i rendiment
Mòdul 11: Frameworks i llibreries de Java
- Introducció als frameworks de Java
- Spring Framework
- Hibernate
- JUnit
- Maven
- Proves avançades amb Mockito
- Llibreries essencials de l'ecosistema
