Is it possible to write a Java annotation for a class that generates a method that overrides the class's parent method?
In my case I want to do it in android:
#OverrideOnTouch
class Foo extends Activity {
And it will generate an onTouch override method in compile time.
Is it possible?
An annotation cannot generate code.
You could write an annotation processor that added a method at compile time wherever it found your annotation.
Here is a tutorial on this subject:
Annotation Processing 101.
However, beware that writing an annotation processor is a significant amount of Java coding work. Also note that an annotation processor (implemented using the AnnotationProcessor API and called via the Java compiler) cannot modify Java source code. It can only generate new ".java" files.
So, if you want to inject new method into an existing class, you would need to compile the class, and then use a post-compilation annotation processor that used BCEL or equivalent to add the required methods to the ".class" files produced by the compiler. Implementing a BCEL-based processor is ... even harder. And such processors have a tendency to break when you upgrade Java. (It is easy to make assumptions about the JVM / bytecode level implementation that are not supported by the relevant specs ... and no longer "work" when the platform changes.)
This approach is mentioned in some of the answers to this Question:
How to write a Java annotation processor?
Related
The documentation for Reflections gives the first line on how to use Reflections:
Reflections reflections = new Reflections("com.my.project");
Except i don't know the name of the package. This is a piece of library code that should just be able to scan everything in the current package.
What is the Reflections equivalent of the .NET:
//Find all methods in all classes tagged with #Test annotation,
//and add them to a list.
List<MethodInfo> testMethods = new ArrayList<>();
//Enumerate all assemblies in the current application domain
for (Assembly a : AppDomain.currentDomain.getAssemblies()) {
//Look at each type (i.e. class) in the assembly
for (Type t : a.getTypes()) {
...
}
}
in other words, the "current" package? Or in the parlance of .NET
AppDomain.currentDomain
Edit:
Is it a duplicate? No.
Is it not a programming question? No
Does it need details or clarity? No
Does it need more focus? No
Is it opinion based? No
Bonus Reading
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
And the final straw:
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies
Java's concept of 'package' is much weaker than .net. In Java, the package containing a class is, for most purposes, just the prefix of the classes name.
OSGi, and recent Java versions with Modules, have a stronger model.
If you read down the documentation to https://github.com/ronmamo/reflections#scan, you will see that there are a number of filters that you can apply to control what this library looks at. If you are writing a library, you can either expose that API to your callers and let them tell you what classes to look at, or decide for yourself what to look at. But there is not requirement to have a single focal Java package as far as I see in that documentation.
Calling this.getClass().getPackage().getName() will mean that reflection is only looking at your code, not the rest of the application using your library.
Cannot be done.
Java does not have a reflection system.
Research Effort
Get all methods with a particular annotation in a package (Question isn't about the current package. Accepted answer uses 3rd party library.)
Java seek a method with specific annotation and its annotation element (Question is about a specific class, rather than finding the classes)
How to find annotated methods in a given package?
How to run all methods with a given annotation?
getConstructor with no parameters
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
Default access modifier for a Java constructor
Can you find all classes in a package using reflection?
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
Additional research effort
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies
Oracle: Handling Initialization Status With Event Handlers
how to register a java class if the static initializer isn't called till the class is referenced
Dynamic object registration in Java
getConstructor with no parameters
Load Jar dynamically and register class(es) in applicationContext at runtime
Is it possible to determine descendants solely through Java reflection API?
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
At runtime, find all classes in a Java application that extend a base class
Default access modifier for a Java constructor
Find Java classes implementing an interface
Finding all classes implementing a specific interface
How does JUnit find tests?
Book: Unit Testing in Java
[2/28/1998: JUnit 1.0][2]
JUnit Cookbook
How can I get a list of all the implementations of an interface programmatically in Java?
How can I get all Class files in a specific package in Java?
Class Loaders in Java
How can I enumerate all classes in a package and add them to a List?
Java Reflection - Get List of Packages
Getting the list of packages in a java project
Tool to convert java to c# code
Package Initialization in Java
How to write a package-level static initializer in Kotlin?
https://stackoverflow.com/questions/72795950/java-initialize-all-classes-in-package-without-knowing-names
https://github.com/classgraph/classgraph
What is an initialization block?
Package Initialization in Java
I'm trying to create an annotation processor that works on top of realm.io
Sadly to use realm you need an android project, while to create an annotation processor you need a java one (in order to import javax.annotation.processing.*)
Anyone know a way to import AbstractProcessor and all the other needed stuff on an android library? I can't find I way to do this (already switched targetCompatibility and sourceCompatibility to 1.7)
a way to import AbstractProcessor and all the other needed stuff on an android library
The better question is: why do you want that?
If you are under impression that your processor would depend on Realm classes (or any other Android classes), — that's not the case. When you write code, that uses APT Mirror API, you don't have to reference those classes directly, only by names. The resulting code will look like this:
DeclaredType theBinder = lookup("android.os.Binder");
DeclaredType theIInterface = lookup("android.os.IInterface");
DeclaredType theCreator = lookup("android.os.Parcelable.Creator");
...
private DeclaredType lookup(CharSequence name) {
return types.getDeclaredType(elements.getTypeElement(name));
}
You will then proceed to manipulate created TypeMirrors by using methods of Types and Elements utility classes. You can also convert those mirrors to alternative formats, such as Square's JavaPoet TypeName, but you really don't have to, because Mirror API provides most facilities you may ever need.
You definitely don't want to load Realm's classes inside your annotation processor. Firstly, there is simply not need for that. But more importantly, as you pointed out in the question, it is often not possible to share the same setup between annotation processor and it's runtime appliances. This issue isn't unique to Android, — for example, nobody expects to set up full-blown application server to compile a server program, that uses JAXB-aware annotation processor.
If you really want some piece of code from Realm in your processor, and it is not available as separate Java library, the simplest way is to just copy that code to your processor.
What I have known are:
annotation was added in java 5
annotation can be using in method, class, and property
annotation can work in RUNTIME, CLASS, SOURCE( I don't know how to work with CLASS and SOURCE, and their's features)
annotation with retention which is RUNTIME can be implement when java program is running.
And I want to implement a annotation to have follows features:
ensure class only being allowed to create a instance
ensure methods only being allowed to access method in the class
it is like as friend in c++
it is same as public and private , but more dynamicall, like
#MyAnnotation(allowMethods={xxx.doSomething})
public void getValue(){}
the getValues method only can be accessed in the instance self and xxx.doSomething() method
What should I do and learn in next?
And Where can I learn about these?
I think you might be misunderstanding something there. Annotations are descriptive elements, not parts of your program. You can write as many annotations as you want, and people who use your code will still be able to ignore them.
That said, an annotation that enforces a policy (as yours does) can actually be implemented, either at compile or at runtime, but you need an external mechanism to help you. I can think of 3:
Annotation processing lets you interact with the compiler and process annotations by generating code or by omitting compiler errors. Unfortunately, I don't think it will work for your case, as you want to protect your annotated type from instantiation, and that means the call site doesn't actually have an annotation. Annotation processing only gives you access to the actual code pieces that have annotations, not to those that refer to them.
AspectJ allows you to write policy enforcement aspects and omit compiler errors, based on static pointcuts. The problem here is that static pointcuts have very limited semantics, so while you could forbid the instantiation of your class altogether, or from certain packages, you could not limit the your class instantiations to 1.
The third way, and probably the only sane way is that you use a container like Spring or Guice and configure your class as singleton. As long as you only retrieve your class from the container, it will never create a second instance.
Finally: If you want to limit the number of instantiations of your class, you can always use a classic Singleton pattern approach.
I've implemented some custom runtime method annotation. Now I want to check (preferably in compile-time) that all methods which were marked with my newly implemented annotation are static and have only one serializable argument. How can I archive it in Java 7?
You can use annotation processing to do that. Run javac with proc, processor and processorpath option and implement a Processor that does all the checking you want.
Note that you can't enforce others to use these options, so you should still include appropriate runtime checking.
I have created an annotation, applied it to a DTO and written a Java 1.6 style annotationProcessor. I can see how to have the annotationProcessor write a new source file, which isn't what I want to do, I cannot see or find out how to have it modify the existing class (ideally just modify the byte code). The modification is actually fairly trivial, all I want the processor to do is to insert a new getter and setter where the name comes from the value of the annotation being processed.
My annotation processor looks like this;
#SupportedSourceVersion(SourceVersion.RELEASE_6)
#SupportedAnnotationTypes({ "com.kn.salog.annotation.AggregateField" })
public class SalogDTOAnnotationProcessor extends AbstractProcessor {
#Override
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
//do some stuff
}
}
You are looking for "Instrumentation", which is what frameworks like AspectJ do. In this case you have to specify a jar in the command line with the "-agent" option, and then have the possibility to filter all loaded classes. During this filter step you can check for annotations, and modify the bytecode before it gets loaded in the virtual machine. Libraries for doing the actual bytecode modification include "asm", and maybe the highlevel wrappers "cglib" and "javassist". You could even precompile your classes to generate a list of classes which have to be instrumented by you, to make filtering in the beginning a bit faster.
See java.lang.instrumentation for more info.
By design, the annotation processing facility does not allow direct modification of the source code being processed. However, one can generate subclasses of the type being processed or the superclass of the type being processed. With some planning, this does allow some of the effect of modifying the type in question. I've written up an example of how this can fit together; see this blog entry for a more detailed explanation and some sample code.
You have to use internal compiler's classes – some inspiration:
AOP or APT for overriding methods from super classes
RomanNumeralProcessor.java
Java Multiline String
But it is brinkmanship. Your program will compile only on Sun/OpenJDK and there can be problems in future versions (internal API can change). Although once compiled, it is standard bytecode and will run everywhere.
BTW: if you want use it in Eclipse, you should add some special support for it because Eclipse uses non-standard compiler. Your design should be more complex and you should add a level of abstraction to your processor – like Lombok does.
You have to extend the javac compiler for this, which means building your program won't be as portable as a regular application. See http://weblogs.java.net/blog/cayhorstmann/archive/2006/06/say_no_to_prope.html for more details on how someone achieved this.