可能有点烦人的事情之一就是表达概念所需的代码量。我相信“代码更少更好”的理念,而且我想知道如何编写Java而不会如此令人沮丧地冗长。最近,我阅读了Hidden Features of Java问题,并介绍了使用double-brace initialization来模拟List或Map文字。当然,使用这种方法有一些缺点,但它确实允许你用明显更少的字符做某些事情(如果你正确格式化),使代码更清晰,更清晰。我想知道是否没有其他聪明的技巧和鲜为人知的语言功能可以使我的代码更简洁。
我希望看到答案,解释该技术,它取代的冗长方式,以及使用该技术的任何潜在缺点。
答案 0 :(得分:9)
在Java 7中引入diamond operator之前,可以使用用于创建泛型类型的静态工厂方法来减少重复类型参数的需要,从而减少冗长。 (这是因为没有菱形运算符,Java永远不会在构造函数上推断出类型参数,但它会在方法调用上。)Google Collections使用这种技术,所以你可以写:
Set<MyClassWithALongName> set = Sets.newHashSet();
而不是:
Set<MyClassWithALongName> set = new HashSet<MyClassWithALongName>();
查看Google Collections的Lists
,Sets
和Maps
类,了解以“new”开头的方法,了解更多相关示例。
除非您是为旧版Java编写的,否则从Java 7开始,最好只使用菱形运算符。
答案 1 :(得分:8)
您可能已经知道的类似的一个,使用“varargs”功能:
String[] array = new String[] {"stack", "over", "flow"};
List<String> list = Arrays.asList(array);
可以缩写
List<String> list = Arrays.asList("stack", "over", "flow");
不可否认,这不会带来巨大的节省,但确实可以减少一点点的冗长。 正如托马斯所说,列表将是不可变的,所以要小心。实际上,你可以修改列表,你只是无法改变它的长度。感谢pimlottc指出这一点。
答案 2 :(得分:8)
使用像spring这样的依赖注入框架。我几乎总是对很多代码构造逻辑产生的方式感到惊讶。
答案 3 :(得分:3)
我发现编写简洁java的最有效的方法是不写java。如果我需要快速编写仍可与Java互操作的东西,我发现Groovy是一个很好的选择。使用仍然编译为JVM字节码的更简洁的语言可能是一个很好的解决方案。虽然我没有个人经验,但我听说Scala在很多情况下比Groovy更好。
答案 4 :(得分:3)
结帐lambdaj。它具有许多功能,可以帮助您的代码更简洁和可读。
答案 5 :(得分:2)
Fluent interfaces可以提供帮助 - 使用构建器和方法链来在java中创建类似于DSL的东西。你最终得到的代码可能有点难以阅读,因为它打破了Java的常规编码约定,例如从属性中删除set / get。
因此,在假的Swing流畅界面中,您可以定义一个按钮:
JButton button = Factory.button().icon(anIcon).tooltip("Wow").swing();
另一种方法是使用另一种语言,其中许多语言与JVM很好地集成,例如:
答案 6 :(得分:2)
在关闭时IO异常无趣(或不可能)的情况下,可以在try / finally块中使用“closeQuietly”方法。
Closeable c = null;
try {
...
c = openIt(...);
...
} finally {
closeQuietly(c);
}
其中:
/** Close 'c' if it is not null, squashing IOExceptions */
public void closeQuietly(Closeable c) {
if (c != null) {
try {
c.close();
} catch (IOException ex) {
// log error
}
}
}
请注意,对于Java 7及更高版本,新的“try with resources”语法使这个特定示例变得多余。
答案 7 :(得分:1)
我发现了一篇博客文章,提供了一种有趣的技术,允许用Java编写地图文字,就像在Perl,Python,Ruby等中一样:Building your own literals in Java - Tuples and Maps 我真的很喜欢这种方法!我在这里总结一下。
基本思想是创建一个通用的对类,并定义构造一对的静态函数,以及来自varargs对的数组。这允许以下简洁的地图文字定义:
Map(o("height", 3), o("width", 15), o("weight", 27));
其中o
是构造一对T1和T2对象的静态函数的名称,对于任何对象类型T1和T2,Map
是要构造的静态函数的名称地图。我不确定我喜欢选择Map
作为地图构造函数的名称,因为它与Java接口的名称相同,但概念仍然很好。
答案 8 :(得分:0)
静态初始化程序
示例1(地图):
Map<String, String> myMap = new HashMap<String, String>() {{
put ("a", "b");
put ("c", "d");
}};
示例2(列表):
List<String> myList = new ArrayList<String>() {{
add("a");
add("b");
add("c");
}};
答案 9 :(得分:0)
更多Guave善于初始化不可变地图(我发现这是比初始化可变地图更常见的情况):ImmutableMap.of(...) variants
Map<Service, Long> timeouts = ImmutableMap.of(
orderService, 1500,
itemService, 500);
答案 10 :(得分:0)
是否必须遍历集合,只是通过其中一个属性映射其元素?不仅如此,感谢Maps.uniqueIndex()
:
private void process(List<Module> modules) {
Map<String, Module> byName = Maps.uniqueIndex(modules, new Function<Module, String>() {
@Override public String apply(Module input) {
return input.getName();
}
});
或者如果这种情况经常发生,请将该函数设为public static final
成员Module
,以便将上述内容简化为:
Map<String, Module> byName = Maps.uniqueIndex(modules, Module.KEY_FUNCTION);