您的位置:首页 > 编程语言 > Java开发

Java基础8--单例设计模式--继承

2013-12-09 10:07 477 查看

8-1,文档注释

文档注释其实就是将自己写的程序根据这些注释生成文档保存在硬盘上,与Java的API长的一样。
1,格式:
/**
注释内容...
*/

2,在命令行中通过javadoc命令生成文档注释,在工作开发中必须加文档注释。
例如:
/**
建立一个用于操作数组的工具类,其中包含常见的对数组操作的函数,如最值,排序等。
@author 张三   作者
@version 1.0   当前程序的版本号
*/
class ArrayTool {
/**
获取整形数组的最大值。
@param arr 接收一个元素为int类型的数组
@return 该数组中最大的元素值
*/
public static int getMax(int[] arr) {......}
}

3,用javadoc命令可以查看这个命令的用法。



-d : 输出目录(生成的文档放到指定目录)
例如:



4,加入文件夹目录:javadoc –d myhelp – author –versionArrayTool.java
在当前目录下创建一个myhelp文件,把生成的文档都放进去。
会生成一些html文件,打开index.html文件查看即可。

5,文档注释能提取的只有共有的和受保护的,不能提取私有的,将私有的加到普通多行注释中就可以。
文件的路径修改后要编译需要重新设定classpath,设置了classpath就不在当前目录找了。

8-2,单例设计模式-概述-体现

1,设计模式:对问题进行行之有效的解决方式,其实就是一种思想。
2,单例设计模式:
能解决的问题:可以保证一个类在内存中的对象唯一性。
必须对多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。
如何保证唯一性?
(1)不允许其他程序用new的方式创建该类对象。
(2)在该类创建一个本类实例。
(3)对外提供一个方法让其他程序可以获取该对象。
步骤:
(1)私有化该类的构造函数。
(2)通过new在本类中创建一个本类的对象。
(3)定义一个公有的方法,将创建的对象返回。
例如:
class Test {
private int num;
private static Test t = new Test();
private Test() {}
public static Test getInstance() {
return t;
}
public void setNum(int num) {
this.num = num;
}
public int getNum() {
return num;
}
}
class SingleDemo {
public static void main(String[] args) {
Test t1 = Test.getInstance();
Test t2 = Test.getInstance();
System.out.println(t1 == t2);  // true
t1.setNum(10);
t2.setNum(20);
System.out.println(t1.getNum());//20
System.out.println(t2.getNum());//20
}
}

单例的通用写法:(饿汉式)
class Single {
private static Single s = new Single();//new一个本类对象并静态私有化
private Single(){}//构造函数私有化
public static Single getInstance() { //提供公共访问方式
return s;
}
}

8-5,单例设计模式内存图解

class Single {
private static Single s = new Single();//new一个本类对象并静态私有化
private Single(){}//构造函数私有化
public static Single getInstance() { //提供公共访问方式
return s;
}
}class SingleDemo {
public static void main(String[] args) {
Single s1 = Single.getInstance();
Single s2 = Single.getInstance();
System.out.println(s1 == s2);
}
}



步骤:
(1)main函数所在的类加载,将方法加载到方法区,main函数进栈,局部变量s1进栈。
(2) Single s1,这时Single加载,将方法加载到方法区。private static Single s = new Single();这一句在堆中创建了一个对象,分配地址为0X0056。并赋给静态方法区的变量s。
(3)调用getInstance方法,进栈。
(4)获取到静态区中变量s的值,并返回,这个getInstance方法弹栈。
(5)将s的值赋给s1,main中的s1指向堆中的对象。
(6)局部变量s2进栈。
(7)调用getInstance方法,再次直接将s的值赋给s2。
(8)getInstance方法执行完毕弹栈。
(9)s2指向堆中的实体。

8-6,单例-懒汉式

1,写法:
class Single2{
private static Single2 s = null;
private Single2(){}
public static Single2 getInstance() {
if(s == null) {
s = new Single2();
}
return s;
}
}

Single2类加载的时候不创建对象,只有调用getInstance方法的时候才创建对象。
2,与饿汉式的区别
懒汉式只有当用到getInstance()方法的时候才建立对象,饿汉式只要类一加载就建立对象。
3,懒汉式缺点
懒汉式在处理多线程问题的时候可能保证不了对象的唯一性。

8-7,继承-概述

