Java即将推出版本7.在我看来,必须有大量的教科书和培训手册,这些教科书和培训手册都是基于Java的旧版本教授方法,其中教授的方法现在有更好的解决方案。
什么样的样板代码情况,特别是那些你看到人们通过习惯实现的情况,你发现自己重构利用最新版本的Java?
答案 0 :(得分:70)
枚举。替换
public static final int CLUBS = 0;
public static final int DIAMONDS = 1;
public static final int HEARTS = 2;
public static final int SPADES = 3;
与
public enum Suit {
CLUBS,
DIAMONDS,
HEARTS,
SPADES
}
答案 1 :(得分:45)
泛型,不再需要创建迭代器来遍历集合中的所有元素。新版本更好,更易于使用,更易于理解。
编辑:
在:
List l = someList;
Iterator i = l.getIterator();
while (i.hasNext()) {
MyObject o = (MyObject)i.next();
}
在
List<MyObject> l = someList;
for (MyObject o : l) {
//do something
}
答案 2 :(得分:37)
使用StringBuffer
类型的局部变量来执行字符串连接。除非需要同步,否则现在建议使用StringBuilder
,因为此类提供了更好的性能(可能是因为它不同步)。
答案 3 :(得分:35)
从标准输入读取字符串:
Java pre-5 :
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String str = reader.readLine();
reader.close();
}
catch (IOException e) {
System.err.println("error when closing input stream.");
}
Java 5 :
Scanner reader = new Scanner(System.in);
String str = reader.nextLine();
reader.close();
Java 6 :
Console reader = System.console();
String str = reader.readLine();
答案 4 :(得分:24)
这是我看到的一个:
String.split()
与StringTokenizer
。
StringTokenizer
不建议用于新代码,但我仍然看到人们使用它。
至于兼容性,Sun努力让Java向后兼容。这部分地解释了为什么泛型如此复杂。弃用也应该有助于简化从旧代码到新代码的转换。
答案 5 :(得分:24)
使用Thread而不是Thread的许多其他替代品的旧代码......现在,我运行的代码中很少有代码仍然需要使用原始线程。抽象级别可以提供更好的服务,特别是Callable / Futures / Executors。
请参阅:
答案 6 :(得分:21)
VARARGS也很有用。
例如,您可以使用:
public int add(int... numbers){
int sum = 0 ;
for (int i : numbers){
sum+=i;
}
return sum ;
}
而不是:
public int add(int n1, int n2, int n3, int n4) ;
或
public int add(List<Integer> numbers) ;
答案 7 :(得分:17)
使用Vector类型的局部变量来保存对象列表。除非需要同步,否则现在建议使用List实现,例如ArrayList,因为此类提供了更好的性能(因为它是不同步的)。
答案 8 :(得分:16)
格式化打印是在JDK 1.5中引入的。所以不要使用:
String str = "test " + intValue + " test " + doubleValue;
或使用StringBuilder的等效文件,
可以使用
String str = String.format("test %d test %lg", intValue, doubleValue);
后者更易读,无论是字符串连接还是字符串构建器版本。我仍然发现人们很慢地采用这种风格。例如,Log4j框架不使用它,虽然我相信它会大大受益。
答案 9 :(得分:15)
原语和包装类型之间的显式转换(例如,Integer转换为int,反之亦然),自Java 1.5以来,自动装箱/取消装箱会自动处理。
一个例子是
Integer myInteger = 6;
int myInt = myInteger.intValue();
可以简单地写成
Integer myInteger = 6;
int myInt = myInteger;
但请注意NullPointerExceptions:)
答案 10 :(得分:12)
Q1:嗯,最明显的情况是在泛型/类型特定的集合中。另一个立即浮现在脑海中的是改进的循环,我觉得它看起来更清晰,更容易理解。
第二季度:总的来说,我一直在将JVM与我的应用程序一起捆绑在面向客户的应用程序中。这使我们可以使用新的语言功能,而不必担心JVM不兼容。如果我没有捆绑JRE,出于兼容性原因,我可能会坚持使用1.4。
答案 11 :(得分:12)
自1.5以来的一个简单更改,但在Swing API访问JFrame的contentPane时产生了一些小的差异:
myframe.getContentPane().add(mycomponent);
变为
myframe.add(mycomponent);
当然,Enums的引入改变了许多过去使用常量的应用程序的行为方式。
String.format()极大地改进了字符串操作,而三元if语句在使代码更易于阅读方面非常有用。
答案 12 :(得分:11)
通用集合使编码更具抗bug性。 OLD:
Vector stringVector = new Vector();
stringVector.add("hi");
stringVector.add(528); // oops!
stringVector.add(new Whatzit()); // Oh my, could spell trouble later on!
NEW:
ArrayList<String> stringList = new ArrayList<String>();
stringList.add("hello again");
stringList.add(new Whatzit()); // Won't compile!
答案 13 :(得分:11)
使用迭代器:
List list = getTheList();
Iterator iter = list.iterator()
while (iter.hasNext()) {
String s = (String) iter.next();
// .. do something
}
或者有时会看到另一种形式:
List list = getTheList();
for (Iterator iter = list.iterator(); iter.hasNext();) {
String s = (String) iter.next();
// .. do something
}
现在全部被替换为:
List<String> list = getTheList();
for (String s : list) {
// .. do something
}
答案 14 :(得分:11)
虽然我承认静态导入很容易被滥用,但我喜欢使用
import static Math.* ;
在使用大量数学函数的类中。它确实可以降低代码的冗长程度。但是,我不建议将它用于鲜为人知的图书馆,因为这会导致混淆。
答案 15 :(得分:10)
将现有数组复制到新数组:
pre-Java 5 :
int[] src = new int[] {1, 2, 3, 4, 5};
int[] dest = new int[src.length];
System.arraycopy(src, 0, dest, 0, src.length);
Java 6 :
int[] src = new int[] {1, 2, 3, 4, 5};
int[] dest = Arrays.copyOf(src, src.length);
以前,我必须显式创建一个新数组,然后将源元素复制到新数组(调用一个包含大量参数的方法)。现在,语法更清晰,新的数组从方法返回,我不必创建它。顺便说一下,方法Arrays.copyOf有一个名为Arrays.copyOfRange的变体,它复制了源数组的特定区域(非常像System.arraycopy)。
答案 16 :(得分:10)
将数字转换为字符串:
String s = n + "";
在这种情况下,我认为一直有更好的方法:
String s = String.valueOf(n);
答案 17 :(得分:8)
新的for
- 迭代数组和集合的每个构造对我来说是最大的。
这些天,当我看到样板for
循环使用索引变量逐个遍历数组时,它让我想要尖叫:
// AGGHHH!!!
int[] array = new int[] {0, 1, 2, 3, 4};
for (int i = 0; i < array.length; i++)
{
// Do something...
}
用for
construct introduced in Java 5替换上述内容:
// Nice and clean.
int[] array = new int[] {0, 1, 2, 3, 4};
for (int n : array)
{
// Do something...
}
干净,简洁,最重要的是,它为代码提供含义,而不是显示如何做某事。
显然,代码有意义迭代集合,而不是旧的for
循环说如何迭代数组。
此外,由于每个元素都独立于其他元素进行处理,因此可以允许将来优化并行处理,而无需对代码进行更改。 (当然是猜测。)
答案 18 :(得分:7)
与varargs相关;实用方法Arrays.asList(),从Java 5开始,采用varargs参数非常有用。
我经常发现自己简化了像
这样的东西List<String> items = new ArrayList<String>();
items.add("one");
items.add("two");
items.add("three");
handleItems(items);
使用
handleItems(Arrays.asList("one", "two", "three"));
答案 19 :(得分:6)
注解
我不知道到目前为止还没有人提到它,但很多框架都依赖于注释,例如Spring和Hibernate.今天通常不赞成使用xml配置文件来支持代码中的注释(尽管这意味着在从配置转向元代码时失去灵活性,但通常是正确的选择。最好的例子是EJB 2(和更早版本)与EJB 3.0相比以及如何通过注释简化EJB的编程。
我发现注释与AspectJ或Spring AOP等一些AOP工具结合使用也非常有用。这种组合可以非常强大。
答案 20 :(得分:5)
更改JUnit 3样式测试:
class Test extends TestCase {
public void testYadaYada() { ... }
}
到JUnit 4式测试:
class Test {
@Test public void yadaYada() { ... }
}
答案 21 :(得分:4)
改进的单身人士模式。从技术上讲,这些都包含在流行的答案枚举中,但它是一个重要的子类别。
public enum Singleton {
INSTANCE;
public void someMethod() {
...
}
}
比
更清洁,更安全public class Singleton {
public static final Singleton INSTANCE = new Singleton();
private Singleton() {
...
}
public void someMethod() {
...
}
}
答案 22 :(得分:3)
好的,现在轮到我了。
我不建议这些变化的90%。
并不是将它们与新代码一起使用并不是一个好主意,但是将现有代码更改为for循环更改为for循环只是浪费时间和破坏某些东西的机会。 (IIWDFWI)如果有效,请不要修复它!
如果您是一家真正的开发公司,那么这项变更现在可以进行代码审查,测试和调试。
如果有人无缘无故地做这种重构会导致任何类型的问题,我就不会给他们任何结果。
另一方面,如果您正在使用代码并更改该行的内容,请随时清理它。
此外,“性能”名称中的所有建议确实需要了解优化规律。用两个词来说,不要!永远! (谷歌“如果你不相信我的优化规则”。
答案 23 :(得分:3)
如果您对源代码树所做的一切都是如此,我会对这些行进行重构时保持警惕。到目前为止,这些示例似乎并不仅仅是改变任何工作代码库的原因,但是如果您要添加新功能,则应该利用所有新功能。
在一天结束时,这些示例并没有真正删除锅炉板代码,他们只是使用更易管理的新JDK构造来制作漂亮的锅炉板代码强>
使代码优雅的大多数方法都不在JDK中。
答案 24 :(得分:3)
转换类以使用泛型,从而避免不必要的强制转换。
答案 25 :(得分:3)
使用Swing的新DefaultRowSorter
对表进行排序,而不是从头开始自己滚动。
答案 26 :(得分:2)
Java的新版本很少破坏现有代码,所以只留下旧代码并专注于新功能如何让您的生活更轻松。
如果你只留下旧代码,那么使用新功能编写新代码并不是那么可怕。
答案 27 :(得分:1)
使用Vector代替新的集合。
使用类而不是枚举
public class Enum
{
public static final Enum FOO = new Enum();
public static final Enum BAR = new Enum();
}
使用Thread而不是新的java.util.concurrency包。
答案 28 :(得分:1)
字符串比较,我见过的老派Java程序员会这样做:
String s1 = "...", s2 = "...";
if (s1.intern() == s2.intern()) {
....
}
(据性能原因)
而现在大多数人都这样做:
String s1 = "...", s2 = "...";
if (s1.equals(s2)) {
....
}
答案 29 :(得分:0)
值得注意的是,Java 5.0已经出现了五年,从那以后只有很小的变化。您必须处理非常旧的代码才能重构它。