How do you extend a Java class and change annotations? - java

I have one Java class that uses annotations. I want to write a version that extends it and changes the annotations on existing methods.
So there will be a method that has:
#myAnnotation(value=VALUE_THAT_CHANGE_IN_SUBCLASS)
myMethod(){
}
The subclass will have a couple new methods, but will mostly just change annotations in the manner I said.

Though I'm not sure why you'd want to, you'd need to extend the class, override the methods, and apply the annotations:
public class App
{
public static void main(String[] args) throws NoSuchMethodException
{
Class<MyClass> c = MyClass.class;
MyAnnotation a = c.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());
Class<MySubclass> c2 = MySubclass.class;
a = c2.getMethod("someMethod",null).getAnnotation(MyAnnotation.class);
System.out.println(a.name());
}
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#interface MyAnnotation {
String name() default "";
}
class MyClass {
#MyAnnotation(name="Some value")
public String someMethod() {
return "Hi!";
}
}
class MySubclass extends MyClass {
#Override
#MyAnnotation(name="Some other value")
public String someMethod() {
return super.someMethod();
}
}
Output:
Some value
Some other value

Related

custom annotations for method in java

I am new to annotations in java, I want to have an annotation on method to do some stuff for me like:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface LogActivity {
String logMessage() default "default message";
}
I want to have some methods in different classes like:
public class A {
#LogActivity(logMessage = "called foo() in class A")
public void foo() {
// some code
}
}
and
public class B {
#LogActivity(logMessage = "called foo() in class B")
public void foo() {// some code}
#LogActivity(logMessage = "called foo1() in class B")
public void foo1() {// some code}
}
I need a method which will print these logMessages on the screen.
I just need help writing the method which will be executed after the call to these foo and foo1 goes but before their execution starts.
Blockquote I need this annotation in any number of classes in my project so I cannot prefer to do something like:
Method [] methods = Class.forName(theObject.getClass().getName()).getMethods();
and
LogActivity logActivity = methods[i].getAnnotation(LogActivity.class);
I googled some things but didn't really understand the solution.
Thank you in advance.

Method Parameter Annotations in overridden methods

Is there any way to get the parameter annotations of a method in child class? I tried using the getParameterAnnotations but it not works. I wrote a test class to demonstrate:
public class ParameterAnnotationInheritanceTest {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.PARAMETER)
#Inherited
public #interface MockAnnotation {
}
public class A {
public void test(#MockAnnotation String value) {
}
}
public class B extends A {
#Override
public void test(String value) {
}
}
#Test
public void TestA() throws NoSuchMethodException, SecurityException {
Method AMethod = A.class.getMethod("test", String.class);
Annotation[][] AMethodParameterAnnotations = AMethod.getParameterAnnotations();
assertTrue(Arrays.asList(AMethodParameterAnnotations[0]).size() > 0);
}
#Test
public void TestB() throws NoSuchMethodException, SecurityException {
Method BMethod = B.class.getMethod("test", String.class);
Annotation[][] BMethodParameterAnnotations = BMethod.getParameterAnnotations();
assertTrue(Arrays.asList(BMethodParameterAnnotations[0]).size() > 0);
}
}
Thanks in advance!
It does not work because the test method in the child class B is not the same test method as in the super class. By overriding it, you have practically defined a new test method that gets called instead of the original one. If you define your child class like this
public class B extends A {
}
and run your code again, it works fine because it is the inherited test method that gets called, which is what you want as far as I understand.

Java: Return an object that extends an abstract class which takes arguments

I've got an interface
public interface I
{
public AnAbstractClass k(); //Abstract Class constructor takes two arguments
}
For an implementation of this interface's method I want to return a generic object which extends that AbstractClass and also give it its two argument constructor
To clarify what I want to achieve. In a class which implements I:
public AnAbstractClass k()
{
//return a new implementing AbstractClass object AbstractClassObject(arg1,arg2)
}
Constructors are not inherited, so subclasses of AnAbstractClass won't necessarily have a two-argument constructor. If a subclass does have a two-argument constructor, there is nothing stopping you from creating an instance of that subclass using the two-argument constructor and returning it:
public abstract class AnAbstractClass
{
public AnAbstractClass(String foo, String bar) {
System.out.format("created with (%s, %s)\n", foo, bar);
}
}
public class BaseClass extends AnAbstractClass
{
public BaseClass(String foo, String bar) {
super(foo, bar);
}
}
public interface I
{
public AnAbstractClass k();
}
public class Implementation implements I
{
#Override public AnAbstractClass k() {
return new BaseClass("hello", "world");
}
}
public class Demo
{
public static void main(String[] args) {
I i = new Implementation();
AnAbstractClass a = i.k();
}
}
There are sophisticated solutions for this problem (roughly: Everything that is related to dependency injection). However, in this case, there are not so many options: Someone HAS to provide these arguments, and they obviously can not be passed to the interface method. So you'll probably need something like
class Creator implements I
{
private Object arg0;
private Object arg1;
void setArgs(Object arg0, Object arg1)
{
this.arg0 = arg0;
this.arg1 = arg1;
}
#Override
public AnAbstractClass k()
{
return new ConcreteClassExtendingAnAbstractClass(arg0, arg1);
}
}
The drawback is that this interface might become more or less useless: If it was designed to be a factory, you can no longer use it in its abstract form...
I i = obtainFromSomewhere();
AnAbstractClass a = i.k();
but you always have to know the particular type
Creator i = obtainFromSomewhere();
i.setArgs(..., ...);
AnAbstractClass a = i.k();

Annotate class with inner class

