java static 修改_java的static关键字

1、在类中,用static声明的成员变量为静态成员变量,他为该类的公用变量,在第一次使用时被初始化,对于该类的所有对象来说static成员变量只有一份

2、用static声明的方法为静态方法,在调用该方法时,不会将对象的引用传递给他,所以在static方法中不可访问非static的成员

静态方法不在是针对某个对象调用,所以不能访问非静态成员

3、可以通过对象引用或类名(不需要实例化)访问静态成员

static 方法:

static 修饰的方法称为静态方法,可以不用创建对象即可使用,对于静态方法来说没有this的,因为它不依附于任何对象,既然没有对象就谈不上this,并且这个由于特性,在静态方法中不能访问类的非静态成员变量和非静态方法,因为非静态成员方法/变量都是必须依赖于具体的对象才可以被调用,注意:在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中可以访问静态成员方法/变量的

下面例子:

6db42c82286602334ba4358f7cd514ec.png

在上面的代码中,由于print2方法是独立于对象存在的,可以直接用过类名调用。假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:

MyObject.print2();

此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。

而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。

因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。

static变量:

static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

static成员变量的初始化顺序按照定义的顺序进行初始化。

static代码块:

static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次。下面看个例子:

classPerson{privateDate birthDate;publicPerson(Date birthDate) {this.birthDate =birthDate;

}

boolean isBornBoomer() {

Date startDate= Date.valueOf("1946");

Date endDate= Date.valueOf("1964");return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;

}

}

isBornBoomer是用来这个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成这样效率会更好:

classPerson{privateDate birthDate;private staticDate startDate,endDate;static{

startDate= Date.valueOf("1946");

endDate= Date.valueOf("1964");

}publicPerson(Date birthDate) {this.birthDate =birthDate;

}

boolean isBornBoomer() {return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;

}

}

static关键字的误区:

1.static关键字不会改变类中成员的访问权限

Java中的static关键字不会影响到变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected(包括包访问权限)这几个关键字。看下面的例子就明白了:

b964875e8a3940b57099f60778ebbc46.png

提示错误"Person.age 不可视",这说明static关键字并不会改变变量和方法的访问权限。

2.能通过this访问静态成员变量吗?

public classMain {static int value = 33;public static voidmain(String[] args) throws Exception{newMain().printValue();

}private voidprintValue(){int value = 3;

System.out.println(this.value);

}

}

输出33

这里面主要考察队this和static的理解。this代表什么?this代表当前对象,那么通过new Main()来调用printValue的话,当前对象就是通过new Main()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是33。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出结果是33。在这里永远要记住一点:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要访问权限足够)。

3.static能作用于局部变量么?

static是不允许用来修饰局部变量。

下面利用画内存学习更加深刻的需东西这一小节:

package satic;public classCat {private static int sid = 0; //sid是静态的可以直接用类名变量名直接用

private String name; //Cat类私有的属性name 初始值为0

int id; //变量

Cat(String name) {this.name = name; //将调用Cat方法时传入的值赋值给name属性

id = sid++; //将sid的值赋值给id并且sid自增1

}//info方法输入name和id的值

public voidinfo(){

System.out.println

("My name is"+name+"No."+id);

}public static voidmain(String arg[]){

Cat.sid= 100; //将sid的值变为100

/** 调用Cat 方法更改name与id的值并打印

**/Cat mimi= new Cat("mimi");Cat pipi= new Cat("pipi");

mimi.info();

pipi.info();

}

}

先从main函数入口开始,

Cat.sid = 100在数据区当中有一个sid,被赋值为100,Cat mimi = new Cat("mimi")时,在栈内存当中有一个叫mimi的内存具体内容不知,但他指向堆内存当中的一块内存,在堆内存当中有两个分别是id和name的属性,而mimi这个字符串是存储在数据区的,字符串也是个引用类型,所以说字符串可以看作是一个对象,执行

Cat(String name) {

this.name = name; //将调用Cat方法时传入的值赋值给name属性

id = sid++; //将sid的值赋值给id并且sid自增1

}

时在栈内存里面有一个name的内存然后,这个"mimi"的引用交到name中,现在name指向"mimi"字符串,this.name = name,这句话中

将栈内存的name的值赋值给堆内存中mimi这个对象的name,也就是mimi这个对象的name也指向数据区里面的“mimi”字符串,然后将sid的

值赋值给id,sid自身+1,这时候的内存中的图如下:

a140d45eef7a683c14df4e1c7f28b840.png

然后构造方法执行完毕,给这个构造方法分配的局部变量所占的内存空间全部消失,所以位于栈内存的name这块内存消失了,栈内存里面指向数据区里面的字符串对象"mimi"的引用也随之消失,此时只剩下堆内存里面的字符串对象“mimi”的引用没有消失,此时的内存布局如下

