很多人喜欢在action 或service或dao层继承一些公共的东西 比如jdbc或一些其他的东西 我看过一些小源码也经常这样 废话不多说 直入正题 
 直入正题前先科普一下TheardLocal类 懂的人直接跳 
 线程不安全指的是一个带有类成员变量(状态)的类的单列被多个线程访问时才会造成线程不安全,TheardLocal简单来说就是一个map (线程ID,对象),具体就不多说了,需要详细了解的请百度。 
 TheardLocal的出现解决了这一问题,现在很多框架都运用了这个技术,将所有的成员变量都放在TheardLocal内,这样就不会出现线程安全了,这也是为什么Spring jdbcTemplate的事物管理不会存在多线程安全问题。(你没发现你所有的注入用的都是这一个单列对象吗)还有很多很多地方都是这样的。 
 现在SpringMvc等使用的是方法及传惨,方法体有独自的栈,不存在线程安全,这样就可以让你的action无论多少个请求都只实列化一次并且不会造成线程安全。 
 上面这一段只 为告诉你 减少实例对象 使用单列模式 不然下面的没必要看了 因为目的就是为了减少实例对象 
 正题 
 四个很简单的java类 
 [code="java"]public class Animal { 
 public Animal(){ 
 System.out.println(1); 
 } 
 } 
 [code="java"]public class Dog extends Animal{ 
 } 
 [code="java"]public class Pig extends Animal{ 
 } 
 [code="java"]public class Test { 
 public static void main(String[] args) { 
 new Dog(); 
 new Pig(); 
 } 
 } 
 输出的肯定是两个1 
 这能证明什么呢? 
 Animal 被实例化了两次 如果你的项目中action多达100个 甚至1000个 那么这个类被实例化的次数会随着你的action数量变得越来越多,如果你使用的是单列还好,如果是多列那这个次数就等于 请求数*子类 
 请使用注入的方式,因为它只是一个对象的引用,10000个引用它在内存中还是那么大。 
 不要为了那么两行代码的方便性影响了性能 
 使用继承前先想好它可能会有多少个子类,太多了就用注入,也就多两行代码。 
 楼主目前做的两个项目中业务层都没有用过继承,虽然几乎每个类都用了jdbc但是都是注入进来的。 
 实践验证真理 额 我承认我错了 不过也学到很多东西 感谢大家的打击 
 下面是我的实践 
 第一段 
 public class Animal { 
 public void getInfo(){ 
 //一大堆代码 
 } 
 //还可以加N多方法运行结果也一致 
 } 
 public class Dog extends Animal{ 
 } 
 public class Pig { 
 public Animal animal; 
 } 
 第一种运行方式 继承 
 public static void main(String[] args) { 
 Long begin = new Date().getTime(); 
 List<Dog> l = new ArrayList<Dog>(); 
 for (int i = 0; i < 1000000; i++) { 
 Dog d = new Dog(); 
 l.add(d);//添加到一个集合里避免无引用被垃圾回收 
 } 
 Long runTime = new Date().getTime()-begin; 
 System.out.println(runTime); 
 } 
 第二种运行方式 注入 
 public static void main(String[] args) { 
 Long begin = new Date().getTime(); 
 List<Pig> l = new ArrayList<Pig>(); 
 Animal animal = new Animal(); 
 for (int i = 0; i < 1000000; i++) { 
 Pig d = new Pig(); 
 d.animal = animal; 
 l.add(d);//添加到一个集合里避免无引用被垃圾回收 
 } 
 Long runTime = new Date().getTime()-begin; 
 System.out.println(runTime); 
 } 
 两个运行结果占用内存一致时间几乎一致 
 证明一个非静态方法在内存中只会占一个地址 与静态的区别在于静态是系统启动时分配 非静态是第一次实例时分配 无论后续实例多少次它只会占用一个内存地址 所以测试时应该独立启动运行 不然第二步骤实例Animal类时其实一点时间也没花内存也没变 
 第二段 
 将Animal类添加一个非静态成员变量 
 public Integer age = new Integer(10); 
 两个运行结果 第二种运行时间内存占用比第一种小一倍 
 证明一个类在实例化的时候会为成员变量分配内存空间 而方法不会 
 第三段 
 将Animal类添加一个方法引用age 
 与第二段一致 
 证明方法在使用成员变量时只是引用不是复制 
 第四段 
 将Animal类添加一个构造函数 
 public Animal(){ 
 //打印 
 } 
 注入的方式构造函数运行一次 
 继承的方式随子类实例次数 
 最后总结 
 1一个类在实例化时 
 非静态并且有值的成员变量(int long String这些类型在不使用构造传参时 如果参数一致在内存中也会存在一个)会在分配在内存中 以后每次实例也都会 
 非静态方法只会在第一次实例化时分配 以后每次的实例都只是引用 
 2父类在很多子类继承时构造函数不要过于复杂,因为构造函数在每次实例化时都会运行一次 
 3一个类如果构造函数是空并且也没有非静态不为空的成员变量那么 
 new 一个类一百次 和new一个类一次 加100此空循环 无论内存占用还是速度都一致 
 
转载于:https://www.cnblogs.com/shhaoran/archive/2013/02/04/2924524.html