15.11.1 小节 任何基本類型都不能作爲類型參數 的例子
import net.mindview.util.*;
// Fill an array using a generator:
class FArray {
public static <T> T[] fill(T[] a, Generator<T> gen) {
for(int i = 0; i < a.length; i++)
a[i] = gen.next();
return a;
}
}
public class PrimitiveGenericTest {
public static void main(String[] args) {
//书上没说这句会报错,但编译报错
String[] strings = FArray.fill(new String[7], new RandomGenerator.String(10));
for(String s : strings)
System.out.println(s);
//书上没说这句会报错,但编译报错
Integer[] integers = FArray.fill(new Integer[7], new RandomGenerator.Integer());
for(int i: integers)
System.out.println(i);
// Autoboxing won't save you here. This won't compile:这句确实会报错
int[] b = FArray.fill(new int[7], new RandomGenerator.Integer());
}
} /* Output:
这个例子很简单,只是想告诉我们,自动拆装箱,只能用在非数组的变量上。这里还得导入作者的 jar 包,很讨厌。(我想这里,作者是指,泛型方法的返回值,如果返回的 Integer[],不能拆箱为 int[])。顺着看这些作者写的类的源码,如下:
public class RandomGenerator {
//省略
public static class String extends net.mindview.util.CountingGenerator.String {
public String() {
this.cg = new RandomGenerator.Character();
}
public String(int length) {
super(length);
this.cg = new RandomGenerator.Character();
}
}
}
好了,这是一个静态内部类。但这个静态内部类还继承了别人,再去看:
public class CountingGenerator {
//省略
public static class String implements Generator<java.lang.String> {
private int length = 7;
Generator<java.lang.Character> cg = new CountingGenerator.Character();
public String() {
}
public String(int length) {
this.length = length;
}
public java.lang.String next() {
char[] buf = new char[this.length];
for(int i = 0; i < this.length; ++i) {
buf[i] = (java.lang.Character)this.cg.next();
}
return new java.lang.String(buf);
}
}
}
好了,找到源头了,原来它继承了 Generator<java.lang.String>,但我就不理解了,那为啥String[] strings = FArray.fill(new String[7], new RandomGenerator.String(10));
会报错呢?类型参数 T 推断成 String 不就皆大欢喜了吗,怎么它还说推断不出来了呢。
第二个报错也没理解。
1
cigarzh 2019-10-09 01:08:15 +08:00
你想让编译器推断成哪个 String ?
java.lang.String 还是 net.mindview.util.RandomGenerator.String? 编译器懵逼了 |
2
gIrl1990 2019-10-09 01:13:18 +08:00
试了下,执行成功,没报错。on eclipse (myeclipse)
```java public class GeneratorTest { public static void main(String[] args) { String[] strings = FArray.fill(new String[1], new RandomGenerator.String()); for (String s : strings) System.out.println(s); Integer[] integers = FArray.fill(new Integer[1], new RandomGenerator.Integer()); for (Integer i : integers) System.out.println(i); } static class FArray { public static <T> T[] fill(T[] a, Generator<T> gen) { for (int i = 0; i < a.length; i++) a[i] = gen.next(); return a; } } static interface Generator<T> { public default T next() { return null; } } static class RandomGenerator { public static class String implements Generator<java.lang.String> { } public static class Integer implements Generator<java.lang.Integer> { } } } ``` |
3
amiwrong123 OP @cigarzh
难道编译器真的会蒙蔽吗,我看 import 语句是 import net.mindview.util.*; 看图片,那个类 net.mindview.util.RandomGenerator.String,那么 import net.mindview.util.RandomGenerator.String 去掉导入的 net.mindview.util.*,这个名字应该是 RandomGenerator.String 啊,不会歧义啊== |
4
amiwrong123 OP @gIrl1990
有点奇怪了,那我导入作者的 jar 包就会出错。 |
5
guyeu 2019-10-09 10:23:53 +08:00
import 不会递归导入包下面所有的类。。
我猜二楼的 import 语句是 ide 帮忙做了一些事情 |
6
amiwrong123 OP @guyeu
@cigarzh @gIrl1990 找到原因了,因为我之前在当前工程里面新建了很多 java 文件(都是 java 编程思想的例子),有一个例子里面的接口刚好是也叫 Generator (但这个接口我给放到默认包下了),导致 fill 静态函数的那个形参的类型是默认包的 Generator,而不是 net.mindview.util 包的 Generator。 然后我单独再加一句 import net.mindview.util.Generator;就好了。。。 若若问一句,我都 import net.mindview.util.*;了,为啥编译器还是认为是默认包的 Generator,而不是 net.mindview.util 包的 Generator 呢?难道优先默认包的吗? |
7
gIrl1990 2019-10-10 00:50:34 +08:00
@guyeu 哈哈,我是单文件执行的,全拷贝放到一个类文件下。
@amiwrong123 你的意思是 PrimitiveGenericTest.java 同级目录下有个 Generator.java ?所以 PrimitiveGenericTest.java 优先使用了 Generator.java ?即使使用 import net.mindview.util.*?如果再加一个 import net.mindview.util.Generator;就正确了? 那我猜测是 import 的规则吧,比如有*的默认排后面,顺序是 1. import 没*的,2. 同级 package 下的,3. import 带*的 ps 我瞎猜的。 |
8
gIrl1990 2019-10-10 00:52:39 +08:00
@amiwrong123 你的意思是 PrimitiveGenericTest.java 同级目录下有个 Generator.java ?所以 PrimitiveGenericTest.java 优先使用了 Generator.java ?即使使用 import net.mindview.util.\*?如果再加一个 import net.mindview.util.Generator;就正确了? 那我猜测是 import 的规则吧,比如有\*的默认排后面,顺序是 1. import 没\*的,2. 同级 package 下的,3. import 带\*的 ps 我瞎猜的。
你的意思是 PrimitiveGenericTest.java 同级目录下有个 Generator.java ?所以 PrimitiveGenericTest.java 优先使用了 Generator.java ?即使使用 import net.mindview.util.*?如果再加一个 import net.mindview.util.Generator;就正确了? 那我猜测是 import 的规则吧,比如有*的默认排后面,顺序是 1. import 没*的,2. 同级 package 下的,3. import 带*的 ps 我瞎猜的。类似 css 的匹配就是有权重的 |