static习题练习

static习题练习

static关键字

概述:不依赖于任何对象就可以直接访问

static关键字可以修饰成员变量和成员方法

static修饰成员变量

static修饰的成员变量是一个共享资源,被所有对象共享,在类初次加载的时候才会初始化

static修饰的成员变量的生存期和类对象的生存期完全不同,而是和类的生存期相同,即:static成员变量在类对象创建之前可以使用,类对象销毁之后依然可以使用,所以static修饰的成员变量和类对象无关。

static修饰成员方法

static修饰的成员方法不依赖于任何对象就可以直接访问

主要作用:工具类(静态成员方法使用的数据都是外来数据,且静态成员方法可以摆脱类对象约束,通过类名直接调用。)

优点:

1、节约内存,简化逻辑。(不需要创建对象,不需要申请对象空间,也不需要销毁对象空间。)

2、复用度更高。(摆脱对象限制,更加自由)

注意事项

1、静态成员变量具有数据共享性,不管通过那种方式修改,都会影响所有人

2、static修饰的成员变量和成员方法,从属于类,普通变量和方法从属于对象

3、静态成员变量与静态成员方法推荐使用类名直接调用

4、static修饰的成员变量的生存期和类对象的生存期完全不同,而是和类的生存期相同

5、静态成员方法中不能够使用类内非静态成员变量与非静态成员方法 ,但是在非静态成员方法中,可以使用静态成员变量与静态成员方法。

6、静态成员方法可以使用类内的其他静态成员变量和静态成员方法

7、不能在static修饰的静态内容中,使用this关键字

eg:

class Person {
	public String name;
	public static String country = "China";
	
	// 构造方法
	public Person() {}
	public Person(String name) {
		this.name = name;
	}
	
	public void test() {
		System.out.println("非静态成员方法");
	}
	
	public static void test2() {
		System.out.println("静态成员方法");
	}
	
	// getter与setter方法
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
} 

public class Demo {
	public static void main(String[] args) {
		// 静态成员变量在没有创建对象的情况,可以通过类名使用
		System.out.println("Country: " + Person.country);
		
		// 静态成员变量与对象无关
		System.out.println("Name: " + new Person("张三").getName() + "\t" + "Country: " + Person.country);
		
		//非静态成员方法,通过匿名对象调用
		new Person().test();
		
		//静态成员方法,通过类名调用
		Person.test2();
	}
}

运行结果:

Country: China
Name: 张三	Country: China
非静态成员方法
静态成员方法
构造代码块与静态代码块

构造代码块:

功能:
初始化当前类所有的类对象,只要【使用new + 构造方法创建当前类对象】,就一定会执行构造代码块中的内容

格式:
在class大括号以内,成员变量之后,构造方法之前
// 构造代码块
{

​ }

静态代码块:

功能:
类文件加载,静态代码块中的内容一定会执行,有且只执行一次!
类文件的加载是当前代码中的确需要当前类,才会进行加载。

格式:
在class大括号以内,成员变量之后,构造方法之前
// 静态代码块
static {

}

注意:非静态成员变量,非静态成员方法,this关键字都无法在静态代码块中使用。

eg1:

class Demo {
    static Demo demo1 = new Demo();
    static Demo demo2 = new Demo();
    
    {
    	System.out.println("构造代码块");   
    }
    
    static {
        System.out.println("静态代码块");  
    }
    
    public Demo() {
        System.out.println("构造方法");  
    }
    
    public static void main(String[] args) {
        Demo demo1 = new Demo();
    }
}

运行结果:

构造代码块
构造方法
构造代码块
构造方法
静态代码块
构造代码块
构造方法

分析:

1、找到main方法程序入口,在执行main方法之前应该先加载Demo类,

2、加载Demo类时,按照基本顺序结构(从上至下,从左至右),先执行静态成员变量demo1初始化,又由于构造代码块只要【使用new + 构造方法创建当前类对象】,就一定会执行构造代码块中的内容,所以先输出构造代码块,再输出构造方法

3、静态成员变量demo2同理,输出先输出构造代码块,再输出构造方法

4、然后发现静态代码块,执行静态代码块中的内容,输出静态代码块

5、执行main方法,采用无参数构造方法对Demo类对象demo1进行初始化,先输出构造代码块,在输出构造方法。

eg2:

class Demo {
    static int num1 = 10;
    static int num2 = 20;
    
    {
    	System.out.println("构造代码块");
    }
    
    static {
        num1 = 20;
        num2 = 100;
    }
    
    public Demo() {
        System.out.println("构造方法");
    }
    
    public static void main(String[] args) {
        new Demo();
    }
}
/*
代码执行效果已经num1和num2的值是多少
*/

分析:
1、找到main方法程序入口,在执行main方法之前应该先加载Demo类,
2、加载Demo类时,按照基本顺序结构(从上至下,从左至右),先执行静态成员变量,此时num1 = 10, num2 = 20.
3、然后发现静态代码块,执行静态代码块中的内容,此时num1 = 20, num2 = 100.
4、执行main方法,采用无参数构造方法对匿名对象进行初始化,先输出构造代码块,再输出构造方法。

eg3:

class Demo {
    Demo demo1 = new Demo();
    Demo demo2 = new Demo();
    
    {
    	System.out.println("构造代码块");   
    }
    
    static {
        System.out.println("静态代码块");  
    }
    
    public Demo() {
        System.out.println("构造方法");  
    }
    
    public static void main(String[] args) {
        Demo demo1 = new Demo();
    }
}
/*
问:
	代码执行流程!!!
*/
分析:
1、找到main方法程序入口,在执行main方法之前应该先加载Demo类,
2、加载Demo类时,按照基本顺序结构(从上至下,从左至右),先执行静态代码块,输出静态代码块.
3、然后在main方法中对Demo类对象demo1进行实例化,将非静态成员变量加载到Demo类对象demo1指向的堆空间中,由于该成员变量为Demo类自身对象的实例化,形成了闭环,则会出现无限递归现象造成堆栈溢出错误。

你可能感兴趣的:(每日学习打卡)