您的经历中发现了最糟糕的Java实践?

与此问题类似……

您在Java代码中实际发现的最差实践是什么?

我的是:

  • 在servlet中使用实例变量(这不仅仅是不好的做法,而是bug,实际上)
  • 使用像HashMap这样的Collection实现,而不是使用适当的接口
  • 使用看似神秘的类名,如SmsMaker(SmsFactory)或CommEnvironment(CommunicationContext)

我必须维护java代码,其中大多数exception处理如下:

catch( Exception e ) {} 

一旦遇到’singleton’exception:

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

每次都抛出相同的exception实例 …与完全相同的堆栈跟踪,与实际代码流无关:-(

六个非常糟糕的例子;

  • 而不是错误报告,只是System.exit没有警告。 例如
    if(properties.size()>10000) System.exit(0); 埋藏在图书馆深处。
  • 使用字符串常量作为锁。 例如, synchronized("one") { }
  • 锁定可变字段。 例如synchronized(object) { object = ...; } synchronized(object) { object = ...; }
  • 在构造函数中初始化静态字段。
  • 触发exception只是为了获得堆栈跟踪。 例如, try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); } try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); } try { Integer i = null; i.intValue(); } catch(NullPointerException e) { e.printStackTrace(); }
  • 无意义的对象创建,例如new Integer(text).intValue() or worse new Integer(0).getClass()
 if{ if{ if{ if{ if{ if{ if{ if{ .... 

当人们创建接口只是为了挂起一组常量时,我​​讨厌它:

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

– 接口用于指定行为合同,而不是用于包含常量的便利机制。

严格地说与Java没有关系,但是当你知道它不会改变时,反复调用昂贵的函数而不是存储结果。 例:

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

最糟糕的Java实践几乎涵盖了所有其他实践: 全局可变状态。

荒谬的OO狂热与阶级层次10+级深。

这就是DefaultConcreteMutableAbstractWhizzBangImpl这样的名字来自的地方。 试着调试那种代码 – 你会在课堂上上下几个小时。

当您不应该进行子类化时,例如,而不是使用组合,聚合等。

编辑:这是锤子的一个特例。

看到这样的事情:

 public static boolean isNull(int value) { Integer integer = new Integer(value); if(integer == null) { return true; } else { return false; } } 

他们对多头有类似的方法。

我认为他们最初做过类似的事情

 if(value == null) { 

并得到一个编译错误,仍然没有意识到原始值不能为空。

我们的实习生使用static修改器将当前登录的用户存储在Seam应用程序中。

  class Identity{ ... public static User user; ... } class foo{ void bar(){ someEntity.setCreator(Identity.user); } } 

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

不关闭finally {}中的数据库连接,文件句柄等

我曾经不得不调查一个Web应用程序,其中所有状态都保存在发送给客户端的网页中,而Web服务器中没有状态。

尽管比例很好:)

需要调用者执行的API:

 Foobar f = new Foobar(foobar_id); f = f.retrieve(); 

以下任何一项都会更好:

 Foobar f = Foobar.retrieve(foobar_id); 

要么

 Foobar f = new Foobar(foobar_id); // implicit retrieve 

要么

 Foobar f = new Foobar(); f.retrieve(foobar_id); // but not f = ... 

将function抽象到库类中,永远不会被重复使用,因为它对于要解决的原始问题是如此具体 。 因此最终得到了大量的库类,没有人会使用它们,这完全掩盖了你实际拥有的两个有用的实用程序(即CollectionUtilsIOUtils )。

……停下来呼吸……

所有私有变量创建acessors和mutator,而不是停下来思考,有时是自动的。

封装是出于某种原因而发明的。

不像程序员那样思考。

长时间曝光后,Java会对某些人这样做。

为什么? 我的观点是,这是因为有太多的智能感知而且毫无意义 。 它可以让你快速做出愚蠢的事情,人们不会停下来思考。

例1:

 boolean negate( boolean shouldNegate, boolean value ) { return (shouldNegate?(!value):value; } 

当然,它与值^ shouldNegate相同,是一个简单的XOR。

例2 🙁我发誓我不是这样做的)

 boolean isNotNull( Object o ) { return o != null; } 

两者都有额外的4-6行Javadoc, 解释了这些方法的作用。

例3:

 /** * * */ 

一个空的Javadoc,让那些讨厌的 Eclipse“缺少Javadoc”的警告消失了。

例3b:

 /** * A constructor. Takes no parameters and creates a new instance of MyClass. */ public MyClass() { } 

面向对象设计的过度抽象(仅删除10k)。

类似线程上的相同答案(适用于允许面向对象设计的所有语言)。

我最喜欢的排序算法,礼貌的灰胡子旅:

 List needsToBeSorted = new List (); ...blah blah blah... Set sorted = new TreeSet (); for (int i = 0; i < needsToBeSorted; i++) sorted.add (needsToBeSorted.get (i)); needsToBeSorted.clear (); for (Iterator i = sorted.iterator (); i.hasNext ();) needsToBeSorted.add (i.next ()); 

不可否认,它确实奏效了,但最终我对他说,也许Collections.sort会更容易。

几分钟前我看到了这条线:

 Short result = new Short(new Integer(new Double(d).intValue()).shortValue()); 

在文件I / O中:错误使用try-catch块。

 try { /* open file */ } catch(Exception e) { e.printStackTrace(); } try { /* read file content */ } catch (Exception e) { e.printStackTrace(); } try { /* close the file */ } catch (Exception e) { e.printStackTrace(); } 

@madlep完全正确! Java社区的某些部分真的过于极端抽象和疯狂深层次的层次结构。 几年前史蒂夫·耶格(Steve Yegge)有一篇关于它的好文章: 在名词王国中执行 。

使用for循环或任何forms的循环就足够的exception来定义逻辑。

例:

 while(i < MAX_VALUE) { try { while(true) { array[j] = //some operation on the array; j++; } } catch(Exception e) { j = 0; } } 

严肃的,我知道写这段代码的人。 我查看了它并更正了代码:)

与您的相似,但更进了一步:

在Struts操作中,当请求范围变量是正确的事情时,使用类(静态)变量。 :o

这实际上已经在生产中部署了几个月,在我有一天审查代码之前没有人注意到任何事情。

过度关注重复使用导致各处静止物体的物体。 (在某些情况下,重复使用可能非常有用)。

Java具有GC内置function,如果需要对象,请创建一个新对象。

这是一个来自实际applet的裁剪样本我维护它让我永远意识到正在做的事情。

 int sval, eval, stepv, i; double d; if (/*someCondition*/) { sval = 360;//(all values multiplied by 20) eval = -271; stepv = -10; } else if (/*someCondition*/) { sval = 320; eval = -601; stepv = -10; } else if (/*someCondition*/) { sval = 0; eval = -311; stepv = -10; } else { sval = 360; eval = -601; stepv = -10; } for (i = sval; i > eval; i = i + stepv) { d = i; d = d / 20.0; //do some more stuff in loop } 

结果他想在循环上迭代.5而不是粘贴错误,即缩进方案

巨大的class级名称。 我记得: AbstractTableComponentListeningBehaviourPanel.java和其他类似的怪物。

最糟糕的是,尽管命名约定是疯狂详细的,但我仍然需要分开文件以确定其目的。

初级程序员犯的错误:不必要地使用成员变量而不是局部变量。

一个Java EE示例:

在servlet或EJB中启动线程(例如,启动异步处理任务)。

这打破了Java EE应用程序的可伸缩性。 您不应该在Java EE组件中混淆线程,因为应用服务器应该为您管理。

我们通过让servlet在JMS队列上放置消息并编写消息驱动的bean来处理异步处理任务来重构这一点。

我认为这个对我来说必须是一个记录。 类用于为前端构建涉及过滤的复杂数据模型。 所以返回对象列表的方法是这样的:

  public DataObjectList (GenerateList (massive signature involving 14 parameters, three of which are collections and one is a collection of collections) try { 250 lines of code to retrieve the data which calls a stored proc that parses some of it and basically contains GUI logic } catch (Exception e) { return new DataObjectList(e, filterFields); } 

所以我到这里是因为我想知道以下调用方法是如何失败的,我无法看到Exception字段的设置位置。

 DataObjectList dataObjectList= EntireSystemObject.getDataObjectList Generator().generateDataObjectList (viewAsUserCode, processedDataRowHandler, folderQuery, pageNumber, listCount, sortColumns, sortDirections, groupField, filters, firstRun, false, false, resetView); dataObjectList.setData(processedDataRowHandler.getData()); if (dataObjectList.getErrorException() == null) { do stuff for GUI, I think, put lots of things into maps ... 250 lines or so } return dataObjectList; } else { put a blank version into the GUI and then throw new DWRErrorException("List failed due to list generation error", "list failed due to list generation error for folder: " + folderID + ", column: " + columnID, List.getErrorException(), ListInfo); } 

到目前为止一直伴随着我?

好吧,至少他们确实在前端告诉我们确实出了问题!

AbstractSpringBeanFactoryFactoryFacadeMutatorBeanFactory。 我无法忍受这个过度设计,难以理解的BS。 Benji Smith把它放得更优雅。