Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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:如何从泛型类型获取类文本?_Java_Generics_Class_Literals - Fatal编程技术网

Java:如何从泛型类型获取类文本?

Java:如何从泛型类型获取类文本?,java,generics,class,literals,Java,Generics,Class,Literals,通常,我看到人们使用类文字如下: Class<Foo> cls = Foo.class; Class cls=Foo.Class; 但是如果类型是泛型的,例如列表,该怎么办?这工作正常,但有一个警告,因为列表应该参数化: Class<List> cls = List.class Class cls=List.Class 那么为什么不添加一个?这会导致类型不匹配错误: Class<List<?>> cls = List.class Clas

通常,我看到人们使用类文字如下:

Class<Foo> cls = Foo.class;
Class cls=Foo.Class;
但是如果类型是泛型的,例如列表,该怎么办?这工作正常,但有一个警告,因为列表应该参数化:

Class<List> cls = List.class
Class cls=List.Class
那么为什么不添加一个
?这会导致类型不匹配错误:

Class<List<?>> cls = List.class
Class你不能因为

Java泛型只不过是对象强制转换的语法糖。证明:

List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal
重要的部分是

换句话说,从以下方面:

为什么具体的参数化类型没有类文字? 因为参数化类型没有精确的运行时类型表示。

类文字表示
表示给定类型的。 例如,类literal
String.class
表示
class
对象,该对象表示该类型
字符串
在 方法
getClass
String
对象。类文本可以 用于运行时类型检查和 供思考

参数化类型将丢失其类型 将参数转换为时的参数 编译过程中的字节码 这个过程称为类型擦除。作为一个 类型擦除的副作用,所有 泛型类型共享的实例化 相同的运行时表示, 即对应的原始 类型。换句话说,参数化 类型没有类型表示 他们自己的。因此,有 形成类文本没有意义 例如
List.class
List.class
List.class
,因为不存在此类
对象。 只有原始类型
列表
具有
表示其运行时的 类型。它被称为
List.class

你不能因为这个原因

Java泛型只不过是对象强制转换的语法糖。证明:

List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = (List<String>)list1;
list2.add("foo"); // perfectly legal
重要的部分是

换句话说,从以下方面:

为什么具体的参数化类型没有类文字? 因为参数化类型没有精确的运行时类型表示。

类文字表示
表示给定类型的。 例如,类literal
String.class
表示
class
对象,该对象表示该类型
字符串
在 方法
getClass
String
对象。类文本可以 用于运行时类型检查和 供思考

参数化类型将丢失其类型 将参数转换为时的参数 编译过程中的字节码 这个过程称为类型擦除。作为一个 类型擦除的副作用,所有 泛型类型共享的实例化 相同的运行时表示, 即对应的原始 类型。换句话说,参数化 类型没有类型表示 他们自己的。因此,有 形成类文本没有意义 例如
List.class
List.class
List.class
,因为不存在此类
对象。 只有原始类型
列表
具有
表示其运行时的 类型。它被称为
List.class


为了解释克莱特斯的答案,在运行时删除了所有泛型类型的记录。泛型仅在编译器中处理,用于提供额外的类型安全性。它们实际上只是一种简写,允许编译器在适当的位置插入类型转换。例如,以前您必须执行以下操作:

List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
变成

List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
List x=new ArrayList();
x、 添加(newsomeclass());
迭代器i=x.Iterator();
SomeClass z=i.next();

这允许编译器在编译时检查您的代码,但在运行时它看起来仍然像第一个示例。

为了详细说明cletus的答案,在运行时删除所有泛型类型的记录。泛型仅在编译器中处理,用于提供额外的类型安全性。它们实际上只是一种简写,允许编译器在适当的位置插入类型转换。例如,以前您必须执行以下操作:

List x = new ArrayList();
x.add(new SomeClass());
Iterator i = x.iterator();
SomeClass z = (SomeClass) i.next();
变成

List<SomeClass> x = new ArrayList<SomeClass>();
x.add(new SomeClass());
Iterator<SomeClass> i = x.iterator();
SomeClass z = i.next();
List x=new ArrayList();
x、 添加(newsomeclass());
迭代器i=x.Iterator();
SomeClass z=i.next();

这允许编译器在编译时检查代码,但在运行时它看起来仍然像第一个示例。

参数化类型没有类文本,但是存在正确定义这些类型的类型对象

请参见java.lang.reflect.ParameterizedType -

Google的Gson库定义了一个TypeToken类,该类允许简单地生成参数化类型,并使用它以通用友好的方式为json对象指定复杂的参数化类型。在您的示例中,您将使用:

Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()
Type-typeOfListOfFoo=new-TypeToken(){}.getType()

