I have a utility that scans different classes in the classpath, and checks for unused classes.
Some classes need special treatment, like interfaces and abstract classes. Those can be easily identified using reflection.
The problem arises when trying to identify a class that is an annotation class (i.e. #interface).
Is it possible to know if a class is really an annotation?
Yeah.. It's possible to know if a class is really an annotation.
Please try this:
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#isAnnotation%28%29
http://java.dzone.com/articles/discovering-java-annotations
It may help you
Related
Suppose I have this annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface Name
{
String value();
}
This is going to be used as follows
#Name("name1")
public static Foo foo = new Foo();
I have multiples of these across my project source files. Is there an fairly simple way to search and collect all those "foo"s that're preceded by #Name?
In other words, I'd like to write a method that would return a Set<Foo> containing these.
Thanks!!!
I am not really familiar with the classpath scanners that others are suggesting. They seem like a robust - if not ideal - solution.
If you have control over the source, then you could use annotation processing.
Create an annotation processor that will create a class - MapClass with a static member Map<String,Foo>. Every time the annotation processor encounters the #Name annotation, it adds that to the source code of MapClass. When it finishes processing the annotations, it will have the same effect as if you hard coded the map.
Annotation processing happens during compile time. If some of the classes in your project are not compiled by you. For example, if someone else compiles some classes and gives a jar to you, then it won't work as easily. But if all the classes are compiled by you then it should not be a problem.
To create an annotation processor, extend AbstractProcessor. You will want to annotate your class with a # SupportedAnnotationTypes ( "Name" ) annotation (make sure name is the fully qualified name of your annotation.
Override the process method. process has two parameters: annotations and roundEnv. annotations is just the set of annotations that this particular processor supports - in your case it should be (Name). roundEnv is a useful utility class.
Iterate through the one annotation in annotations. Use roundEnv to getElementsAnnotatedWith. This should give you the set of all elements that carry the #Name annotation.
AbstractProcessor has another utility member - processingEnv. Use its getFiler method to createSourceFile.
Then you have to modify your compilation a little bit. You must compile your processor separately and before the other classes. After the processor is compiled and you are compiling the other classes you must tell the compiler about your processor. If you are using the command line you would add -processorpath /path/to/processor/class[es] and -processor qualified.name.of.processor.
The advantages of this approach over the class path scanner is that everything happens at compile time. So for example, if you accidentally add a #Name annotation to a Bar element, then you can have the processor throw a compile time error (if you wish the processor can ignore it). Then you can fix it before the product ships. With a class path scanner, any error thrown is a run time error - which the user will see.
The disadvantage of this approach is also that everything happens at compile time. This makes it harder to dynamically add classes to the project.
What you need is a Classpath scanner. I have used Metapossum Scanner (it won out because it is in the mvn repo) to scan for annotated Classes, but I do not think it would scan for annotated Fields.
The other option I looked into was Reflections. I have not used Reflections, only researched it. The documentation has a getFieldsAnnotatedWith query that seems like what you need.
Be forewarned, the Classpath scanners are slooow and get slooower the more you have in your Classpath.
No not really (not from code).
A solution would be to put them all in a class, and then iterate on the Fields (getFields()) of the class and check for Annotations (getAnnotation())
You may want to have a look at Scannotation! It may solve your problem!!!
Scannotation is a Java library that creates an annotation database from a set of .class files. This database is really just a set of maps that index what annotations are used and what classes are using them.
PS.: VRaptor framework uses it internally!
I'm working with java. I have an interface that has an annotated method in it. Is there a way to access that annotation in a class implementing that interface?
Thanks.
Edit: sorry, I shoudl've been clearer: I'm using reflection to access elements of Java, and I'm wondering how to access the annotations in a class implementing an interface (where the annotation is declared).
Sure. Reflection allows you to check for the presence of an annotation. There are methods at the class, method, paramter levels: reflection and annotations
Using reflection you can get pretty much everything relating to a class. You can get all the declared methods, fields and classes (and possibly even more), but i couldn't find a way to reflect on a method so i could find out what classes that method might be using.
Essentially i would like to find out all dependencies to other classes that a given class has.
Example:
Given the following code:
import com.yada.yada.yada.SomeClass
public class MyClass
{
public MyClass
{
new SomeClass();
}
}
How can i find out that MyClass is using SomeClass in its constructor?
I was trying to think of a way to get all import statements defined in a class file but i couldn't find anything that way either. But, assuming there's a way to somehow dig up all import statements defined in a class file, how would one find out about classes defined in the same package, which do not require an import statement?
EDIT:
Scenario: The goal is to send the bytecode of this class (MyClass) to another process. This other process then takes in the bytecode and loads the class (MyClass) using class loaders, and so on. The problem is that when i try to create and run an instance of MyClass in the other process it fails because it cannot find a definition for SomeClass.
If SomeClass were a member of MyClass it wouldn't be a problem but since the only reference to it lies in a method, there's no way to get to it via reflection?
I think the closest you can come to getting all of a class's dependencies is by hooking into the class loader mechanism and recording what classes get loaded when the class you're examining is instantiated and its methods are called. Of yourse, you'd transitively also get all the classes that it indirectly depends on, but depending on what you want to do with the information, that may be what you actually need.
But it's impossible to do for all cases (just imagine a method that uses Class.forName() to ask for a random class name every time it's called).
how would one find out about classes defined in the same package
That's actually impossible to do in general, since the class loader concept really only allows asking for a fully qualified class name, and either getting that class or a ClassNotFoundException. Classes can be loaded from a webserver (in the case of applets) or generated on the fly, so you cannot know whether a specific class exists except by asking for it.
You can't (unless you decompile the bytecode). A local variable is not tied to any class instance, and it does not even exist for most of the lifetime of the class or its instances, so you can't access it via reflection.
What are you trying to achieve? Maybe if you tell us about your actual problem, rather than a perceived solution, we are better able to help.
Reflection does not help you here. The only way I can think of that you can achieve this is through a byte code tool like asm.
Create a ClassVisitor that gathers dependencies from
Class declarations
Annotations
Local variable declarations
Field declarations
Method declarations
Method invocations
(have I forgotten anything?)
I'm writing a functionality where it would be helpful to get the classes inside a certain package of my program. Also, I only want the classes that subclass a certain class.
I need the classes in order to call static methods on them.
Is there an automatic way to do this? If so, is it slow?
In case I was not clear, what I want is something like this:
ArrayList<Class<? extends MySuperClass>> classes = ;
classes.add(MyClass.class);
classes.add(MyClass2.class);
Instead of having to call add for each class, I would like to automatically get that class list.
The number of classes is small, so I would not mind declaring them manually if the automatic trick would be slow - this app is for a mobile platform.
In either way, I would also like to know how to call the static method for each method in the ArrayList:
// error The method nameOfStaticMethod is undefined for the type Class<capture#2-of ? extends MySuperClass>
classes.get(0).nameOfStaticMethod ();
Thanks for your comments.
Java doesn't provide this ability. There is no introspection at the package level. The classes could be records in a database, or on the other side of a network connection. There's no requirement for them to be stored and organized so as to facilitate enumerating them by package.
You could make a custom class loader and API to provide a method of listing the class names.
I too would like to list all classes in a package but so far the methods of doing this is pretty bad:
Like JOTN suggested - needs file access - not if it is a jar
Listing a JAR entries - well, also needs the jar file
Quoting a older SO question:
It isn't possible to query a Package for it's Classes (or even its subpackages). http://forums.sun.com/thread.jspa?threadID=341935&start=0&tstart=0 contains a very good discussion about why this is problematic, as well as a handful of solutions to your problem.
Anyways, here is how you invoke static methods on the class:
Method m = Integer.class.getMethod("toString", Integer.TYPE);
System.out.println(m.invoke(null, 123));
I have two Strings:
String a="org.test.A";
String b="org.test.B";
I get a class by Reflection
Class aClass = Class.forName(a);
I want aClass extends b, like:
Class okClass=aClass.extends(b);//how to implement this?
how to implement this?
how to get okClass?
thanks!
Apart from using a JDK dynamic proxy, which works only by interface, you can use CGLIB or javassist for extending classes at runtime.
Generally speaking you want to be able to create new classes (not objects) at runtime. You can use bytecode engineering or java compiler api for that.
You could start by reading up on dynamic proxies. Proxies do not extend classes, but they do implement interfaces which you can map on your class implementation through the invocation handler.
As said before I'd recommend to look at CGLIB but there is also javassist which is a class library for editing bytecodes...