您的位置:首页 > 职场人生

黑马程序员_Java基础_面向对象(二)_06

2014-01-17 21:39 253 查看
------- android培训java培训、期待与您交流!
----------

导读:static关键字、main函数、工具类、帮助文档、静态代码、对象初始化、单例模式



1、Static关键字


l 例:static
Stringcountry = “cn”;

被static修饰后它已经不在堆内存中了。静态修饰的内容被对象所共享,其他对象都能访问到,在内存中只存了一份,节省了内存空间。被static修饰的成员,不存在堆内存也不存在栈内存,它存在方法区(也叫数据区,共享区)。在这个区域中有更详细的划分,类中的方法,和类中的共享数据也在这里面。如,人说话,这个方法存在方法区里面,而人的姓名和年龄是人所特有的数据,存在对象当中。

用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。不能用于修饰局部的。

l static特点:

(1)随着类的加载而加载。

也就说:静态会随着类的消失而消失。说明它的生命周期最长。

(2)优先于的对象存在(先来后到)

明确一点:静态是先存在。对象是后存在的。

(3)被所有对象所共享

(4)可以直接被类名所调用。(当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接被类名调用。格式:类名.静态成员。)

l 实例变量和类变量的区别:

(1)存放位置。

类变量随着类的加载而存在于方法区中。

实例变量随着对象的建立而存在于堆内存中。

(2)生命周期:

类变量生命周期最长,随着类的消失而消失。(其次是实例变量)

实例变量生命周期随着对象的消失而消失。

l 为什么不都设置成static的变量?

什么数据是对象共有的,什么数据是特有的要区分出来,这样符合现实生活中的描述。另外,都是static的话生命周期长,消耗内存。是共享的话,再设为static.

l 静态有利有弊

利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。

弊端:生命周期过长。访问出现局限性。(静态虽好,只能访问静态。)

l 静态使用注意事项:

(1)静态方法只能访问静态成员。

非静态方法既可以访问静态也可以访问非静态。

(2)静态方法中不可以定义this,super关键字。

因为静态优先于对象存在。所以静态方法中不可以出现this。

(3)主函数是静态的。

2、main函数

l 主函数:是一个特殊的函数。作为程序的入口,可以被jvm调用。

l 主函数的定义:

public:代表着该函数访问权限是最大的。

static:代表主函数随着类的加载就已经存在了。

void:主函数没有具体的返回值。

main:不是关键字,但是是一个特殊的单词,可以被jvm识别。主函数可以重载,但是虚拟机只识别一种情况(固定格式):public
staticvoid main(String[] args)

(String[] args):函数的参数,参数类型是一个数组,该数组中的元素是字符串。Args是一个参数名字,来自英文arguments比较长,写为args。也可以改为x等。它接收的数据有两种:要么是一个new的数组(有指向,引用),要么是null(指向,引用)。

l jvm在调用主函数时,传入的是new
String[0];

一个程序在执行前,是可以接受用户往里面传入的数据的,而数据的最方便表示的形式就是字符串。

命令:java MainDemohaha hehe heihei , java调用JVM,MainDemo传入类,haha,hehe,heihei为传入的主函数的参数。自动的存入数组中

l 什么时候使用静态?(要从两方面下手,因为静态修饰的内容有成员变量和函数)

(1)什么时候定义静态变量(类变量)呢?

当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态存在于堆内存中。

(2)什么时候定义静态函数呢?

当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

3、静态的应用—工具类(通常工具类中定义的都是静态的方法)

l 每一个应用程序中都有共性的功能,可以将这些功能进行抽取,独立封装。以便复用。

l 对象是用来封装数据的,如果对象产生过程中没有封装任何数据,可以建立工具类。

l 虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。但发现了问题:

(1)对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。

(2)操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。

这时就考虑,让程序更严谨,是不需要对象的。可以将ArrayTool中的方法都定义成static的。直接通过类名调用即可。

l 将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。为了更为严谨,强制让该类不能建立对象。可以通过将构造函数私有化完成。

l 如果一个类中还用到其他的类的时候,在编译的时候会产生多个.class文件。运行时,它会在当前目录下(如果在classpath中指定的话,可以指定目录下)找要用到类的.class文件。如果没有找到的话,虚拟机会再找一次,有没有相应的类的java文件,先把这个java文件给编译了再编译自己的。

4、帮助文档的制作(也称为API帮助文档)

l 将ArrayTool.class文件发送给其他人,其他人只要将该文件设置到classpath路径下,就可以使用该工具类。但是,很遗憾,该类中到底定义了多少个方法,对方(程序员)不清楚。因为该类并没有使用说明书。

l 开始制作程序的说明书。java的说明书通过文档注释来完成。/**
*/

包括:是什么样的工具类,有什么功能。这个工具是谁做的,什么时候做的,版本是多少号(如果新版本出现瑕疵了,要先回到旧的版本让用户可以使用)。

@author张三 //@是一个特殊的标识可被文档注释工具提取并识别

@version V1.1

凡是public的工具都用/** */来描述,可以被文档注释工具提取。例:

/**

获取一个整形数组中的最大值。

@param arr 接收一个int类型的数组。

@return 会返回一个该数组中最大值。

*/

l 命令:javadoc
–d myhelp–author –version ArryToolDemo.java (-d代表目录的意思)

