static的使用

一、JAVA的内存分析

内存概述

java的内存存储总共分为5大区域:堆、栈、方法区、本地方法区、寄存器区

其中本地方法区(存第三方语言-C/C++)和寄存器区(多线程资源)不用区分析,没法跟踪这两个区域

重点分析:堆,栈,方法区

  • 堆:存new对象,成员属性,常量池(放字符串常量,之前方法区,现在放堆区-性能考虑,但沿用了方法区特点)
  • 栈:存局部变量
  • 方法区:class资源,static资源; 特点:优先于对象的加载,且相同资源只维护一份

内存分析流程:

  1. 加载Test1.class与Person.class—方法区(class字节码文件)
  2. new对象开辟空间-------堆区
  3. 将地址赋值给引用变量person-------栈区

接下来,使用简单的面向对象案例,说明内存的执行过程

案例分析

//案例:小明在打游戏
//分析:类-Person,对象:new   属性-姓名,方法:打游戏
class Person{
	String name;
	public void play() {
		System.out.println(name+"正在打游戏");
	}
}
public class Test1 {
	public static void main(String[] args) {
		Person person = new Person();
		person.name = "小明";
		person.play();
	}
}

二、静态-修饰属性

静态属性与成员属性

  • 成员变量结论:实例化多个对象,每个对象都有独立的成员属性
  • 静态变量结论:实例化多个对象,共享同一份静态变量

成员变量 VS 静态变量

1. 存储位置:

  • 静态变量-方法区
  • 成员变量-堆

2. 所属资源:

  • 静态变量-类
  • 成员变量-对象

3. 执行顺序:

  • 静态变量优先于成员变量进行加载;在类加载时,就已经加载了静态资源

4. 调用方式:

  • 静态变量-推荐用类调
  • 成员变量-对象调
//案例:女朋友帮忙洗衣服
class Girl{
	//String name;  //成员变量
	static String name;  //静态变量
	
	public void wash() {
		System.out.println("女朋友"+name+"正在帮忙洗衣服");
	}
}
public class Test1 {
	public static void main(String[] args) {
		Girl lyf = new Girl();
		Girl.name="刘亦菲";   //lyf.name = "刘亦菲";  
		
		Girl fj = new Girl();
		Girl.name  = "凤姐";
		
		lyf.wash();  //凤姐
		fj.wash();   //凤姐
		
	}
}

在这里插入图片描述

场景-统计全局资源

说明: 在面向对象中,直接使用静态变量场景不多;但有些场景下,还是用得较多

例如:统计全局资源及作为状态值(静态常量)的使用

//案例:统计某个对象被new了多少次
//分析:实例化对象后,使用构造方法来记录次数
class A{
	//int count;   //初始为0  //成员变量:每个对象都是独立的一份
	static int count;  //静态变量:所有对象共享同一份
	public A() {
		count++;  //每次new了之后,然后+1
	}
}
public class Test2 {
	public static void main(String[] args) {
		new A();
		new A();
		new A();
		System.out.println("次数:"+A.count);//3
	}
}

场景-状态值应用

状态值 — 静态常量 static+final

  • final最终的,修饰变量,变为常量;所存的数值不可改变

  • 往往这种静态常量可以用于状态值,也就是系统给定值(也可自定义),用于判断,不要改变它

  • 好处:可读性很强,维护性很强

//案例:200响应码-成功    404-找不到访问页面   500-服务器报错
//模拟代码实现:
public class Test3 {
	public static final  int HTTP_OK = 200;  //状态值
	public static final int HTTP_ERR = 404;
	public static final int SERVER_ERR = 500;
	
	public static void main(String[] args) {
		int repcode = getResponseCode();
		//HTTP_OK = 400;  final修饰的不能更改
		switch (repcode) {
		case HTTP_OK:
			System.out.println("返回成功页面!");
			break;
		case HTTP_ERR:
			System.out.println("访问页面未找到!");
			break;
		case SERVER_ERR:
			System.out.println("服务器出现异常");
			break;
		default:
			System.out.println("错误的响应码");
			break;
		}
	}
	private static int getResponseCode() {
		//执行了很多后端操作
		return HTTP_OK;
	}
}

三、静态-修饰方法

特点

修饰方法时,在静态方法中不能使用成员变量

注意事项:

  • 在静态方法中不能使用成员变量,因为加载时机问题-static优先加载,不认识成员
  • 静态方法可以继承,但不能重写
  • 静态方法中不能使用this或super关键字
class A{
	String name;  //成员变量
	static int age;
	public void eat() {  //成员方法
		System.out.println(name+"正在吃");
		System.out.println(age); //在成员方法中,可以使用静态变量
	}
	public static void test() {  //静态方法
		//在静态方法中不能使用成员变量,因为加载时机问题-static优先加载,不认识成员
		//System.out.println(name); 
		//System.out.println(this.name);  //静态方法中不能使用this或super关键字
		//静态方法可以继承,但不能重写
	}
}
class B extends A{
	/*@Override   //静态方法不能重写
	public static void test() {
	}*/
}
public class Test1 {
	public static void main(String[] args) {
		B.test();  //静态方法具有继承性
	}
}

