Skip to content

Commit eba2f4c

Browse files
authored
Merge pull request #1210 from realwunan/annotations
Simplify Chinese translation of Scala Tour: annotations.md
2 parents db4042a + 4a7271a commit eba2f4c

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

_zh-cn/tour/annotations.md

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: tour
3-
title: Annotations
3+
title: 注解
44

55
discourse: false
66

@@ -13,3 +13,114 @@ language: zh-cn
1313
next-page: default-parameter-values
1414
previous-page: by-name-parameters
1515
---
16+
17+
注解将元信息与定义相关联。 例如,方法之前的注解 `@deprecated` 会导致编译器在该方法被使用时打印警告信息。
18+
```
19+
object DeprecationDemo extends App {
20+
@deprecated("deprecation message", "release # which deprecates method")
21+
def hello = "hola"
22+
23+
hello
24+
}
25+
```
26+
这个程序可以编译,但编译器将打印一个警告信息: "there was one deprecation warning"。
27+
28+
注解作用于其后的第一个定义或声明。 在定义和声明之前可以有多个注解。 这些注解的顺序并不重要。
29+
30+
## 确保编码正确性的注解
31+
如果不满足条件,某些注解实际上会导致编译失败。 例如,注解 `@tailrec` 确保方法是 [尾递归](https://en.wikipedia.org/wiki/Tail_call)。 尾递归可以保持内存需求不变。 以下是它在计算阶乘的方法中的用法:
32+
```tut
33+
import scala.annotation.tailrec
34+
35+
def factorial(x: Int): Int = {
36+
37+
@tailrec
38+
def factorialHelper(x: Int, accumulator: Int): Int = {
39+
if (x == 1) accumulator else factorialHelper(x - 1, accumulator * x)
40+
}
41+
factorialHelper(x, 1)
42+
}
43+
```
44+
方法 `factorialHelper` 使用注解 `@tailrec` 确保方法确实是尾递归的。 如果我们将方法 `factorialHelper` 的实现改为以下内容,它将编译失败:
45+
```
46+
import scala.annotation.tailrec
47+
48+
def factorial(x: Int): Int = {
49+
@tailrec
50+
def factorialHelper(x: Int): Int = {
51+
if (x == 1) 1 else x * factorialHelper(x - 1)
52+
}
53+
factorialHelper(x)
54+
}
55+
```
56+
我们将得到一个错误信息 "Recursive call not in tail position".
57+
58+
59+
## 影响代码生成的注解
60+
`@inline` 这样的注解会影响生成的代码(即你的 jar 文件可能与你没有使用注解时有不同的字节)。 内联表示在调用点插入被调用方法体中的代码。 生成的字节码更长,但有希望能运行得更快。 使用注解 `@inline` 并不能确保方法内联,当且仅当满足某些生成代码大小的启发式算法时,它才会触发编译器执行此操作。
61+
62+
### Java 注解 ###
63+
在编写与 Java 互操作的 Scala 代码时,注解语法中存在一些差异需要注意。
64+
**注意:** 确保你在开启 `-target:jvm-1.8` 选项时使用 Java 注解。
65+
66+
Java 注解有用户自定义元数据的形式 ,参考 [annotations](https://docs.oracle.com/javase/tutorial/java/annotations/) 。 注解的一个关键特性是它们依赖于指定 name-value 对来初始化它们的元素。 例如,如果我们需要一个注解来跟踪某个类的来源,我们可以将其定义为
67+
```
68+
@interface Source {
69+
public String URL();
70+
public String mail();
71+
}
72+
```
73+
74+
并且按如下方式使用它
75+
76+
```
77+
@Source(URL = "http://coders.com/",
78+
mail = "support@coders.com")
79+
public class MyClass extends HisClass ...
80+
```
81+
82+
Scala 中的注解应用看起来像构造函数调用,要实例化 Java 注解,必须使用命名参数:
83+
84+
```
85+
@Source(URL = "http://coders.com/",
86+
mail = "support@coders.com")
87+
class MyScalaClass ...
88+
```
89+
90+
如果注解只包含一个元素(没有默认值),则此语法非常繁琐,因此,按照惯例,如果将元素名称指定为 `value`,则可以使用类似构造函数的语法在 Java 中应用它:
91+
```
92+
@interface SourceURL {
93+
public String value();
94+
public String mail() default "";
95+
}
96+
```
97+
98+
然后按如下方式使用
99+
100+
```
101+
@SourceURL("http://coders.com/")
102+
public class MyClass extends HisClass ...
103+
```
104+
105+
在这种情况下, Scala 提供了相同的可能性
106+
107+
```
108+
@SourceURL("http://coders.com/")
109+
class MyScalaClass ...
110+
```
111+
112+
`mail` 元素在定义时设有默认值,因此我们不需要显式地为它提供值。 但是,如果我们需要显示地提供值,我们则不能在 Java 中混合使用这两种方式:
113+
114+
```
115+
@SourceURL(value = "http://coders.com/",
116+
mail = "support@coders.com")
117+
public class MyClass extends HisClass ...
118+
```
119+
120+
Scala 在这方面提供了更大的灵活性
121+
122+
```
123+
@SourceURL("http://coders.com/",
124+
mail = "support@coders.com")
125+
class MyScalaClass ...
126+
```

0 commit comments

Comments
 (0)