I create my enums through reflection, for that I add to each enum an inner class which implements the abstract factory. Now I want to access this inner class in order to invoke the method:
#Factory(FooFactory.class)
public enum Foo {
FOO, BAR;
public class FooFactory implements AbstractFactory<Foo> {
public Foo create(String value) {
return valueOf(value.toUpperCase());
}
}
}
The definition of #Factory is:
#Retention(RetentionPolicy.RUNTIME)
public #interface Factory {
Class<?> value();
}
With this, however, I receive the following error:
Class cannot be resolved to a type FooFactory.java
When I try #Factory(Foo$FooFactory.class) I receive the error:
The nested Foo$FooFactory cannot be referneced using its binary name.
So is it even possible to reference a nested class?
From the comments... apparently
#Factory(Foo.FooFactory.class)
was needed.
You're using a non-static nested class, which is scoped to the individual instances of the enum.
Instead, you need a static nested class, like so:
public static class FooFactory implements AbstractFactory<Foo> {
public static Foo create(String value) {
return valueOf(value.toUpperCase());
}
}
However, all of this is redundant: you can simply call Foo.valueOf(value) to achieve this goal. I don't see any value added here (no pun intended).
Factory.java
import java.lang.annotation.*;
#Retention(RetentionPolicy.RUNTIME)
public #interface Factory {
Class<?> value();
}
FooEnum.java
#Factory(FooEnum.FooFactory.class)
public enum FooEnum {
FOO, BAR;
public static class FooFactory {
public static FooEnum create(String value) {
return valueOf(value.toUpperCase());
}
}
}
FooEnumMain.java
public class FooEnumMain {
public static void main(String[] args) {
FooEnum f = FooEnum.FooFactory.create("foo");
System.out.println(f);
}
}
At the point when your annotation is presented, FooFactory is undefined, so the full path needs to be specified:
#Factory(Foo.FooFactory.class)

java subclass have method to return its class

Ok, maybe this is a stupid question. But i'm just wondering if this can be done in java.
abstract public class ParentClass<T> {
abstract public T getTest();
}
in the subclass
public class SubClass extends ParentClass<MyObject> {
public MyObject getTest() {
// I can return the object with class MyObject
return null;
}
}
My question is can I return the class type in the child method? I mean, is it can be done by adding some code in the ParentClass, so I can do this below?
For example
public class Sub1Class extends parentClass<Object1> {
public Object1 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub1Class getItClassObject() { }
}
other example
public class Sub2Class extends parentClass<Object2> {
public Object2 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub2Class getItClassObject() { }
}
one example again
public class Sub3Class extends parentClass<Object3> {
public Object3 getTest() { }
// I want to have a method that return it's class in the superclass
public Sub3Class getItClassObject() { }
}
if you see, method getItClassObject in Sub1Class, Sub2Class and Sub3Class will follow it's class. But I don't want to add same method for every subclass, just want to add some code (if feasible) in the ParentClasss, so in the subclass, I just can call getItClassObject directly without write all the code in every subclass.
Usually I add method in ParentClass like this.
abstract public class ParentClass<T> {
abstract public T getTest();
public Object getItClassObject() { }
}
so in the subclass I just instance the class, but I have to cast again :(
Sub1Class sub1Class = new Sub1Class();
Sub1Class after1Cast = (Sub1Class) sub1Class.getItClassObject();
Sub2Class sub2Class = new Sub2Class();
Sub2Class after2Cast = (Sub2Class) sub2Class.getItClassObject();
I think it cannot be done in java. But I don't know if there is a clue to solve this. Thanks
This is what you want I think. The following compiles:
abstract class A {
public abstract A getA();
}
class B extends A {
// Declared to return a B, but it still properly overrides A's method
#Override
public B getA() {
return new B();
}
}
class C extends A {
// Declared to return a B, but it still properly overrides A's method
#Override
public C getA() {
return new C();
}
}
As you can see, A declares that the getA() method returns an A. But, you can restrict the return type in subclasses as shown.
I'm not sure if I understand your intent correctly, but I think the built-in Object.getClass() method will do what you want. Given classes defined as:
public abstract class ParentClass<T> {
public abstract T getTest();
}
class SubClassString extends ParentClass<String> {
public String getTest() {
return "";
}
}
class SubClassInteger extends ParentClass<Integer> {
public Integer getTest() {
return Integer.valueOf(0);
}
}
getClass() will return the correct run-time class
public static void main(String[] args) {
SubClassString subString = new SubClassString();
// displays "class SubClassString"
System.out.println(subString.getClass());
SubClassInteger subInteger = new SubClassInteger();
// displays "class SubClassInteger"
System.out.println(subInteger.getClass());
ParentClass<?> parentInstance = new SubClassInteger();
// displays "class SubClassInteger"
System.out.println(parentInstance.getClass());
}
The only way I can think of is by telling the parent class what the subclass is when you extend it (just like you did with 'T'). Eg:
public abstract class ParentClass<T,U> {
abstract public T getTest();
abstract public U getItClassObject();
}
They you define your subclass like so:
public class Sub1Class extends ParentClass<Object1,Sub1Class> {
public Object1 getTest() { }
public Sub1Class getItClassObject() { }
}
Then you can do what you want without the typecast:
Sub1Class sub1Class = new Sub1Class();
Sub1Class after1Cast = sub1Class.getItClassObject();
If your objects have no-arg constructors (or some consistent form of constructor across all of them), you can use reflection to do it. Some pseudocode would be
public class MyClass {
public MyClass instantiateType() {
Class<?> actualClass = getClass();
return actualClass.newInstance();
}
}
This is using the runtime type of the class, so subclasses will return their type. This works only for a no-arg constructor though.

Categories

Resources