Dynamique De La Coulée À L'Aide De Java Réflexion
J'ai deux classes, comme suit:
public class Person {
private String dob;
private PersonName personName;
}
public class PersonName {
private String firstName;
private String lastName;
}
Je suis la définition de ces valeurs de manière dynamique à l'aide de Java Réflexion.
Tout d'abord, je crée une instance de Person
et j'ai mis la valeur de dob
. Après cela, j'ai besoin de mettre un PersonName
valeur dans Person
. J'ai donc créé une autre instance de PersonName
et j'ai mis les valeurs que PersonName
. Après cela, je suis en train de mettre la PersonName
exemple dans le Person
entité.
Pour cela j'ai utilisé un code comme ceci:
Class componentClass = Class.forName(clazz.getName());
Field field = parentClass.getDeclaredField(Introspector
.decapitalize(clazz.getSimpleName()));
field.setAccessible(true);
field.set(parentClass, componentClass);
Ici, parentClass
est un Person
instance et componentClass
est un PersonName
instance. Je suis en train de mettre la PersonName
dans le Person
, mais je suis l'exception suivante:
java.lang.IllegalArgumentException: Can not set com.rise.common.model.PersonName field
com.rise.common.model.Person.personName to java.lang.Class
Alors, comment puis-je définir les valeurs dynamiquement?
Grâce.
Tout Mon Code:
protected void assignProperties(List<Object[]> argResults,
List<Class> argAllClassesList, Class argParentClass)
throws ClassNotFoundException, NoSuchFieldException,
SecurityException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException, InstantiationException {
List<Object[]> results = (List<Object[]>) Precondition.ensureNotEmpty(
argResults, "Output List");
List<Class<?>> personClassList = new ArrayList<Class<?>>();
for (Object[] recordValues : results) {
Class parentClass = Class.forName(this.getPersistentClass()
.getName());
parentClass.newInstance();
int count = 0;
count = assignValues(recordValues, parentClass, count);
for (Class clazz : argAllClassesList) {
Class componentClass = Class.forName(clazz.getName());
componentClass.newInstance();
String decapitalize = Introspector.decapitalize(clazz
.getSimpleName());
Field field = parentClass.getDeclaredField(decapitalize);
field.setAccessible(true);
assignValues(recordValues, componentClass, count);
field.set(parentClass, componentClass);
}
personClassList.add(parentClass);
}
for (Class<?> class1 : personClassList) {
Class<Person> person = (Class<Person>) class1;
System.out.println(person);
}
}
private int assignValues(Object[] argRecordValues, Class argClass,
int argCount) {
String paramName = Introspector.decapitalize(argClass.getSimpleName());
if (Precondition.checkNotEmpty(paramName)) {
List<Field> fieldNames = TenantConfigHelper.getInstance()
.getModelNameVsFieldsMap().get(paramName);
try {
for (Field field : fieldNames) {
BeanUtils.setProperty(argClass, field.getName(),
argRecordValues[argCount]);
++argCount;
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
return argCount;
}
Class.forName(clazz.getName())
semble un peu redondant.Hay Paul, Pourquoi sa redondant..?
Vous avez la classe, et que vous êtes en lui demandant ce nom, afin d'obtenir la classe qui a ce nom. Mais vous avez eu depuis le début.
Class.forName(clazz.getName()) == clazz
.Java réflexions n'est pas simple. Il nécessite une bonne compréhension de base de la distinction entre les différents concepts de classe, d'exemple, de référence, de la valeur, membre, etc. Et, en particulier, la documentation pour le java.lang.refléter les classes nécessite TRÈS prudent de la lecture, même pour quelqu'un qui est assez à l'aise avec la terminologie. Ralentir et prendre le temps de comprendre.
OriginalL'auteur Amar | 2013-08-01
Vous devez vous connecter pour publier un commentaire.
Je pense qu'il peut y avoir une certaine confusion sur la différence entre Java définitions de classes et d'instances à l'œuvre ici. Vous souhaitez définir les valeurs des champs de cas particuliers, pas les classes elles-mêmes. Quelque chose comme cela peut fonctionner:
En regardant l'exemple de code entier, cependant, il est un peu difficile à suivre. Pourquoi avoir une
List
deClass
es, avec un nom commepersonClassList
, ce qui semblerait indiquer que chaque classe doit être la même classe,Person
? Je sens qu'il devrait probablement être plutôt uneList<Person>
ou peut-êtreList<Object>
, qui vous permettraient d'alimenter avec votrePerson
cas, pas de laClass
objets eux-mêmes.Modifier pour répondre à la question suivante en commentaire:
Vous ne pouvez pas lancer de
Class
àPerson
, depuisPerson
est probablement pas une sous-classe deClass
.Au lieu de cela, déclarer votre liste comme un
List<Person>
au lieu d'unList<Class<?>>
Puis ajouter le
Person
objets au lieu de lesClass
objets de votre liste en bas de votre premièrefor
boucle.Et la boucle à l'arrière doivent changer:
Édité pour répondre à votre question.
OriginalL'auteur user506069
Le message explique ce qu'est le problème: componentClass n'est pas un instance de PersonName. C'est un objet de type
Class
(probablementClass<PersonName>
). Vous avez probablement oublié d'instancier la classe.Edit:
Votre code:
et
C'est l'équivalent de faire
et
De sorte qu'il crée une instance, mais ne pas l'affecter à une variable quelconque, et n'a donc pas faire n'importe quoi avec l'instance créée, qui sera ordures exigible immédiatement.
Vous voulez
Class.forName()
renvoie la classe (c'est à direPersonName.class
). Pas une instance de cette classe (c'est à direnew PersonName()
). Pour obtenir une instance, vous devez appeler un constructeur.J'ai fait la classe.méthode newInstance (). Mais j'ai oublié de mentionner cette étape. Désolé pour ça.
Peut-être que vous avez fait, mais votre code est toujours mauvais. Sans le voir, nous ne pouvons pas vous dire où et pourquoi. Tout ce que nous savons, c'est que componentClass est de type Classe dans le code que vous avez posté. Si vous êtes de passage d'une Classe, et non pas une instance.
Hay JB Nizet j'ai juste collé mon code entier et pouvez-vous s'il vous plaît dites-moi le problème, mais enfin j'ai besoin de retour à la "Liste<Personne>" les objets...
OriginalL'auteur JB Nizet
J'étais à la recherche de ce même type de réponse et, fondamentalement, ce que tout le monde est de spécifier avec l'Objet est correct. J'ai également créé une liste générique comme
List<Object>
au lieu du nom de la classe réelle. Ci-dessous est une fonction qui retourne une Liste de type de l'Objet. Je passe le nom de la classe et de la charge que avec la .loadClass. Que de créer un nouvel objet avec cette nouvelle instance de classe avec le .newInstance. Le dList est chargé avec toutes les informations pour chaque objectClass qui est la classe je passe avec celui de la classe de la variable. Le reste est fondamentalement juste dynamiquement en invoquant tous les "set" méthodes au sein de la classe particulière avec les valeurs de l'ensemble de résultats.instanceOf
pourrait également être utile ici.OriginalL'auteur PaperBeatsRock-PFFFT
Le système de type est vérifié par le compilateur. Alors qu'il y a plus de sécurité possible lors de l'exécution, que la sécurité supplémentaire est même pas proche de la sécurité le compilateur impose. Ce qui pose la question, Pourquoi?
En supposant que vous pourriez obtenir les choses à travailler, exactement comment voulez-vous être en mesure de justifier de la coulée
class1
ci-dessous dans unClass<Person>
type? Vous déclaré unClass<?>
!Il me semble que vous voulez dynamique de la vérification de type. Si oui, vous ne pouvez pas utiliser Java de la Classe du système; car, il est destiné à imposer la vérification des types statiques. Juste faire tout un Objet, comme c'est le seul type qui tout des actions, et puis les écrire dans votre propre code pour vérifier quel que soit le système que vous mettre en œuvre pour vérifier les types à l'exécution. Mais, s'il vous plaît, arrêter d'essayer de faire l'exécution dynamique il existe des types de manière statique. Il ne fonctionnera pas.
OriginalL'auteur Edwin Buck