寻找有用的Eclipse Java代码模板

521

你可以通过Window > Preferences > Java > Editor > Templates在Eclipse中创建各种Java代码模板。

例如,sysout 被扩展为:

System.out.println(${word_selection}${});${cursor}

你可以通过输入sysout然后按下CTRL+SPACE来激活它。

你目前使用了哪些有用的Java代码模板?请包括其名称和描述以及为什么这很棒。

我正在寻找一个原创/新颖的模板用法,而不是一个内置的现有功能。

  • 创建Log4J日志记录器。
  • 从显示器中获取Swt颜色。
  • 同步执行-Eclipse Framework。
  • Singleton模式/枚举Singleton生成。
  • 读取文件。
  • Const。
  • Traceout。
  • 格式化字符串。
  • 注释代码审查。
  • 字符串格式化。
  • 尝试最终锁定。
  • 消息格式化i18n和日志记录。
  • Equalsbuilder。
  • Hashcodebuilder。
  • Spring对象注入。
  • 创建FileOutputStream。

5
有没有一些工具可以根据枚举类型自动生成包含所有可能情况的switch语句?我知道可以使用CTRL+1来完成,但我更愿意使用命令完成。 - GreenKiwi
4
System.out.println(${word_selection}${});${cursor} 的意思是什么?听起来好像有一种方法可以选择一个单词并自动将其包裹在 sysout 调用中,我是对的吗?如何实现? - CodyBugstein
3
你可以在sysout调用中选择要突出显示的单词,然后按Ctrl-Space键(如果你有很多高亮感知模板,则输入模板名称)。 - JReader
1
@JReader ${}是做什么用的? - Roland
作为 Stack Overflow 的专横版主 中的一个示例。但请注意,该视频中有大量事实信息是错误的,例如 Google 会将对答案的投票考虑在内以进行搜索排名。 - Peter Mortensen
46个回答

427

以下代码模板将同时创建一个记录器并创建所需的正确导入。

SLF4J

${:import(org.slf4j.Logger,org.slf4j.LoggerFactory)}
private static final Logger LOG = LoggerFactory.getLogger(${enclosing_type}.class);

Log4J 2

${:import(org.apache.logging.log4j.LogManager,org.apache.logging.log4j.Logger)} 
private static final Logger LOG = LogManager.getLogger(${enclosing_type}.class); 

Log4J

${:import(org.apache.log4j.Logger)}
private static final Logger LOG = Logger.getLogger(${enclosing_type}.class);

Source.

JUL

${:import(java.util.logging.Logger)}
private static final Logger LOG = Logger.getLogger(${enclosing_type}.class.getName());

3
我认为${:import...}只适用于较新版本的Eclipse。我被困在3.2上,无法使用它。 - Adam Crume
5
我喜欢它!但是我将${import ...}放在Logger声明下面,这样它就不会添加新行了。 - Dario Seidl
对于log4j2,我必须将模板设置为:${:import(org.apache.logging.log4j.LogManager,org.apache.logging.log4j.Logger)} private static final Logger LOG = LogManager.getLogger(${enclosing_type}.class); - TMS
这将在当前位置添加声明。是否可能将声明作为类的第一个成员添加? - gammay
@gammay - 我不知道有没有,但如果你找到了方法,请随意改进答案。 - Robert Munteanu
显示剩余3条评论

49

这里还有一些额外的模板:链接 I - 链接 II

我喜欢这个:

readfile

 ${:import(java.io.BufferedReader,  
           java.io.FileNotFoundException,  
           java.io.FileReader,  
           java.io.IOException)}  
 BufferedReader in = null;  
 try {  
    in = new BufferedReader(new FileReader(${fileName}));  
    String line;  
    while ((line = in.readLine()) != null) {  
       ${process}  
    }  
 }  
 catch (FileNotFoundException e) {  
    logger.error(e) ;  
 }  
 catch (IOException e) {  
    logger.error(e) ;  
 } finally {  
    if(in != null) in.close();  
 }  
 ${cursor} 

更新: 这个模板的Java 7版本为:

${:import(java.nio.file.Files,
          java.nio.file.Paths,
          java.nio.charset.Charset,
          java.io.IOException,
          java.io.BufferedReader)}
try (BufferedReader in = Files.newBufferedReader(Paths.get(${fileName:var(String)}),
                                                 Charset.forName("UTF-8"))) {
    String line = null;
    while ((line = in.readLine()) != null) {
        ${cursor}
    }
} catch (IOException e) {
    // ${todo}: handle exception
}

