Skip to content

Commit a3a0d44

Browse files
committed
Fix issue 117, 翻译数组部分 五,六,七三个小节
Signed-off-by: cogitates <[email protected]>
1 parent 2907703 commit a3a0d44

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed

docs/book/21-Arrays.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,250 @@ Lazy, Brown, Dog, &, friend]]
574574
<!-- Arrays and Generics -->
575575
## 泛型数组
576576

577+
一般来说,数组和泛型并不能很好的结合。你不能实例化参数化类型的数组:
578+
579+
```Java
580+
Peel<Banana>[] peels = new Peel<Banana>[10]; // Illegal
581+
```
582+
583+
类型擦除需要删除参数类型信息,而且数组必须知道它们所保存的确切类型,以强制保证类型安全。
584+
585+
但是,可以参数化数组本身的类型:
586+
587+
```Java
588+
// arrays/ParameterizedArrayType.java
589+
590+
class ClassParameter<T> {
591+
public T[] f(T[] arg) { return arg; }
592+
}
593+
594+
class MethodParameter {
595+
public static <T> T[] f(T[] arg) { return arg; }
596+
}
597+
598+
public class ParameterizedArrayType {
599+
public static void main(String[] args) {
600+
Integer[] ints = { 1, 2, 3, 4, 5 };
601+
Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
602+
Integer[] ints2 =
603+
new ClassParameter<Integer>().f(ints);
604+
Double[] doubles2 =
605+
new ClassParameter<Double>().f(doubles);
606+
ints2 = MethodParameter.f(ints);
607+
doubles2 = MethodParameter.f(doubles);
608+
}
609+
}
610+
```
611+
612+
比起使用参数化类,使用参数化方法很方便。您不必为应用它的每个不同类型都实例化一个带有参数的类,但是可以使它成为 **静态** 的。你不能总是选择使用参数化方法而不用参数化的类,但通常参数化方法是更好的选择。
613+
614+
你不能创建泛型类型的数组,这种说法并不完全正确。是的,编译器不会让你 *实例化* 一个泛型的数组。但是,它将允许您创建对此类数组的引用。例如:
615+
616+
```Java
617+
List<String>[] ls;
618+
```
619+
620+
无可争议的,这可以通过编译。尽管不能创建包含泛型的实际数组对象,但是你可以创建一个非泛型的数组并对其进行强制类型转换:
621+
622+
```Java
623+
// arrays/ArrayOfGenerics.java
624+
import java.util.*;
625+
626+
public class ArrayOfGenerics {
627+
@SuppressWarnings("unchecked")
628+
public static void main(String[] args) {
629+
List<String>[] ls;
630+
List[] la = new List[10];
631+
ls = (List<String>[])la; // Unchecked cast
632+
ls[0] = new ArrayList<>();
633+
634+
//- ls[1] = new ArrayList<Integer>();
635+
// error: incompatible types: ArrayList<Integer>
636+
// cannot be converted to List<String>
637+
// ls[1] = new ArrayList<Integer>();
638+
// ^
639+
640+
// The problem: List<String> is a subtype of Object
641+
Object[] objects = ls; // So assignment is OK
642+
// Compiles and runs without complaint:
643+
objects[1] = new ArrayList<>();
644+
645+
// However, if your needs are straightforward it is
646+
// possible to create an array of generics, albeit
647+
// with an "unchecked cast" warning:
648+
List<BerylliumSphere>[] spheres =
649+
(List<BerylliumSphere>[])new List[10];
650+
Arrays.setAll(spheres, n -> new ArrayList<>());
651+
}
652+
}
653+
```
654+
655+
一旦你有了对 **List<String>[]** 的引用 , 你会发现多了一些编译时检查。问题是数组是协变的,所以 **List<String>[]** 也是一个 **Object[]** ,你可以用这来将 **ArrayList<Integer> ** 分配进你的数组,在编译或者运行时都不会出错。
656+
657+
如果你知道你不会进行向上类型转换,你的需求相对简单,那么可以创建一个泛型数组,它将提供基本的编译时类型检查。然而,一个泛型 **Collection** 实际上是一个比泛型数组更好的选择。
658+
659+
一般来说,您会发现泛型在类或方法的边界上是有效的。在内部,擦除常常会使泛型不可使用。所以,就像下面的例子,不能创建泛型类型的数组:
660+
661+
```Java
662+
// arrays/ArrayOfGenericType.java
663+
664+
public class ArrayOfGenericType<T> {
665+
T[] array; // OK
666+
@SuppressWarnings("unchecked")
667+
public ArrayOfGenericType(int size) {
668+
// error: generic array creation:
669+
//- array = new T[size];
670+
array = (T[])new Object[size]; // unchecked cast
671+
}
672+
// error: generic array creation:
673+
//- public <U> U[] makeArray() { return new U[10]; }
674+
}
675+
676+
```
677+
678+
擦除再次从中作梗,这个例子试图创建已经擦除的类型数组,因此它们是未知的类型。你可以创建一个 **对象** 数组,然后对其进行强制类型转换,但如果没有 **@SuppressWarnings** 注释,你将会得到一个 "unchecked" 警告,因为数组实际上不真正支持而且将对类型 **T** 动态检查 。这就是说,如果我创建了一个 **String[]** , Java将在编译时和运行时强制执行,我只能在数组中放置字符串对象。然而,如果我创建一个 **Object[]** ,我可以把除了基元类型外的任何东西放入数组。
679+
680+
577681

