Java 编程思想 一个小例子编译不过

2019-10-08 23:33:24 +08:00
 amiwrong123

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 不就皆大欢喜了吗,怎么它还说推断不出来了呢。

第二个报错也没理解。

3524 次点击
所在节点    Java
8 条回复
cigarzh
2019-10-09 01:08:15 +08:00
你想让编译器推断成哪个 String ?
java.lang.String 还是 net.mindview.util.RandomGenerator.String?
编译器懵逼了
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> {
}
}

}
```
amiwrong123
2019-10-09 09:46:11 +08:00
@cigarzh
难道编译器真的会蒙蔽吗,我看 import 语句是 import net.mindview.util.*; 看图片,那个类 net.mindview.util.RandomGenerator.String,那么 import net.mindview.util.RandomGenerator.String 去掉导入的 net.mindview.util.*,这个名字应该是 RandomGenerator.String 啊,不会歧义啊==
amiwrong123
2019-10-09 09:48:32 +08:00
@gIrl1990
有点奇怪了,那我导入作者的 jar 包就会出错。
guyeu
2019-10-09 10:23:53 +08:00
import 不会递归导入包下面所有的类。。
我猜二楼的 import 语句是 ide 帮忙做了一些事情
amiwrong123
2019-10-09 22:58:07 +08:00
@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 呢?难道优先默认包的吗?
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 我瞎猜的。
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 的匹配就是有权重的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/607250

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX