今天在看HashMap源码的时候,发现里面传参的时候有很多? extends K,java不是支持参数的自动向上类型转换嘛? 所以今天晚上做了几个小测试。
首先,看方法中的参数自动类型转换:
方法代码:
private static void test(InterfaceTest t){ System.out.println(t.getClass()); }
接口和子类:
public interface InterfaceTest { public void test1(); } class ClassTest1 implements InterfaceTest{ @Override public void test1() { // TODO Auto-generated method stub } public void test2(){ } }
实例并传参:
ClassTest1 c = new ClassTest1(); InterfaceTest c1 = new ClassTest1(); test(new InterfaceTest(){ @Override public void test1() { // TODO Auto-generated method stub } }); test(new ClassTest1(){ }); test(c); test(c1);
可以发现,用接口实例化,用子类实例化,用匿名类都是没问题的,结果:
class otherTest.ParameterUp$1 class otherTest.ParameterUp$2 class otherTest.ClassTest1 class otherTest.ClassTest1
其中$1表示在ParameterUp类里面的第一个内部类。
PS:如果要用接口去实例化一个子类,要注意实例出来的子类是不能访问没有在接口里面定义的方法的。
接着看泛型:
public static void main(String[] a){ List<Object> t = new ArrayList<String>();//报错 List<String> t1 = new ArrayList<Object>();//报错 List<? extends Object> t3 = new ArrayList<String>(); List t4 = new ArrayList<String>(); // 可以add object对象 List<String> t5 = new ArrayList(); //只能add String对象 t5.add(new Object()); //报错 List<? extends Object> t6 = new ArrayList<String>(); //很神奇的list,只能加null List<? extends String> t7 = new ArrayList<String>(); testGeneric(t7); testString(t3);//报错 testList(t3); testGeneric(t3); testString(t4); testList(t4); testGeneric(t4); testString(t5); testList(t5); testGeneric(t5); testString(t6);//报错 testList(t6); testGeneric(t6); } private static void testObject(List<Object> t){ System.out.println(t.getClass()); } private static void testObject(List<String> t){//报错 System.out.println(t.getClass()); } private static void testString(List<String> t){ System.out.println(t.getClass()); } private static void testList(List t){ System.out.println(t.getClass()); } private static void testGeneric(List<? extends Object> t){ System.out.println(t.getClass()); }
以上基本上综合了我能想到的情况,分析一下:
首先在实例化的时候不要加?extends泛型,代码里t6和t7虽然没有报错,但是这个list是只能加null的。。。 具体原因还未明。。。
在实例化集合类的时候,泛型不支持向上自动转型,最好也不要用?extends,老老实实的传你想要的参数就行,最多传个object。。
在方法需要的参数里面如果有集合类,如list的时候,list里的泛型不支持自动转型,如果需要可以用?extends实现自动转型,比如testGeneric(List<? extends Object> t) 表示testGeneric方法接收以object为父类的一切子类的list集合类。
在实例化集合类的时候,如果左边有泛型,右边最好泛型,不做死就不会死。。。 实例化对象以左边为准。比如代码中t4可以add object对象,t5只能add String对象