578682
<!-- Arrays.fill() -->
579683
## Arrays的fill方法
580684

685+
通常情况下,当对数组和程序进行实验时,能够很轻易地生成充满测试数据的数组是很有帮助的。 Java 标准库 **Arrays** 类包括一个普通的 **fill()** 方法,该方法将单个值复制到整个数组,或者在对象数组的情况下,将相同的引用复制到整个数组:
686+
687+
```Java
688+
// arrays/FillingArrays.java
689+
// Using Arrays.fill()
690+
import java.util.*;
691+
import static onjava.ArrayShow.*;
692+
693+
public class FillingArrays {
694+
public static void main(String[] args) {
695+
int size = 6;
696+
boolean[] a1 = new boolean[size];
697+
byte[] a2 = new byte[size];
698+
char[] a3 = new char[size];
699+
short[] a4 = new short[size];
700+
int[] a5 = new int[size];
701+
long[] a6 = new long[size];
702+
float[] a7 = new float[size];
703+
double[] a8 = new double[size];
704+
String[] a9 = new String[size];
705+
Arrays.fill(a1, true);
706+
show("a1", a1);
707+
Arrays.fill(a2, (byte)11);
708+
show("a2", a2);
709+
Arrays.fill(a3, 'x');
710+
show("a3", a3);
711+
Arrays.fill(a4, (short)17);
712+
show("a4", a4);
713+
Arrays.fill(a5, 19);
714+
show("a5", a5);
715+
Arrays.fill(a6, 23);
716+
show("a6", a6);
717+
Arrays.fill(a7, 29);
718+
show("a7", a7);
719+
Arrays.fill(a8, 47);
720+
show("a8", a8);
721+
Arrays.fill(a9, "Hello");
722+
show("a9", a9);
723+
// Manipulating ranges:
724+
Arrays.fill(a9, 3, 5, "World");
725+
show("a9", a9);
726+
}
727+
}gedan
728+
/* Output:
729+
a1: [true, true, true, true, true, true]
730+
a2: [11, 11, 11, 11, 11, 11]
731+
a3: [x, x, x, x, x, x]
732+
a4: [17, 17, 17, 17, 17, 17]
733+
a5: [19, 19, 19, 19, 19, 19]
734+
a6: [23, 23, 23, 23, 23, 23]
735+
a7: [29.0, 29.0, 29.0, 29.0, 29.0, 29.0]
736+
a8: [47.0, 47.0, 47.0, 47.0, 47.0, 47.0]
737+
a9: [Hello, Hello, Hello, Hello, Hello, Hello]
738+
a9: [Hello, Hello, Hello, World, World, Hello]
739+
*/
740+
741+
```
742+
743+
你既可以填充整个数组,也可以像最后两个语句所示,填充一系列的元素。但是由于你只能使用单个值调用 **Arrays.fill()** ,因此结果并非特别有用。
744+
581745

