简述static关键字的用法,请写出对static关键字的理解,它怎么使用
在我们开始讨论静态之前,我想向您展示一个有趣的代码:
公共类测试{
静态{
System.out.println(“测试静态1”);
}
静态{
System.out.println(“测试静态2”);
}
公共静态void main(String[] args) {
}
}看完节目,小白童鞋发言:什么鬼?主方法里什么都没有。你能跑什么?博主,你是明星.
运行结果:
测试静态1
测试静态2白色童鞋:什么.什么.博主,我说什么了?我什么也没说.
其实上面的代码自然能看懂,不懂的自然不懂,因为上面的代码涉及到了JVM的类加载!当然不在这篇博文的讨论范围之内。如果你有兴趣了解上述程序,这篇文章可能会帮助你。
1、static存在的主要意义
静态的主要含义是创建独立于特定对象的域变量或方法。以致于即使没有创建对象,也能使用属性和调用方法!
静态关键字的另一个关键功能是用来形成静态代码块以优化程序性能。静态块可以放在类中的任何地方,一个类中可以有多个静态块。当第一次加载类时,每个静态块将按照静态块的顺序执行,并且只执行一次。
为什么静态块可以用来优化程序性能,是因为它的特性:它只会在类被加载的时候执行一次。所以很多情况下,一些只需要执行一次的初始化操作会在静态代码块中执行。
2、static的独特之处
1.static修改的变量或方法是独立于这个类的任何对象,也就是这些变量和方法是不属于任何一个实例对象,而是被类的实例对象所共享。
2.第一次加载类的时候会加载静态修改的部分,只有第一次使用类的时候才会加载初始化。注意这是第一次,会被初始化,以后可以根据需要再次赋值。
3.静态变量值在加载类时分配空间,以后创建类对象时不会被重新分配。赋值就可以随意赋值!
4.被static修改的变量或方法拥有比对象更高的优先级,也就是说,一个类被加载后,即使没有创建对象也可以被访问。
3、static应用场景
因为static是由类的实例对象共享的,如果某个成员变量是被所有对象所共享的,那么这个成员变量就应该定义为静态变量。
因此,常见的静态应用程序场景有:
下面将陆续讨论上述应用场景。
4、静态变量和实例变量的概念
静态变量:
由static修改的成员变量称为静态变量[也叫类变量],静态变量属于这个类,不属于对象。
示例变量:
不被static修改的成员变量称为实例变量,实例变量是属于这个类的实例对象。
还有一点要注意:static是不允许用来修饰局部变量,不要问我问什么,因为java规定了!
5、静态变量和实例变量区别【重点常用】
静态变量:
因为静态变量不属于任何实例对象,它们属于类,所以在内存中只会有一个副本。在类加载过程中,JVM只为静态变量分配一次内存空间。
示例变量:
每次创建一个对象,都会为每个对象分配成员变量的内存空间,实例变量属于实例对象。在内存中,当一个对象被多次创建时,成员变量会有多个副本。
怎么理解呢?让我们打个比方.假设程序员小王是一个温柔阳光的男孩。1024年的这一天,老板无事可做,只好拉着程序员小王去玩。他怎么玩?老板和小王拿着菜刀。规则很简单。他们互相伤害,一刀换一刀,一刀换你,一刀换我.游戏开始,老板二话不说跳起来,程序员小王二话不说拿着菜刀回去了。这时候老板生气了,眼睛瞪得好大,又一刀跳了起来。这个时候程序员小王不敢还手,就没做了。没想到老板越来越凶。当他一左一右把整个过程砍下来的时候,几乎砍成了两半.程序员小王一直没有还手,因为小王知道自己是老大。
这个程序员小王第一次挥刀只会给老板一刀,然后就不还手了。这时候我们把程序员小王看成一个静态变量,他老板第一次向小王挥刀看成是类加载,小王回挥给老板看成是分配内存空间,这一轮一刀看成是类加载,然后他老板每一刀都看成是创建一个对象一次。
Coherence是指静态变量值在第一次加载类时分配空间,以后创建类对象时不会被重新分配。
之后老板挨了一刀,然后在医院呆了一年。回到公司,他做的第一件事就是把程序员伊春拉出去玩。老板不知道。这个博主程序员伊春性格异常暴躁,老板递给程序员伊春一把菜刀。博主伊春一拿菜刀,就被老板打了个措手不及,跳起来当刀使。程序员伊春痛苦地尖叫,但是脾气暴躁的程序员伊春没有说完。同时跳起来对着老板就是一刀。然后老板跳起来又给了一刀,程序员伊春又给了一刀。老板跳起来又给了一刀,程序员伊春又给了一刀。只要老板没停,程序员伊春就没停,因为程序员伊春知道他气得不敢动。肯定有几个老铁知道。
程序员伊春,类似于实例变量。每次创建对象时,都会为每个对象分配成员变量的内存空间。就像老板拿刀一样,程序员宜春也会拿刀回去。
6、访问静态变量和实例变量的两种方式
我们都知道静态变量属于这个类,不属于对象,静态是独立于对象的。
但是,你想过没有:虽然静态成员变量是独立于对象的,但不代表不能通过对象访问。所有静态方法和变量都可以通过对象访问[只要访问权限足够]。不懂他们也没关系。编码就行了。
公共类StaticDemo {
静态int值=666;
公共静态void main(String[] args)引发异常{
新的StaticDemo()。方法();
}
私有void方法(){
int value=123
system . out . println(this . value);
}
}猜猜结果。我猜你的成绩是123。哈哈,是meh吗?实际上
润:666再回去品味一下上面那段,你会很客观很清楚。这个思路和概念应该是有的,但是不推荐这种用法!
所以总结两种访问静态变量和实例变量的方法:
静态变量:
静态方法:
7、static静态方法
静态修改的方法也叫静态方法。不知道你有没有找到。其实最熟悉的静态法才是主要方法~小白童鞋:哦,好像是真的~。因为静态方法不属于任何实例对象,所以这指的是当前对象。因为静态静态方法不属于任何对象,所以不存在这种情况。
还有一点:构造方法不是静态方法!
8、static静态代码块
先看一个程序,看你是否掌握了静态代码块。下面的程序代码继承关系是BaseThree—— BaseTwo—— BaseOne。
BaseOne类
包com . GX . initialization block;
公共类BaseOne {
public BaseOne() {
System.out.println(BaseOne构造函数);
}
{
System.out.println(BaseOne初始化块);
system . out . println();
}
静态{
System.out.println(BaseOne静态初始化块);
}
}BaseTwo类
包com . GX . initialization block;
公共类BaseTwo扩展BaseOne {
public BaseTwo() {
System.out.println(BaseTwo构造函数);
}
{
System.out.println(BaseTwo初始化块);
}
静态{
System.out.println(BaseTwo静态初始化块);
}
}BaseThree类
包com . GX . initialization block;
公共类BaseThree扩展BaseTwo {
public BaseThree() {
System.out.println(BaseThree构造函数);
}
{
System.out.println(BaseThree初始化块);
}
静态{
System.out.println(BaseThree静态初始化块);
}
}测试演示2类
包com . GX . initialization block;
/*
注:此处ABC对应BaseOne、BaseTwo、BaseThree。
*初始化块、静态初始化块和构造函数在多个类继承中的执行顺序
在继承中,父类A的静态块、父类B的静态块和最后一个子类的静态块被相继执行。
然后执行父类A的非静态块和构造函数,再执行类B的非静态块和构造函数,最后执行子类的非静态块和构造函数。
*/
公共类演示2 {
公共静态void main(String[] args) {
base three base three=new base three();
system . out . println(-);
base three base three 2=new base three();
}
}运行结果
BaseOne静态初始化块
BaseTwo静态初始化块
三进制静态初始化块
BaseOne初始化块
BaseOne构造函数
二进制初始化块
BaseTwo构造函数
基数三初始化程序块
基数三构造函数
-
BaseOne初始化块
BaseOne构造函数
二进制初始化块
BaseTwo构造函数
基数三初始化程序块
BaseThree构造函数至于静态代码块运行结果不是很清楚的童鞋,详细解释请参考这个静态代码块以及各个代码块之间的执行顺序。
以上只是让你知道代码块之间的运行顺序,显然是不够的。静态代码块通常用于初始化静态变量,比如定义枚举类。代码如下:
公共枚举WeekDayEnum {
星期一(1,星期一),
星期二(2,星期二),
星期三(3,星期三),
星期四(4,星期四),
星期五(5,“星期五”),
星期六(6,星期六),
星期日(7,星期日);
私有int代码;
私弦desc;
WeekDayEnum(int代码,字符串desc) {
this.code=code
this . desc=desc;
}
private static final MapInteger,WeekDayEnum WEEK _ ENUM _ MAP=new hashmap integer,WeekDayEnum();
//初始化地图
静态{
for(WeekDayEnum weekDay:WeekDayEnum . values()){
WEEK _ ENUM _ map . put(weekDay . get code(),weekDay);
}
}
公共静态weekday enum findByCode(int code){
返回WEEK_ENUM_MAP.get(代码);
}
public int getCode() {
返回代码;
}
public void setCode(int code) {
this.code=code
}
公共字符串getDesc() {
归还desc;
}
public void setDesc(字符串desc) {
this . desc=desc;
}
}当然不仅仅是枚举这方面,我们熟悉的singleton模式也使用了静态代码块,如下:
公共类Singleton {
私有静态单一实例;
静态{
instance=new Singleton();
}
私有Singleton() {}
公共静态Singleton getInstance() {
返回实例;
}
}9、static变量与普通变量区别
静态变量也叫静态变量。静态变量和非静态变量的区别在于,静态变量是所有对象共享的,内存中只有一个副本。当且仅当类第一次被加载时,它才会被初始化。非静态变量归对象所有,创建对象时初始化,有多个副本,每个对象拥有的副本互不影响。
还有一点就是静态成员变量的初始化顺序是按照定义好的顺序初始化的。
10、静态内部类
静态内部类和非静态内部类有一个最大的区别。我们知道非静态内部类在编译后会隐式持有一个引用,指向创建它的外围,而静态内部类没有。缺少此参考意味着:
1.它的创建不依赖于外围类的创建。
2.它不能使用任何外围类的非静态成员变量和方法。
代码示例(静态内部类实现单例模式)
公共类Singleton {
//声明private以避免调用默认构造函数来创建对象
私有Singleton() {
}
//声明为private表示该类只能在这个Singleton类中静态访问。
私有静态类SingletonHolder {
private static final Singleton实例=new Singleton();
}
公共静态Singleton getUniqueInstance() {
返回SingletonHolder。实例;
}
}加载Singleton类时,静态内部类SingletonHolder不会加载到内存中。只有在调用getUniqueInstance()方法时,才会触发SingletonHolder。实例时,将加载SingletonHolder。此时,实例被初始化,JVM可以确保实例只被实例化一次。
这种方法不仅具有延迟初始化的优点,还提供了JVM对线程安全的支持。
11、静态导包
静态包指南格式:导入静态
这两个关键字可以一起使用来指定要导入到类中的指定静态资源,而不是使用类名来调用类中的静态成员,可以直接使用类中的静态成员变量和成员方法。
//数学。-导入Math中的所有静态资源。这时候可以直接使用里面的静态方法,而不是通过类名来调用。
//如果只想导入单个静态方法,只需要改成对应的方法名即可。
导入静态Java . lang . math;
//替换为导入静态Java . lang . math . max;有异曲同工之妙。
公开课演示{
公共静态void main(String[] args) {
int max=max(1,2);
system . out . println(max);
}
}静态引导包在编写代码时确实可以节省一点代码,可以直接调用里面的静态成员,但是会影响代码的可读性,所以一般不建议在开发中使用。
12、static注意事项
1.静态只能访问静态。
2.非静态可以访问非静态和静态。
13、final与static的藕断丝连
文章本该到此结束,但static的使用总是离不开final这个词。两者往往交织在一起,我觉得还是有必要说一下的。所以我们来看看下面的程序。
包演示;
类别FinalDemo {
公共final double I=math . random();
公共静态double t=math . random();
}
公共类DemoDemo {
公共静态void main(String[] args) {
final demo demo 1=new final demo();
final demo demo 2=new final demo();
system . out . println( final decorated I= demo 1 . I);
system . out . println( static modified t= demo 1 . t);
system . out . println( final decorated I= demo 2 . I);
system . out . println( static modified t= demo 2 . t);
system . out . println( t1= demo 2 . t);
//system . out . println(demo 2 . I);//编译失败
}
}
运行结果:
最终修正后的I=0。58660.78888888671
静态修正t=0.580 . 000000000000001 . 50001
最终修正后的I=0 . 18860 . 488888886865
静态修正t=0.580 . 000000000000001 . 50001
t1=1.307205456785776由static修改的static变量没有改变是因为static作用于成员变量只是为了表示保存了一个副本,不会改变。你怎么理解这个文案?其实静态修改是在类加载的时候完成(初始化)的,只会加载一次,也就是初始化一次,所以不会变!
至于最后的修改,反而改了?它是否推翻了你对期末考试的看法?详细解释一下final。博主也准备了一篇文章。程序员,你真的懂final关键字吗?
好了,文章到此为止。希望这篇文章能帮助你了解静电。如有不足或不规范之处,望各位理解,欢迎批评指正!
本文来自java入门专栏,欢迎学习!以上是深入了解静态关键字的详细内容。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。