getClass () et les méthodes statiques: quelle est la meilleure pratique?
-
03-07-2019 - |
Question
Je cherche à apporter une certaine commodité en réfléchissant aux programmeurs qui utiliseront mon code. Pour obtenir le résultat souhaité, je souhaite obtenir l’objet classe des classes qui étendent mon code. Même s'ils ne peuvent pas remplacer la méthode statique à partir de laquelle je souhaite accéder aux informations, cela serait actuellement utile. Je vais peut-être simplement refacturer un peu le design pour éviter cette situation, mais je voulais lancer cette question à la communauté.
Le seul moyen d'y parvenir que je sache est de prendre le thread actuel, de parcourir la trace de la pile et d'extraire le nom de la classe, puis de le convertir en une instance réelle de la classe.
D'autres suggestions?
Note latérale: l’approche ci-dessus est également la seule façon pour moi d’obtenir la méthode d’appel.
La solution
Lorsque vous utilisez la méthode statique, quelle est la garantie qu'une classe (n'importe laquelle) qui a été étendue à partir de la vôtre est sur la pile?
Si vous y réfléchissez un peu, je suppose que vous réaliserez que ce que vous recherchez n'existe pas.
/ EDIT 1 / Je pense que ce dont vous avez besoin est
abstract class B {
<T extends B> B create(Class<T> clazz) {
....
}
Hmmm. Que faire si create
est la méthode protected
? Ensuite, vous pouvez être à peu près certain que l'appelant est un B
, vous pouvez même l'exiger en lançant UnsupportedOperation
ou IllegalState
si l'appelant n'est pas assignable. B
.
Vous pouvez utiliser Thread.currentThread (). getStackTrace ()
Autres conseils
Malheureusement, marcher dans la pile n'est pas forcément sûr:
À partir de la Javadoc JDK 6 pour getStackTrace:
Certaines machines virtuelles peuvent, sous certaines circonstances, omettez une ou plusieurs piles cadres de la trace de la pile. dans le cas extrême, une machine virtuelle qui n'a aucune information de trace de pile concernant ce jetable est autorisé pour renvoyer un tableau de longueur nulle à partir de cette méthode. De manière générale, le tableau retourné par cette méthode contenir un élément pour chaque image qui serait imprimé par printStackTrace.
Vous pouvez peut-être utiliser l’API du débogueur pour le faire. Je crois que le processus de débogage est capable d’utiliser HotSpot à pleine vitesse (je peux me tromper) afin que vous ne voyiez pas un impact de vitesse énorme pour le faire. Vous pourriez commencer par regarder: http: // java .sun.com / javase / 6 / docs / technotes / guides / jpda / trace.html
En outre, en vous appuyant sur la réponse à la question Sans réponse ...
class Base
{
// instance method helper
public final int foo()
{
return (foo(this.getClass()));
}
// the real helper, with access to the class
private static int foo(final Class clazz)
{
return (0);
}
}
class Child
extends Base
{
public void bar()
{
final int x;
x = foo();
}
}
Créer un Throwable est très coûteux, donc ne l'utilisez pas si votre méthode est appelée souvent (par exemple plus d'une fois par seconde). Thread.currentThread (). GetStackTrace ().
Si vous utilisez la machine virtuelle Java de Sun, une autre approche est Reflection.getCallerClass (n). C'est beaucoup plus rapide mais pas portable vers d'autres machines virtuelles. Si cela vous préoccupe, vous pourriez avoir une autre méthode qui appelle cela si elle est disponible et utilise sinon la trace de la pile.
Tout cela suppose que votre méthode statique n'est PAS publique. Si tous les paris sont ouverts, votre méthode peut être appelée par n’importe quelle classe, et non par une seule qui étend la vôtre.
Je suggère d'éviter le bourbier de la réflexion. Vous semblez faire une sorte de programmation simple. Utilisez une implémentation simple (il n’ya pas assez d’informations pour permettre de deviner ce que cela pourrait être).