最近要想获得泛型类型,总结多方意见,再通过实践,最终获得了结果。
当然也被许多文章给误导过……
下面我们看一个例子,这个例子是我自己写的
/*
* Copyright 2010 Sandy Zhang
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/**
*
*/
package org.javazone.jroi.test.reflect;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* @author Sandy Zhang
*/
public class Bean
{
public Map<String, ListBean> list = new HashMap<String, ListBean>();
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException
{
Field c = Bean.class.getField("list");
Field f = Field.class.getDeclaredField("signature");
f.setAccessible(true);
System.out.println(((String) f.get(c)));
}
}
这个只是我最近在写一个反射调用的东西想到的问题,所以很无奈才必须要这样得到东西
下面是结果
Ljava/util/Map<Ljava/lang/String;Lorg/javazone/jroi/test/reflect/ListBean;>;
字符串都有了,你怕什么呢?呵呵!
后话:这个方法并不应该被推荐,因为java api下并未提供任何方法实现,也就是说我们必须在特定环境和版本下才能这样干,至少得是1.5之后的版本以后sun(现在是oracle了)准备怎么改,这个是他的说法。。。
--------------------------------------------------------------------
OK,这个是一个引子,从这里我们看到了好些个玩意,也就是java其实提供了获取的方案的
那么我们要进行私有操作的,这样对我们写代码养成这样的习惯可不好,没事就去拿私有的东西,那是不是应该有公共的方法呢?我们试一下
将main里的调用修改一下
Field c = Bean.class.getField("list");
System.out.println(c.toGenericString());
public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.list
看看,我们拿到了什么,不需要setAccess了,呵呵
哦,对了,你或许要问如果我不是字段呢?是方法怎么办。。于是乎
package org.javazone.jroi.test.reflect;
import java.util.HashMap;
import java.util.Map;
/**
* @author Sandy Zhang
*/
public class Bean
{
public Map<String, ListBean> list = new HashMap<String, ListBean>();
public Map<String, ListBean> getList()
{
return list;
}
public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException
{
System.out.println(Bean.class.getMethod("getList").toGenericString());
}
}
public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.getList()
---------------------------------------------------------------------
字符串有了,我们考虑下,API里是不是应该也提供了方法直接获取泛型类型,参考下
getGenericType
public Type getGenericType()返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。
如果 Type 是一个参数化类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。
如果底层字段的类型是一个类型变量或者是一个参数化类型,则创建它。否则将解析它。
返回:
返回表示此 Field 对象所表示字段的声明类型的 Type 对象
抛出:
GenericSignatureFormatError - 如果一般字段签名不符合 Java Virtual Machine Specification, 3rd edition 中指定的格式
TypeNotPresentException - 如果底层字段的一般类型签名引用了不存在的类型声明
MalformedParameterizedTypeException - 如果底层字段的一般签名引用了一个因某种原因而无法实例化的参数化类型
从以下版本开始:
1.5
由此可见,在1.5之后添加了众多以Generic为关键字的方法,这些方法就是用来获取泛型参数的有效途径,但是或许表面上看不出来,因为他们都是返回的Type接口,而非ParameterizedType接口,所以我困惑了很久。OK,下面我们看一下怎么实现吧
public class GenericTest
{
public List<String> list = new LinkedList<String>();
public static void main(String[] args) throws SecurityException, NoSuchFieldException
{
ParameterizedType pt = (ParameterizedType) GenericTest.class.getField(
"list").getGenericType();
System.out.println(pt.getActualTypeArguments().length);
System.out.println(pt.getActualTypeArguments()[0]);
}
}
1
class java.lang.String
这里是结果
---------------------------------------------------------------------
于是乎,所有的问题都迎刃而解了。
似乎文章很长,我通过Debug的方式发现了代码的运行过程,最终找到了核心字符串,说明即使是檫除式的泛型java也会记录下这些东西,没道理拿不到
分享到:
相关推荐
综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...
Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...
因此,虽然在编译期间我们能获得类型检查的好处,但在运行时,泛型接口和类的行为与无参数类型版本基本相同。 5. **通配符** 在某些情况下,我们可能不关心类型参数的具体类型,而只关心它是某个类的子类或者实现...
3. **类型擦除**:Java的泛型在编译后会执行类型擦除,这意味着在运行时,所有的泛型类型信息都会丢失。因此,虽然在编译时提供了类型检查,但在运行时,泛型对象仍然是Object类型。这就是为什么你仍然可以将任何...
Java泛型技术的发展不仅标志着编程语言对类型安全和代码复用的重视,也反映了软件工程领域对模块化、复用性和维护性的不断追求。自JDK1.4以来,泛型技术已成为Java开发不可或缺的一部分,极大地提升了开发效率和代码...
- **泛型擦除的影响**:运行时不能获取类型参数的具体类型,也无法实例化泛型类型参数。 - **类型参数的限制**:类型参数不能用于静态上下文中,因为静态成员与类关联而非对象关联。 #### 结语 通过本文的介绍,...
例如,以下代码在Java 7中是不合法的,因为编译器无法从上下文中推断出`ArrayList`的泛型类型: ```java List<String> list = new ArrayList(); list.add("A"); list.addAll(new ArrayList()); ``` 在Java 8中,...
在Java中,泛型是一种允许开发者在类、接口和方法中使用类型参数的功能。通过使用泛型,可以在编写代码时指定一个或多个类型参数,从而使得编写的代码更加灵活且重用性更高。这种机制在Java 5中被引入,并在集合框架...
泛型是Java SE 5版本引入的一个新特性,它的主要目的是允许在使用类、接口和方法时能够引用到任何类型的对象,同时在编译期间就能进行类型检查,提供更安全的代码。泛型类和泛型方法可以提高代码的复用性,并减少...
虽然Java编译器在编译期间检查泛型类型的有效性,但在生成字节码时会进行所谓的“类型擦除”过程。这意味着在运行时,泛型类型信息会被抹去,所有泛型类型都会转换成其对应的原始类型。 例如,`List<String>` 和 `...
8. 泛型集合:泛型引入后,Java 集合框架得到了极大的增强。使用泛型集合,可以避免在添加、删除和访问元素时出现 ClassCastException。 9. 泛型和多态:泛型可以与多态结合使用,使代码更加灵活。例如,一个接受 `...
这意味着所有泛型类型最终都会被转换为非泛型类型。例如,`List<String>`和`List<Integer>`在运行时实际上是相同的类型,都被擦除成了`List`。 ##### 类型擦除的影响 - **静态成员问题**:泛型类中的静态成员无法...
Java 泛型是Java 5引入的一个重要特性,它允许在类、接口和方法中使用类型参数,从而提高了代码的重用性和安全性。泛型的主要目的是在编译时检查类型安全,并且允许程序员以更方便的方式操作集合。 1. **无泛型的...
例如,类型擦除(Erasure)是Java泛型的一个重要概念,意味着泛型信息在编译后将被擦除,使得在运行时无法获得泛型类型的详细信息。因此,不能使用instanceof检查泛型类型的参数化形式,只能检查其擦除形式,例如...
例如,如果泛型类中的方法接受或返回泛型类型,那么应该考虑使用类型参数来定义这些方法,以保持类型安全性。 7. 通配符的使用场景: 通配符在读取时使用非常方便,因为读者不需要关心具体的类型。但在写入时就有...
3. 一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。 4. 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。 5. 泛型方法体的声明和其他方法一样。 注意...