Spec-Zone.ru › Scala 2.13 Reflection

Трейт scala.reflect.api.Constants

Трейт Constants extends AnyRef

ЭКСПЕРИМЕНТАЛЬНО

Согласно разделу 6.24 «Выражения констант» спецификации языка Scala, некоторые выражения (называемые выражениями констант) могут быть вычислены компилятором Scala во время компиляции.

Экземпляры scala.reflect.api.Constants#Constant представляют определённые типы таких выражений (с значениями, хранящимися в поле value и его сильно типизированными представлениями, называемыми booleanValue, intValue и т.д.), а именно:

  1. Литералы примитивных типов (байты, короткие, целые, длинные, float, double, char, boolean и void).
  2. Строковые литералы.
  3. Ссылки на классы (обычно создаются с помощью scala.Predef#classOf).
  4. Ссылки на значения перечислений.

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

Пример

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

Ссылки на классы представлены экземплярами scala.reflect.api.Types#Type (потому что когда компилятор Scala обрабатывает ссылку на класс, подлежащий класс во время выполнения может еще не быть скомпилирован). Для преобразования такой ссылки в класс во время выполнения следует использовать метод runtimeClass зеркала, такого как scala.reflect.api.Mirrors#RuntimeMirror (простейший способ получить такое зеркало — использовать scala.reflect.runtime.package#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)).asInstanceOf[LiteralArgument].value

  val classRef = jarg("classRef").typeValue
  println(showRaw(classRef))             // TypeRef(ThisType(<empty>), JavaAnnottee, List())
  println(cm.runtimeClass(classRef))     // class JavaAnnottee

  val enumRef = jarg("enumRef").symbolValue
  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
}
Self Type
Universe
Source
Constants.scala
Линейные супертипы
AnyRef, Any
Известные подклассы
JavaUniverse, Universe, Universe

Типовые члены

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

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

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

К константам можно подходить с помощью совпадений и создавать их напрямую, как если бы они были классами-случаями:

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 могут содержать определённые типы этих выражений:

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

Ссылки на классы представлены экземплярами 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
}

абстрактный класс ConstantApi extends AnyRef

абстрактный класс ConstantExtractor extends AnyRef

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

абстрактный val Constant: Universe.ConstantExtractor

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

final def !=(arg0: Any): Boolean

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

final def ##(): Int

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

def +(other: String): String

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вany2stringadd[Constants] выполненного методом any2stringadd в scala.Predef.
Определяющие классы
any2stringadd

def ->[B](y: B): (Constants, B)

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вArrowAssoc[Constants] выполненного методом ArrowAssoc в scala.Predef.
Определяющие классы
ArrowAssoc
Аннотации
@inline()

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()

def ensuring(cond: (Constants) => Boolean, msg: => Any): Constants

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вEnsuring[Constants] выполненного методом Ensuring в scala.Predef.
Определяющие классы
Ensuring

def ensuring(cond: (Constants) => Boolean): Constants

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вEnsuring[Constants] выполненного методом Ensuring в scala.Predef.
Определяющие классы
Ensuring

def ensuring(cond: Boolean, msg: => Any): Constants

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вEnsuring[Constants] выполненного методом Ensuring в scala.Predef.
Определяющие классы
Ensuring

def ensuring(cond: Boolean): Constants

Неявное
Этот член добавлен с помощью неявного преобразования из Constants вEnsuring[Constants] выполненного методом Ensuring в scala.Predef.
Определяющие классы
Ensuring

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])

def formatted(fmtstr: String): String

Неявный
Этот член добавлен неявным преобразованием из Constants в StringFormat[Constants] с помощью метода StringFormat в scala.Predef.
Классы определений
StringFormat
Аннотации
@inline()

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.html

Spec-Zone.ru

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