9d45da69220abb36fc9023ad59fdd217.png

执行Cat pipi = new Cat("pipi"),执行过程u第一次一样,这里就不过多解释了,此时的内存布局如下图:

d73ae96592c84b36be093d591f754d57.png

The result is:

My name is mimi No.100

My name is pipi No.2000

由此可以看出这个静态的sid可以计数用的

这里调用构造方法Cat(String name) 创建出两只猫,首先在栈内存里面分配两小块空间mimi和pipi,里面分别装着可以找到这两只猫的地址,mimi和pipi对应着堆内存里面的两只猫的引用。这里的构造方法声明有字符串类型的变量,字符串常量是分配在数据区里面的,所以这里会把传过来的字符串mimi和pipi都存储到数据区里面。所以数据区里面分配有存储字符串mimi和pipi的两小块内存,里面装着字符串“mimi”和“pipi”,字符串也是引用类型,除了那四类8种的基础数据类型之外,其他所有的数据类型都是引用类型。所以可以认为字符串也是一个对象。

这里是new了两只猫出来,这两只猫都有自己的id和name属性,所以这里的id和name都是非静态成员变量,即没有static修饰。所以每new出一只新猫,这只新猫都有属于它自己的id和name,即非静态成员变量id和name是每一个对象都有单独的一份。但对于静态成员变量来说,只有一份,不管new了多少个对象,哪怕不new对象,静态成员变量在数据区也会保留一份。如这里的sid一样,sid存放在数据区,无论new出来了多少只猫在堆内存里面,sid都只有一份,只在数据区保留一份。

静态成员变量是属于整个类的,它不属于专门的某个对象。那么如何访问这个静态成员变量的值呢?首先第一点,任何一个对象都可以访问这个静态的值,访问的时候访问的都是同一块内存。第二点,即便是没有对象也可以访问这个静态的值,通过“类名.静态成员变量名”来访问这个静态的值,所以以后看到某一个类名加上“.”再加上后面有一个东西,那么后面这个东西一定是静态的,如”System.out”,这里就是通过类名(System类)再加上“.”来访问这个out的,所以这个out一定是静态的

下面再看这段代码:

package satic;public classCat {/** 这里的sid不在是静态的了*/

private int sid = 0;/** 这里的name和id是非静态的成员变量

**/

private String name; //Cat类私有的属性name 初始值为0

int id; //变量

Cat(String name) {this.name = name; //将调用Cat方法时传入的值赋值给name属性

id = sid++; //将sid的值赋值给id并且sid自增1

}//info方法输入name和id的值

public voidinfo(){

System.out.println

("My name is"+name+"No."+id);

}public static voidmain(String arg[]){//Cat.sid = 100; 上面的sid不在是静态的了,所以不能这样来访问了

/** 调用Cat 方法更改name与id的值并打印

**/Cat mimi= new Cat("mimi");

mimi.sid= 2000;

Cat pipi= new Cat("pipi");

mimi.info();

pipi.info();

}

}

这段代码与上面的代码不同的是,将sid变成了非静态的,就不再有计数功能了,sid和name与id一样都属于属性,当然在面的代码当中也不能使用Cat.sid访问了,把Cat.sid那行去掉即可,这样的话,内存图就变成了下面的:

893e9a3db69ef4748e3a119b0c73b097.png

成员变量(属性)与局部变量的区别在于,成员变量(属性)初始的值为0,而局部变量没有初始化不能使用,所以,每次执行Cat方法,sid由0变为1,这样sid就没有了计数的功能

在一个静态方法里,如果想访问一个非静态的成员变量,是不能直接访问的,必须在静态方法里new一个对象出来才能访问。如果是加了static的成员变量,那么这个成员变量就是一个静态的成员变量,就可以在main方法里面直接访问了。

main方法是一个静态的方法,main方法要执行的时候不需要new一个对象出来。

动态方法是针对于某一个对象调用的,静态方法不会针对某一个对象来调用,没有对象照样可以用。所以可以使用”classname.method()”.的形式来调用静态方法。所以想在main方法里面访问非静态成员变量是不可以的,想在main方法里面访问非静态方法也是不可以的,因为非静态方法只能针对于某个对象来调用,没有对象,就找不到方法的执行者了。

成员变量只有在new出一个对象来的时候才在堆内存里面分配存储空间。局部变量在栈内存里面分配存储空间。

静态方法不再是针对某一个对象来调用,所以不能访问非静态的成员。

非静态成员专属于某一个对象,想访问非静态成员必须new一个对象出来才能访问。

静态的变量可以通过对象名去访问,也可以通过类名去访问,两者访问的都是同一块内存。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值