Annotate class with inner class - java

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)

Related

How Functions can be called from java enum?

I'm trying to understand how the static method calls from a Java enum works.
To see the full code of this "Working example"
I have the following scenario working, I don't know why
public enum Condition {
GREATER_THAN(PredicateBuilder::generateGreaterThan, ">"),
more values...
private Condition(BiFunction<PredicateBuilder, PredicateContent<?>, Predicate> predicate, String operator) {
this.operator = operator;
this.predicate = predicate;
}
This is the predicate builder, it's an interface implemented by a #Component from Spring:
#Component
public class PredicateLogicalBuilder<V extends Comparable> implements PredicateBuilder<V> {
#Override
public Predicate generateGreaterThan(PredicateContent<V> predicateContent) {
return predicateConversion(predicateContent,Condition.GREATER_THAN);
}
}
The static reference in above Condition enum doesn't complain about:
Non-static method cannot be referenced from a static context
and I don't why because now I'm trying to do something similar and it fails because the static reference of a method isn't static. In the code above is not static either.
Code I'm trying:
public interface MethodCalls<T> {
void randomMethod(T content);
}
#Component
public class TestEnumMethoCalls implements MethodCalls<SomeBean> {
#Override
public void randomMethod(SomeBean content){
System.out.println("Works!!!!");
}
}
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final Function<SomeBean,Void> method;
private NotificationType(Function<SomeBean,Void> method){
this.method=method;
}
}
public class TestClass{
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(new SomeBean())
}
}
This piece of code fails saying the Non-static method cannot be referenced from a static context:
ENUM_TEST_1(MethodCalls::randomMethod);
I would like to have 2 answers:
Why the code of the "Working example" works.
If it's mandatory for my current test to use the instance of the MethodCalls how can be injected with DI to the enum (is a static context so I understand it might be tricky if not impossible).
Thanks for the help, now I understood why my "working example" works and how to "Fix" my current issue:
To fix it I have to pass an instance of the implementation of the interface as it's pointed out that enums can only access static methods or an instance of the object to access the method that way.
Final Code
public enum NotificationType {
ENUM_TEST_1(MethodCalls::randomMethod);
public final BiFunction<MethodCalls,SomeBean,Void> method;
private NotificationType(BiFunction<MethodCalls,SomeBean,Void> method){
this.method=method;
}
}
So when I call the apply it looks like this:
public class TestClass{
#Autowired MethodCalls methodCalls;
public void testMethtod(){
NotificationType.ENUM_TEST_1.method.apply(methodCalls,new SomeBean())
}
}
I someone finds out a cleaner way to do this, I would apreciate it.

How can i create instance conditionally(by string) in Java?

I'm trying to create(initiate) instance conditionally.
I have an interface and there are several classes which implement the interface.
(e.g. interface named "itfc" and there class "classA", "classB", "classC"
when I get a string from outside, (e.g. "a") then I wanna make class of A
so, it can be written like this:
public class someClass {
itfc interface;
public someClass(String name) {
this.inteface = makeInstanceByName(name);
}
public makeInstanceByName(name) {
if (name == "A") { return new classA(); }
else if (name == "B") { return new classB(); }
...
else { return null; }
}
}
but I have lots of classes which implements the interface, and also this codes don't look good.
I've searched the enums, but I don't know how to apply it into my one.
Can you help me?
Try class.forName(String), e.g. something like
Class.forName("my.package.name.ClassPrefix" + name)
Also make sure you take care of proper exception handling.
Update: Here is a complete MCVE as a proof of concept which also shows you how to instantiate the class via reflection API. But in this case you need to make sure that each target class has a default (no-arguments) constructor.
package de.scrum_master.app;
public interface MyInterface {}
package de.scrum_master.app;
public class Foo implements MyInterface {}
package de.scrum_master.app;
public class Bar implements MyInterface {}
package de.scrum_master.app;
public class Zot implements MyInterface {}
package de.scrum_master.app;
public class UhOh /*implements MyInterface*/ {}
package de.scrum_master.app;
public class Application {
public static void main(String[] argv) throws Exception {
System.out.println(makeInstanceByName("Foo"));
System.out.println(makeInstanceByName("Bar"));
System.out.println(makeInstanceByName("Zot"));
System.out.println(makeInstanceByName("UhOh"));
}
public static MyInterface makeInstanceByName(String name) throws Exception {
return
(MyInterface) Class.forName("de.scrum_master.app." + name)
.getConstructor()
.newInstance();
}
}
Console log:
de.scrum_master.app.Foo#6d06d69c
de.scrum_master.app.Bar#7852e922
de.scrum_master.app.Zot#4e25154f
Exception in thread "main" java.lang.ClassCastException: de.scrum_master.app.UhOh cannot be cast to de.scrum_master.app.MyInterface
at de.scrum_master.app.Application.makeInstanceByName(Application.java:15)
at de.scrum_master.app.Application.main(Application.java:8)

generic factory method convention

Let me say there is an abstract class which looks like
abstract class Parent<V> {
protected static <T extends Parent<V>, V> T newInstance(
final Class<T> type, final V value) {
// ...
}
}
Within following Child class
class Child extends Parent<XXX> {
public static Child newInstance1(final XXX value) {
// ...
}
public static Parent<XXX> newInstance2(final XXX value) {
// ...
}
}
Which one is preferable? newInstance1 or newInstancw2?
It actually depends on the scenario in which you are you using the newInstance(). In most general cases:
Since Child is implementing newInstance(), According to me
protected static Child newInstance()
{
// ...
}
would be more appropriate.
Usually, factory method defined inside some class returns instance of this particular class, so it should be:
public class Foo ...
{
public static Foo newInstance ()
{
...
}
}
regardless of what class this class extends and what interfaces it implements.

How do you extend a Java class and change annotations?

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

Access static method on generic class

I'd like to access a static method on a class, but have that class passed in a generic.
I've done the following:
class Base{
public static String getStaticName(){
return "Base";
}
}
class Child extends Base{
public static String getStaticName(){
return "Child";
}
}
class StaticAccessor{
public static <T extends Base>String getName(Class<T> clazz){
return T.getStaticName();
}
}
StaticAccessor.getName() // --> "Base"
This will return "Base" but what i'd like is "Child" anybody a suggestion without reflections?
You can't do that without reflection, because the type T is erased at runtime (meaning it will be reduced to its lower bound, which is Base).
Since you do have access to a Class<T> you can do it with reflection, however:
return (String) clazz.getMethod("getStaticName").invoke(null);
Note that I'd consider such code to be code smell and that it is pretty fragile. Could you tell us why you need that?
If it is OK for you to pass an object instance rather than Class in your static accessor, then, there is a simple and elegant solution:
public class Test {
static class Base {
public static String getStaticName() { return "Base"; }
public String myOverridable() { return Base.getStaticName(); };
}
static class Child extends Base {
public static String getStaticName() { return "Child"; }
#Override
public String myOverridable() { return Child.getStaticName(); };
}
static class StaticAccessor {
public static <T extends Base>String getName(T instance) {
return instance.myOverridable();
}
}
public static void main(String[] args) {
Base b = new Base();
Child c = new Child();
System.out.println(StaticAccessor.getName(b));
System.out.println(StaticAccessor.getName(c));
}
}
The output is:
Base
Child
I don't believe you can do this without reflection.
It appears you should be doing is not using static methods. You are using inheritance but static methods do not follow inheritance rules.

Categories

Resources