Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Annotation like Lombok

I want to implement a custom annotation which when used by other classes exposes two methods to them. Something like shown below:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface BaseEntity{
     public String toString(){ return "Hello" ;}
     public String toCustomString() { return "my hello";}
}

Now what I want is whenever any class uses the above annotation. It gets these methods exposed to it by default, something like what Lombok does when we use @Getter

@BaseEntity
public class Person{}
Person p = new Person();
p.toCustomString(); // this should work
like image 639
Harshit Gupta Avatar asked Oct 31 '25 05:10

Harshit Gupta


1 Answers

While not exactly what you asked, I think you can achieve what you want with a class hierarchy that takes advantage of the annotation:

@Retention(RetentionPolicy.RUNTIME)                                             
@Target(ElementType.TYPE)                                                       
public @interface BaseEntity {                                                  
    String string();                                                            
    String customString();                                                      
}                                                                               
                                                                                
public abstract class AbstractClass {                                           
    @Override                                                                   
    public String toString() {                                                  
        return getClass().getAnnotation(BaseEntity.class).string();             
    }                                                                           
                                                                                
    public String toCustomString() {                                            
        return getClass().getAnnotation(BaseEntity.class).customString();       
    }                                                                           
}

And then a concrete subclass:

@BaseEntity(string = "Hello", customString = "my hello")                        
public class Example extends AbstractClass {                                    
    public static void main(String[] args) throws Exception {                   
        Example example = new Example();                                        
                                                                                
        System.out.println(example.toString());                                 
        System.out.println(example.toCustomString());                           
    }                                                                           
}

yields:

Hello                                                                           
my hello

In response to your comment, my real-world solution is to define an annotation and an interface with default methods (which makes a toString() implementation problematic):

@BaseEntity(customString = "my hello")                                          
public class Example implements BaseEntityAnnotated {                           
    public static void main(String[] args) throws Exception {                   
        Example example = new Example();                                        
                                                                                
        System.out.println(example.toCustomString());                           
    }                                                                           
}                                                                               
                                                                                
@Retention(RetentionPolicy.RUNTIME)                                             
@Target(ElementType.TYPE)                                                       
public @interface BaseEntity {                                                  
    String customString();                                                      
}                                                                               
                                                                                
public interface BaseEntityAnnotated {                                          
    default String toCustomString() {                                           
        return this.getClass().getAnnotation(BaseEntity.class).customString();  
    }                                                                           
}

I then implement a Processor that enforces an entity annotated with BaseEntity must also implement BaseEntityAnnotated.

I have examples at AntTask, AnnotatedAntTask.getAntTaskName(), and AntTaskProcessor.

like image 198
Allen D. Ball Avatar answered Nov 02 '25 19:11

Allen D. Ball



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!