首页 > 编程语言 >Java5泛型的用法,T.class的获取和为擦拭法站台

Java5泛型的用法,T.class的获取和为擦拭法站台

时间:2023-07-13 19:32:48浏览次数:35  
标签:Java 擦拭法 public Java5 泛型 ParameterizedType class


Java 5的泛型语法已经有太多书讲了,这里不再打字贴书。GP一定有用,不然Java和C#不会约好了似的同时开始支持GP。但大家也清楚,GP和Ruby式的动态OO语言属于不同的意识形态,如果是一人一票,我想大部分的平民程序员更热衷动态OO语言的平白自然。但如果不准备跳槽到支持JSR223的动态语言,那还是看看GP吧。

胡乱总结泛型的四点作用:
第一是泛化,可以拿个T代表任意类型。 但GP是被C++严苛的静态性逼出来的,落到Java、C#这样的花语平原里----所有对象除几个原始类型外都派生于Object,再加上Java的反射功能,Java的Collection库没有范型一样过得好好的。

第二是泛型 + 反射,原本因为Java的泛型拿不到T.class而觉得泛型没用,最近才刚刚学到通过反射的API来获取T的Class,后述。

第三是收敛,就是增加了类型安全,减少了强制类型转换的代码。这点倒是Java Collection历来的弱项。

第四是可以在编译期搞很多东西,比如MetaProgramming。但除非能完全封闭于框架内部,框架的使用者和扩展者都不用学习这些东西的用法,否则那就是自绝于人民的票房毒药。C++的MetaProgramming好厉害吧,但对比一下Python拿Meta Programming生造一个Class出来的简便语法,就明白什么才是真正的叫好又叫座。

所以,作为一个架构设计师,应该使用上述的第2,3项用法,在框架类里配合使用反射和泛型,使得框架的能力更强; 同时采用收敛特性,本着对人民负责的精神,用泛型使框架更加类型安全,更少强制类型转换。

擦拭法避免了Java的流血分裂 :
大家经常骂Java GP的擦拭法实现,但我觉得多亏于它的中庸特性---如果你用就是范型,不用就是普通Object,避免了Java阵营又要经历一场to be or not to be的分裂。
最大的例子莫过Java 5的Collection 框架, 比如有些同学坚持认为自己不会白痴到类型出错,而且难以忍受每个定义的地方都要带一个泛型定义List〈Book〉,不用强制类型转换所省下的代码还不够N处定义花的(对了,java里面还没有tyepdef.....),因此对范型十分不感冒,这时就要齐齐感谢这个搽拭法让你依然可以对一个泛型框架保持非泛型的用法了...

通过反射获得 T.class:

不知为何书上不怎么讲这个,是差沙告诉我才知道的,最经典的应用见Hibernate wiki的Generic Data Access Objects, 代码如下:

abstract public class BaseHibernateEntityDao<T> extends HibernateDaoSupport { 

 private Class<T> entityClass; 

 public BaseHibernateEntityDao() { 

 entityClass =(Class<T>) ((ParameterizedType) getClass() 

 .getGenericSuperclass()).getActualTypeArguments()[0]; 

 } 

 public T get(Serializable id) { 

 T o = (T) getHibernateTemplate().get(entityClass, id); 

} 

}



精华就是这句了:
Class<T> entityClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

泛型之后,所有BaseHibernateEntityDao的子类只要定义了泛型,就无需再重载getEnttityClass(),get()函数和find()函数,销益挺明显的,所以SpringSide的Dao基类毫不犹豫就泛型了。

不过擦拭法的大棒仍在,所以子类的泛型语法可不能乱写,最正确的用法只有:

public class BookDao extends BaseHibernateEntityDao<Book>



评论
# re: Java5泛型的用法,T.class的获取和为擦拭法站台
Strategy Pattern with Generics

http://www.javaspecialists.co.za/archive/newsletter.do?issue=123&locale=en_US

贴一篇用泛型的方式实现策略模式...
theone 评论于 2006-04-28 17:27 回复 更多评论
# re: Java5泛型的用法,T.class的获取和为擦拭法站台
I encounter same problem with http://forum.java.sun.com/thread.jspa?threadID=684429&messageID=3985573

how about this?
faint 评论于 2006-04-28 21:48 回复 更多评论
# re: Java5泛型的用法,T.class的获取和为擦拭法站台

package test; 


import java.lang.reflect.ParameterizedType; 

import java.lang.reflect.Type; 


import junit.framework.TestCase; 


class TClass<T> { 

} 


class GoodClass<T> extends TClass<String> { 

public ParameterizedType getClassT() { 

return (ParameterizedType) getClass().getGenericSuperclass(); 

} 

} 


