Is there a way to pass a Java annotation as a parameter? - java

Guys is there a way to pass a Annotation as a direct parameter (rather by doing all the reflection overhead)? For example in the following code, I have a annotation Number that holds a int value, I want to pass as a parameter to the addImpl method, how can I do that (other than by reflection)?
Code Snippet:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public #interface Number {
int value();
}
public void add(int x2) {
addImpl(#Number(value = 10) lol, x2);
}
public void addImpl(Number a, int b) {
System.out.println(a.value() + b);
}
public static void main(String[] args) {
new TestClass().add(3);
}

Yes, you can pass around annotations like this (just as if they were normal interfaces).
The only thing you can't do is to create instances of that interface at runtime. You can only take existing annotations and pass them around.
import java.lang.annotation.*;
public class Example {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public static #interface Number {
int value();
}
#Number(value = 42)
public int adder(final int b) throws SecurityException, NoSuchMethodException {
Number number = getClass().getMethod("adder", int.class).getAnnotation(Number.class);
return addImpl(number, b);
}
public int addImpl(final Number a, final int b) {
return a.value() + b;
}
public static void main(final String[] args) throws SecurityException, NoSuchMethodException {
System.out.println(new Example().adder(0));
}
}

You can do it like:
public void add(int x2) {
addImpl(new Number() {
#Override
public int value() {
return 10;
}
#Override
public Class<? extends Annotation> annotationType() {
return Number.class;
}
}, x2);
}
Since Number is basically an interface, you have to create an instance of an anonymous class that implements that interface, and pass that to the method.
Although why you want to do this is beyond me. If you need to pass a value to something, you should really use a class.

To the best of my knowledge, there's no such thing as an "annotation literal" as you want to use it in your add implementation.
I think the closest thing to this would be to declare the method to take a parameter of type java.lang.annotation.Annotation - but then you'd still need to obtain those instances via reflection from the class/method objects.

Number is also a good old interface, you can implement a concrete class.
Guys, this is useful. While a module mostly deals with annotations which are fixed at compile time, sometimes we need to feed it other info obtained at runtime from other sources(like xml, gush!) We can over-architect the thing, or we can simply creat a runtime object of the annotaion type.

If you need to pass annotation in test, you can make mock of it.
For example test of JSR 303 validator could look like this:
public void test() {
final TextLengthValidator validator = new TextLengthValidator();
validator.initialize(mock(TextLength.class));
final boolean valid = validator.isValid("some text", mock(ConstraintValidatorContext.class));
assertThat(valid, is(true));
}

Related

A java method with both variable return type and variable input arguments

I have an abstract java class "BaseOperation". This class only has a single abstract method:
public abstract T execute()
{
...
return T;
}
Subclasses of BaseOperation must implement this method:
public class GetUsersOperation extends BaseOperation<GetUsersResponse>
{
...
#Override
public GetUsersResponse execute()
{
...
return GetUsersResponse;
}
}
This is a great way to put all common "operation" logic in the BaseOperation class, but still have every concrete subclass's execute() method have a different return type.
Now I need to change this structure to allow the execute() methods to have a variable amount of arguments. For example, one concrete subclass would require:
execute(String, int)
and another would need:
execute(Date, Date, String)
This is tricky, because the execute method is declared in the base class. Simply overloading the execute methods in the base is not ideal. Firstly, the amount of overloads would be huge. Secondly, every subclass will only ever use one of the execute methods, what's the point of all the others?
The (in my opinion) easiest solution would be to declare the execute method with varargs:
execute(Object... arguments)
And then downcast all arguments in the subclasses:
execute(Object... arguments)
{
String s = (String) arguments[0];
...
}
Obviously this has 2 major downsides:
Reduced performance because of all the downcasting operations
Calling the execute() methods is no longer strictly typed because any amount of objects can be passed witout compiler warnings.
Are there patterns or other solutions that could don't have these disadvantages?
You could use a bean holding the parameters:
public interface BaseOperation<T, U> {
T execute(U input);
}
public class GetUsersOperation implements BaseOperation<GetUsersResponse, UserInput> {
#Override
public GetUsersResponse execute(UserInput input) {
Date date = input.getDate();
return new GetUsersResponse(date);
}
}
Your abstract class only has one single abstract method: better use an interface. You can implement several interfaces while you can extend only one class.
As already said, the common approach for solving your issue is using a bean holding parameters. But here is another solution, based on a builder approach:
public interface BaseOperation<T> {
public T execute();
}
public class AddOperation implements BaseOperation<Integer> {
private int a, b;
public void setA(int arg){
a = arg ;
return this;
}
public void setB(int arg){
b = arg;
return this;
}
#Override
public Integer execute() {
return a+b ;
}
}
And then use it like this :
new AddOperation().setA(1).setB(2).execute();
You can mix required and optional parameters in this way:
public class MultipleAddOperation implements BaseOperation<Integer> {
private int sum ;
public MultipleAddOperation(int requiredInt){
sum = requiredInt;
}
public void add(int optionalInt){
sum += optionalInt ;
return this;
}
#Override
public Integer execute(){
return sum;
}
}
And so:
new MultipleAddOperation(5).add(1).add(2).execute();

