Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java I';当使用varargs传递给第二个泛型方法时,我将丢失泛型方法中的变量类型_Java_Generics - Fatal编程技术网

Java I';当使用varargs传递给第二个泛型方法时,我将丢失泛型方法中的变量类型

Java I';当使用varargs传递给第二个泛型方法时,我将丢失泛型方法中的变量类型,java,generics,Java,Generics,我想最好从我所看到的行为开始: public class genericTest { public static void main(String[] args) { String str = "5318008"; printClass(str); // class java.lang.String callPrintClass(str); // class java.lang.String

我想最好从我所看到的行为开始:

public class genericTest {
    public static void main(String[] args) {
        String str = "5318008";

        printClass(str);              // class java.lang.String
        callPrintClass(str);          // class java.lang.String

        printClassVarargs(str);       // class java.lang.String
        callPrintClassVarargs(str);   // class java.lang.Object
    }

    public static <T> void printClass(T str) {
        System.out.println(str.getClass());
    }

    public static <T> void printClassVarargs(T ... str) {
        System.out.println(str.getClass().getComponentType());
    }

    public static <T> void callPrintClass(T str) {
        printClass(str);
    }

    @SuppressWarnings("unchecked")
    public static <T> void callPrintClassVarargs(T str) {
        printClassVarargs(str);
    }
}
公共类泛型测试{
公共静态void main(字符串[]args){
字符串str=“5318008”;
printClass(str);//class java.lang.String
callPrintClass(str);//class java.lang.String
printClassVarargs(str);//class java.lang.String
callPrintClassVarargs(str);//类java.lang.Object
}
公共静态无效打印类(T str){
System.out.println(str.getClass());
}
公共静态无效printClassVarargs(T…str){
System.out.println(str.getClass().getComponentType());
}
公共静态void callPrintClass(T str){
打印类(str);
}
@抑制警告(“未选中”)
公共静态void callPrintClassVarargs(T str){
printclassvargs(str);
}
}
看看
printClass()
callPrintClass()
,似乎一切都很正常
callPrintClass()
接受一个泛型参数并传递它
printClass()
通过正确的类型识别此变量,而不管是谁发送参数,然后按照它的预期操作并打印
java.lang.String

但是当我们尝试使用varargs时,它就停止工作了。我希望
printClassVarargs()
能够识别它的参数类型为
String[]
,这与不带varargs的方法识别其参数类型非常相似。还要注意,如果我直接调用
printClassVarargs()
(在那里输出
String
,这是非常愉快的),但只有当它被
callPrintClassVarargs()
调用时才会发生这种情况,因为它忘记了参数的类型,并假定它得到了一个
对象。我还意识到我必须在这里抑制编译器警告,这通常是在我尝试转换泛型时出现的,但我不确定那里到底发生了什么

所以我的问题是两个。这种行为背后的原因是什么?这是类型擦除的结果,还是Java处理数组的方式?第二,有没有办法解决这个问题


当然,这只是一个简单的例子。我不想用这种方式打印类名,但最初是在编写重载方法连接数组时发现问题的

我认为问题归结为无法创建泛型类型的数组。如果
callPrintClassVarargs
被修改为显式创建一个新的数组实例并将其传递给
printClassVarargs
,则潜在问题将变得明确

// doesn't work, gives compiler error (cannot create array of generic type)
public static <T> void callPrintClassVarargs(T str) {
        printClassVarargs(new T[]{str});
}

//This works
public static <T> void callPrintClassVarargs(T str) {
        printClassVarargs(new Object[]{str});
}
//不工作,出现编译器错误(无法创建泛型类型的数组)
公共静态void callPrintClassVarargs(T str){
printclassvargs(新的T[]{str});
}
//这很有效
公共静态void callPrintClassVarargs(T str){
printClassVarargs(新对象[]{str});
}
-
这个问题涉及为什么不可能创建泛型类型的数组,也许同样可以解释这个问题

