前几天又重新学习了JAVA内存分析部分,温故确实可以知新,结合最近对面向对象的总结,找到二者可以连通的对比,从而把这两个结点连接起来。
面向对象
先说说面向对象,众所周知,面向对象三大特性为:继承、封装、多态。但是再细想,这三个特性的实现还是有前后的依赖关系的,即先封装才能有继承,有了继承才能体现多态。如果你往前想一步,对,在封装前面还应该有个抽象,有了抽象,才有类,才有封装的载体,所以如果给这些特性加上顺序,应该是:
- 抽象:面对这个世界,首先抽象、归类、汇总
- 封装:使用类这个载体,将这组有共同特性的内容封装起来
- 继承:有了封装后,可以在一个类的基础上继续添加内容,从而有了继承
- 多态:有了继承和接口后,从而有了多态的实现基础
- 更多:面向对象有了以上特性,再加上灵活的思路,从而有了延迟实现、动态加载等更多特性
内存分析
以上是从概念上分析了面向对象,接下来我们看一下他们在内存中是如何实现的,首先来看一下内存的划分图:
其中:
- stack用于存放局部变量名及其值,对象类型则为指针
- heap用于存放对象
- data segment用于存放静态变量和字符串常量
- code segment用于存放代码
抽象
抽象,是对众多事物的归类,可以说是找出类的过程,如果要将抽象与内存关联起来,虽然有些牵强,但可以反应到类,即代码上,从而体现在code segment。
封装
封装即是将有一组有共同特性的属性和方法包装起来,它们是作为一个整体出现的,这个体现在内存中,我的理解是,以对象在堆的方式保存着,即只要在为对象分配的地址内,就属于这个整体;属于这个整体就要在这个地址段内:
继承
在以前的博客中也提到过,在内存中,父对象包含在子对象中,通过子对象super指针指向父对象,通过this指向自身,我们以父类为animal,子类为dog为例:
我们可以理解成,继承在内存中的表现形式是子类将父类包含起来,将animal融合到dog中,封装起来(参见上面的封装),进而dog可以使用animal中的内容。
多态
多态的实现在内存中体现的较为复杂,但是其核心还是提前定义,延迟实现。我们仍以dog继承animal为例,让dog中的eat()覆写animal中的eat():
一旦覆写,那么即使以animal为类型实例化的dog对象,执行eat()时,父类animal中的eat()指向了dog的eat(),从而执行dog的eat()。
这种利用父类类型实例化,子类覆写父类的方法后,运行时,动态的再指向子类的实现,即为多态。
实例
我们看一个多态的很简单实例,以cat、dog继承animal为例:
public class animal
{
public static void main( String[ ] args )
{
//以父类的名义实例化
animal dog=new dog( );
animal cat=new cat( );
//以子类自己的形式实现
dog.eat( );
cat.eat( );
}
public void eat()
{
System.out.println( "animal.eat" );
}
}
class dog extends animal
{
@Override
public void eat()
{
System.out.println( "dog.eat" );
}
}
class cat extends animal
{
@Override
public void eat()
{
System.out.println( "cat.eat" );
}
}
运行结果
dog.eat
cat.eat
设计模式
看完上面的分析,再来看设计模式,其实设计模式核心就是提前定义、延迟实现,然后在此基础上灵活多变,从而实现相当经典的设计模式。
策略模式
我们以策略模式为例:
package muiltple;
public class StrategyDemo
{
/** @MethodName : main
* @Description : TODO
* @param args
*/
public static void main( String[ ] args )
{
Context ctx=new Context( new Minus( ) );
ctx.count( );
Context ctx1=new Context( new Add( ) );
ctx1.count( );
}
public int count(int x,int y)
{
return x+y;
}
}
//上下文,用于决定执行哪个策略子类算法
class Context
{
Strategy strategy;
public Context(Strategy strategy)
{
this.strategy=strategy;
}
public void count()
{
strategy.count( );
}
}
//策略父类
class Strategy
{
public void count()
{
}
}
//Minus算法系类
class Minus extends Strategy
{
@Override
public void count()
{
System.out.println( "我执行Minus中的count算法");
}
}
//Add算法系类
class Add extends Strategy
{
@Override
public void count()
{
System.out.println( "我执行Add中的count算法");
}
}
执行结果
我执行Minus中的count算法
我执行Add中的count算法
比较策略模式和上面多态的例子,你会发现,我去,仅仅是多了一个Context这个中转类而已。
总结
从比较基础的内容出发,多比较,再去分析上层的内容,会简单的多。