黑马程序员技术交流社区
标题:
JAVA之静态关键字,自己的理解...
[打印本页]
作者:
lyg0374
时间:
2016-8-2 07:22
标题:
JAVA之静态关键字,自己的理解...
------<a target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
----------
**概述:**
* 随着类的加载而加载
* 被所有对象所共享/明确一点,静态是先存在,对象是后存在的.
* 优先于对象存在
* 可以直接被类名调用
*特性*:
1. 随着类的加载和消失而加载和消失,生命周期最长.
非static变量称为成员变量,实例变量.
Static变量称为静态成员变量,类变量.可以通过对象名和类名调用.
实例变量和类变量的区别:
1,存放位置
类变量随着类的加载而存在于方法区中
实例变量随着对象的建立而存在于堆内存中
2,生命周期:
类变量生命周期最长,随着累的消失而消失.
实例变量生命周期随着对象的消失而消失.
**访问机制**
1. 静态方法只能访问静态成员,非静态方法可以访问静态也可以访问非静态.
2. 静态方法中不可以定义this,super关键字.因为静态优先于对象存在,所以静态方法中不可以出现.
3. 主函数是静态函数.主函数是一个特殊的函数,可以被jvm调用,是成语的起始点.
> **主函数的定义**
* public 代表该函数访问权限最大
* Static 代表主函数随着类的加载而加载.
* void 主函数没有具体的返回值.
* main 不是关键字,但是是一个特殊的单词,可以被jvm识别.
* 函数的参数(String [] args) 参数的类型是一个数组,元素是字符串类型. (注意:args可以随意更改)
* 主函数是固定格式的,jvm识别的唯一函数,不可改变!
* Jvm在调用主函数的时候,传入的是new String[0];
**静态之利弊**
利:对对象的共享数据进行单独空间的存储,节省内存空间,没有必要每个对象中都存一份./可以直接被类名调用.
弊:生命周期过长.访问出现局限性.(静态虽好,只能访问静态).
**静态的使用场景**
关于何时使用静态,我们要从两方面下手:
因为静态修饰的内容有成员变量和成员函数.
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被static修饰.对象中的特有数据要定义成非静态,存在于堆内存中.
什么时候定义静态函数呢?
当功能内部没有访问非晶态数据(对象的特有数据)时,该功能可以定义为静态的.
```
class Person
{
String name;
Public static void show() { // 该功能没有访问到非静态数据,就可以定义为static函数.
System.out.println("haha");
}
}
```
每一个应用程序中都有共性的功能,可以讲这些功能进行抽取,独立封装.以便复用,
我们在定义一个工具类的时候,虽然可以通过建立tool的对象使用tool工具这些方法,对数组操作,但是对象是用于封装数据的,tool并没有封装其特有数据,操作数组的每一个方法都没有用到其特有的数据.这时候就应该考虑让程序更加严谨,是不需要对象的.我们可以让tool里面的方法都定义成static.
这样即可直接通过类名调用即可.将方法都静态后可以方便使用,但是该类还是可以被其他程序建立对象的,为了更为严谨,强制让该类不能建立对象,此时私有化其构造函数就可以实现.将编译好的工具类发送给别人别人就可以用这个工具类,需要设置classpath后即可使用.
```
构造代码块----------------------------------
静态代码块 //随着类的加载而执行(不需要调用),只执行一次,优先于主函数执行.
Class StaticCode
{
Static{
System.out.println();
}
}
```
![静态代码块运行顺序实例](http://img.blog.csdn.net/20151110173455031)
我们在面试的时候多会遇到这样的问题:
在下面的代码中,调用StaticCode.show()运行结果是?
```
class StaticCode{
StaticCode(){
System.out.println("b");
}
static{
System.out.println("a");
}
{
System.out.println("c");
}
StaticCode(int x){
System.out.println("d");
}
public static void show(){
System.out.println("show run");
}
}
```
答案应该是:
*a*//静态代码块优先执行
*show run*//由于未产生对象,所以构造带代码块未执行,同理,构造函数也没有执行.
如果调用new StaticCode().show();
运行结果应该是:
*a*
*c*
*b*
*show run*
**那么在初始化一个对象的时候,调用顺序又是如何呢?**
假设一个class Person{}
那么在对象的初始化过程
Person p = new person();
1. 从硬盘中通过jvm将class文件加载到内存.因为new用到了Person.class文件,因此加载到内存
2. 静态代码块被执行.给该类初始化.
3. 在堆内存中开辟空间,分配内存地址.
4. 在堆内存中建立对象的特有属性,并进行默认初始化
5. 对属性进行显式初始化.
6. 对对象进行构造代码块初始化.
7. 对对象进行与之对应的构造函数初始化.
8. 将内存地址赋给栈内存中的对象名.
**静态在单例模式中的应用**
我们要想保证对象的唯一性,首先想到的就是单例设计模式.
1. 为了避免其他程序过多,保证对象唯一,先禁止其他程序建立该类对象.
2. 为了让其他程序可以访问到该对象,可以在本类中自定义一个对象.
3. 为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式.
这三步怎么用代码体现呢?
1. 将构造函数私有化.
2. 在类中创建一个本类的对象.
3. 提供一个方法可以获取到该对象.
构造函数代码:
```
Private Single()
{
Private Static Single s = new Single();
Public static Single getInstance(){
return s;
}
}
```
通过语句Single s = Single.getInstance();得到Single的实例对象.对于类中对事物的描述遵循以前的原则,当需要将该事物的对象保证在内存中唯一时,加上上述三步.
面试考试多的是懒汉式
两种不同的地方是饿汉式直接定义一个对象,Single类一进内存就已经创建了对象.懒汉式则在方法中创建.Single类进内存,对象还没有存在,只有滴哦啊用了getInstance方法时,才建立对象.
懒汉式容易出现同步的问题,出现多重对象.所以在应用中多选择饿汉式.
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2