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
64
125
65
-
```
126
+
{% tabs annotations_5 %}
127
+
{% tab 'Java' for=annotations_5 %}
128
+
```java
66
129
@interfaceSource {
67
-
public String URL();
130
+
publicStringurl();
68
131
publicStringmail();
69
132
}
70
133
```
134
+
{% endtab %}
135
+
{% endtabs %}
71
136
72
137
And then apply it as follows
73
138
74
-
```
75
-
@Source(URL = "https://coders.com/",
139
+
{% tabs annotations_6 %}
140
+
{% tab 'Java' for=annotations_6 %}
141
+
```java
142
+
@Source(url="https://coders.com/",
76
143
mail="support@coders.com")
77
-
public class MyClass extends TheirClass ...
144
+
publicclassMyJavaClassextendsTheirClass ...
78
145
```
146
+
{% endtab %}
147
+
{% endtabs %}
79
148
80
149
An annotation application in Scala looks like a constructor invocation, for instantiating a Java annotation one has to use named arguments:
81
150
82
-
```
83
-
@Source(URL = "https://coders.com/",
151
+
{% tabs annotations_7 %}
152
+
{% tab 'Scala 2 and 3'for=annotations_7 %}
153
+
```scala
154
+
@Source(url="https://coders.com/",
84
155
mail="support@coders.com")
85
156
classMyScalaClass ...
86
157
```
158
+
{% endtab %}
159
+
{% endtabs %}
87
160
88
161
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:
112
198
113
-
```
199
+
{% tabs annotations_11 %}
200
+
{% tab 'Java'for=annotations_11 %}
201
+
```java
114
202
@SourceURL(value="https://coders.com/",
115
203
mail="support@coders.com")
116
-
public class MyClass extends TheirClass ...
204
+
publicclassMyJavaClassextendsTheirClass ...
117
205
```
206
+
{% endtab %}
207
+
{% endtabs %}
118
208
119
-
Scala provides more flexibility in this respect
209
+
Scala provides more flexibility in this respect, so we can choose to only name the `mail` parameter:
0 commit comments