48
我认为这就是方法存在的原因 :) - benmmurphy
3
抱歉,我理解为您没有抓住重点。您所说的,实际上我不知道您的重点是什么。这是关于代码生成而不是模块化的问题。 - Jonathan Holloway
21
我认为关键是在模板中添加这么多代码,这是一种非常常见的剪切和粘贴编程。 - Scott McIntyre
6
是的,你应该使用一个实用方法来读取文件,而不是粘贴代码块。你可以自己编写一个方法,或者使用Apache commons-io IOUtils。但是,如果你频繁创建不同classpath的临时项目,添加JAR包或链接到你的实用类中仅仅为了读取文件可能会很麻烦。有时候,你只需要写一些临时性的代码来读取文件,并继续你的生活。 - Mike Clark
1
在Java 7中,建议使用StandardCharsets.UTF_8而不是Charset.forName("UTF-8") - Mike Clark
显示剩余3条评论

33

格式化字符串

使用MessageFormat将所选内容包装起来。

 ${:import(java.text.MessageFormat)} 
 MessageFormat.format(${word_selection}, ${cursor})

这让我可以将光标移动到一个字符串上,通过 Shift-Alt-Up 快捷键将选择扩展到整个字符串,然后按两次 Ctrl-Space。

锁定选择

lock - 将选定的行用 try finally lock 包围起来。假设存在一个 lock 变量。

${lock}.acquire();
try {
    ${line_selection}
    ${cursor}
} finally {
    ${lock}.release();
}

Surround With菜单(Alt-Shift-Z)中会显示NB ${line_selection} 模板。


我使用这个与日志语句结合的方式:logger.info(MessageFormat.format(${word_selection}, ${cursor}); - Pierre Henry
获取和释放锁的方法称为“lock”和“unlock”。在信号量中使用“acquire”和“release”,但在try-finally块中使用它们并不像在锁中那样被强烈建议。参考:https://dev59.com/l1_Va4cB1Zd3GeqPY_sR - Marco Lackovic
按两次Ctrl+Space似乎不再起作用了,会弹出SWT模板。有替代方法吗? - Noumenon

28

我知道这是一个已经过时的帖子,但出于完整起见,我想分享一下:

一个正确的单例生成模板,可以克服有缺陷的双重检查锁定设计(如上所述并在其他地方提到)

单例创建模板: 将其命名为createsingleton

static enum Singleton {
    INSTANCE;

    private static final ${enclosing_type} singleton = new ${enclosing_type}();

    public ${enclosing_type} getSingleton() {
        return singleton;
    }
}
${cursor}


访问使用上述方法生成的单例:

单例引用模板: 将其命名为getsingleton

${type} ${newName} = ${type}.Singleton.INSTANCE.getSingleton();

4
它并没有死亡,它是一个社区维基页面,因此当您找到更多模板时将其添加进去是有意义的。其他地方实际上没有一个全面的这些模板集合... - Jonathan Holloway
Jon,我发帖和你之前的帖子相隔近8个月,这就是为什么我引用你的评论的原因。我无法比你的评论表达得更好 :) - questzen
当我将其作为类的一部分创建时(在类中嵌套枚举),${enclosing_type}会得到类的名称 - 这是预期的吗? - Mr_and_Mrs_D
1
@Mr_and_Mrs_D,我认为这就是关键所在。你可以在这个模板中获取一个类的单例实例。现在你只需要将封闭类型的构造函数设为私有,并拥有一个相当安全的单例生成器。 - Mike Adler
如果您想使用此代码创建枚举,请使用${primary_type_name}作为示例:`public enum ${primary_type_name} { INSTANCE; private ${return_type} ${name} = new ${return_type}(); public ${return_type} ${getName}(${}) { return ${name}; } ${cursor} }` - Robert Smit

28

将代码片段添加到循环遍历Map.entrySet()

模板:

${:import(java.util.Map.Entry)}
for (Entry<${keyType:argType(map, 0)}, ${valueType:argType(map, 1)}> ${entry} : ${map:var(java.util.Map)}.entrySet())
{
    ${keyType} ${key} = ${entry}.getKey();
    ${valueType} ${value} = ${entry}.getValue();
    ${cursor}
}

生成的代码:

for (Entry<String, String> entry : properties.entrySet())
{
    String key = entry.getKey();
    String value = entry.getValue();
    |
}

屏幕截图


1
喜欢你的图片,它向我展示了你可以在${}中使用变量,并且这样做可以启用字段之间的“制表符迭代”,而不是${cursor}。谢谢。 - WesternGun

25

对于log,在成员变量中加入这个有用的小诀窍。

private static Log log = LogFactory.getLog(${enclosing_type}.class);