Overload Java Data Field Type by Another Field Type

Is it possible to overload a field type to be another field type?
If so, would it be possible to provide some examples?
You can't overload fields (only methods can be overloaded), you might be confused with overriding fields - which anyway is not possible, you end up hiding the fields from superclasses. Take a look at this post.
I believe that java supports interfaces, and interfaces should be able to help you achieve what you're trying to achieve
here's an example i found quick
here's a tutorial
just make sure that you're not overloading public members that way.
look at this code
class A<T> {
protected T field1;
}
class B extends A<String> {
public char field1;
public static void main(String[] args) {
A a = new B();
a.field1 = 12442;
}
}
it runs without any exception,
if field1 overrided, it should raise an exception, but it doesn't
and also this runs without any exception
class A<T> {
protected T field1;
}
class B extends A<Character> {
public char field1;
public static void main(String[] args) {
A a = new B();
a.field1 = 12442;
}
}
It's impossible
The Java language (JLS) does not allow it, but Java bytecode (JVMS) does
Oracle JDK 1.8.0_45 even relies on it to implement assert. For example:
public class Assert {
static final int[] $assertionsDisabled = new int[0];
public static void main(String[] args) {
System.out.println(int.length);
assert System.currentTimeMillis() == 0L;
}
}
generates two Oracle JDK 1.8.0_45, one explicit (int[]) and one synthetic (bool), and is happily able to distinguish between them. But if we had declared:
static final boolean $assertionsDisabled = false;
it would fail to compile with:
the symbol $assertionsDisabled conflicts with a compile synthesized symbo
See https://stackoverflow.com/a/31355548/895245 for more details.
Possible rationale why it's not possible
The problem is that it would not be possible to determine the type of the field. Consider:
void f(int i) { System.out.println("int"); }
void f(float i) { System.out.println("float"); }
int i;
float i;
// Which overridden method is called?
void m() { f(i); }

Enum and Generic constant specific method

I have an enum like:
enum TEST {
TEST1, TEST 2;
public abstract <T> String stringify (T input);
}
I need to add a constant specific method , something like stringify.
This method will take different types of inputs (for each enum). Can I do that? Eclipse is not letting me do it ..something like:
enum TEST {
TEST1(
public <Float> String stringify (Float input){
return String.valueOf(input);
}
)
}
You can't do it with enums, but you can simulate this behaviour with generic class:
public abstract class TEST<T> {
public static final TEST<Float> TEST1 = new TEST<Float>() {
public String stringify (Float input){
return String.valueOf(input);
}
};
public abstract <T> String stringify(T input);
}
you can do it. but it's not clear what the benefit is:
enum TEST {
TEST1 {
public <Float>String stringify(Float input) {
System.out.println("TEST1");
return String.valueOf(input);
}
},
TEST2 {
public <Integer>String stringify(Integer input) {
System.out.println("TEST2");
return String.valueOf(input);
}
},
TEST3 {};
public <T>String stringify(T input) {
System.out.println("super");
return "";
}
public <Integer>String stringify2(Object input) {
System.out.println("non generic");
return String.valueOf(input);
}
}
public class Main{
public static void main(String[] args) {
for(TEST test:TEST.values()) {
System.out.println(test.stringify(new Float(1.23)));
System.out.println(test.stringify(new Integer(42)));
System.out.println(test.stringify(new Double(4.56)));
}
for(TEST test:TEST.values()) {
System.out.println(test.stringify2(new Float(1.23)));
System.out.println(test.stringify2(new Integer(42)));
System.out.println(test.stringify2(new Double(4.56)));
}
}
}
Think of each Enum value as a class. So yes, the enums can have methods, just like a class does -- they all have the same methods though.
http://download.oracle.com/javase/tutorial/java/javaOO/enum.html
Look at the Planet example.
Also note that the enum itself can have static methods....(just like a class)
No, you can't make each enum constant implement an abstract method but require a different type of input than the other enum constants. If you could, what would happen if you were given an instance of your TEST enum (you don't know what constant it is) and tried to call stringify on it? What type would you pass it?
Edit: Given what you've said about these enums being used to decode strings into objects, it seems to me you have several options:
You could get a String representation of each decoded object by just calling toString() on it.
You could add a set of overloaded static method on the enum class itself, called stringify(Float) and stringify(Double), etc. Then you could just call TEST.stringify(value) and if there were a stringify method for the value's type, it'd work fine.
I imagine there are other options as well.
You can't use generics with enums, because the enum constants themselves are already the concrete (singleton) instances. At instance level, the generics must already be concrete.
So, I would stringly recommend going with one of the alternatives given in the other answers.
If you must do it in an enum, you could consider the following, which at least gives you a runtime means of type checking, including ClassCastExceptions. You won't have any support from the compiler though.
public enum TestEnum {
Test1(Float.class),
Test2(Integer.class),
Test3(String.class);
private final Class<?> iInputType;
private TestEnum(final Class<?> pInputType) {
iInputType = pInputType;
}
public Class<?> getInputType() {
return iInputType;
}
public String stringify(final Object pInput) {
return String.valueOf(iInputType.cast(pInput));
}
}
Test Code:
System.out.println(TestEnum.Test1.stringify(1.23f));
System.out.println(TestEnum.Test2.stringify(42));
System.out.println(TestEnum.Test3.stringify("foo"));
// but:
// System.out.println(TestEnum.Test1.stringify("foo")); // -> ClassCastException!
for (TestEnum test : TestEnum.values()) {
for (Object input : new Object[]{1.23f, 42, "foo"}) {
if (test.getInputType().isAssignableFrom(input.getClass())) {
System.out.println(test.stringify(input));
}
}
}

