V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  Java

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

  •  
  •   amiwrong123 · 2019-10-08 23:33:24 +08:00 · 3514 次点击
    这是一个创建于 1873 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    第二个报错也没理解。 uhTmKs.png

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

    }
    ```
    amiwrong123
        3
    amiwrong123  
    OP
       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
        4
    amiwrong123  
    OP
       2019-10-09 09:48:32 +08:00
    @gIrl1990
    有点奇怪了,那我导入作者的 jar 包就会出错。
    guyeu
        5
    guyeu  
       2019-10-09 10:23:53 +08:00
    import 不会递归导入包下面所有的类。。
    我猜二楼的 import 语句是 ide 帮忙做了一些事情
    amiwrong123
        6
    amiwrong123  
    OP
       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
        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 我瞎猜的。
    gIrl1990
        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 的匹配就是有权重的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2644 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 05:51 · PVG 13:51 · LAX 21:51 · JFK 00:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.