以前使用泛型方法的时候一直未注意到一个问题,原代码如下
package test;public class GenTest{
public <T>  void  copy(T from,T to){

}
public static <T> void staticCopy(T from,T to){

}
public <T> T get(T t){
return t;
}public static void main(String[] args) {
GenTest t = new GenTest();
t.copy(new Integer(1), "elliott");
}
}奇怪的是为什么t.copy(new Integer(1), "elliott");这行编译器没有报错
而使用类定义泛型时class GenTest<T>他才会报错

解决方案 »

  1.   

    你想定义自己的泛型类吗,你用的是jdk几啊,为什么在我电脑上这样class GenTest<T>不报错啊
      

  2.   

    jdk1.6
    class GenTest<T>是不会报错,new 对象时类型检查通不过,单独的泛型方法或者那个静态方法就会报错
    不明白为什么编译器类型检查会通过
      

  3.   

    1.类中所有个构造器,实例变量,实例方法即便你声明为泛型的只要class不是泛型的(或者class定义为泛型,但是你还是用了原生类型 比如 class GenTest<T> {} GenTest t = new GenTest();),这些构造器,实例变量,实例方法都会编程非泛型。但是静态字段和方法除外。
     GenTest t = new GenTest();
     t.copy(new Integer(1), "elliott");
    实例方法copy相当于copy(Object from,Object to),所以不会报错。连警告都没。
     
    2.GenTest.staticCopy(new Integer(1), "elliott"); 现在staticCopy是静态方法,为什么也不报错?因为你没有指定staticCopy方法的类型信息。此时staticCopy相当于staticCopy(Object from,Object to);
    改为GenTest.<Integer>staticCopy(new Integer(1), "elliott");这样就报错了。3.把GenTest改为GenTest<T>,并且创建方式也改了:GenTest<Integer> t = new GenTest<Integer>();
     t.copy(new Integer(1), "elliott"); 为什么还报错呢?原因是:
      public <T>  void  copy(T from,T to){ }这里的<T>隐藏了class的<T>。
    改正:
        public <T>  void  copy(T from,T to){ } 改为 public void  copy(T from,T to){ }
    或者t.copy(new Integer(1), "elliott");改为 t.<Integer>copy(new Integer(1), "elliott");
      

  4.   

    那个静态方法,编译器不会推测类型吗?
    为什么下面就可以工作
    public static <T extends Comparable<T>> T max(T t1, T t2) {
    if (t1.compareTo(t2) > 0)
    return t1;
    else
    return t2;
    }
      

  5.   

    public static <T extends Number> void staticCopy(T from, T to) {
    }
    max(new Integer(1), new Float(2));
    这个会编译错误
      

  6.   

    这个定义好奇怪啊, 不过不管了. 直接说吧:
    t.copy(new Integer(1), "elliott"), 不报错, 因为此时泛型类型是Comparable, 反正是Integer和String的都实现的接口.
    "而使用类定义泛型时class GenTest<T>他才会报错", 这要能用, 你也要定义类的时候使用泛型啊, 如
    class ClassName<T> 这样才行, 楼主那压根不是泛型类.
      

  7.   

    public static <T extends Comparable<T>> T max(T t1, T t2) {
    if (t1.compareTo(t2) > 0)
    return t1;
    else
    return t2;
    }max(new Integer(1), "elliott");上面会报错
      

  8.   


    当然报错了, 你的Integer类和String类不一样, Integer实现的是Comparable<Integer>, String实现的是Comparable<String>, 不兼容.就算改成T extends Comparable<? super T>也会报错. 因为求Integer类和String类的混合体的最大值逻辑上说不通, 觉得这样很好啊.
      

  9.   

    public static <T> void max(T t1,T t2){
    }
    public static void main(String[] args) {
        max(new Integer(1), "elliott");
    }
    最后问一下,为什么max函数里面t1和t2的都是T类型,但是编译器为什么不进行类型检查
    但是下面代码使用extends后却会检查
    public static <T extends Comparable<T>> void max(T t1, T t2) {
    System.out.println("caopare");
    }
      

  10.   

    简单的解释下:
    1、泛型类、泛型方法 编译时类型变量都是会擦除的;
    2、类型变量如果没有限定类型,就会用Object替换,如果有会用第一个限定类型替换,必要时会转换成其它的限定类型;
    3、所有的泛型类都有其原型;
    4、编译器总会进行类型检查,Java是强类型语言;
    5、Java中对象方法的调用执行采用的是动态绑定,实际的对象类型能根据隐藏参数this的类型推断出;public <T>  void  copy(T from,T to){
    }
    编译替换后是:
    public void  copy(Object from,Object to){
    }public static <T extends Comparable<T>> void max(T t1, T t2) {
    }
    编译替换后是:
    public static void max(Comparable t1, Comparable t2) {
    }t.copy(new Integer(1), "elliott");这里编译不会出错了;
    编译时编译器查看对象类型的方法列表(包括父类型中的方法),但只能找到copy(Object from,Object to)方法,因为Integer、String都是可以转换成Object的,编译器会进行转换t.copy((Object)new Integer(1), (Object)"elliott"),强制转换参数类型后符合方法签名中的参数类型的方法;max(new Integer(1), "elliott");编译出错;
    这是个static方法,编译max(new Integer(1), "elliott")会静态绑定,编译器直接找类GenTest中是否有max方法,找到了有个名为max的方法,参数类型中的Comparable是个泛型类型(你声明的是个Comparable<T>,编译器会记录下T的类型是Comparable<T>类型或其子类型,尽管擦除时用的是原型Comparable替换),于是max(new Integer(1), "elliott")会进行转换:max((Comparable<Integer>)new Integer(1), (Comparable<String>)"elliott"),尽管Integer是Comparable<Integer>的子类型、String是Comparable<String>的子类型,但Comparable<Integer>和Comparable<String>是没有什么关系的,编译器就报错,类型替换失败;
    但你自己强制类型转换为Comparable<T>的父类型Comparable就不会报错了,即max((Comparable)new Integer(1), (Comparable)"elliott");或去掉方法声明中的Comparable<T>中的T;