Smart annotation

I have created many annotation in my life and now came to strange case that i need this annotation to do and dont think it is supported by Java at all. Please someone tell me that i am right or wrong.
Here is my annotation :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface DetailsField {
public String name();
}
And now the question! I would like that the default value of the name() function would be the name of the field it self where I have posted the annotation.
Dont know exactly how the classloader processes the annotations, i am pretty sure that this is not implemented in a standard classloader , but could be maybe achieved by bytecode instrumentation in the time of classloading by a custom classloader ?
(I am pretty sure if this is the only solution i would find a way around , just curious )
Any ideas? Or do i wish too much ?
I think that it is possible to instrument the bytecode (at class loading) to get this working, but this seems like a highly complicated, and possibly non-portable, solution.
The best solution to your problem is to create a class that decorates (a-la the Decorator design pattern) an instance of your annotation with the name calculation logic.
[Edit: Added the name() definition at the interface]
package p1;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class A {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface DetailsField {
public int n1();
public String name() default "";
}
public static class Nameable implements DetailsField {
private final DetailsField df;
private final Field f;
public Nameable(Field f) {
this.f = f;
this.df = f.getAnnotation(DetailsField.class);
}
#Override
public Class<? extends Annotation> annotationType() {
return df.annotationType();
}
#Override
public String toString() {
return df.toString();
}
#Override
public int n1() {
return df.n1();
}
public String name() {
return f.getName();
}
}
public class B {
#DetailsField(n1=3)
public int someField;
}
public static void main(String[] args) throws Exception {
Field f = B.class.getField("someField");
Nameable n = new Nameable(f);
System.out.println(n.name()); // output: "someField"
System.out.println(n.n1()); // output: "3"
}
}

Static method in a generic class?

