`

Jave获得泛型类型(转)

阅读更多

原文http://www.iteye.com/topic/585900

Java代码 复制代码 收藏代码
  1. /*  
  2.  * Copyright 2010 Sandy Zhang  
  3.  *   
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not  
  5.  * use this file except in compliance with the License. You may obtain a copy of  
  6.  * the License at  
  7.  *   
  8.  * http://www.apache.org/licenses/LICENSE-2.0  
  9.  *   
  10.  * Unless required by applicable law or agreed to in writing, software  
  11.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  
  12.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the  
  13.  * License for the specific language governing permissions and limitations under  
  14.  * the License.  
  15.  */  
  16.   
  17. /**  
  18.  *   
  19.  */  
  20. package org.javazone.jroi.test.reflect;   
  21.   
  22. import java.lang.reflect.Field;   
  23. import java.util.HashMap;   
  24. import java.util.Map;   
  25.   
  26. /**  
  27.  * @author Sandy Zhang  
  28.  */  
  29. public class Bean   
  30. {   
  31.     public Map<String, ListBean> list = new HashMap<String, ListBean>();   
  32.   
  33.     public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException   
  34.     {   
  35.         Field c = Bean.class.getField("list");   
  36.         Field f = Field.class.getDeclaredField("signature");   
  37.         f.setAccessible(true);   
  38.         System.out.println(((String) f.get(c)));   
  39.   
  40.     }   
  41. }  
/*
 * 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)));

	}
}


这个只是我最近在写一个反射调用的东西想到的问题,所以很无奈才必须要这样得到东西
下面是结果

Java代码 复制代码 收藏代码
  1. Ljava/util/Map<Ljava/lang/String;Lorg/javazone/jroi/test/reflect/ListBean;>;  
Ljava/util/Map<Ljava/lang/String;Lorg/javazone/jroi/test/reflect/ListBean;>;


字符串都有了,你怕什么呢?呵呵!

后话:这个方法并不应该被推荐,因为java api下并未提供任何方法实现,也就是说我们必须在特定环境和版本下才能这样干,至少得是1.5之后的版本以后sun(现在是oracle了)准备怎么改,这个是他的说法。。。
--------------------------------------------------------------------
OK,这个是一个引子,从这里我们看到了好些个玩意,也就是java其实提供了获取的方案的
那么我们要进行私有操作的,这样对我们写代码养成这样的习惯可不好,没事就去拿私有的东西,那是不是应该有公共的方法呢?我们试一下
将main里的调用修改一下

Java代码 复制代码 收藏代码
  1. Field c = Bean.class.getField("list");   
  2. System.out.println(c.toGenericString());  
Field c = Bean.class.getField("list");
System.out.println(c.toGenericString());

 

Java代码 复制代码 收藏代码
  1. public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.list  
public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.list


看看,我们拿到了什么,不需要setAccess了,呵呵

哦,对了,你或许要问如果我不是字段呢?是方法怎么办。。于是乎

Java代码 复制代码 收藏代码
  1. package org.javazone.jroi.test.reflect;   
  2.   
  3. import java.util.HashMap;   
  4. import java.util.Map;   
  5.   
  6. /**  
  7.  * @author Sandy Zhang  
  8.  */  
  9. public class Bean   
  10. {   
  11.     public Map<String, ListBean> list = new HashMap<String, ListBean>();   
  12.   
  13.     public Map<String, ListBean> getList()   
  14.     {   
  15.         return list;   
  16.     }   
  17.   
  18.     public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException, NoSuchMethodException   
  19.     {   
  20.         System.out.println(Bean.class.getMethod("getList").toGenericString());   
  21.     }   
  22. }  
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());
	}
}


Java代码 复制代码 收藏代码
  1. public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.getList()  
public java.util.Map<java.lang.String, org.javazone.jroi.test.reflect.ListBean> org.javazone.jroi.test.reflect.Bean.getList()


---------------------------------------------------------------------
字符串有了,我们考虑下,API里是不是应该也提供了方法直接获取泛型类型,参考下

Java代码 复制代码 收藏代码
  1. getGenericType   
  2. public Type getGenericType()返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型。    
  3. 如果 Type 是一个参数化类型,则返回的 Type 对象必须准确地反映源代码中使用的实际类型参数。    
  4. 如果底层字段的类型是一个类型变量或者是一个参数化类型,则创建它。否则将解析它。    
  5. 返回:   
  6. 返回表示此 Field 对象所表示字段的声明类型的 Type 对象    
  7. 抛出:    
  8. GenericSignatureFormatError - 如果一般字段签名不符合 Java Virtual Machine Specification, 3rd edition 中指定的格式    
  9. TypeNotPresentException - 如果底层字段的一般类型签名引用了不存在的类型声明    
  10. MalformedParameterizedTypeException - 如果底层字段的一般签名引用了一个因某种原因而无法实例化的参数化类型   
  11. 从以下版本开始:    
  12. 1.5   
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,下面我们看一下怎么实现吧

Java代码 复制代码 收藏代码
  1. public class GenericTest   
  2. {   
  3.     public List<String> list = new LinkedList<String>();   
  4.   
  5.     public static void main(String[] args) throws SecurityException, NoSuchFieldException   
  6.     {   
  7.         ParameterizedType pt = (ParameterizedType) GenericTest.class.getField(   
  8.                 "list").getGenericType();   
  9.         System.out.println(pt.getActualTypeArguments().length);   
  10.         System.out.println(pt.getActualTypeArguments()[0]);   
  11.     }   
  12. }  
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 泛型类的类型识别示例

    综上所述,虽然Java泛型在编译后会进行类型擦除,但通过上述技巧,我们仍然能够在运行时获得关于泛型类实例化类型的一些信息。在实际开发中,这些方法可以帮助我们编写更加灵活和安全的代码。在示例文件`GenericRTTI...

    Java 中泛型类型概述

    5. 泛型类型必须是一个合法的标识符,并且其类型会在实例化时由具体类型所取代。 6. 泛型类型之间不能直接相互赋值,即使它们是同一泛型类但具体的类型参数不同。 7. 泛型不支持重载方法,由于泛型会擦除具体的...

    Java泛型的用法及T.class的获取过程解析

    Java泛型是Java编程语言中的一种重要特性,它允许开发者在编写代码时指定类型参数,从而提高代码的灵活性和可读性。本文将详细介绍Java泛型的用法 及T.class的获取过程解析。 一、泛型的基本概念 泛型是Java 5中...

    java 泛型接口示例

    Java 泛型是Java SE 5.0引入的一项重要特性,极大地增强了代码的类型安全性和重用性。泛型接口是泛型在接口中的应用,它允许我们在接口中定义带有类型参数的方法,使得实现该接口的类可以使用不同的数据类型。下面...

    java.泛型与反射(解决方案).md

    如果字段是泛型类型,通过`ParameterizedType`接口获得其泛型参数列表,并根据需要获取第一个泛型参数。如果字段不是泛型类型,直接返回字段的类型,这可能需要在使用时考虑类型擦除的影响。 需要注意的是,如果...

    java.泛型与反射.md

    由于类型擦除的存在,当使用反射来操作泛型类时,我们不能直接得到泛型类的类型参数信息。不过,反射API提供了一些方法来获取关于泛型的信息。如`Class&lt;?&gt;`类中的`getTypeParameters()`方法可以获取到泛型类声明的...

    Java泛型技术之发展

    Java泛型技术的发展不仅标志着编程语言对类型安全和代码复用的重视,也反映了软件工程领域对模块化、复用性和维护性的不断追求。自JDK1.4以来,泛型技术已成为Java开发不可或缺的一部分,极大地提升了开发效率和代码...

    Java泛型的深度解析:原理、应用与最佳实践

    Java中的泛型类型擦除导致了运行时对于泛型类型信息的不可见性,从而带来了一些限制。例如,不能创建泛型数组,因为泛型类实例在运行时会丢失其泛型类型信息,变成原始类型的数组。这一限制也意味着所有泛型类在运行...

    java.泛型类与方法(解决方案).md

    - **反射中的泛型**:Java反射机制在处理泛型时提供了额外的API来获取泛型类型的具体信息。 ### 总结 Java泛型通过类型参数的引入,增强了Java程序的灵活性和安全性。它不仅支持数据类型的抽象,而且在编译时提供...

    Java1.5泛型指南中文版

    3. **类型擦除**:Java的泛型在编译后会执行类型擦除,这意味着在运行时,所有的泛型类型信息都会丢失。因此,虽然在编译时提供了类型检查,但在运行时,泛型对象仍然是Object类型。这就是为什么你仍然可以将任何...

    Java泛型深入解析:灵活编程与类型安全的结合

    Java不允许创建泛型类型的数组,但可以通过反射来解决这。通过使用泛型,我们可以编写出更加灵活和安全的代码。理解泛型的基本概念、类型参数、泛型类、泛型接口和泛型方法,可以帮助我们更好地利用Java泛型的特性。...

    JAVA的泛型指南

    - **泛型擦除的影响**:运行时不能获取类型参数的具体类型,也无法实例化泛型类型参数。 - **类型参数的限制**:类型参数不能用于静态上下文中,因为静态成员与类关联而非对象关联。 #### 结语 通过本文的介绍,...

    java泛型类和函数

    在Java中,泛型是一种允许开发者在类、接口和方法中使用类型参数的功能。通过使用泛型,可以在编写代码时指定一个或多个类型参数,从而使得编写的代码更加灵活且重用性更高。这种机制在Java 5中被引入,并在集合框架...

    详谈Java8新特性泛型的类型推导

    例如,以下代码在Java 7中是不合法的,因为编译器无法从上下文中推断出`ArrayList`的泛型类型: ```java List&lt;String&gt; list = new ArrayList(); list.add("A"); list.addAll(new ArrayList()); ``` 在Java 8中,...

    Java编程语言中的泛型

    虽然Java编译器在编译期间检查泛型类型的有效性,但在生成字节码时会进行所谓的“类型擦除”过程。这意味着在运行时,泛型类型信息会被抹去,所有泛型类型都会转换成其对应的原始类型。 例如,`List&lt;String&gt;` 和 `...

    Java基础入门四泛型反射注解.pdf

    泛型是Java SE 5版本引入的一个新特性,它的主要目的是允许在使用类、接口和方法时能够引用到任何类型的对象,同时在编译期间就能进行类型检查,提供更安全的代码。泛型类和泛型方法可以提高代码的复用性,并减少...

Global site tag (gtag.js) - Google Analytics