You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Annotations associate meta-information with definitions. For example, the annotation `@deprecated` before a method causes the compiler to print a warning if the method is used.
14
-
```
14
+
15
+
{% tabs annotations_1 class=tabs-scala-version %}
16
+
{% tab 'Scala 2' for=annotations_1 %}
17
+
```scala mdoc:fail
15
18
objectDeprecationDemoextendsApp {
16
19
@deprecated("deprecation message", "release # which deprecates method")
17
20
defhello="hola"
18
21
19
-
hello
22
+
hello
20
23
}
21
24
```
25
+
{% endtab %}
26
+
{% tab 'Scala 3' for=annotations_1 %}
27
+
```scala
28
+
objectDeprecationDemoextendsApp:
29
+
@deprecated("deprecation message", "release # which deprecates method")
30
+
defhello="hola"
31
+
32
+
hello
33
+
```
34
+
{% endtab %}
35
+
{% endtabs %}
36
+
22
37
This will compile but the compiler will print a warning: "there was one deprecation warning".
23
38
24
39
An annotation clause applies to the first definition or declaration following it. More than one annotation clause may precede a definition and declaration. The order in which these clauses are given does not matter.
25
40
26
41
27
42
## Annotations that ensure correctness of encodings
28
43
Certain annotations will actually cause compilation to fail if a condition(s) is not met. For example, the annotation `@tailrec` ensures that a method is [tail-recursive](https://en.wikipedia.org/wiki/Tail_call). Tail-recursion can keep memory requirements constant. Here's how it's used in a method which calculates the factorial:
44
+
45
+
{% tabs annotations_2 class=tabs-scala-version %}
46
+
{% tab 'Scala 2' for=annotations_2 %}
29
47
```scala mdoc
30
48
importscala.annotation.tailrec
31
49
@@ -38,8 +56,26 @@ def factorial(x: Int): Int = {
38
56
factorialHelper(x, 1)
39
57
}
40
58
```
41
-
The `factorialHelper` method has the `@tailrec` which ensures the method is indeed tail-recursive. If we were to change the implementation of `factorialHelper` to the following, it would fail:
59
+
{% endtab %}
60
+
{% tab 'Scala 3' for=annotations_2 %}
61
+
```scala
62
+
importscala.annotation.tailrec
63
+
64
+
deffactorial(x: Int):Int=
65
+
66
+
@tailrec
67
+
deffactorialHelper(x: Int, accumulator: Int):Int=
68
+
if x ==1then accumulator else factorialHelper(x -1, accumulator * x)
69
+
factorialHelper(x, 1)
42
70
```
71
+
{% endtab %}
72
+
{% endtabs %}
73
+
74
+
The `factorialHelper` method has the `@tailrec` which ensures the method is indeed tail-recursive. If we were to change the implementation of `factorialHelper` to the following, it would fail:
75
+
76
+
{% tabs annotations_3 class=tabs-scala-version %}
77
+
{% tab 'Scala 2' for=annotations_3 %}
78
+
```scala mdoc:fail
43
79
importscala.annotation.tailrec
44
80
45
81
deffactorial(x: Int):Int= {
@@ -50,76 +86,134 @@ def factorial(x: Int): Int = {
50
86
factorialHelper(x)
51
87
}
52
88
```
53
-
We would get the message "Recursive call not in tail position".
89
+
{% endtab %}
90
+
{% tab 'Scala 3' for=annotations_3 %}
91
+
```scala
92
+
importscala.annotation.tailrec
54
93
94
+
deffactorial(x: Int):Int=
95
+
@tailrec
96
+
deffactorialHelper(x: Int):Int=
97
+
if x ==1then1else x * factorialHelper(x -1)
98
+
factorialHelper(x)
99
+
```
100
+
{% endtab %}
101
+
{% endtabs %}
102
+
103
+
We would get the message "Recursive call not in tail position".
55
104
56
105
## Annotations affecting code generation
106
+
107
+
{% tabs annotations_4 class=tabs-scala-version %}
108
+
{% tab 'Scala 2' for=annotations_4 %}
109
+
57
110
Some annotations like `@inline` affect the generated code (i.e. your jar file might have different bytes than if you hadn't used the annotation). Inlining means inserting the code in a method's body at the call site. The resulting bytecode is longer, but hopefully runs faster. Using the annotation `@inline` does not ensure that a method will be inlined, but it will cause the compiler to do it if and only if some heuristics about the size of the generated code are met.
58
111
112
+
{% endtab %}
113
+
{% tab 'Scala 3' for=annotations_4 %}
114
+
115
+
Some annotations like `@main` affect the generated code (i.e. your jar file might have different bytes than if you hadn't used the annotation). A `@main` annotation on a method generates an executable program that calls the method as an entry point.
116
+
117
+
{% endtab %}
118
+
{% endtabs %}
119
+
59
120
### Java Annotations ###
60
121
When writing Scala code which interoperates with Java, there are a few differences in annotation syntax to note.
61
122
**Note:** Make sure you use the `-target:jvm-1.8` option with Java annotations.
62
123
63
124
Java has user-defined metadata in the form of [annotations](https://docs.oracle.com/javase/tutorial/java/annotations/). A key feature of annotations is that they rely on specifying name-value pairs to initialize their elements. For instance, if we need an annotation to track the source of some class we might define it as
This syntax is quite tedious if the annotation contains only one element (without default value) so, by convention, if the name is specified as `value` it can be applied in Java using a constructor-like syntax:
89
162
90
-
```
163
+
{% tabs annotations_8 %}
164
+
{% tab 'Java'for=annotations_8 %}
165
+
```java
91
166
@interfaceSourceURL {
92
167
publicStringvalue();
93
168
publicStringmail() default "";
94
169
}
95
170
```
171
+
{% endtab %}
172
+
{% endtabs %}
96
173
97
-
And then apply it as follows
174
+
And then apply it as follows:
98
175
99
-
```
176
+
{% tabs annotations_9 %}
177
+
{% tab 'Java' for=annotations_9 %}
178
+
```java
100
179
@SourceURL("https://coders.com/")
101
-
public class MyClass extends TheirClass ...
180
+
publicclassMyJavaClassextendsTheirClass ...
102
181
```
182
+
{% endtab %}
183
+
{% endtabs %}
103
184
104
-
In this case, Scala provides the same possibility
185
+
Inthiscase, Scala provides the same possibility:
105
186
106
-
```
187
+
{% tabs annotations_10 %}
188
+
{% tab 'Scala 2 and 3'for=annotations_10 %}
189
+
```scala
107
190
@SourceURL("https://coders.com/")
108
191
classMyScalaClass ...
109
192
```
193
+
{% endtab %}
194
+
{% endtabs %}
110
195
111
-
The `mail` element was specified with a default value so we need not explicitly provide a value for it. However, if we need to do it we can not mix-and-match the two styles in Java:
196
+
The `mail` element was specified with a default value so we need not explicitly provide a value for it.
197
+
However, if we need to provide one then in Java we must also explicitly name the `value` parameter:
0 commit comments