1,类之间可以继承,接口之间也可以继承,子类继承父类,子类继承了父类后,拥有父类非私有的成员,不用再在子类中定义,子类可以定义一些自己私有的内容。
父类是由子类不断向上抽取共性内容而来的。
继承的形式如:
class Person {
String name;
int age;
}
class Student extends Person {
void study(){...}
}
class Worker extends Person {
void work(){...}
}

Student和Worker继承了Person类中的成员,可在Student和Worker中直接使用name和age。
2,继承的好处
(1)提高了代码的复用性
(2)让类与类之间产生了关系,给多态提供了前提。

8-8,单继承和多重继承

1,Java中支持单继承,不直接支持多重继承,但对C++中的多继承机制进行了改良。
2,单继承:一个子类中只能有一个直接父类。
多继承:一个子类可以有多个直接父类(Java不允许,进行改良)。
3,Java更注重多继承的问题
问题如:
class A {
void show() {
System.out.println("a");
}
}
class B {
void show() {
System.out.println("b");
}
}
class C extends A,B{
public static void main(String[] args) {
new C().show();
}
}

C类继承了A和B类,创建了C对象,调用show方法,但是A和B中都有show方法,这时就不知道调用哪个类的show方法。
所以Java不直接支持多重继承的原因就是:会产生调用的不确定性。
4,Java支持多层继承
如:C extends B , B extends A,这样会出现继承体系。
当要使用一个继承体系时:
(1)查看该体系的顶层类,了解该体系的基本功能。
(2)创建该体系的最子类对象,完成功能的调用。

Java中的多继承是通过多实现的方式体现出来的,也就是通过接口的方式体现。

5,什么时候定义继承呢?
当类与类之间存在着所属关系的时候,就定义继承。
Xxx是Yyy的一种。Xxx extendsYyy。
所属关系就是is a的关系。

8-9,子父类中成员变量的特点:

1,特点:
(1)成员变量
(2)成员函数
(3)构造函数
2,当本类的成员和局部变量同名用this区分。
当子父类中的成员变量同名时用super来区分。
This:代表一个本类对象的引用。
Super:代表一个父类空间,不代表父类对象,因为不用创建父类对象就可以用super引用父类。
例如:
class Fu {
int num = 4;
}
class Zi extends Fu {
int num = 5;
void show() {
System.out.println(this.num + "..." + super.num);
}
}
class Demo {
public static void main(String[] args) {
Zi zi = new Zi();
zi.show();
}
}

结果:5...4

上例的内存图解:



首先主类Demo加载进内存,将方法加载进方法区,main加载进静态方法区(没有画出)。
然后main函数进栈,局部变量z进栈。
在堆中创建Zi的对象,JVM发现这个Zi类有个父类Fu,所以先加载其父类,先将父类的成员变量加载到Zi的单独的一片空间中,先加载父类是因为子类要用到父类的内容,那么父类就必须先初始化,否则子类无法使用。
然后将这个地址引用赋给main中的z,z指向堆内存的对象。
调用show函数,先在Zi的方法区中找这个方法,找到了,直接进栈执行,执行完毕之后,弹栈。
注意:如果这个show不是定义在子类,而是定义在父类中,那么上面这一步在Zi类方法区中是找不到show方法的,他就会通过Zi中的super引用去父类中找,如果找到,则执行,如果还没有,会到Object中找(所有类都继承自Object),如果有则执行,如果还没有,则报NoSuchMethod没有这个方法异常。
通过这个分析可以看出,super并不是指向的对象,而只是子类对父类的一个指向而已。

8-10,子父类中成员函数的特点-覆盖

1,当子父类中出现成员函数一模一样的情况,会运行子类的函数。
这种现象,称为覆盖操作,这是函数在子父类中的特性。
2,函数的两个特性
(1)重载:在同一个类中。
(2)覆盖:在子类中,也成为重写,覆写。
3,覆盖注意事项
(1)子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
(2)静态只能覆盖静态,或被静态覆盖。
如果父类方法为private,则子类无法对这个方法进行覆盖,因为私有化以后子类将无法看到这个方法,就谈不上覆盖了。

8-11,覆盖的应用

什么时候使用覆盖操作?
当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就是用覆盖操作完成。
class Phone {
void call() {}
void show() {
sop("number");
}
}
class NewPhone extends Phone {
void show() {
sop("name");
sop("pic");
super.show();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: