经常注意的小常识

原创 2013年10月26日 23:54:54

开发经验告诉我,从长远角度来看,以下这些Java SE功能/API,开发者最好停止使用。 

  • Reflection
  • Bytecode manipulation 
  • ThreadLocals
  • Classloaders
  • Weak/Soft references
  • Sockets 

1.Reflection

Reflection即反射,在许多流行的库里面都有反射机制,比如Spring和Hibernate。通过对业务代码进行反思,我建议大家避免使用反射。下面列出我反对使用的原因:

首先涉及到代码可读性/工具支持。打开IDE并且在Java代码里找到相互依赖关系。使用relection替换方法调用,并且试着重复该步骤。事情变的愈发不可收拾,正常情况下都应该封装好了再修改状态。下面来看看具体代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Secret {
    private String secrecy;
    public Secret(String secrecy) {
        this.secrecy = secrecy;
    }
    public String getSecrecy() {
        return null;
    }
}
public class TestSecrecy {
    public static void main(String[] args) throws Exception {
        Secret s = new Secret("TOP SECRET");
        Field f = Secret.class.getDeclaredField("secrecy");
        f.setAccessible(true);
        System.out.println(f.get(s));
    }
}

通过查看以上代码可以得知,方法getDeclaredField()参数只有在运行时才可以被发现。而你也清楚,运行时产生的bug总比不执行脚本要更加棘手。

其次,反射调用优化是由JIT执行的,一些优化可能需要花费很长时间才能得到应用,而有些优化甚至都得不到应用,所以关于反射的性能优化有时会被数量化。但在一个典型的业务应用程序中——你可能不会真正意识到这些性能开销。

总之,开发者应该通过AOP合理地在业务层使用反射,除此以外,你最好离它远远的。

2.Bytecode manipulation.

字节码操作,如果我看到你在Java EE应用程序里直接使用CGLIBASM,我可能会立即跑开。

最糟糕的事情莫过于在编译期间没有任何可执行的代码。实际上,当产品在运行时,你根本不知道哪块代码在运行。所以,当你遇到麻烦时,会自然地把错误抛给运行时故障排除和调试,不过这样反而会更麻烦。

3.ThreadLocals

这里有两个不相关的原因,当我在业务层代码里看到ThreadLocals时会颤抖。首先,在ThreadLocals的帮助里,你可能会看到许多变量的使用都没有通过方法调用链来明确地向下传递。这在某些场合下是有用的,但当你一旦粗心,你会在代码里构建许多意料不到的依赖关系。

第二个不相关的原因与我日常的工作相关,在ThreadLocals里存储数据会引发内存泄露。最起码我遇到的Permgen泄露有十分之一都是使用ThreadLocals造成的,在结合了类加载器和线程池后,“java.lang.OutOfMemoryError:Permgen space”异常可能就马上出现了。

4.Classloaders

首先,类加载器是一个复杂的野兽。你必须先了解它的层次结构、委托机制、类缓存等等。即使你认为自己已经掌握了,它可能还是不能正常工作。最终将导致一个类加载器泄露问题。因此我只能建议你将这个任务留给应用服务器处理

5.Weak/Soft references

现在,你应该更好的理解Java的内部方法。使用软引用来重写所有的缓存并不明智。我知道,当你手上拿着锤子的时候,就会到处寻找钉子。可对于锤子来说,缓存并不是个好钉子。为什么?基于软引用构建缓存可能是如何委托一些复杂因素到GC而不是通过自身实现的一个好例子。

下面举个缓存的例子,你使用软引用来创建数据,当内存被耗尽时,GC进入并且进行清理。但是,缓存中被删除的对象并未得到你的控制,而且很有可能在下一次的cache-miss中重新创建。如果内存仍然不足,你可以触发GC进行再次清理。你可能已经看出了整个运行过程的恶性循环,整个应用程序就变成了CPU与GC不断运行的状态

6.Sockets 