Varargs是由编译器转换为给定类型数组的语法糖。 这意味着
方法(类型arg…
将成为
方法(类型[]arg)

在Java中,不能创建(类型信息因擦除而丢失的类型)的数组。因此,诸如
printclassrargs(T…str)
之类的泛型varargs将转换为
printclassrargs(Object[]str)
,从而有效地删除类型信息。这就是你在测试中观察到的情况

---编辑---

要回答您关于
printClassVarargs(str)
callPrintClassVarargs(str)
之间差异的问题(cfr注释),我们可以查看您测试类的字节码,以获得所需的线索:

public Test();
  Code:
   0:   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   ldc #16; //String 5318008
   2:   astore_1
   3:   aload_1
   4:   invokestatic    #18; //Method printClass:(Ljava/lang/Object;)V
   7:   aload_1
   8:   invokestatic    #22; //Method callPrintClass:(Ljava/lang/Object;)V
   11:  iconst_1
   12:  anewarray   #25; //class java/lang/String
   15:  dup
   16:  iconst_0
   17:  aload_1
   18:  aastore
   19:  invokestatic    #27; //Method printClassVarargs:([Ljava/lang/Object;)V
   22:  aload_1
   23:  invokestatic    #31; //Method callPrintClassVarargs:(Ljava/lang/Object;)V
   26:  return

public static void printClass(java.lang.Object);
  Code:
   0:   getstatic   #40; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   aload_0
   4:   invokevirtual   #46; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   7:   invokevirtual   #50; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   10:  return

public static void printClassVarargs(java.lang.Object[]);
  Code:
   0:   getstatic   #40; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   aload_0
   4:   invokevirtual   #46; //Method java/lang/Object.getClass:()Ljava/lang/Class;
   7:   invokevirtual   #59; //Method java/lang/Class.getComponentType:()Ljava/lang/Class;
   10:  invokevirtual   #50; //Method java/io/PrintStream.println:(Ljava/lang/Object;)V
   13:  return

public static void callPrintClass(java.lang.Object);
  Code:
   0:   aload_0
   1:   invokestatic    #18; //Method printClass:(Ljava/lang/Object;)V
   4:   return

public static void callPrintClassVarargs(java.lang.Object);
  Code:
   0:   iconst_1
   1:   anewarray   #3; //class java/lang/Object
   4:   dup
   5:   iconst_0
   6:   aload_0
   7:   aastore
   8:   invokestatic    #27; //Method printClassVarargs:([Ljava/lang/Object;)V
   11:  return

}
公共测试();
代码:
0:aload_0
1:特别是#8//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:ldc#16//字符串5318008
2:astore_1
3:aload_1
4:invokestatic#18//方法printClass:(Ljava/lang/Object;)V
7:aload_1
8:invokestatic#22//方法callPrintClass:(Ljava/lang/Object;)V
11:iconst_1
12:anewarray#25//类java/lang/String
15:dup
16:iconst_0
17:aload_1
18:aastore
19:invokestatic#27//方法printclassvargs:([Ljava/lang/Object;)V
22:aload_1
23:invokestatic#31;//方法callPrintClassVarargs:(Ljava/lang/Object;)V
26:返回
公共静态void打印类(java.lang.Object);
代码:
0:getstatic#40;//字段java/lang/System.out:Ljava/io/PrintStream;
3:aload_0
4:invokevirtual#46;//方法java/lang/Object.getClass:()Ljava/lang/Class;
7:invokevirtual#50;//方法java/io/PrintStream.println:(Ljava/lang/Object;)V
10:返回
公共静态void printclassvargs(java.lang.Object[]);
代码:
0:getstatic#40;//字段java/lang/System.out:Ljava/io/PrintStream;
3:aload_0
4:invokevirtual#46;//方法java/lang/Object.getClass:()Ljava/lang/Class;
7:invokevirtual#59;//方法java/lang/Class.getComponentType:()Ljava/lang/Class;
10:invokevirtual#50;//方法java/io/PrintStream.println:(Ljava/lang/Object;)V
13:返回
公共静态void callPrintClass(java.lang.Object);
代码:
0:aload_0
1:invokestatic#18;//方法printClass:(Ljava/lang/Object;)V
4:返回
公共静态void callPrintClassVarargs(java.lang.Object);
代码:
0:iconst_1
1:anewarray#3;//类java/lang/Object
4:dup
5:iconst_0
6:aload_0
7:aastore
8:invokestatic#27;//方法printClassVarargs:([Ljava/lang/Object;)V
11:返回
}
在main#12上观察字符串obj i的新字符串[]