java重载时泛型遇见Object类型时报错both methods have same erasu

测试问题

至于为什么要在一个泛型类重载泛型参数方法和Object参数方法请看我的另一篇文章:java泛型参数和Object参数的区别
首先定义一个泛型类并定义一个set方法

class main1 <T>
{
    public T a;

    public void setA(T a)
    {
        System.out.println("Tset");
    }
}

再定义一个测试类

public class main2
{
    public static void main(String[] args)
    {
        main1<Integer> main1 = new main1<>();
        main1.setA(1);
    }
}

看一下输出结果,没问题
在这里插入图片描述
添加一个普通的重载方法

public void setA(float a)
{
   System.out.println("Fset");
}

修改一下测试类

public class main2
{
    public static void main(String[] args)
    {
        main1<Integer> main1= new main1<>();
        main1.setA(1);
        main1.setA(1.0f);
    }
}

看一下测试结构
java重载时泛型遇见Object类型时报错both methods have same erasu_第1张图片
也没问题,但是你会发现两次都是调用的第二个方法,虽然他们的参数类型不同,这个会稍后解释

接下来在添加一个重载方法

public void setA(Object a)
{
    System.out.println("Oset");
}

在这里插入图片描述
编译器直接报错
java重载时泛型遇见Object类型时报错both methods have same erasu_第2张图片
究竟为什么?我们只需要打印一下a的类型信息就知道了
先将最后一个重载方法注释,并修改一下

class main1<T>
{
    public T a;

    public void setA(T a) throws NoSuchFieldException
    {
        System.out.println("Tset"+main1.class.getField("a"));
    }

//    public void setA(Object a) throws NoSuchFieldException
//    {
//        System.out.println("Oset"+main1.class.getField("a"));
//    }
}

修改一下测试类打印并看下结果

public class main2
{
    public static void main(String[] args) throws NoSuchFieldException
    {
        main1<Integer> main1=new main1<>();
        main1.setA(1);
    }
}

在这里插入图片描述
可以看见虽然我们实现对象的时候是Integer类型,但是确是Object类型
我们将a的类型改为Object打印一下

public Object a;

在这里插入图片描述
可以看见是Object,所以在字节码中他们的类型信息是相同的,那么它们重载的方法也是相同的,所以才会出现相同擦除的错误,这也解释了第二次打印时为什么都调用同一个方法并且类型不出错。如果你对泛型和擦除不了解可以查看我的另一篇文章:java 泛型详解

解决问题

那么怎么解决这个问题呢?我有两种方法,第一种就是将Object方法修改名字这个理所当然就不说了,第二种就是为泛型类定义一个擦除界限

class main2<T extends Number>//修改此处
{
    public T a;

    public void setA(T a) throws NoSuchFieldException
    {
        System.out.println("Tset"+main1.class.getField("a"));
    }

    public void setA(Object a) throws NoSuchFieldException
    {
        System.out.println("Oset"+main1.class.getField("a"));
    }
}

此时编译器就不会报错了,为什么,打印一下就知道了
java重载时泛型遇见Object类型时报错both methods have same erasu_第3张图片
此时a的类型已经变成Number了,所以他们的擦除就不一样了。

编译器三种重载方法的挑选顺序

普通方法>泛型方法>Object方法

你可能感兴趣的:(java,java,python,类,scala,class)