In Java, I'd like to have something as:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
But I get
Cannot make a static reference to the non-static type T
I don't understand generics beyond the basic uses and thus can't make much sense of that. It doesn't help that I wasn't able to find much info on the internet about the subject.
Could someone clarify if such use is possible, by a similar manner? Also, why was my original attempt unsuccessful?
You can't use a class's generic type parameters in static methods or static fields. The class's type parameters are only in scope for instance methods and instance fields. For static fields and static methods, they are shared among all instances of the class, even instances of different type parameters, so obviously they cannot depend on a particular type parameter.
It doesn't seem like your problem should require using the class's type parameter. If you describe what you are trying to do in more detail, maybe we can help you find a better way to do it.
Java doesn't know what T is until you instantiate a type.
Maybe you can execute static methods by calling Clazz<T>.doit(something) but it sounds like you can't.
The other way to handle things is to put the type parameter in the method itself:
static <U> void doIt(U object)
which doesn't get you the right restriction on U, but it's better than nothing....
I ran into this same problem. I found my answer by downloading the source code for Collections.sort in the java framework. The answer I used was to put the <T> generic in the method, not in the class definition.
So this worked:
public class QuickSortArray {
public static <T extends Comparable> void quickSort(T[] array, int bottom, int top){
//do it
}
}
Of course, after reading the answers above I realized that this would be an acceptable alternative without using a generic class:
public static void quickSort(Comparable[] array, int bottom, int top){
//do it
}
I think this syntax has not been mentionned yet (in the case you want a method without arguments) :
class Clazz {
static <T> T doIt() {
// shake that booty
}
}
And the call :
String str = Clazz.<String>doIt();
Hope this help someone.
It is possible to do what you want by using the syntax for generic methods when declaring your doIt() method (notice the addition of <T> between static and void in the method signature of doIt()):
class Clazz<T> {
static <T> void doIt(T object) {
// shake that booty
}
}
I got Eclipse editor to accept the above code without the Cannot make a static reference to the non-static type T error and then expanded it to the following working program (complete with somewhat age-appropriate cultural reference):
public class Clazz<T> {
static <T> void doIt(T object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
private static class KC {
}
private static class SunshineBand {
}
public static void main(String args[]) {
KC kc = new KC();
SunshineBand sunshineBand = new SunshineBand();
Clazz.doIt(kc);
Clazz.doIt(sunshineBand);
}
}
Which prints these lines to the console when I run it:
shake that booty 'class com.eclipseoptions.datamanager.Clazz$KC' !!!
shake that booty 'class com.eclipseoptions.datamanager.Clazz$SunshineBand' !!!
It is correctly mentioned in the error: you cannot make a static reference to non-static type T. The reason is the type parameter T can be replaced by any of the type argument e.g. Clazz<String> or Clazz<integer> etc. But static fields/methods are shared by all non-static objects of the class.
The following excerpt is taken from the doc:
A class's static field is a class-level variable shared by all
non-static objects of the class. Hence, static fields of type
parameters are not allowed. Consider the following class:
public class MobileDevice<T> {
private static T os;
// ...
}
If static fields of type parameters were allowed, then the following code would be confused:
MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
Because the static field os is shared by phone, pager, and pc, what is the actual type of os? It cannot be Smartphone, Pager, and
TabletPC at the same time. You cannot, therefore, create static fields
of type parameters.
As rightly pointed out by chris in his answer you need to use type parameter with the method and not with the class in this case. You can write it like:
static <E> void doIt(E object)
Something like the following would get you closer
class Clazz
{
public static <U extends Clazz> void doIt(U thing)
{
}
}
EDIT: Updated example with more detail
public abstract class Thingo
{
public static <U extends Thingo> void doIt(U p_thingo)
{
p_thingo.thing();
}
protected abstract void thing();
}
class SubThingoOne extends Thingo
{
#Override
protected void thing()
{
System.out.println("SubThingoOne");
}
}
class SubThingoTwo extends Thingo
{
#Override
protected void thing()
{
System.out.println("SuThingoTwo");
}
}
public class ThingoTest
{
#Test
public void test()
{
Thingo t1 = new SubThingoOne();
Thingo t2 = new SubThingoTwo();
Thingo.doIt(t1);
Thingo.doIt(t2);
// compile error --> Thingo.doIt(new Object());
}
}
Since static variables are shared by all instances of the class. For example if you are having following code
class Class<T> {
static void doIt(T object) {
// using T here
}
}
T is available only after an instance is created. But static methods can be used even before instances are available. So, Generic type parameters cannot be referenced inside static methods and variables
When you specify a generic type for your class, JVM know about it only having an instance of your class, not definition. Each definition has only parametrized type.
Generics work like templates in C++, so you should first instantiate your class, then use the function with the type being specified.
Also to put it in simple terms, it happens because of the "Erasure" property of the generics.Which means that although we define ArrayList<Integer> and ArrayList<String> , at the compile time it stays as two different concrete types but at the runtime the JVM erases generic types and creates only one ArrayList class instead of two classes. So when we define a static type method or anything for a generic, it is shared by all instances of that generic, in my example it is shared by both ArrayList<Integer> and ArrayList<String> .That's why you get the error.A Generic Type Parameter of a Class Is Not Allowed in a Static Context!
#BD at Rivenhill: Since this old question has gotten renewed attention last year, let us go on a bit, just for the sake of discussion.
The body of your doIt method does not do anything T-specific at all. Here it is:
public class Clazz<T> {
static <T> void doIt(T object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
So you can entirely drop all type variables and just code
public class Clazz {
static void doIt(Object object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
Ok. But let's get back closer to the original problem. The first type variable on the class declaration is redundant. Only the second one on the method is needed. Here we go again, but it is not the final answer, yet:
public class Clazz {
static <T extends Saying> void doIt(T object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
// Output:
// KC
// Sunshine
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}
However, it's all too much fuss about nothing, since the following version works just the same way. All it needs is the interface type on the method parameter. No type variables in sight anywhere. Was that really the original problem?
public class Clazz {
static void doIt(Saying object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}
T is not in the scope of the static methods and so you can't use T in the static method. You would need to define a different type parameter for the static method. I would write it like this:
class Clazz<T> {
static <U> void doIt(U object) {
// ...
}
}
For example:
public class Tuple<T> {
private T[] elements;
public static <E> Tuple<E> of(E ...args){
if (args.length == 0)
return new Tuple<E>();
return new Tuple<E>(args);
}
//other methods
}

Categories