Agora que entendemos tanto getClass() quanto instanceof, vamos criar uma classe utilitária mais abrangente que pode imprimir informações detalhadas de tipo para qualquer objeto Java.
Criando uma Utilitário TypeInfo Reutilizável
Uma classe utilitária bem projetada pode facilitar a inspeção de objetos em seu código. Vamos criar um arquivo chamado TypeInfo.java no diretório java-type-printing:
import java.lang.reflect.Modifier;
public class TypeInfo {
/**
* Prints detailed information about an object's type
*/
public static void printTypeInfo(Object obj) {
if (obj == null) {
System.out.println("Cannot determine type: object is null");
return;
}
Class<?> clazz = obj.getClass();
System.out.println("Type Information for: " + obj);
System.out.println("---------------------------");
System.out.println("Class name: " + clazz.getName());
System.out.println("Simple name: " + clazz.getSimpleName());
System.out.println("Package: " + clazz.getPackageName());
System.out.println("Is Array: " + clazz.isArray());
System.out.println("Is Interface: " + clazz.isInterface());
System.out.println("Is Primitive: " + clazz.isPrimitive());
// Get modifiers (public, private, final, etc.)
int modifiers = clazz.getModifiers();
System.out.println("Is Public: " + Modifier.isPublic(modifiers));
System.out.println("Is Final: " + Modifier.isFinal(modifiers));
// Get superclass
Class<?> superClass = clazz.getSuperclass();
System.out.println("Superclass: " + (superClass != null ? superClass.getName() : "none"));
// Get interfaces
Class<?>[] interfaces = clazz.getInterfaces();
System.out.print("Interfaces: ");
if (interfaces.length > 0) {
for (int i = 0; i < interfaces.length; i++) {
System.out.print(interfaces[i].getName());
if (i < interfaces.length - 1) {
System.out.print(", ");
}
}
System.out.println();
} else {
System.out.println("none");
}
}
}
Criando uma Classe de Teste para TypeInfo
Agora, vamos criar outro arquivo chamado TypeInfoDemo.java para testar nossa classe utilitária:
import java.util.ArrayList;
import java.util.List;
public class TypeInfoDemo {
public static void main(String[] args) {
// Test with different types of objects
String text = "Hello, TypeInfo!";
Integer number = 200;
ArrayList<String> list = new ArrayList<>();
// Print type information for different objects
TypeInfo.printTypeInfo(text);
System.out.println();
TypeInfo.printTypeInfo(number);
System.out.println();
TypeInfo.printTypeInfo(list);
System.out.println();
// Try with an array
int[] numbers = {1, 2, 3, 4, 5};
TypeInfo.printTypeInfo(numbers);
}
}
Compile e Execute o Programa
Compile e execute o programa de teste:
cd ~/project/java-type-printing
javac TypeInfo.java TypeInfoDemo.java
java TypeInfoDemo
Você deve ver uma saída detalhada para cada objeto, semelhante a:
Type Information for: Hello, TypeInfo!
---------------------------
Class name: java.lang.String
Simple name: String
Package: java.lang
Is Array: false
Is Interface: false
Is Primitive: false
Is Public: true
Is Final: true
Superclass: java.lang.Object
Interfaces: java.io.Serializable, java.lang.Comparable, java.lang.CharSequence
Type Information for: 200
---------------------------
Class name: java.lang.Integer
Simple name: Integer
Package: java.lang
Is Array: false
Is Interface: false
Is Primitive: false
Is Public: true
Is Final: true
Superclass: java.lang.Number
Interfaces: java.lang.Comparable, java.lang.constant.Constable, java.lang.constant.ConstantDesc
...
Entendendo a API de Reflexão (Reflection API)
Nosso utilitário TypeInfo demonstra o poder da API de Reflexão do Java, que permite que você examine a estrutura das classes em tempo de execução (runtime). A API de Reflexão pode:
- Inspecionar classes, interfaces, campos e métodos
- Determinar os modificadores, tipos de retorno e parâmetros
- Criar novas instâncias, invocar métodos e acessar campos
Embora poderosa, a Reflexão deve ser usada com cuidado, pois pode impactar o desempenho e pode quebrar a encapsulação. No entanto, para fins de depuração e aprendizado, é uma excelente ferramenta para entender o sistema de tipos do Java.