你的经验中发现的最糟糕的Java实践是什么?

29

类似于这个问题...

你在 Java 代码中发现的最糟糕的实践是什么?

我的发现有:

  • 在 servlet 中使用实例变量(这不仅是坏实践,事实上它还可能导致错误)
  • 使用像 HashMap 这样的集合实现,而不是使用适当的接口
  • 使用看似难以理解的类名,比如 SmsMaker(SmsFactory)或 CommEnvironment(CommunicationContext)

2
在servlet中简单地使用实例变量并不是一个错误或者不好的做法。在初始化servlet之后更改变量可能是一个错误(这取决于这些变量代表什么),并且是不好的做法,但是仅仅在servlet中使用实例变量并不是不好的做法。 - MetroidFan2002
使用集合实现而不是接口也不是一个错误。只有当接口的具体实现与客户端无关时,才算是错误。 - Steve B.
31个回答

96

我需要维护Java代码,其中大部分异常处理方式如下:

catch( Exception e ) {}

20
人们也会这样写: catch(Exception e){ // 不会发生的情况 }:) - jb.
29
很不幸,我的当前项目情况变差:catch(Throwable th) { logger.log("something went wrong"); } - Alan
5
嘿,在C#代码中这也是很常见的。 - Malik Daud Ahmad Khokhar
8
我承认,在使用Oracle的JDBC库时,我写了 catch (SQLException ex) { /* 这里可能抛出什么异常呢? */ } 来关闭一个连接。 - Powerlord
4
Java经常要求你捕获一个永远不会发生的异常。例如,当从一个字节数组输入流(ByteArrayInputStream)读取数据时可能会抛出IOException异常,但只有在你控制创建该字节数组输入流(ByteArrayInputStream)时才会出现这种情况。 - slim
显示剩余11条评论

39

我曾经遇到过“单例”异常:

class Singletons {
    public static final MyException myException = new MyException();
}

class Test {
    public void doSomething() throws MyException {
        throw Singletons.myException;
    }
}

每次抛出的异常实例都相同...具有完全相同的堆栈跟踪,与真实代码流程无关 :-(


2
最近在我参与的一次讨论中,这个问题被提出来了。(我皱了皱眉头。):o - Sam Harwell
我在想这是否就是.NET异常处理方式的理由。 - finnw
@finnw:你能详细说明一下吗?我对.NET异常一无所知,但现在我很想知道你的意思。 - Peter Štibraný
我指的是当异常被抛出时,堆栈跟踪会被填充,而不是在构造异常时。 - finnw
@finnw:一年后重新阅读,如果多个不同的线程同时抛出异常,那该怎么办? - Peter Štibraný

28

以下是六个非常糟糕的例子:

  • 没有错误报告,直接使用System.exit退出程序而不经过警告。例如:
    if(properties.size()>10000) System.exit(0); 会深埋在一个库中。
  • 使用字符串常量作为锁。例如:synchronized("one") { }
  • 对可变字段进行锁定。例如:synchronized(object) { object = ...; }
  • 在构造函数中初始化静态字段。
  • 触发异常只是为了获取堆栈跟踪信息。例如:try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); }
  • 无意义的对象创建。例如:new Integer(text).intValue()或更糟糕的是new Integer(0).getClass()

3
我仍然不明白拥有一万个财产有什么问题。 ;) - Peter Lawrey
1
哇,字符串常量作为锁是很不错的... :) - thenickdude
1
我必须承认,当我调试时,有时会抛出异常以获取堆栈跟踪,但我绝不会将其检查进去!如果我感到愚蠢,我会创建一个ExpectedException类。 - Captain Man
1
@CaptainMan 这很快也很粗糙,就像系统输出println语句一样。如果您不以这种方式发布代码,我认为这是可以的。 - Peter Lawrey
https://dev59.com/vmkw5IYBdhLWcg3w1d4m - user2418306

25
if{
 if{
  if{
   if{
    if{
     if{
      if{
       if{
         ....

23
}}} else { ... 如果出现这个代码片段,意味着前面的条件不成立,执行后面的操作。 - user85421
4
相关说明,使用if而不是if-else: 如果 (i==1) {} 如果 (i==2) {} 而不是 如果 (i==1) {} 否则如果 (i==2) {} - dogbane

24

我讨厌人们只是为了把一组常量挂在上面而创建接口:

public interface InterfaceAntiPattern {
  boolean BAD_IDEA = true;
  int THIS_SUCKS = 1;
}

—接口用于指定行为契约,而不是用于包含常量的方便机制。


我猜你喜欢 Java 6 中的静态导入? - Thorbjørn Ravn Andersen
3
静态导入是在Java 5中引入的,我不明白它们和这一点有什么关系。 - John Topley
3
数学(Math)是一个具体类而不是接口,因此 Math.PI 不是这种反模式的例子。 - John Topley
4
静态导入与这一点的相关性在于,它们允许您方便地只说 if (BAD_IDEA) 而不是 if (ConstantsClassPattern.BAD_IDEA),而无需扩展 InterfaceAntiPattern。请注意,此处的翻译将保留英文原文中的专业术语和代码片段。 - David Moles
《Effective Java》第19条的论述(第98-99页)实际上是反对那些实现常量接口以使用其常量的类。这不是我使用它们的方式。因此,在我的情况下,从未出现过“泄漏到类的导出API”这种情况,仅仅因为我从未有其他类实现常量接口。在这方面,我完全同意第19条的观点。 - Rogério
显示剩余7条评论

20

这并不仅仅与Java相关,而是指在知道结果不会改变时,反复调用一个昂贵的函数而不是将结果存储起来的情况。例如:

if (expensiveFunction() > aVar)
    aVar = expensiveFunction();
for (int i=0; i < expensiveFunction(); ++i)
    System.out.println(expensiveFunction());

这取决于你对“昂贵”一词的理解。马丁·福勒在他关于重构的书中实际上推荐像这样编写代码,因为这样更容易进行重构。 - oxbow_lakes
4
使用函数返回的变量值相比于使用变量更容易吗?例如,一行代码 vs X 行代码... - dusoft
3
你必须完全确信方法的结果不会发生改变。如果方法发生了改变,因此结果比编写相关方法时想象的更频繁地发生变化,你的代码将会崩溃,而你却不知道原因。如果你想要进行缓存,请在被调用的耗时方法中进行。在那里,你可以知道结果是否发生了改变。 - Janusz
而 Haskell 程序员则在嘲笑... - Mechanical snail

18

最糟糕的Java编程实践之一:全局可变状态(Global mutable state)。


3
如果你可以使用不可变状态,就不要使用可变状态。 - RAY

18

荒谬的面向对象狂热者们,追求层次结构超过10级。

这就是像DefaultConcreteMutableAbstractWhizzBangImpl这样的名称产生的原因。试着调试这种代码-你将在类树上上下翻飞数小时。


13

当你不应该使用子类化时,例如,而应该使用组合、聚合等。

编辑: 这是the hammer的一个特殊情况。


12

我们的实习生使用static修饰符来存储Seam应用程序中当前登录的用户。

 class Identity{
    ...
    public static User user; 
    ...
 }

 class foo{

    void bar(){
       someEntity.setCreator(Identity.user); 
    }

 }

当然,在他测试时它是有效的 :)


5
实习生在那里学习,所以我想这是可以原谅的。希望他不会再犯! - TM.
5
我已经做过了!唯一能挽救我的是我当时还是个学生,虽然给我打分的人没有发现我的错误,但在下一个项目中我自己发现了它。 - Athena

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