Spec-Zone.ru › Scala 2.13 Reflection

Аннотация scala.reflect.api.Constants.Constant

Компаньон класс ConstantExtractor

абстрактный тип Constant >: Null <: Universe.ConstantApi

Этот "виртуальный" класс-case представляет интерфейс рефлексии для литеральных выражений, которые не могут быть далее разложены или оценены, такие как "true", "0", "classOf[List]". Такие значения становятся частями абстрактного синтаксического дерева Scala, представляющего программу. Константы соответствуют разделу 6.24 "Постоянные выражения" Спецификации языка Scala.

Такие константы используются для представления литералов в абстрактных синтаксических деревьях (узел scala.reflect.api.Trees#Literal) и литеральных аргументов для аннотаций файлов Java-классов (класс scala.reflect.api.Annotations#LiteralArgument).

Константы могут быть сопоставлены и могут быть построены напрямую, как будто они были классами case:

assert(Constant(true).value == true)
Constant(true) match {
  case Constant(s: String) =>  println("A string: " + s)
  case Constant(b: Boolean) => println("A boolean value: " + b)
  case Constant(x) =>          println("Something else: " + x)
}

Constant экземпляры могут оборачивать определенные типы этих выражений:

  1. Литералы примитивных классов значений (Byte, Short, Int, Long, Float, Double, Char, Boolean и Unit) - представлены непосредственно соответствующим типом
  2. Строковые литералы — представлены как экземпляры String.
  3. Ссылки на классы, обычно создаваемые с помощью scala.Predef#classOf — представлены как типы.
  4. Ссылки на значения перечислений — представлены как символы.

Ссылки на классы представлены как экземпляры scala.reflect.api.Types#Type (потому что при обработке компилятором Scala ссылки на классы, базового времени выполнения класс может еще не быть скомпилирован). Чтобы преобразовать такую ссылку в класс времени выполнения, следует использовать метод runtimeClass зеркала, такого как RuntimeMirror (самый простой способ получения такого зеркала — использовать scala.reflect.runtime.currentMirror).

Ссылки на значения перечислений представлены как экземпляры scala.reflect.api.Symbols#Symbol, которые в JVM указывают на методы, возвращающие базовые значения перечислений. Чтобы просмотреть базовое перечисление или получить значение времени выполнения ссылки на перечисление, необходимо использовать scala.reflect.api.Mirrors#RuntimeMirror (самый простой способ получения такого зеркала — опять же scala.reflect.runtime.package#currentMirror).

Пример использования:

enum JavaSimpleEnumeration { FOO, BAR }

import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface JavaSimpleAnnotation {
  Class<?> classRef();
  JavaSimpleEnumeration enumRef();
}

@JavaSimpleAnnotation(
  classRef = JavaAnnottee.class,
  enumRef = JavaSimpleEnumeration.BAR
)
public class JavaAnnottee {}
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}

object Test extends App {
  val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs
  def jarg(name: String) = jann(TermName(name)) match {
    // Constant is always wrapped into a Literal or LiteralArgument tree node
    case LiteralArgument(ct: Constant) => value
  }

  val classRef = jarg("classRef").value.asInstanceOf[Type]
                                         // ideally one should match instead of casting
  println(showRaw(classRef))             // TypeRef(ThisType(<empty>), JavaAnnottee, List())
  println(cm.runtimeClass(classRef))     // class JavaAnnottee

  val enumRef = jarg("enumRef").value.asInstanceOf[Symbol]
                                         // ideally one should match instead of casting
  println(enumRef)                       // value BAR

  val siblings = enumRef.owner.info.decls
  val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic)
  println(enumValues)                    // Scope{
                                         //   final val FOO: JavaSimpleEnumeration;
                                         //   final val BAR: JavaSimpleEnumeration
                                         // }

  // doesn't work because of https://github.com/scala/bug/issues/6459
  // val enumValue = mirror.reflectField(enumRef.asTerm).get
  val enumClass = cm.runtimeClass(enumRef.owner.asClass)
  val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null)
  println(enumValue)                     // BAR
}
Источник
Constants.scala
Линейные супертипы
Universe.ConstantApi, AnyRef, Any

Абстрактные члены-значения

абстрактный def tpe: Universe.Type

Тип Scala, описывающий константу. Он генерируется автоматически на основе типа значения.

Определяющие классы
ConstantApi

абстрактный val value: Any

Загрузка константы, к которой можно получить доступ напрямую или к которой можно применить сопоставление с образцом.

Определяющие классы
ConstantApi

Члены конкретных значений

final def !=(arg0: Any): Boolean

Определяющие классы
AnyRef → Any

final def ##(): Int

Определяющие классы
AnyRef → Any

final def ==(arg0: Any): Boolean

Определяющие классы
AnyRef → Any

final def asInstanceOf[T0]: T0

Определяющие классы
Any

def clone(): AnyRef

Атрибуты
protected[java.lang]
Определяющие классы
AnyRef
Аннотации
@throws(classOf[java.lang.CloneNotSupportedException]) @native()

final def eq(arg0: AnyRef): Boolean

Определяющие классы
AnyRef

def equals(arg0: AnyRef): Boolean

Определяющие классы
AnyRef → Any

def finalize(): Unit

Атрибуты
protected[java.lang]
Определяющие классы
AnyRef
Аннотации
@throws(classOf[java.lang.Throwable])

final def getClass(): Class[_ <: AnyRef]

Определяющие классы
AnyRef → Any
Аннотации
@native()

def hashCode(): Int

Определяющие классы
AnyRef → Any
Аннотации
@native()

final def isInstanceOf[T0]: Boolean

Определяющие классы
Any

final def ne(arg0: AnyRef): Boolean

Определяющие классы
AnyRef

final def notify(): Unit

Определяющие классы
AnyRef
Аннотации
@native()

final def notifyAll(): Unit

Определяющие классы
AnyRef
Аннотации
@native()

final def synchronized[T0](arg0: => T0): T0

Определяющие классы
AnyRef

def toString(): String

Определяющие классы
AnyRef → Any

final def wait(): Unit

Определяющие классы
AnyRef
Аннотации
@throws(classOf[java.lang.InterruptedException])

final def wait(arg0: Long, arg1: Int): Unit

Определяющие классы
AnyRef
Аннотации
@throws(classOf[java.lang.InterruptedException])

final def wait(arg0: Long): Unit

Определяющие классы
AnyRef
Аннотации
@throws(classOf[java.lang.InterruptedException]) @native()

© 2002-2019 EPFL, with contributions from Lightbend.
Licensed under the Apache License, Version 2.0.
https://www.scala-lang.org/api/2.13.0/scala-reflect/scala/reflect/api/Constants$Constant.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API