以网页的形式存在的,你想把网页存在什么地方,这个很重要。

注意:一个报错。如果某一个类想要生成帮助文档的话,必须有public修饰

生成文件中生成的是你想要往外面暴露的内容,是你想让别人看并,想让别人用的内容,私有的是不会提取的,即使你写了文档注释。有两个权限是可以被提取的一个是public一个protected

l 默认构造函数

Class Dem0 //不写就是默认的。

{

}

Class Demo

{

Demo(){}

//不要以为空参数构造函数就是默认构造函数。这样写叫做自定义构造函数。

}

5、静态代码块

l 格式:

static

{

静态代码块中的执行语句。

}

l 特点:随着类的加载而执行,只执行一次。用于给类进行初始化的。(少用,对对象的初始化比较常用)

l Class static StaticCode

{

Static //静态代码块,给类初始化的

{

System.out.println(“a”);

}

{ //构造函数代码块,给构造函数初始化的

System.out.println(“b”);

}

StaticCode(intx) //构造函数,给对应对象初始化的

{

System.out.println(“c”);

}

}

Class static Demo

{

Static

{

System.out.println(“d”);

}

New static StaticCode();

New static StaticCode()//StaticCode这个类已经在内存中了,不会重新加载

Static

{

System.out.println(“e”);

}

}

只有用到了类中内容的时候才会被加载。

StaticCode s =null; //这时没有被加载到内存中

s = new StaticCode() //这里用到了才被加载。

6、对象的初始化过程

第一步:new之后先找到.class文件并把类加载到内存

第二步:静态代码块被执行(如果有的话)

第三步:在堆内存中开辟空间,分配内存地址。

第四步:在堆内存中建立对象的特有属性。并进行默认初始化。

第五步:对属性进行显示初始化。(成员变量:private Stringname = “haha”)

第六步:对对象进行构造代码块初始化。

第七步:对对象进行对应的构造函数初始化。

第八步:将内存地址会给栈内存中的p变量

(产生属性,进行初始化动作[先默认初始化,接着显式初始化,再构造构造代码块初始化,再构造函数初始化])

7、对象调用成员过程

类名.方法,调用的时候走的是静态方法区中的数据,跟堆没有关系

非静态中省略的是“this.” 静态中省略的是“类名.”

8、单例设计模式

l 设计模式:(最早出现在建筑学中)它是是解决问题中最行之有效的方法。它不是偏代码的,它是偏思想的,思想是通用的。是不断是劳动过程中总结出来的一些经验。

l Java中有23种通用设计模式。(哥四个叫JOF)

几个复杂的模式综合起来的话,就是一个比较复杂的模式,我们称之为框架。

l 单例设计模式:一个类在内存只存在一个对象(唯一性)。

l 想要保证对象唯一。

(1)为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象

(2)还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。

(3)为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

l 这三部怎么用代码体现呢?

(1)将构造函数私有化。

(2)在类中创建一个本类对象。

(3)提供一个方法可以获取到该对象。

l 对于事物该怎么描述,还怎么描述。当需要将该事物的对象保证在内存中唯一时,就将以下的三步加上即可。

class Student

{

private age;

private Student (){} //禁止其他程序建立该类对象

private static Student s = new Student ();

//这是先初始化对象。称为饿汉式。(单例第一种方法,第二种见下面懒汉式)

//内部成员变量,私有化一下。静态方法要访问内部的成员,static一下。

public static Student getStudent () //要保证唯一性,就不能用对象访问,用类名访问,就要用static

{

return s; //只有一句话,不会像懒汉式那样出现问题,要么执行,要么不执行

}

public void setAge(int age)

{

this.age = age;

}

public int getAge()

{

return age;

}

}

Student s1 =Student.getStudent(); //s1和s2指向了唯一的一个对象

Student s2 =Student.getStudent();

l 饿汉式,类加载后(方法区),s就已经确定了。这时堆内存中已经有对象了,把地址值 赋给s。

l 对象是方法被调用时,才初始化,也叫做对象的延时加载。称为懒汉式。(开发中一般用饿汉式,因为它简单还安全,面试会考懒汉式。记住原则:定义,建议使用饿汉式)

懒汉式,类加载后(方法区),s为null,当调用方法的时候,才初始化,也叫做对象的延时加载。Single类进内存,对象还没有存在,只有调用了getInstance方法时(方法运行),才建立对象。并把对象的内存地值值赋给s。代码如下:

class Single

{

private Single (){}

private static Single s = null;

public static Student getInstance ()

{

If(s ==null)

s = new Single();

return s;

}

}

获取对象,是单例中一定要做的事情。单例之外还要定义很多的方法。先用单例获取对象之后再调用其他的方法。

l 懒汉式的安全性问题:

If(s ==null)

àA 1

àB 2

s = new Single(); 3

若AB都在此时中断,接下来执行是:1开,3,2开,3则建立的对象不唯一了。有解决办法用synchronized,但它一进来效率就变低了。

最终解决方案:两次判断(判断锁的次数减少了,可以提高效率)

if(s==null) //代码变多了。

{

synchronized(Single.class)

{

if(s==null)

àA //A进来如果死到这里了,B进不来,不会创建对象。A如果再活过来,创建对象。C进来,不为空,直接读

s = new Single();

}

}

------- android培训java培训、期待与您交流!
----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: