我们真的了解泛型吗?--从一个不菜的泛型菜问题中发现的问题

一、疑问-我们真的了解java 泛型吗?

二、困惑-不菜的泛型菜问题

三、突破-VectortoArray()方法

四、结局-掀起你的盖头来

五、小结

六、附件

一、  疑问-我们真的了解java 泛型吗?

我以为对泛型已经很熟悉了。如果别人问泛型是什么?我会举一个简单的例子,比如

    Vector<String> sv = new Vector<String>();

就用到了泛型,这样写代码的一个明显的好处就是以后不用类型检查。比如

    String s = sv.get(i);

一点

    for (Iterator<String> it = sv.iterator(); it.hasNext(); ) {

        s = it.next();

    }  

另外jsdk还提供了ArraysCollections两个类,其中包含了大量操作数组和Collection的方法。总之java中使用泛型很方便也很简单。

 

Java Tutorial中介绍了java泛型的很多好处,其中印象最深的是这句

 

Historically, collections frameworks have been quite complex...

We believe that the Java Collections Framework breaks with this tradition.

 

今天我才明白JavaTutorial介绍的是Collections Framework不是真正的泛型。Java使用泛型实现了Collections Framework,并封装起来,我们所能看到的仅仅是冰山一角。

二、  困惑-不菜的泛型菜问题

这得从我前天在csdn看到的一个问题(一个泛型的菜问题)说起。楼主看到一条这样的语句,不知道是什么意思。

public static <K,V> Map<K,V> newHashMap()

我也觉得很奇怪。当时第一放映,这只是个语法结构的描述,不是真正意义的语句。在真正语句里<K, V>应该用具体的类来代替。因为不知道出处,为了证明,只好自己写代码。

首先,根据我的思路,我写了一个static方法,

    public static <String, Integer> Map<String, Integer> newHashMap1() {

        HashMap<String, Integer> map = new HashMap<String, Integer>();

        return map;

    }

编译通过。但还没来得及高兴,发现问题了。当我在其中加入这两条语句时,

        symbol  : method valueOf(int)

        map.put("1", Integer.valueOf(1));

却无法编译,提示如下信息:

TestGenericSyntax.java:10: cannot find symbol

其中symbol指的是map.put("1", Integer.valueOf(1))。这怎么可能?我又查了API Spec,没错。在别的地方插入这条语句也没错,单单是在这里不行。

于是,兴趣来了。又做了一些测试(见附件)。最后,一个令我非常吃惊的发现。

    public static <K, V> Map<K, V> newHashMap4() {

        HashMap<K, V> map = new HashMap<K, V>();

        return map;

    }

居然编译通过。但令人不解的是,public static Map<K, V> newHashMap5()却不能通过编译。

 

当时手头有别的事,没有时间深究,只把我做的测试和疑问回复过去了。一心等待楼主写明出处贴,令我失望的是帖子沉的很深了,楼主始终没漂上来。

三、  突破-VectortoArray()方法

没想到今天一个关于泛型的帖子(关于Collection中的toArray()方法的困惑)使我找到了突破口。回复了bryantd (Delphi菜鸟) 的问题,我突然发现API Spec中关于vector.oArray方法的声明是这样的,

public <T> T[] toArray(T[] a)

这个<T>是什么?以前没认真考虑,但今天我注意了,这不是那个<K, V>吗?接着我又想起泛型的始祖,C++中的Template(使用Collections Framework太顺手,把这岔儿给忘了)。于是我就想到了一个问题,我们知道

    Vector<Integer> vi = new Vector<Integer>();

创建了一个储存IntegerVector,而

    Vector<String> vs = new Vector<String>();

又创建了一个储存StringVector。那么,这种功能,在Vector类的内部是怎么实现的?回到前面的问题,

public <K, V> Map<K, V> newHashMap()

我断定前面的<K, V>是对Map<K, V>中的<K, V>的类型声明,或者准确的说是泛化。没有原因,我一下想到了继承,于是,又写了两个类,

    class A {

        public <K, V> Map<K, V> newHashMap() {

            HashMap<K, V> map = new HashMap<K, V>();

            return map;

        }

    }

 

    class B extends A{

        public Map<Integer, String> newHashMap() {

            HashMap<Integer, String> map = new HashMap<Integer, String> ();

 

            map.put(1, "A");

            map.put(2, "B");

 

            return map;

        }

    }

 

天总算亮了。

 

四、  结局-掀起你的盖头来

到了这里,其实问题也就明白了,看下面的代码,

        A[] aa = new A[2];

 

        aa[0] = new B();

        aa[1] = new C(); // C也是继承自A,见附件

 

        for (int i=0; i<aa.length; i++) {

            Map map = aa[i].newHashMap();

            Set keyset = map.keySet();

            for (Iterator it = keyset.iterator(); it.hasNext();) {

                Object k = it.next();

                Object v = map.get(k);

 

                System.out.println(k + " " + v);

            }

        }

再看这里,

    class D extends A {

        public Map<S, T> newHashMap() {

           HashMap<S, T> map = new HashMap<S, T> ();

 

           S s = new S();

           T t = new T();

 

           map.put(s, t);

 

           return map;

       }

    }

 

    class S extends JLabel{}

    class T extends Component{}

 

如果你在设计类库时声明了class D,那么在该类后续的使用中,开发人员可以拥有很大的自由度。这种功能是不是很强大?

 

还是时间的原因,不能再深究下去了,需要掌握的东西还很多,一下子不能扎得太深。再说,老婆也不会允许我掀别人的盖头。^_^

 

好吧,就此别过,后会有期。

五、  小结 

其实该说的都说了,没什么可总结的。留待大家讨论吧。

六、  附件

1) 测试1

// TestGenericSyntax.java

 

import java.util.*;

import java.lang.reflect.*;

 

public class TestGenericSyntax {

    static String  s = "Hello";

    static Integer I = 0;

    //static HashMap<s, I> hMap;

 

    // 这也能过?

    public static <s, I> Map<String, Integer> newHashMap() {

      

        HashMap<String, Integer> map =

           // TestGenericSyntax.java:12: incompatible types

           // found   : java.util.Map<java.lang.String,java.lang.Integer>

           // required: java.util.HashMap<java.lang.String,java.lang.Integer>

           //newHashMap2();

 

           // TestGenericSyntax.java:19: incompatible types; no instance(s) of type variable(s) String,Integer exist so that java.util.Map<String,Integer> conforms to java.util.HashMap<java.lang.String,java.lang.Integer>

           // found   : <String,Integer>java.util.Map<String,Integer>

           // required: java.util.HashMap<java.lang.String,java.lang.Integer>

           // newHashMap1();

 

           // 通过

           new HashMap<String, Integer>();

 

        map.put("A", 1);

        map.put("B", 2);

        return map;

    }

 

    public static <String, Integer> Map<String, Integer> newHashMap1() {

        HashMap<String, Integer> map = new HashMap<String, Integer>();

 

       //map =

       //    new HashMap<String, Integer>(newHashMap2());

 

       // err msg

       // TestGenericSyntax.java:10: cannot find symbol

       // symbol  : method valueOf(int)

       // map.put("1", Integer.valueOf(1));

 

       // err msg

       // TestGenericSyntax.java:14: cannot find symbol

       // symbol  : method put(java.lang.String,java.lang.Integer)

       // map.put(s, I);

 

       // err msg       

       // TestGenericSyntax.java:15: incompatible types

       // map = newHashMap2();

 

        return map;

    }

 

    public static Map<String, Integer> newHashMap2() {

        HashMap<String, Integer> map = new HashMap<String, Integer>();

        map.put("1", Integer.valueOf(1));

 

       // err msg

       // symbol  : constructor HashMap(java.util.Map<java.lang.Object,java.lang.Object>)

        // map = new HashMap<String, Integer>(newHashMap1());

 

       map = new HashMap<String, Integer>(newHashMap3());

 

        return map;

    }

 

    public static Map<String, Integer> newHashMap3() {

        HashMap<String, Integer> map = new HashMap<String, Integer>();

        map.put("1", Integer.valueOf(1));

        return map;

    }

 

    // 这是什么?居然通过了。

    public static <K, V> Map<K, V> newHashMap4() {

        HashMap<K, V> map = new HashMap<K, V>();

        return map;

    }

 

    // 通不过,错误一大堆。

    /*

    public static Map<K, V> newHashMap5() {

        HashMap<K, V> map = new HashMap<K, V>();

        return map;

    }

    */

 

    public static void main(String[] args) {

       // TestGenericSyntax.java:73: incompatible types; no instance(s) of type variable(s) String,Integer exist so that java.util.Map<String,Integer> conforms to java.util.HashMap

        // found   : <String,Integer>java.util.Map<String,Integer>

       // required: java.util.HashMap

       // HashMap map = newHashMap1();

 

       // hMap = newHashMap1();

 

 

       Class c = TestGenericSyntax.class;

        Method[] methods;

 

       /*

        methods = c.getMethods();

       for (int i=0; i<methods.length; i++) {

           System.out.println(methods[i]);

       }

       */

 

        methods = c.getDeclaredMethods();

       for (int i=0; i<methods.length; i++) {

           System.out.println(methods[i]);

           Type rt = methods[i].getGenericReturnType();

 

           System.out.println(rt);

           System.out.println();

       }

    }

}

 

2) 测试2

// TestGenericSyntax_2.java

import java.awt.*;

import java.util.*;

import javax.swing.*;

 

public class TestGenericSyntax_2 {

    public static void main(String[] args) {

       A[] aa = new A[2];

 

       aa[0] = new B();

       aa[1] = new C();

 

       for (int i=0; i<aa.length; i++) {

           Map map = aa[i].newHashMap();

           Set keyset = map.keySet();

           for (Iterator it = keyset.iterator(); it.hasNext();) {

               Object k = it.next();

               Object v = map.get(k);

 

               System.out.println(k + " " + v);

           }

       }

 

        HashMap<S, T> map1 = new HashMap<S, T>();

        map1.put(new S(), new T());

    }

}

 

class A {

   public <K, V> Map<K, V> newHashMap() {

        HashMap<K, V> map = new HashMap<K, V>();

        return map;

    }

}

 

class B extends A{

    public Map<Integer, String> newHashMap() {

        HashMap<Integer, String> map = new HashMap<Integer, String> ();

 

        map.put(1, "A");

        map.put(2, "B");

 

        return map;

    }

}

 

class C extends A{

    public Map<Long, String> newHashMap() {

        HashMap<Long, String> map = new HashMap<Long, String> ();

 

        map.put(1L, "S");

        map.put(2L, "T");

        return map;

    }

}

 

class D extends A {

    public Map<S, T> newHashMap() {

        HashMap<S, T> map = new HashMap<S, T> ();

 

       S s = new S();

       T t = new T();

       // TestGenericSyntax_2.java:54: cannot find symbol

       // symbol  : method put(S,T)

        map.put(s, t);

 

        return map;

    }

}

 

class S extends JLabel{}

class T extends Component{}

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值