本文提到的类型擦除与java中的重载有关。我们先看一下重载的定义:重载是Java多态性的表现,是用统一的处理方式处理不同数据的机制。Java方法的重载,即方法具有相同的命名,但参数列表(类型或个数)不同。
以下是我写的两个方法,用于将用户列表或不同类型用户列表的List加入包含收件人、主题、邮件正文的一个数据结构中。如下:
private void addEmailRecipients(FlowRunTime startFlowRunTime, List<String> userIds, ProcessContext context, List<Task> taskList) private void addEmailRecipients(FlowRunTime startFlowRunTime, List<Set<String>> userSetList, ProcessContext context, List<Task> taskList)
不仔细观察,参数列表是相似的,唯一的区别是第二个参数,方法1为List<String>、方法2为List<Set<String>>,我认为这样的参数列表是不同的,可以认定为重载。
但在保存时,编译器报出如下错误:
Method addEmailRecipients(FlowRunTime, List<String>, ProcessContext, List<Task>) has the same erasure addEmailRecipients(FlowRunTime, List<E>, ProcessContext, List<E>) as another
method in type ProcessActivityService
将has the same erasure等关键字搜索,有这样一篇文章叫《Java语法糖的味道:泛型与类型擦除》,文章来自与《深入理解Java虚拟机:JVM高级特性与最佳实践》 。
文章主要讲了Java语法中泛型的实现。下面是我对上篇文章读后的简单总结:
泛型是一种将参数类型作为参数实现更广泛应用的一种机制,在C++、C#中有所谓模板与泛型的机制是相似的。Java中的泛型与其他语言的泛型实现机制不同,是一种基于擦除的伪泛型。比如List<String>与List<Integer>在代码编写期间是不同的,但在编译好的字节码文件中却都被转化为原生类型。我们知道JDK1.5出现之前类似泛型的实现是通过继续以及类型强转实现,在字节码文件中泛型好像又回到了JDK1.5出现之前。关于Java为什么使用这种机制实现泛型,不同的人有不同的解决,比如效率等。但比如我们上述代码中的两个方法,如我们将其中一个返回值改为其他类型,编译是可以通过的。文章又对所谓的特征签名(源码签名,只包含参数类型、个数等)和方法描述(字节码签名,包括参数列表和返回值、原生类型等)进行了解释。重载是根据字节码的特殊签名,而返回值不参与特殊签名;但原本报类型擦除错误的方法加上不同返回值却可以通过编译,这是因为只要两个具有不同方法描述的方法均可以存在于同一个字节码文件中,所以通过了编译。另外,文章还对为什么类型在编译后被擦除,我们却可以通过反射等机制得到其原始类型。这是因为类型擦除了code级别的字节码文件,但特殊签名中包含的元数据特殊签名保留了原始类型。
2.2.1) ERROR 1222 (21000): The used SELECT statements have a different number of columns :
这是因为使用union的两个SQL语句产生的记录的表结构不一致. 必须是结构完全一致的记录集合才可以使用UNION.以上就是两个表的字段不一样导致。下面是我们使用的sql。这是一个查询所有代码工作的语句。前半部分是查询所有OA中的jbpm待办,而下半部分则是查询所有来自另外系统的待办工作。因为新需求需要在OA的jbpm待办中新增委托人、转交人等属性,而其他系统的待办工作则没有类似概念。两个UNION语句之间出现了表结构的不一致导致了上面的错误。
解决方法:
‘‘ as newFiled
<select id="queryMyTodoTask" resultMap="ExecutionResultMap" parameterType="com.fx.oa.module.bpm.workflow.api.shared.domain.ProcessExecutionEntity"> SELECT pexec.id, ptask.taskId, ptask.activityName, ptask.substituteUserCode, pexec.processDefineId, pdefine.name, pexec.processInstanceId, pexec.tableName, pexec.formDefineId, pexec.pkValue, pexec.urgencyDegree, suser.userName as ‘createUserCode‘, pexec.createTime, pexec.active, pexec.status, pexec.id AS todoUrl, pexec.id AS relateid, pexec.id AS domain FROM t_bpm_process_task ptask LEFT OUTER JOIN t_bpm_process_execution pexec ON ptask.processExecutionId = pexec.id LEFT OUTER JOIN t_bpm_process_define pdefine ON pexec.processDefineId = pdefine.id LEFT OUTER JOIN t_sys_user suser ON pexec.createUserCode = suser.userCode and suser.accessControl=‘Y‘ WHERE ptask.taskId IN ( SELECT DISTINCT taskimpl.dbid_ FROM jbpm4_task taskimpl LEFT OUTER JOIN jbpm4_participation participat ON taskimpl.dbid_ = participat.task_ WHERE taskimpl.assignee_ = #{createUserCode} OR (taskimpl.assignee_ IS NULL AND participat.type_ = ‘candidate‘ AND participat.userid_ = #{createUserCode}) ) AND ptask.STATUS = 0 AND pexec.STATUS IN (1, 6,8) AND pexec.active = ‘Y‘ <!-- <if test="createUserCode != null and createUserCode !=‘‘"> AND ptask.createUserCode = #{createUserCode} </if> --> <if test="createUserName != null and createUserName !=‘‘"> AND suser.userName LIKE ‘%‘ #{createUserName} ‘%‘ </if> <if test="name != null and name !=‘‘"> AND pdefine.name LIKE ‘%‘ #{name} ‘%‘ </if> <if test="startCreateTime != null and startCreateTime !=‘‘"> AND pexec.createTime <![CDATA[>= #{startCreateTime} ]]> </if> <if test="endCreateTime != null and endCreateTime !=‘‘"> AND pexec.createTime <![CDATA[<= #{endCreateTime}]]> </if> UNION SELECT todo.p_relate_id AS id, todo.id AS taskId, todo.p_activity_name AS activityName , todo.p_relate_id AS processDefineId, ‘‘ as substituteUserCode, todo.p_task_name AS NAME , todo.p_relate_id AS processInstanceId, todo.p_relate_id AS tableName, todo.p_relate_id AS formDefineId, todo.p_relate_id AS pkValue, todo.p_urgency_degree AS urgencyDegree , todo.p_applicant_name AS createUserCode , todo.p_applicant_time AS createTime , ‘Y‘ AS active, todo.p_urgency_degree AS STATUS , todo.p_url AS todoUrl , todo.id AS relateid , todo.p_domain AS domain FROM m_Todo todo where 1=1 AND todo.p_approval_id = #{createUserCode} <if test="createUserName != null and createUserName !=‘‘"> AND todo.p_applicant_name LIKE ‘%‘ #{createUserName} ‘%‘ </if> <if test="name != null and name !=‘‘"> AND todo.p_task_name LIKE ‘%‘ #{name} ‘%‘ </if> <if test="startCreateTime != null and startCreateTime !=‘‘"> AND todo.p_applicant_time <![CDATA[>= #{startCreateTime} ]]> </if> <if test="endCreateTime != null and endCreateTime !=‘‘"> AND todo.p_applicant_time <![CDATA[<= #{endCreateTime}]]> </if> ORDER BY createTime DESC </select>