最近开始看起了Java,选择了《On Java8》这本教材作为了学习材料,看了几章感觉讲解的还是挺好的,然后下载了随书代码进行学习

1
2
3
4
5
6
7
git clone https://github.com/BruceEckel/OnJava8-Examples.git --depth=1
// 我使用jenv管理了多java环境
jenv local zulu64-1.8.0.362
./gradlew test
./gradlew build
./gradlew run
./gradlew xx:xx

不得不说,异常顺利

然后用IDEA打开项目,几乎没有文件是不报红的,代码补全等功能近乎瘫痪。讽刺的是作者在书中和Readme中鼓励大家使用IDEA,在issue中有人报告IDE打开有问题,作者的回复也都是该代码是IDE无关的,反正能跑就行。也不知道作者有没有用IDEA编辑过它这个学习代码。吐槽也没啥用,该教程推荐的人很多,但是我居然很神奇的没有搜到有人和我同样的问题(IDEA打开该项目尽量不报红),随后我就开始了零基础两天多的折腾,最终效果尚可

1. 修正项目结构

问题的关键在于IDEA的模块管理和包索引,当代码中存在package xxx的时候,IDEA强制要求你的文件应该存放到$Project/xxx里面,但是实际上javac进行编译的时候是不要求package xxx和文件系统结构是一致的,所以编译能通过,但是IDEA识别会有各种问题。因此直接新建一个目录,将文件移动到新目录里面去,文件夹比较多,写了一个python脚本进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import os
import shutil

exclude = ['buildSrc', 'gradle', 'test', 'build']


def handle_directory(directory_path, project_name, new_directory_name, exculde=[]):
new_foldername = os.path.join(directory_path, new_directory_name)
if not os.path.exists(new_foldername):
os.makedirs(new_foldername)
for filename in os.listdir(directory_path):
if filename == project_name:
continue
if filename in exculde:
continue
src = os.path.join(directory_path, filename)
dst = os.path.join(new_foldername, filename)
shutil.move(src, dst)


for foldername in os.listdir('.'):
if os.path.isdir(foldername) and not foldername.startswith('.') and foldername not in exclude:
handle_directory(foldername, foldername, foldername, ['tests', 'jmh'])
if os.path.exists(os.path.join(foldername, "tests")):
handle_directory(os.path.join(foldername, "tests"), foldername, foldername)
if os.path.exists(os.path.join(foldername, "jmh")):
handle_directory(os.path.join(foldername, "jmh"), foldername, os.path.join(foldername, "jmh"))

同时针对testsjmh文件夹特殊处理,并不放到主文件夹之下(之所以这样做,我各种尝试调整了sourceSets配置,当为子文件的时候IDE会存在问题,同样的子文件配置,我使用最新版本的gradle IDEA能正确识别,我也就不折腾了,直接移动出来了)

2. 修正sourcesSets excludes

因为有一些文件是不进行编译的(比如展示新功能),在buildSrc里面会使用project.sourceSets.main.java.excludes.add添加,达到忽略的目的,修改前使用文件名就行,修改后明显就多了一级

因此, buildSrc/src/main/groovy/com.mindviewinc.plugins/TaggingPlugin第35行

1
project.sourceSets.main.java.excludes.add(project.projectDir.relativePath(file))

3. 修正运行时的work directory

该项目里面存在很多IO操作,文件路径默认使用的相对于Project的目录,增加一个级别后需要进行修改

因此, buildSrc/src/main/groovy/com.mindviewinc.plugins/TaggingPlugin第44行和53行添加

1
workingDir = (project.name == "annotations") ? project.projectDir : "${project.projectDir}/${project.name}"

之所以annotations项目保持不变,是因为它里面都是使用相对路径加载class文件

4. 修正其它造成影响的相对路径

1
2
3
4
5
files/ListOfLines.java 12行  "../../streams/streams/Cheese.dat"
files/Writing.java 22行 "../../streams/streams/Cheese.dat"

enums/Reflection.java 41行 添加 ../
strings/Hex.java 30行 添加 ../

至此IDEA提示基本正常,这也给我学习JAVA生涯上了第一课: 在Java的世界里,你不死板一点,连IDE都与你为敌。

所以啊,这本书的作者肯定是为了要我们深刻的理解这个道理,才故意这样做 :)