我打算发布指向TypeToken和Gson类javadoc的链接,但Stack Overflow不允许我发布多个链接,因为我是一个新用户,您可以使用Google search轻松找到它们。参数化类型没有类文本,但是存在正确定义这些类型的类型对象

请参见java.lang.reflect.ParameterizedType -

Google的Gson库定义了一个TypeToken类,该类允许简单地生成参数化类型,并使用它以通用友好的方式为json对象指定复杂的参数化类型。在您的示例中,您将使用:

Type typeOfListOfFoo = new TypeToken<List<Foo>>(){}.getType()
Type-typeOfListOfFoo=new-TypeToken(){}.getType()
我打算发帖
static void test1() {
        CaptureType<String> t1 = new CaptureType<String>() {
        };
        equals(t1.getRawType(), String.class);
    }

    static void test2() {
        CaptureType<List<String>> t1 = new CaptureType<List<String>>() {
        };
        equals(t1.getRawType(), List.class);
        equals(t1.getParamADT().getParameters().get(0).getRawType(), String.class);
    }


    private static void test3() {
            CaptureType<List<List<String>>> t1 = new CaptureType<List<List<String>>>() {
            };
            equals(t1.getParamADT().getRawType(), List.class);
        equals(t1.getParamADT().getParameters().get(0).getRawType(), List.class);
    }

    static class Test4 extends CaptureType<List<String>> {
    }

    static void test4() {
        Test4 test4 = new Test4();
        equals(test4.getParamADT().getRawType(), List.class);
    }

    static class PreTest5<S> extends CaptureType<Integer> {
    }

    static class Test5 extends PreTest5<Integer> {
    }

    static void test5() {
        Test5 test5 = new Test5();
        equals(test5.getTypeParam(), Integer.class);
    }

    static class PreTest6<S> extends CaptureType<S> {
    }

    static class Test6 extends PreTest6<Integer> {
    }

    static void test6() {
        Test6 test6 = new Test6();
        equals(test6.getTypeParam(), Integer.class);
    }



    class X<T> extends CaptureType<T> {
    }

    class Y<A, B> extends X<B> {
    }

    class Z<Q> extends Y<Q, Map<Integer, List<List<List<Integer>>>>> {
    }

    void test7(){
        Z<String> z = new Z<>();
        TypeADT param = z.getParamADT();
        equals(param.getRawType(), Map.class);
        List<TypeADT> parameters = param.getParameters();
        equals(parameters.get(0).getRawType(), Integer.class);
        equals(parameters.get(1).getRawType(), List.class);
        equals(parameters.get(1).getParameters().get(0).getRawType(), List.class);
        equals(parameters.get(1).getParameters().get(0).getParameters().get(0).getRawType(), List.class);
        equals(parameters.get(1).getParameters().get(0).getParameters().get(0).getParameters().get(0).getRawType(), Integer.class);
    }




    static void test8() throws IllegalAccessException, InstantiationException {
        CaptureType<int[]> type = new CaptureType<int[]>() {
        };
        equals(type.getRawType(), int[].class);
    }

    static void test9(){
        CaptureType<String[]> type = new CaptureType<String[]>() {
        };
        equals(type.getRawType(), String[].class);
    }

    static class SomeClass<T> extends CaptureType<T>{}
    static void test10(){
        SomeClass<String> claz = new SomeClass<>();
        try{
            claz.getRawType();
            throw new RuntimeException("Shouldnt come here");
        }catch (RuntimeException ex){

        }
    }

    static void equals(Object a, Object b) {
        if (!a.equals(b)) {
            throw new RuntimeException("Test failed. " + a + " != " + b);
        }
    }
class SomeClass<T> extends CaptureType<T>{}
SomeClass<String> claz = new SomeClass<>();
@SuppressWarnings("unchecked")
private static <T> Class<T> generify(Class<?> cls) {
    return (Class<T>)cls;
}
Class<List<Foo>> cls = generify(List.class);
  Class<Map<String, Integer>> cls;

  cls = generify(Map.class);

  cls = TheClass.<Map<String, Integer>>generify(Map.class);

  funWithTypeParam(generify(Map.class));

public void funWithTypeParam(Class<Map<String, Integer>> cls) {
}
@SuppressWarnings("unchecked")
Class<List<String>> stringListClass = (Class<List<String>>) (Class<?>) List.class;

List<Integer> intList = new ArrayList<>();
intList.add(1);
List<String> stringList = stringListClass.cast(intList);
// Surprise!
String firstElement = stringList.get(0);