static的作用1:方便在没有创建对象的情况下来进行调用(方法/变量)。
(1)static方法
对于静态方法来说,是没有this的,因为它不依附于任何对象。既然都没有对象,就谈不上this了。
由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。但是要注意的是,非静态成员方法中是可以访问静态成员方法/变量的。
(2)static变量
静态变量仅在类被加载的时候初始化一次,在内存中只有一个副本。static成员变量的初始化按照定义的顺序进行。
static变量归类所有,为类的所有对象共享;非静态变量归对象所有,在创建对象的时候初始化,有多个副本。
static的作用2:static代码只会在类加载的时候执行一次,所有它可以优化程序。
例
class Person{
private Date birthDate;
public Person(Date birthDate) {
this.birthDate= birthDate;
}
boolean isBornBoomer() {
DatestartDate = Date.valueOf("1946");
DateendDate = Date.valueOf("1964");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)< 0;
}
}
每次调用isBornBoomer()方法时,都会产生startDate和birthDate两个对象,造成了空间浪费。
可以改成:
class Person{
private Date birthDate;
private static Date startDate,endDate;
static{
startDate =Date.valueOf("1946");
endDate =Date.valueOf("1964");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
returnbirthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)< 0;
}
}
因此,把只需要进行一次的初始化操作放在static代码块中,可以优化程序。
面试题
1、请问输出结果是什么?
public class Main {
static int value = 33;
public static void main(String[] args) throws Exception{
new Main().printValue();
}
private void printValue(){
int value = 3;
System.out.println(this.value);
}
}
答:
static成员变量虽然属于类,独立于对象,但是是可以被对象访问的。
输出:33
2、JAVA中statci是否可以修饰局部变量?
答:
C/C++中static可以修饰局部变量,JAVA不可以,这是语法规定。
3、下面这段代码的输出结果是什么?
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
答:
(1)先找main方法,main方法在Test类中,加载Test类 -- > 继承Base类;
(2)加载Base类 -- > 发现static块,输出basestatic;
(3)加载Test类 – > 发现static 块,输出teststatic;
(4)执行main() --> new Test() -- > 先调用父类构造器 Base(),输出baseconstructor再-- > 再调用自身构造器Test(),输出test constructor。
所以,最终输出结果:
basestatic
test static
base constructor
test constructor
4、下面这段代码的输出结果是什么?
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
答:
这里要注意的是:加载构造器时,要先初始化成员变量,而不是直接运行构造函数。
输出结果:
test static
myclass static
person static
person Test
test constructor
person MyClass
myclassconstructor
5、下面这段代码的输出结果是什么?
public class Test {
static{
System.out.println("test static 1");
}
public static void main(String[] args) {
}
static{
System.out.println("test static 2");
}
}
答:
虽然main中没有任何语句,但是加载Test会带来输出,且输出所有static。
输出结果:
test static 1
test static 2