普通老式的java.net.Socket实在是太复杂,以至于很难弄正确。我觉得阻塞性是其根本性的缺陷。当你编写一个典型的带有Web前端的Java EE应用程序时,应用程序需要高并发度来支持大量的用户,而你现在最不想发生的是不具有可扩展的线程池坐等阻塞套接字

目前有许多精彩可用的第三方库,使用它们可以更好的完成任务,比如Netty,开发者不妨尝试下。

版权声明:本文为博主原创文章,未经博主允许不得转载。

日本小常识100条

1 日本的入学典礼和公司的入社典礼是在几月举行? 四月2 日语的「屋台」是指什么? 小摊贩 3 天皇家族的家徽是什么图案? 菊花   4 歌舞伎的始祖是谁? 阿国5 在日本的神社里,信徒会将香油钱投进...
  • kevinhalu
  • kevinhalu
  • 2006年08月15日 17:43
  • 681

机械加工小常识

  1:铆工常用的锤有哪几类?          答:有手锤,大锤,型锤。          2:铆工常用的凿子有哪几类?          答:有扁凿和狭凿两大类。          3:什么叫钢?...
  • wilson_jiang
  • wilson_jiang
  • 2009年02月12日 15:47
  • 1034

硬件的一些小常识

处理高频信号的地线时多用via可以降低引线电感 一般情况下,高频电路应就近多点接地,低频电路应一点接地。 在低频电路中,布线和元件间的电感并不是什么大问题,然而接地形成的环路的干扰影响很大...
  • zyboy2000
  • zyboy2000
  • 2009年05月10日 10:21
  • 925

汉语小知识:100个经典错别字!不加(假)思索

汉语小知识:100个经典错别字!不加(假)思索 1.按(安)装2.甘败(拜)下风3.自抱(暴)自弃4.针贬(砭)5.泊(舶)来品6.脉膊(搏)7.松驰(弛)8.一愁(筹)莫展 9.穿(川)流不息10....
  • bobob
  • bobob
  • 2006年02月22日 09:58
  • 1782

支付常识

名词解释 SE:Secure Element,安全元件。手机中的一块独立芯片,被硬件级别的加密保护着,其中的信息无法被破解或非法读取。 NFC:Near Field Communicati...
  • starryheavens
  • starryheavens
  • 2016年01月26日 23:18
  • 4520

Android Studio小常识

初用AS,许多都不会,没事研究一下,把一些小细节记下来和大家相互学习,别嫌太简单了,哈哈! AS下载地址:http://www.android-studio.org/ APP里是我们工程的代码及相关资...
  • jianchideyuanyuan
  • jianchideyuanyuan
  • 2016年04月24日 01:21
  • 216

网络安全的小常识

  安装硬件和软件的Internet防火墙。它们可以互补地进行工作。  安装防病毒软件。只要被病毒攻击过一次,你就会发现这一步骤的价值所在。在安装之后,一定要经常对病毒定义进行更新。  实行经常性的备...
  • cobps007
  • cobps007
  • 2005年10月01日 21:41
  • 553

指针作为函数参数传递时需要注意的问题

#include #include #include void GetMemory(char *p,int num) { p=(char*)malloc(num); } int main() { ...
  • avrmcu1
  • avrmcu1
  • 2014年09月02日 09:45
  • 1018

margin的使用注意事项

1、浏览器在默认状态下会对margin设置初值,所以在没有对div设置margin的情况下,div会出现一定的间隔; 2、margin-top会经常出现bug,所以推荐只在兄弟元素之间使用margi...
  • LJF1994
  • LJF1994
  • 2016年06月26日 09:34
  • 505

sql的小知识点

1,sql语句中加中括号和不加有什么区别吗? 有些可能是SQL里面的保留字,但是你又用了它做字段名 比如 SUM 那么用[SUM] 可以避免这个问题,如果直接SUM SQL 就报错了 2, delet...
  • wxwzy738
  • wxwzy738
  • 2012年07月03日 00:58
  • 2959
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:经常注意的小常识
举报原因:
原因补充:

(最多只允许输入30个字)