I have created a class in java as following:
public class TestAnnotations {
#Retention(value=RetentionPolicy.RUNTIME)
#Target(value=ElementType.FIELD)
protected #interface Addition
{
String location();
}
}
How can I get information about the annotation defined in the class using reflection. To be more specific, I am looking for the information like what is the type of Addition, of course name and its fields in it.
You can use Class#getDeclaredClasses() which
Returns an array of Class objects reflecting all the classes and
interfaces declared as members of the class represented by this Class
object.
You can then iterate over the array, check that that class is an annotation with Class#isAnnotation().
Example
public class Driver {
public static void main(String[] args) throws Exception {
Class<?>[] classes = Driver.class.getDeclaredClasses();
System.out.println(Arrays.toString(classes));
for (Class<?> clazz : classes) {
if (clazz.isAnnotation()) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
}
#Retention(value=RetentionPolicy.RUNTIME)
#Target(value=ElementType.FIELD)
protected #interface Addition
{
String location();
}
}
prints
[interface com.spring.Driver$Addition]
public abstract java.lang.String com.spring.Driver$Addition.location()
Related
When I get method from class instance, and want to get #override annotation.
but method has not any annotation.
Is it impossible to get #override annotation?
code is below.
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import javax.annotation.Resource;
public class ReflectionTest {
public static void main(String[] args) throws Exception {
ChildHoge childHoge = new ChildHoge();
Method method = childHoge.getClass().getMethod("init");
for (Annotation s : method.getAnnotations()) {
System.out.println(s);
}
Method method2 = childHoge.getClass().getMethod("a");
for (Annotation a : method2.getAnnotations()) {
System.out.println(a); // =>#javax.annotation.Resource(mappedName=, shareable=true, type=class java.lang.Object, authenticationType=CONTAINER, lookup=, description=, name=)
}
}
}
class SuperHoge {
public void init() {
}
}
class ChildHoge extends SuperHoge {
#Override
public void init() {
super.init();
}
#Resource
public void a() {
}
}
#Retention(RetentionPolicy.SOURCE)
public #interface Override {
}
It has RetentionPolicy.SOURCE which are discarded by the compiler, which means it cannot be obtained at runtime. You can see this described in JLS 9.6.4.2.
If an annotation a corresponds to a type T, and T has a
(meta-)annotation m that corresponds to
java.lang.annotation.Retention, then:
If m has an element whose value is
java.lang.annotation.RetentionPolicy.SOURCE, then a Java compiler must
ensure that a is not present in the binary representation of the class
or interface in which a appears.
And the Javadoc for RetentionPolicy also describes this:
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
...
You can use Reflection API to check if the method is overridden or not
e.g.
class.getMethod("myMethod").getDeclaringClass();
If the class that's returned is your own, then it's not overridden; if it's something else, that subclass has overridden it.
I can't seem to use getConstructor for constructors with no parameters.
I keep getting the following exception:
java.lang.NoSuchMethodException: classname.<init>()
Here is the code:
interface InfoInterface {
String getClassName();
String getMethodName();
String getArgument();
}
class asa implements InfoInterface {
#Override
public String getClassName() {
return ("jeden");
}
#Override
public String getMethodName() {
return ("metoda");
}
#Override
public String getArgument() {
return ("krzyk");
}
}
class Jeden {
Jeden() {
System.out.println("konstruktor");
}
public void Metoda(String s) {
System.out.println(s);
}
}
class Start {
public static void main(String[] argv) {
if (argv.length == 0) {
System.err.println("Uzycie programu: java Start nazwa_klasy nazwa_klasy2...");
return;
}
try {
for (int x = 0; x < argv.length; x++) {
Class<?> c = Class.forName(argv[x]);
InfoInterface d = (InfoInterface) c.newInstance();
String klasa = d.getClassName();
String metoda = d.getMethodName();
String argument = d.getArgument();
Class<?> o = Class.forName(klasa);
// o.newInstance();
Constructor<?> oCon = o.getConstructor();
System.out.println("ASD");
Class<?> p = (Class<?>) oCon.newInstance();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
o.newInstance(); prints "konstruktor" without problems.
The problem is clear when you read the javadoc of .getConstructor():
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.
Emphasis mine.
In your code, the constructor is not public!
Example:
// Note: class is NOT public -- its default constructor won't be either
final class Test
{
public static void main(final String... args)
throws NoSuchMethodException
{
// throws NoSuchMethodException
Test.class.getConstructor();
}
}
Obligatory link to an SO answer which also gives the JLS reference. In particular, note that the default constructor has the same access modifier as the class.
It seems as if your class provides a constructor that is NOT a default constructor. The call to getConstructor() without parameters requires the class to have a default constructor. The following test illustrates this.
import org.junit.Test;
public class ConstructorTest {
public static class ClassWithParameterizedConstructor {
public ClassWithParameterizedConstructor(final String param) {
// A parameterized constructor, no default constructor exists
}
}
#Test
public void testFoo() throws NoSuchMethodException {
// Parameterized constructor lookup works fine
ClassWithParameterizedConstructor.class.getConstructor(String.class);
// This doesn't work since there is no default constructor
ClassWithParameterizedConstructor.class.getConstructor();
}
}
So, a possible solution is to either change the call to getConstructor() to include the correct type or to provide a default constructor on the object itself (but why would you do that?).
Read this: http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html
It seems that both classes Class and Constructor have the method newInstance the difference is that in the Class class you can only call newInstance with no arguments, so the called constructor must have an no arguments (this also brings a problem when you have more that one constructor).
The methoe newInstance in the Constructor class allows you to call the constructor with arguments also, notice that you can also use the method getConstructors instead of getConstructor that returns you all the class constructors and allows you to call the constructor method you want.
In this case, since you only have one constructor only and with no arguments, Class.newInstance works fine. To use the getConstructor to have the same result you'll need to add in the end oCon.newInstance();
You can use getDeclaredConstructors() which returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object
class SomeClass{
{
System.out.println("I'am here!");
}
}
public class Main {
public static void main(String[] args) throws Exception{
System.out.println(Arrays.toString(SomeClass.class.getDeclaredConstructors()));
// returns public, protected, default (package) access, and private constructors
// System.out.println(SomeClass.class.getConstructor());
// in that case you got:
// NoSuchMethodException: reflection.SomeClass.<init>()
// because SomeClass don't have public constructor
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
constructor.newInstance();
}
}
}
And if you have private constructor like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
You have to set accessible for constructor:
constructor.setAccessible(true);
And get something like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
public class Main {
public static void main(String[] args) throws Exception{
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
// constructor.newInstance("some arg"); // java.lang.IllegalAccessException
constructor.setAccessible(true);
constructor.newInstance("some arg");
}
}
}
Note: if your class declared as private his default constructor must be private too.
And be careful with nonstatic-inner classes, which receives an outer class instance
In this (somewhat convoluted) scenario, it's actually possible to get hold of the (non-public) constructor by replacing:
Constructor<?> oCon = o.getConstructor();
with
Constructor<?> oCon = o.getDeclaredConstructor();
The "default" visibility of the Jeden class (and its constructor) makes it accessible to the Start class, since it's defined in the same package.
The Classes simplified:
public abstract class AbstractFieldGroupBind<T> {
public Class<T> beanClass;
public BeanFieldGroup<T> binder;
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<T>(beanClass);
binder.bindMemberFields(vaadinComponent);
}
public class StammdataEditFGB extends AbstractFieldGroupBind<Cinema> {
public void pushItem(Item item) {
binder.setItemDataSource(item);
}
}
Now I try to invoke the method "initGroupBinder" by a composer Class.
If invoke the method like:
Method method = theFGBClass.getClass().getSuperclass().getDeclaredMethod("initGroupBinder", Object.class);
method.invoke(....)
If will call the class but without the Type . It will not work like this.
I also can get the generic superclass and there I find the type set in extends.
But how to bring it together to invoke the method like:
public void initGroupBinder(Object vaadinComponent){
binder = new BeanFieldGroup<Cinema>(Cinema.class);
binder.bindMemberFields(vaadinComponent);
}
ADD: I get the class "StammdataEditFGB" in the composer via Spring by context.getBean(). This construct run in a Spring Context. So also a solution with Spring's ReflectionUtils is very welcome.
Found the solution! There 2 Problems.
1. getDeclaratedMedothod will not find methods there are in extented Classes. By using getMethod you will get methods (methods must be public) in Abstract Classes.
Here a small example to show.
public class Test {
public abstract class AbstractPerson{
public void callMe(){
System.out.println("Method callMe() in AbstractPerson");
}
}
public class Person extends AbstractPerson{}
public static void main(String[] args) {
Test test = new Test();
Person person = test.new Person();
try {
Method method;
System.out.println("### Use getMethod");
method = person.getClass().getMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
System.out.println("### Use getDeclaredMethod");
method = person.getClass().getDeclaredMethod("callMe", (Class<?>[]) null);
method.invoke(person, null);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Console:
### Use getMethod
Method callMe() in AbstractPerson
### Use getDeclaredMethod
java.lang.NoSuchMethodException: Test$Person.callMe()
at java.lang.Class.getDeclaredMethod(Class.java:2004)
at Test.main(Test.java:27)
After solving that issue there has been the next one with generic type T.
2. The BeanFieldGroup could not be initialized like I did. Of course the beanClass is Null.
Here the solution with setting the beanClass for BeanFieldGroup properly:
public abstract class AbstractFieldGroupBind<T> implements IFieldGroupBind<T>{
protected BeanFieldGroup<T> binder;
#Override
public void initGroupBinder(Object view){
binder = new BeanFieldGroup<T>(getClassForT());
binder.bindMemberFields(view);
}
#Override
public void pushItem(T item) {
binder.setItemDataSource(item);
}
#Override
public T getItem() {
return binder.getItemDataSource().getBean();
}
#SuppressWarnings("unchecked")
private Class<T> getClassForT(){
Type superClazz = this.getClass().getGenericSuperclass();
Type tClazz = ((ParameterizedType)superClazz).getActualTypeArguments()[0];
return (Class<T>) tClazz;
}
}
Now it works!
When you instantiate an object of class StammdataEditFGB, you are already passing the type information to the super class. So, when you call theFGBClass.getClass().getSuperClass(), you will get a AbstractFieldGroupBind class that handles Cinema objects.
I am writing a packet class that will hopefully be able to take all the declared fields of its SubClasses, add them to a list and then send them across the network.
Packet SuperClass:
public class TCPacket {
private PacketType packetType;
private List<Object> packetData = new ArrayList<Object>();
public TCPacket(PacketType type){
this.packetType = type;
packetData.add(type.getIdent());
}
public PacketType getType(){
return packetType;
}
public List<Object> getDataList(){
return packetData;
}
public ByteArrayOutputStream getDataOS() throws IOException{
//writes data to stream
}
public void addData(Object object){
this.packetData.add(object);
}
private void addDeclaredFields(){
Field[] fields = this.getClass().asSubclass(this.getClass()).getDeclaredFields();
for(Field field : fields)
this.packetData.add(field);
}
}
The important line in this is:
Field[] fields = this.getClass().asSubclass(this.getClass()).getDeclaredFields();
My hope, is that with this, i will be able to get all the declared fields of the SubClass ONLY, regardless of the SubClass type.
Obviously i could do something like this:
Field[] fields = this.getClass().asSubclass(PacketRequestLogon.class).getDeclaredFields();
but i'd rather not hard code every packet type. What i am really asking, is will this.getClass() return the SubClass IF the method containing it: addDeclaredFields() is called from within the SuperClass, or will it return the super.
My hope, is that with this, i will be able to get all the declared fields of the SubClass ONLY, regardless of the SubClass type.
From Class#getDeclaredFields jadavoc (emphasis mine):
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields.
So you can be sure you're not getting the fields from the super class.
Tested your current implementation of addDeclaredFields:
class ASuperClass {
protected int fieldInASuperClass;
public final void addDeclaredFields(){
Field[] fields = this.getClass().asSubclass(this.getClass()).getDeclaredFields();
for(Field field : fields) {
//edited this line for test purposes
System.out.println(field.getName());
}
}
}
class ASubClass extends ASuperClass {
private int fieldInASubClass;
}
class AnotherSubClass extends ASuperClass {
private int fieldInAnotherSubClass;
private int justAnotherFieldInAnotherSubClass;
}
public class AMainClass {
public static void main(String[] args) {
new ASuperClass().addDeclaredFields();
System.out.println("--------------------------------------");
new ASubClass().addDeclaredFields();
System.out.println("--------------------------------------");
new AnotherSubClass().addDeclaredFields();
}
}
Prints:
fieldInASuperClass
--------------------------------------
fieldInASubClass
--------------------------------------
fieldInAnotherSubClass
justAnotherFieldInAnotherSubClass
Note that only prints the declared fields of the subclass, the inherited fields are not printed.
I wanted to implement a method in a abstract class that is called by the inherited classes and uses their values.
For instance:
abstract class MyClass{
String value = "myClass";
void foo(){System.out.println(this.value);}
}
public class childClass{
String value="childClass";
void foo(){super.foo();}
}
public static void main(String[] args){
new childClass.foo();
}
This will output "myClass" but what I really want is to output "childClass". This is so I can implement a "general" method in a class that when extended by other classes it will use the values from those classes.
I could pass the values as function arguments but I wanted to know if it would be possible to implement the "architecture" I've described.
A super method called by the inherited class which uses the values from the caller not itself, this without passing the values by arguments.
You could do something like this:
abstract class MyClass {
protected String myValue() {
return "MyClass";
}
final void foo() {
System.out.println(myValue());
}
}
public class ChildClass extends MyClass {
#Override
protected String myValue() {
return "ChildClass";
}
}
and so on
This is a place where composition is better than inheritance
public class Doer{
private Doee doee;
public Doer(Doee doee){
this.doee = doee;
}
public void foo(){
System.out.println(doee.value);
}
}
public abstract class Doee{
public String value="myClass"
}
public ChildDoee extends Doee{
public String= "childClass"
}
...
//Excerpt from factory
new Doer(new ChildDoee);
I believe you are asking whether this is possible:
public class MyClass {
void foo() {
if (this instanceof childClass) // do stuff for childClass
else if (this intanceof anotherChildClass) // do stuff for that one
}
}
So the answer is "yes, it's doable", but very much advised against as it a) tries to reimplement polymorphism instead of using it and b) violates the separation between abstract and concrete classes.
You simply want value in MyClass to be different for an instance of childClass.
To do this, change the value in the childClass constructor:
public class childClass {
public childClass() {
value = "childClass";
}
}
Edited:
If you can't override/replace the constructor(s), add an instance block (which gets executed after the constructor, even an undeclared "default" constructor):
public class childClass {
{
value = "childClass";
}
}