La reflexió és una característica poderosa de Java que permet a un programa inspeccionar i manipular les seves pròpies estructures internes en temps d'execució. Això inclou la capacitat d'examinar classes, mètodes, camps i constructors, així com invocar mètodes i accedir a camps de manera dinàmica.
Conceptes Clau
- API de Reflexió: Java proporciona un conjunt de classes i mètodes dins del paquet
java.lang.reflectper treballar amb la reflexió. - Classe
Class: La classeClassés el punt d'entrada per a la reflexió. Representa una classe o interfície en temps d'execució. - Mètodes de Reflexió: Inclouen mètodes per obtenir informació sobre constructors, mètodes, camps i modificadors d'una classe.
- Invocació Dinàmica: Permet invocar mètodes i accedir a camps de manera dinàmica, és a dir, sense conèixer els noms dels mètodes o camps en temps de compilació.
Exemples Pràctics
Obtenir Informació sobre una Classe
public class Example {
private String field;
public Example() {}
public void method() {}
}
public class ReflectionDemo {
public static void main(String[] args) {
try {
// Obtenir l'objecte Class
Class<?> clazz = Class.forName("Example");
// Obtenir el nom de la classe
System.out.println("Nom de la classe: " + clazz.getName());
// Obtenir els camps de la classe
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("Camp: " + field.getName());
}
// Obtenir els mètodes de la classe
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Mètode: " + method.getName());
}
// Obtenir els constructors de la classe
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}Invocar Mètodes Dinàmicament
public class Example {
public void sayHello(String name) {
System.out.println("Hola, " + name);
}
}
public class ReflectionDemo {
public static void main(String[] args) {
try {
// Obtenir l'objecte Class
Class<?> clazz = Class.forName("Example");
// Crear una instància de la classe
Object instance = clazz.getDeclaredConstructor().newInstance();
// Obtenir el mètode
Method method = clazz.getDeclaredMethod("sayHello", String.class);
// Invocar el mètode
method.invoke(instance, "Món");
} catch (Exception e) {
e.printStackTrace();
}
}
}Accedir a Camps Privats
public class Example {
private String secret = "Això és un secret";
public String getSecret() {
return secret;
}
}
public class ReflectionDemo {
public static void main(String[] args) {
try {
// Obtenir l'objecte Class
Class<?> clazz = Class.forName("Example");
// Crear una instància de la classe
Object instance = clazz.getDeclaredConstructor().newInstance();
// Obtenir el camp privat
Field field = clazz.getDeclaredField("secret");
// Fer el camp accessible
field.setAccessible(true);
// Obtenir el valor del camp
String secretValue = (String) field.get(instance);
System.out.println("Valor del camp secret: " + secretValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}Exercicis Pràctics
Exercici 1: Obtenir Informació sobre una Classe
Descripció: Escriu un programa que obtingui i imprimeixi informació sobre una classe especificada per l'usuari, incloent els seus camps, mètodes i constructors.
Solució:
import java.lang.reflect.*;
public class ClassInfo {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Ús: java ClassInfo <nom de la classe>");
return;
}
try {
Class<?> clazz = Class.forName(args[0]);
System.out.println("Nom de la classe: " + clazz.getName());
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("Camp: " + field.getName());
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Mètode: " + method.getName());
}
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor.getName());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}Exercici 2: Invocar un Mètode Dinàmicament
Descripció: Escriu un programa que invoca un mètode especificat per l'usuari en una classe especificada per l'usuari, passant un argument també especificat per l'usuari.
Solució:
import java.lang.reflect.*;
public class DynamicMethodInvocation {
public static void main(String[] args) {
if (args.length != 3) {
System.out.println("Ús: java DynamicMethodInvocation <nom de la classe> <nom del mètode> <argument>");
return;
}
try {
Class<?> clazz = Class.forName(args[0]);
Object instance = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getDeclaredMethod(args[1], String.class);
method.invoke(instance, args[2]);
} catch (Exception e) {
e.printStackTrace();
}
}
}Errors Comuns i Consells
- ClassNotFoundException: Assegura't que el nom de la classe és correcte i que la classe està en el classpath.
- NoSuchMethodException: Verifica que el mètode existeix i que els tipus de paràmetres són correctes.
- IllegalAccessException: Utilitza
setAccessible(true)per accedir a camps o mètodes privats. - InvocationTargetException: Aquest error es produeix quan el mètode invocat llança una excepció. Gestiona les excepcions adequadament.
Conclusió
La reflexió és una eina poderosa que permet als desenvolupadors escriure codi més flexible i dinàmic. Tot i això, s'ha d'utilitzar amb precaució, ja que pot afectar el rendiment i la seguretat de l'aplicació. Amb la pràctica i la comprensió adequada, la reflexió pot ser una addició valuosa a l'arsenal de qualsevol programador Java.
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
Mòdul 2: Flux de Control
Mòdul 3: Programació Orientada a Objectes
- Introducció a la POO
- Classes i Objectes
- Mètodes
- Constructors
- Herència
- Polimorfisme
- Encapsulació
- Abstracció
Mòdul 4: Programació Orientada a Objectes Avançada
Mòdul 5: Estructures de Dades i Col·leccions
Mòdul 6: Gestió d'Excepcions
Mòdul 7: Entrada/Sortida de Fitxers
- Lectura de Fitxers
- Escriptura de Fitxers
- Fluxos de Fitxers
- BufferedReader i BufferedWriter
- Serialització
Mòdul 8: Multithreading i Concurrència
- Introducció al Multithreading
- Creació de Fils
- Cicle de Vida dels Fils
- Sincronització
- Utilitats de Concurrència
Mòdul 9: Xarxes
- Introducció a les Xarxes
- Sockets
- ServerSocket
- DatagramSocket i DatagramPacket
- URL i HttpURLConnection
