获取带有注释的所有类,并将它们添加到android中的hashMap

时间:2018-06-20 19:24:04

标签: java android hashmap annotations

我不确定这是否可行,但是我基本上希望能够通过添加带有特殊注释的类来轻松地将新项目添加到列表中。我能想到的唯一示例就是我目前正在从事的工作。用户可以完成很多“挑战”,目前我的应用程序中有一个用于“挑战”的程序包,我希望能够在该程序包中创建一个新类,并为其添加一些注释值,例如...

@Challenge(key="new_challenge")
public class NewChallenge extends Achievement {... }

每个挑战的键都不同,它将是挑战名称,然后在我的代码中,我希望能够将所有键都以“键”作为哈希映射键添加到HashMap中。 map.add( annotationkey class );听起来这应该是可行和可行的。我想知道,如果可能,这是否是正确的做法,以及如何做到?

EDIT1 我能够使用gradle实现反射,但是它总是空着。根本找不到注释。这就是我的方式。

Challenge.java

package com.test.annotationtest.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Challenge {
  public String key();
}

那我面临的挑战之一就是... TestChallenge.java

package com.test.annotationtest.challenges

import com.test.annotationtest.R;
import com.test.annotationtest.annotation.Challenge;

@Challenge(key="test_challenge")
public class TestChallenge extends Achievement {
  public String name = "Test Challenge";
  public TestChallenge() {}
}

然后在我的主要活动中,我有... MainActivity.java

package com.test.annotationtest;
import...

public class MainActivity extends AppCompatActivity {
  public Reflections reflections = new Reflections("com.test"); // have tried "com.test.annotationtest" and "com.test.annotationtest.challenges"
  public static Map<String, Achievement> achievements;
  public static List<String> names = new ArrayList<>();

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    achievements = getClasses();
    //setup recycler view and all that to show achievements
  }

  public Map<String, Achievement> getClasses() {
    Set<Class<?>> challengeClasses = reflections.getTypesAnnotatedWith(Challenge.class);
    Log.d("Main Activity", "The Challenges");
    Log.d("MAin Activity", "How many are there? " + Integer.toString(challengeClasses.size());
    //more processing on them;
  }
}

,但是每次我在模拟器上运行该应用程序时,它就会在logcat中显示。 主要活动:挑战 主要活动:有多少人? 0

我在Challenge包中有9个类,所有类都用@Challenge(key =“ name”)进行了注释,但没有一个通过getTypesAnnotatedWith return反射出现。每个人的“名称”都不相同。任何帮助,将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:1)

您可以创建自己的注释:

@Retention(RetentionPolicy.RUNTIME)
public @interface Challenge {
    public String key() default "";

}

然后,您可以使用Reflections获取所有带注释的类。

Set<Class<?>> challengeClasses = reflections.getTypesAnnotatedWith(Challenge.class);

然后您可以通过以下方式提取密钥:

String key = challengeClass.getAnnotation(Challenge.class).key();

但是请注意,只有在确实必要时,才应谨慎使用反射。通过使用它,您将失去对代码正确性的控制。

示例:

com.test.webapp.Main

package com.test.testapp;

import com.test.testapp.annotations.Challenge;
import org.reflections.Reflections;

import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Reflections reflections = new Reflections("com.test.testapp");

        Set<Class<?>> challengeClasses = reflections.getTypesAnnotatedWith(Challenge.class);
        Map challengeClassesMap = challengeClasses.stream().collect(
                                                            Collectors.toMap(
                                                                    challengeClass -> challengeClass.getAnnotation(Challenge.class).key(),
                                                                    Main::createNewInstanceOfClass
                                                            )
        );

        challengeClassesMap.forEach(
                (key, challengeClass) -> System.out.println(key + " = " + challengeClass.toString())
        );
    }

    private static <T> T createNewInstanceOfClass(Class<T> someClass) {
        try {
            return someClass.newInstance();
        } catch (Exception e) {
            return null; //Bad idea but now it's waste of time
        }
    }
}

com.test.testapp.annotations.Challenge

package com.test.testapp.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Challenge {
    public String key();
}

com.test.testapp.challenges.SomeChallenge

package com.test.testapp.challenges;

import com.test.testapp.annotations.Challenge;

@Challenge(key = "some_challenge")
public class SomeChallenge {
    public String name = "Some Challenge";

    @Override
    public String toString() {
        return "SomeChallenge{" +
                "name='" + name + '\'' +
                '}';
    }
}

com.test.testapp.challenges。另一个挑战

package com.test.testapp.challenges;

import com.test.testapp.annotations.Challenge;

@Challenge(key = "another_challenge")
public class AnotherChallenge {
    public String name = "Another Challenge";

    @Override
    public String toString() {
        return "AnotherChallenge{" +
                "name='" + name + '\'' +
                '}';
    }
}

pom.xml依赖项(我正在使用Maven)

<dependency>
        <groupId>org.reflections</groupId>
        <artifactId>reflections</artifactId>
        <version>0.9.11</version>
</dependency>

输出

some_challenge = SomeChallenge{name='Some Challenge'}
another_challenge = AnotherChallenge{name='Another Challenge'}

我没有更多的代码。目录与软件包相同。