0. 背景
ECJ(Eclipse Compiler for Java)就是Eclipse自带的java编译器。
公司的项目都是在Eclipse上面做的。自己用了一段时间的Idea觉得很爽,准备换过来写,发现公司基盘报错了。调查发现是泛型方面的异常。整理如下。
1. 问题
公司源码肯定不能放,把问题整理之后,关键的几个类的UML类为:
出问题的类之间的UML图
各个类的代码为:
基础类:
public abstract class BaseClass<T> {
}
一个继承了基础类的类:
public class TClass extends BaseClass{
}
一个泛型接口:
interface BaseInterface<T extends BaseClass<?>> {
}
运行主类:
public class ECJ_test implements BaseInterface<TClass>{
public static void main(String[] args) {
TClass s = new TClass();
System.out.println(s.hashCode());
}
}
以上代码在Eclipse中会报warning,程序能够编译通过并运行:
Eclipse报警告
但是正常编译,执行
但是javac是编译不通过的:
image.png
那么制定了compiler为javac的Idea编译也就不通过了:
image.png
2. 解决办法:
2.1 设置编译器
公司基盘的代码,而且有部分类已经打包为jar,部署在maven仓库中了。要在Idea中编译就需要把Idea的编译器换成Eclipse:
Preferences > Build, Execution, Deployment > Java Compiler > User Compiler : Eclipse
Idea设置Compiler
2.2 修改代码
在遇到这个问题之前,我直觉上会觉得这个代码是不符合java语法的,应该修改为:
public class TClass extends BaseClass<TClass>{
}
这样修改之后的javac和Idea中都能正常编译执行,且不会有Error或Warning。
3. 后记
看起来javac比ECJ进行了更严格的泛型检查。但是问题不止于此,整理问题的过程中想到以下问题待思考,记下来以后学习:
- 项目部署用的Tomcat,依赖的也是官方jdk,为什么不会报错呢?
- 多数文章只会介绍泛型的使用,而泛型Class<?>和基础性Class在Java规范里的区别究竟是什么呢?