class BadClass<T> extends TClass<T> { 

public ParameterizedType getClassT() { 

return (ParameterizedType) getClass().getGenericSuperclass(); 

} 

} 


public class GenericsTest extends TestCase { 


private void print(Type[] targs) { 

System.out.print("actual type arguments are:"); 

for (int j = 0; j < targs.length; j++) { 

System.out.print(" instance of " + targs[j].getClass().getName() + ":"); 

System.out.println(" (" + targs[j] + ")"); 

} 

} 


public void testGoodClass() throws Exception { 

ParameterizedType type = new GoodClass<String>().getClassT(); 

Type[] types = type.getActualTypeArguments(); 

print(types); 


assertEquals(TClass.class, type.getRawType()); 

assertEquals(String.class, types[0]); 

} 


public void testBadClass() throws Exception { 

ParameterizedType type = new BadClass<String>().getClassT(); 

Type[] types = type.getActualTypeArguments(); 

print(types); 


assertEquals(TClass.class, type.getRawType()); 

assertEquals(String.class, types[0]); 

} 

}

标签:Java,擦拭法,public,Java5,泛型,ParameterizedType,class
From: https://blog.51cto.com/u_1044274/6715588

相关文章

  • 泛型 、entry词遍历方式、迭代器方式遍历
    示例代码publicclassFanxing<T>{//类的模板,类在编译时未确认privateTa;privateTb;publicTadd(){returna;}publicTsub(){returnb;}@Testpublicvoidfanxing(){List<String>list=newArra......
  • C#使用泛型方法将Datatable转换成List对象集合
     在项目中遇到需要将Datatable转换成对象的需求,通过dr[0]取下标这种获取,如果数据的顺序发生了改变则需要改变全部,工作量大foreach(DataRowdrindt.Rows){CheckDetailinfo=newCheckDetail();info.org_id=dr[0].ToStrin......
  • 反射操作泛型
    1、Java采用泛型擦除的机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型将全部擦除。2、为了通过反射操作这些类型以迎合实际开发的需要,Java新增ParameterizedType,GenericArrayType、Type......
  • c++模板相关学习--泛型编程
     类模板基础#define_CRT_SECURE_NO_WARNINGS#include<iostream>usingnamespacestd;#include<string>template<classNAMETYPE,classAGETYPE=int>//类模板中可以有默认参数classPerson{public:Person(NAMETYPEname,AGETYPEage){......
  • 泛型
    泛型泛型的概念编译时检查非法的类型数据结构,本质就是参数化类型,也就是所操作的数据类型被指定为类型数据结构.泛型类定义语法class类名称<泛型标识,泛型标识,...>{private泛型标识变量名;......}常用泛型标识:TEKV泛型类注意事项泛型类,如果没有......
  • 二-编程知识-泛型
    §泛型方法一般定义如下,即方法的前面加了个publicclassFClass{ public<T>List<T>f(Tt){...};}3种泛型参数推断方式:1、直接在f()前面加确定泛型fClass.<Integer>f(xxx)2、通过输入参数确定,下面这个推断为Integerintnumber=0;fClass.f(number)3、通过返......
  • Kotlin中的泛型:协变与逆变
    协变与逆变现在假设存在类A和类B,以及泛型类LIst<A>和泛型类LIst<B>,则协变和逆变的定义如下:协变如果A是B的子类,且List<A>是List<B>的子类,那么可以说泛型List<T>是协变的逆变如果A是B的子类,且List<B>是List<A>的子类,那么可以说泛型List<T>是逆变的Java中的泛型Java中的......
  • # 泛型 \<T>
    泛型是在C++中就已经存在的功能,而C#也自然继承了这一个非常重要的功能。泛型可以应用于完全一致类型的数据交流,但由于不能事先知道数据类型,因此只能做一些访问和相互赋值功能。例如如下代码voidswap<T>(refTa,refTb){Ttemp=a;a=b;b=temp;}//St......
  • C#学习笔记 -- 泛型
    泛型2、C#中的泛型泛型可以让多个类型共享一组代码允许声明类型参数化的代码,用不同的类型来实例化提供5种泛型:类、结构、接口、委托和方法classMyStack<T>{  intStackPointer=0;  T[]StackArray;  publicvoidPush(Tt){...}  public......
  • rust 集合、错误处理、泛型、Trait、生命周期、包
    集合组织特性相同的数据;泛型可以定义任何抽象数据类型;生命周期限制所有权的作用域范围;错误处理使程序更健壮。集合一组特性相同的数据集合,除了基本数据类型的元组、数组。rust标准库提供了一些非常有用的数据结构。Vector存储列表通过类型Vec<T>定义。只能存储相同类型的值,......