2010-12-08 1 views
9

Y a-t-il un utilitaire open source ou un pot pour gérer la réflexion dans Java?Existe-t-il des utilitaires de réflexion Java ou des fichiers JAR?

Je passe des méthodes dynamiquement à une classe et je voudrais récupérer la valeur de retour.

Par exemple:

class Department { 
    String name ; 
    Employee[] employees; 
    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public Employee[] getEmployes() { 
     return employees; 

    } 
} 

Je voudrais imprimer tous les employés à la sortie de la console, mais plutôt l'obtenir à l'exécution comme ceci:

Department dept = new Department(); 
// add employees.. 

getEmployeeNames(dept,"getEmployees.getAddress.getStreet"); 
// So the user says they want employee street, but we don't know that 
// until run-tme. 

Y at-il opensource sur la réflexion pour accueillir quelque chose comme ça?

+2

'getEmployes()' retourne un tableau? Il n'y aura pas de méthode 'getAddress()' sur un '[]' .. – dacwe

Répondre

5

Ce genre de chose sonne toujours des cloches d'alarme design quand je le vois.

Cela étant dit, je pense généralement que JXPath (http://commons.apache.org/jxpath/users-guide.html) est la solution la plus raisonnable pour ce type de problème si elle ne peut pas être résolu d'une manière plus Engineered:

import org.apache.commons.jxpath.JXPathContext; 

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 

/** 
*/ 
public class JXPather { 
    public static void main(String[] args) { 
     Department d = new Department(); 
     d.employees.add(new Employee(new Address("wherever a"))); 
     d.employees.add(new Employee(new Address("wherever b"))); 
     d.employees.add(new Employee(new Address("wherever c"))); 
     d.employees.add(new Employee(new Address("wherever def"))); 

     JXPathContext context = JXPathContext.newContext(d); 
     // access matched xpath objects by iterating over them 
     for (Iterator iterator = context.iterate("/employees/address/street"); iterator.hasNext();) { 
      System.out.println(iterator.next()); 
     } 

     // or directly via standard xpath expressions 

     System.out.println("street of third employee is: "+context.getValue("/employees[3]/address/street")); 

     // supports most (or all ?) xpath expressions 

     for (Iterator iterator = context.iterate("/employees/address/street[string-length(.) > 11]"); iterator.hasNext();) { 
      System.out.println("street length longer than 11 c'ars:"+iterator.next()); 
     } 
    } 

    static public class Department { 
     List<Employee> employees = new ArrayList<Employee>(); 
     public List<Employee> getEmployees() { 
      return employees; 
     } 
    } 

    static public class Employee { 
     Address address; 
     Employee(Address address) { 
      this.address = address; 
     } 
     public Address getAddress() { 
      return address; 
     } 

    } 

    static public class Address { 
     String street; 
     Address(String street) { 
      this.street = street; 
     } 
     public String getStreet() { 
      return street; 
     } 
    } 

} 
+0

C'est une approche très intéressante. Je ne connaissais pas JXPath jusqu'à maintenant. Ça a l'air très bien! –

+0

Très belle approche. – srinannapa

1

Vous pouvez utiliser une bibliothèque tiers que d'autres suggèrent ou peut faire l'affaire manuellement vous-même, il est pas si difficile. L'exemple suivant devrait illustrer la façon dont on pourrait prendre:

 

class Department { 
    Integer[] employees; 
    public void setEmployes(Integer[] employees) { this.employees = employees; } 
    public Integer[] getEmployees() { return employees; } 
} 

Department dept = new Department(); 
dept.setEmployes(new Integer[] {1, 2, 3}); 
Method mEmploees = Department.class.getMethod("getEmployees", new Class[] {}); 
Object o = mEmploees.invoke(dept, new Object[] {}); 
Integer[] employees = (Integer[])o; 
System.out.println(employees[0].doubleValue());; 
 
20

Outre l'utilisation d'Apache BeanUtils ou en utilisant directement l'API java.lang.reflect, comme d'autres ont suggéré, vous pouvez également utiliser jOOR, que je créé pour la verbosité d'utiliser la réflexion en Java. Votre exemple pourrait alors être mis en œuvre comme ceci:

Employee[] employees = on(department).call("getEmployees").get(); 

for (Employee employee : employees) { 
    Street street = on(employee).call("getAddress").call("getStreet").get(); 
    System.out.println(street); 
} 

Le même exemple avec une réflexion normale en Java:

try { 
    Method m1 = department.getClass().getMethod("getEmployees"); 
    Employee employees = (Employee[]) m1.invoke(department); 

    for (Employee employee : employees) { 
    Method m2 = employee.getClass().getMethod("getAddress"); 
    Address address = (Address) m2.invoke(employee); 

    Method m3 = address.getClass().getMethod("getStreet"); 
    Street street = (Street) m3.invoke(address); 

    System.out.println(street); 
    } 
} 

// There are many checked exceptions that you are likely to ignore anyway 
catch (Exception ignore) { 

    // ... or maybe just wrap in your preferred runtime exception: 
    throw new RuntimeException(e); 
} 

En outre, Joor enveloppe la fonctionnalité java.lang.reflect.Proxy d'une manière plus pratique:

interface StringProxy { 
    String mySubString(int beginIndex); 
} 

// You can easily create a proxy of a custom type to a jOOR-wrapped object 
String substring = on("java.lang.String") 
        .create("Hello World") 
        .as(StringProxy.class) 
        .mySubString(6); 
+0

Très propre et ez-cherche à utiliser, bon travail! –

+0

Cela semble très bien, mais êtes-vous sûr que c'est une bonne idée de généraliser le casting dans les méthodes get()? Je suppose que la signature est ' T get()', qui pourrait causer plus de problèmes qu'un bon vieux casting honnête sur le site d'appel. –

+0

@MartinProbst: Oui, vous avez raison à propos de la signature. Je ne pense pas que ce soit une si mauvaise idée. 'java.util.Collections' a un couple de cas similaires ... –

Questions connexes