1

I have the following code (most of it is just from another SE question, Scala returns no annotations for a field):

val cls = peripheral.getClass
import scala.reflect.runtime.universe._
val mirror = runtimeMirror(cls.getClassLoader)
val clsSymbol = mirror.staticClass(cls.getCanonicalName)
val decls = clsSymbol.toType.decls.filter(s => s"$s".startsWith("variable "))
for (d <- decls) {
  val classname = classOf[InjectExt].getCanonicalName
  val list = d.annotations.filter(v => v.toString equals classname)
  if (list.nonEmpty) {
    val annotation = list.head
    // what now?
  }
}

where InjectExt is the following Java annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectExt {
    String id() default "auto";
}

This works, but now I get this "annotation" that only has one method: tree(). What can I do to get my InjectExt.id()?
And also, the filtering by toString() really seems like a workaround, but it doesn't look like there's any isVariable or similar that I can use.

7
  • I agree, this all looks very hacky and complex for doing some simple reflection. What is your end goal ? Commented Mar 2, 2017 at 21:45
  • I have an object and for every field in that object that has an InjectExt annotation I want to set that field's value to an object determined by the "id" string in InjectExt. If that is "auto" it should be determined by the field type (the fields are defined as @InjectExt var whatever: TExtExample = _), in that case it will get set to an instance of TExtExample (I only need the class of TExtExample since I've already got the code that makes new objects). Commented Mar 2, 2017 at 22:44
  • @Dici here's the code I wrote using Java reflection but that didn't work since the annotations aren't there when using that. hastebin.com/wurosuhoni.py Commented Mar 3, 2017 at 9:55
  • Presumably if the annotation comes from Java with a runtime retention policy you should be able to access it pretty easily with Java reflection code (get the Method object and then find the annotation in getAnnotations or getDeclaredAnnotations depending on your use-case) Commented Mar 4, 2017 at 0:48
  • I modified my code to get all methods instead and filter on their annotations, but they all get filtered out on the second line again: hastebin.com/afegapuhov.php Commented Mar 4, 2017 at 9:43

1 Answer 1

2

Using pure Java reflection, you can get what you want with much less hassle. I find Scala reflection over-complicated.

object Test {
  class SomeClass {
    @InjectExt(id = "someCoolId") val myMember = 2
    @InjectExt(id = "someOtherCoolId") val myOtherMember = 2
  }

  def getFieldId(fieldName: String, someInstance: SomeClass): String = {
    val myMember = someInstance.getClass.getDeclaredField(fieldName)
    myMember.getDeclaredAnnotation(classOf[InjectExt]).id()
  }

  def main(args: Array[String]): Unit = {
    println(getFieldId("myMember", new SomeClass))
    println(getFieldId("myOtherMember", new SomeClass))
  }
}

Output:

someCoolId
someOtherCoolId

If I were you, I would avoid using Scala reflection unless I cannot do what I want using Java reflection.

Sign up to request clarification or add additional context in comments.

1 Comment

That works! Somehow getDeclaredAnnotations() didn't list the annotation, but getDeclaredAnnotation() did!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.