582746
<!-- Arrays.setAll() -->
583747
## Arrays的setAll方法
584748

749+
Java 8中, 在**RaggedArray.java** 中引入并在 **ArrayOfGenerics.java.Array.setAll()** 中重用。它使用一个生成器并生成不同的值,可以选择基于数组的索引元素(通过访问当前索引,生成器可以读取数组值并对其进行修改)。 **static Arrays.setAll()** 的重载签名为:
750+
751+
* **void setAll(int[] a, IntUnaryOperator gen)**
752+
* **void setAll(long[] a, IntToLongFunction gen)**
753+
* **void setAll(double[] a, IntToDoubleFunctiongen)**
754+
* **<T> void setAll(T[] a, IntFunction<? extendsT> gen)**
755+
756+
除了 **int** , **long** , **double** 有特殊的版本,其他的一切都由泛型版本处理。生成器不是 **Supplier** 因为它们不带参数,并且必须将 **int** 数组索引作为参数。
757+
758+
```java
759+
// arrays/SimpleSetAll.java
760+
761+
import java.util.*;
762+
import static onjava.ArrayShow.*;
763+
764+
class Bob {
765+
final int id;
766+
Bob(int n) { id = n; }
767+
@Override
768+
public String toString() { return "Bob" + id; }
769+
}
770+
771+
public class SimpleSetAll {
772+
public static final int SZ = 8;
773+
static int val = 1;
774+
static char[] chars = "abcdefghijklmnopqrstuvwxyz"
775+
.toCharArray();
776+
static char getChar(int n) { return chars[n]; }
777+
public static void main(String[] args) {
778+
int[] ia = new int[SZ];
779+
long[] la = new long[SZ];
780+
double[] da = new double[SZ];
781+
Arrays.setAll(ia, n -> n); // [1]
782+
Arrays.setAll(la, n -> n);
783+
Arrays.setAll(da, n -> n);
784+
show(ia);
785+
show(la);
786+
show(da);
787+
Arrays.setAll(ia, n -> val++); // [2]
788+
Arrays.setAll(la, n -> val++);
789+
Arrays.setAll(da, n -> val++);
790+
show(ia);
791+
show(la);
792+
show(da);
793+
794+
Bob[] ba = new Bob[SZ];
795+
Arrays.setAll(ba, Bob::new); // [3]
796+
show(ba);
797+
798+
Character[] ca = new Character[SZ];
799+
Arrays.setAll(ca, SimpleSetAll::getChar); // [4]
800+
show(ca);
801+
}
802+
}
803+
/* Output:
804+
[0, 1, 2, 3, 4, 5, 6, 7]
805+
[0, 1, 2, 3, 4, 5, 6, 7]
806+
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
807+
[1, 2, 3, 4, 5, 6, 7, 8]
808+
[9, 10, 11, 12, 13, 14, 15, 16]
809+
[17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0]
810+
[Bob0, Bob1, Bob2, Bob3, Bob4, Bob5, Bob6, Bob7]
811+
[a, b, c, d, e, f, g, h]
812+
*/
813+
814+
```
815+
816+
* **[1]** 这里,我们只是将数组索引作为值插入数组。这将自动转化为 **long****double** 版本。
817+
* **[2]** 这个函数只需要接受索引就能产生正确结果。这个,我们忽略索引值并且使用 **val** 生成结果。
818+
* **[3]** 方法引用有效,因为 **Bob** 的构造器接收一个 **int** 参数。只要我们传递的函数接收一个 **int** 参数且能产生正确的结果,就认为它完成了工作。
819+
* **[4]** 为了处理除了 **int****long****double** 之外的基元类型,请为基元创建包装类的数组。然后使用 **setAll()** 的泛型版本。请注意,**getChar()** 生成基元类型,因此这是自动装箱到 **Character**
820+
585821

586822
<!-- Incremental Generators -->
587823
## 增量生成

0 commit comments

Comments
 (0)