手动写入日志文件的代码如下:${:import(java.io.PrintWriter, java.io.BufferedWriter, java.io.FileWriter)} try { PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(${logFile:var(String)}, true))); out.println(${logLine:var(String)}${cursor}); out.close(); } catch (IOException e) { /* TODO: 异常处理 */ e.printStackTrace(); } - Jack Miller
在这个上下文中,“ditty”是什么意思? - Peter Mortensen
@PeterMortensen 按照定义,Ditty 是一首短歌曲,但在口语英语中,我听到它被用来表示任何重复的东西。 - cgp

24
使用Mockito创建模拟对象(在“Java语句”上下文中):
${:importStatic('org.mockito.Mockito.mock')}${Type} ${mockName} = mock(${Type}.class);

在“Java类型成员”中:
${:import(org.mockito.Mock)}@Mock
${Type} ${mockName};

模拟一个void方法抛出异常:

${:import(org.mockito.invocation.InvocationOnMock,org.mockito.stubbing.Answer)}
doThrow(${RuntimeException}.class).when(${mock:localVar}).${mockedMethod}(${args});

模拟一个void方法来执行某些操作:
${:import(org.mockito.invocation.InvocationOnMock,org.mockito.stubbing.Answer)}doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
    Object arg1 = invocation.getArguments()[0];
    return null;
}
}).when(${mock:localVar}).${mockedMethod}(${args});

验证模拟方法只被调用一次:

${:importStatic(org.mockito.Mockito.verify,org.mockito.Mockito.times)}
verify(${mock:localVar}, times(1)).${mockMethod}(${args});

验证模拟方法从未被调用:

${:importStatic(org.mockito.Mockito.verify,org.mockito.Mockito.never)}verify(${mock:localVar}, never()).${mockMethod}(${args});

使用Google Guava创建新的链表(对于哈希集和哈希映射也类似):

${import:import(java.util.List,com.google.common.collect.Lists)}List<${T}> ${newName} = Lists.newLinkedList();

我使用一个生成测试类的大型模板。以下是一个缩短版本,每个人都可以根据自己的需求进行定制:

package ${enclosing_package};

import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.runner.RunWith;

// TODO autogenerated test stub
@RunWith(MockitoJUnitRunner.class)
public class ${primary_type_name} {

    @InjectMocks
    protected ${testedType} ${testedInstance};
    ${cursor}

    @Mock
    protected Logger logger;

    @Before
    public void setup() throws Exception {
    }

    @Test
    public void shouldXXX() throws Exception {
        // given

        // when
        // TODO autogenerated method stub

        // then
        fail("Not implemented.");
    }
}
// Here goes mockito+junit cheetsheet

1
我很好奇:你为什么需要模拟日志记录器? - Vladimir Sizikov
6
如果捕获异常(失败情况),您可以验证模拟记录器是否被调用。这特别有用,如果您不打算重新抛出异常,但想要断言它不会被静默忽略。 - mantrid

23

空指针检查!

if( ${word_selection} != null ){
    ${cursor}
}

if( ${word_selection} == null ){
    ${cursor}
}

Guava 中的 PreConditions.checkNotNull(...) 方法是一个非常易读的替代方案(特别是使用静态导入)。 - Thorbjørn Ravn Andersen
1
在检查非空之前,首先检查是否为空(== null)是最佳实践。 - KrishPrabakar

21

我最喜爱的之一是foreach

for (${iterable_type} ${iterable_element} : ${iterable}) {
    ${cursor}
}

还有traceout,因为我经常用它来跟踪:

System.out.println("${enclosing_type}.${enclosing_method}()");

我突然想到另一个关键字并在网上找到了它,const

private static final ${type} ${name} = new ${type} ${cursor};

11
在Eclipse中,foreach作为标准代码助手提供。我认为你的模板没有额外的功能。 - Rich Seller
4
好的,sysout 是一种非常创新的模板。问题是关于我们正在使用的有用模板。 - Artem Barger
4
你的 traceout 已经在 Eclipse 中作为 systrace 可用。 - dogbane
7
好的,我希望你现在可以在Eclipse中看到它,因为这个问题。 - Artem Barger
const作为静态常量,可以作为标准代码辅助(不确定是何时添加的)。 - Armand

20

有一个小技巧是关于sysout的 —— 我喜欢把它改名为“sop”。Java库中没有任何其他以“sop”开头的东西,因此您可以快速输入“sop”,它就会自动插入。


11
默认情况下,只需键入“syso”即可执行与“sysout”相同的操作。 - MasterScrat
9
用 SOP 比你多赢了 25% ,不过... ;) - Scott Stanchfield
2
自从Eclipse Mars版本以来,快捷键“syso”+Ctrl+Space的功能有所退步:它会列出一些类名中包含字符s、y、s和o的类(由于新的CamelCase查找)。因此,现在您还需要从列表中选择sysout并按回车键。 - bobbel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接