场景-工具类

工具类的应用 — 通过类名直接调静态方法

好处:不需要通过new对象进行调用;如果需要多次调用,可节约内存

工具类的修饰符:

  • 类:public + class 类名
  • 方法:public static + 返回值类型 方法名(参数列表)
//例如系统提供的:System,Arrays都是工具类的用法
//System.arraycopy;  Arrays.sort  Array.copyOf  Arrays.toString
class MyArrays{
	public static void sort(int[] a) {
		//冒泡排序:
		for(int i=0;i<a.length-1;i++) {
			for(int j=0;j<a.length-1-i;j++) {
				if(a[j]>a[j+1]) {
					int t = a[j];
					a[j] = a[j+1];
					a[j+1]= t;
				}
			}
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		int[] a = {2,6,4,8,3};
		MyArrays.sort(a);  //自定义工具类
		System.out.println(Arrays.toString(a));
	}
}

四、静态-修饰代码块

动态代码块

在类中写入**{}**,就是一个动态代码块,只要实例化一次对象,即可触发一次代码块

  • 执行时机:属性赋值>动态代码块>构造方法
  • 作用:可用于给属性赋值
//动态代码块应用:
class A{
	String name = "成员属性";
	public A() {  //构造方法
		System.out.println("构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("动态代码块");
	}
}
public class Test1 {
	public static void main(String[] args) {
		new A();
	}
}

输出结果:

在这里插入图片描述

在Java中,属性赋值、动态代码块和构造方法的顺序是固定的。以下是它们的顺序:

1. 属性赋值: 在类中定义的属性会被赋予默认值,例如整数类型默认为0,布尔类型默认为false,引用类型默认为null。然后,按照代码中的顺序,属性会被赋予初始值。
2. 动态代码块(也称为实例初始化块): 动态代码块是在创建对象时执行的代码块。它们在构造方法之前执行,并且可以用于初始化实例变量。如果有多个动态代码块,它们会按照它们在类中出现的顺序依次执行。
3. 构造方法: 构造方法是用于创建对象并初始化其状态的特殊方法。它们在动态代码块之后执行。如果有多个构造方法,它们可以根据参数的不同进行重载。

总结起来,属性赋值发生在动态代码块和构造方法之前,而动态代码块在构造方法之前执行。这个顺序保证了对象在创建时属性得到适当的初始化。

类加载

类加载机制:JVM首次使用某个类,通过classpath找到.class文件,并将类资源加载到内存中

这些类资源包括:包名,类名,属性,方法,对象…

类加载的触发时机:run 配置–verbose

使用场景:

  1. 实例化对象
  2. 实例化子类对象
  3. 静态属性触发
  4. 静态方法触发
  5. 使用反射触发

案例:

class B{
	static String name="静态属性";
	public static void show() {
		System.out.println("静态方法触发");
	}
}
class C extends B{	
}
public class Test2 {
	public static void main(String[] args) throws ClassNotFoundException {
		//new B();  //类加载只有一份;与实例化多次对象无关
		//new B();
		//new C();   //实例化子类对象
		//System.out.println(B.name);  //静态属性
		//B.show();    //静态方法
		Class.forName("com.qf.d_block.B");   //全限定名   反射应用
	}
}

静态代码块

静态代码块: static{}

执行顺序:静态属性 > 静态代码块

作用:用于给静态属性赋值

案例:

class D{
	static String name="静态属性";
	static {
		System.out.println(name);
		System.out.println("静态代码块");
	}
}
public class Test3 {
	public static void main(String[] args) {
		new D();
	}
}

实例化过程

之前学习过实例化对象后,开辟了空间,并赋初值等过程;此处再加上静态代码块与动态代码块的执行

  • 顺序:
静态属性>静态代码块>子类静态属性>子类静态代码块>成员属性
>动态代码块>构造方法>子类成员属性>子类动态代码块>子类构造方法
  • 规则: 先静态后动态,先父类后子类

案例一:

//将静态代码块与动态代码块综合应用:
class Super{
	String name = "成员属性";
	public Super() {  //构造方法
		System.out.println("构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("动态代码块");
	}
	
	static String name2="静态属性";
	static {
		System.out.println(name2);
		System.out.println("静态代码块");
	}
}
public class Test1 {
	public static void main(String[] args) {
		new Super(); //静态属性>静态代码块>成员属性>动态代码块>构造方法
		System.out.println("---------------");
		new Super();  //成员属性>动态代码块>构造方法   静态的只加载一次
	}
}

输出结果:

在这里插入图片描述
案例二:

//实例化子类对象的执行过程:
class Son extends Super{
	String name = "子类成员属性";
	public Son() {  //构造方法
		System.out.println("子类构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("子类动态代码块");
	}
	
	static String name2="子类静态属性";
	static {
		System.out.println(name2);
		System.out.println("子类静态代码块");
	}
}
public class Test2 {
	public static void main(String[] args) {
		new Son();   //实例化子类对象的过程
	}
}

输出结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值