前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java中的static关键字浅析

Java中的static关键字浅析

作者头像
用户7073689
发布2020-03-18 15:24:27
6710
发布2020-03-18 15:24:27
举报
文章被收录于专栏:青柠小鱼青柠小鱼

这是我结合一些自己的思想写的对static关键字的理解。

1. static关键字

【重点】他是单身狗!!!

1.1 static修饰成员变量
1.1.1 static修饰成员变量的需求
在这里插入图片描述
在这里插入图片描述

“这里不希望大量的数据浪费”,打错字了,在这里纠正一下。

数据区也可以叫做共享区,是一个公共资源的放置地方。

static可以节省大量的冗余空间,堆区的String country指向数据区的首地址,类似于栈区指向于堆区。

1.1.2 静态成员变量使用注意事项
  1. 静态成员变量是使用static修饰的成员变量,定义在内存的【数据区】
  2. 静态成员变量不推荐使用类对象调用,会提示警告 The static field SingleDog.info should be accessed in a static way 使用static修饰的SingleDog类内的info成员变量,应该通过静态方式访问. 强烈不推荐通过对象调用,推荐通过类名调用!!! 知道为啥吗?因为static修饰的成员变量是个单身狗!!! 你用你的对象来找饥渴的单身狗修电脑,你愿意吗???人家单身狗愿意吗???
  3. 静态成员变量使用类名调用是没有任何的问题。【墙裂推荐方式】 但是!!!你通过找电脑店,或者找售后,这个大的一个类,虽然给你对象修电脑的还是一个单身狗,但是人家愿意修…
  4. 在代码中没有创建对象时,可以通过类名直接使用静态成员变量,和【对象无关】 这句话什么意思呢?就是说虽然static是单身狗,但是人家也是有追求的,即使没有对象,人家也是要恰饭的!!!
  5. 代码中对象已经被JVM的GC销毁时,依然可以通过类名调用静态成员变量,和【对象无关】 这句话不用我多说什么了吧?相信你们已经可以看出来了,这static丫的是个直男!!! static是个直男单身狗!!!和对象无关!!!
  6. 不管通过哪一种方式调用静态成员变量,修改对应的静态成员变量数据,所有使用到当前静态成员变量的位置,都会受到影响。 一旦单身狗受到刺激或者改变,那么他周围的一切都会影响。

好了,经过上面的脑补后,相信static的形象已经深入人心,下边我们来认真了解一下为什么静态成员变量和对象无关…

1.1.3 为什么静态成员变量和对象无关
  1. 从内存角度出发分析 静态成员变量是保存在内存的数据区 类对象占用的实际内存空间是在内存的堆区 这两个区域是完全不同的,所有可以说静态成员变量和对象没有关系 【没有对象】 这叫啥?天各一方!!!君住长江头,我住长江尾!!!
  2. 从静态成员变量以及类对象生命周期来分析 静态成员变量是随着类文件(.class) 字节码文件的加载过程中,直接定义在内存的数据区。静态成员变量从程序运行开始就已经存在。 类对象是在代码的运行过程中,有可能被创建,也有可能不被创建的。程序的运行过中,有可能会被JVM的CG垃圾回收机制销毁,程序在退出之前一定会销毁掉当前Java程序使用到的所有内存。 而静态成员变量在程序退出之后,才会销毁 静态成员变量的生命周期是从程序开始,到程序结束 类对象只是从创建开始,而且随时有可能被JVM的GC销毁 生命周期不在同一个时间线上,所以静态成员变量和类对象无关,【没有对象】 唉…可悲可叹,我(static)生君(对象)未生,我(static)生君(对象)已老!!! 我就像一粒原子,世界创立时我已存在,经历世间波澜壮阔,沉沉浮浮数万亿年; 而你,一个美丽的女子,你需要我时,我就在你身边任你使用,你不需要我时,我就静静待在这世界中看着你。 我的生命与世界相同,而你的出现却不是定数,即使有那造物主的怜惜,让你出现数十年,却也只相当于我生命的亿万分之一,你不在后,我还要在没有你的世界里待到末日…

代码展示

代码语言:javascript
复制
/*
 * 演示static关键字修饰成员变量
 */
class SingleDog {
	// static修饰的静态成员变量
	public static String info = "单身狗";
	
	// 非静态成员变量
	public String name;
	
	public SingleDog() {}
	
	public SingleDog(String name) {
		this.name = name;
	}
	
	// 非静态成员方法
	public void test() {
		System.out.println("test方法");
	}
}
public class Demo2 {
	public static void main(String[] args) {
		// 在没有类对象的情况下,可以直接通过类名调用静态成员变量
		System.out.println(SingleDog.info);
		
		// 曾经有过一个对象,31行代码运行完成,对象销毁
		new SingleDog();
		
		// 在类对象被销毁之后,依然可以通过类名调用静态成员变量
		System.out.println(SingleDog.info);
	}

}
1.2 static修饰成员方法
1.2.1 静态成员方法的格式

异常熟悉的格式

public static 返回值类型 方法名(形式参数列表) {

}

1.2.2 静态成员方法注意事项 【FFF社】

静态成员方法就是我大FFF社!!!

  1. 静态成员方法推荐使用静态方式调用,通过类名调用【墙裂推荐的】 不推荐使用类对象调用,因为【没有对象】 不用我解释了吧…
  2. 静态成员方法中不能使用非静态成员 ==> (非静态成员方法和非静态成员变量) 因为【没有对象】 嘿嘿嘿,FFF社…
  3. 静态成员方法中不能使用this关键字 回顾:this表示调用当前方法的类对象 因为静态方法中【没有对象】 so…
  4. 静态成员方法中可以使用类内的其他静态成员【难兄难弟】 大FFF社员
  5. 静态成员方法中可以通过new 构造方法创建对象 大FFF社不烧真爱!!!
1.2.3 静态成员方法特征解释
  1. 静态成员方法加载时间问题 静态成员方法是随着.class字节码文件的加载而直接定义在内存的【方法区】,而且此时的静态成员方法已经可以直接运行。可以通过类名直接调用,而此时没有对象存在。【没有对象】
  2. 为什么静态成员方法不能使用非静态成员 非静态成员变量和非静态成员方法时需要类对象调用的,在静态成员方法中,是可以通过类名直接执行的,而此时是【没有对象】的。
  3. 为什么静态成员方法不能使用this关键字 this关键字表示的是调用当前方法的类对象,但是静态成员方法可以通过类名调用,this不能代表类名,同时也是【没有对象】
  4. 静态成员方法可以使用其他静态成员 生命周期一致,调用方式一致
1.3 类变量和类方法

类变量 ==> 静态成员变量 类方法 ==> 静态成员方法 类成员 ==> 静态成员变量和静态成员方法

面试题 类方法中是否可以使用成员变量? 类方法可以使用当前类内的静态成员变量,但是不允许使用非静态成员变量

1.4 静态代码块

补充知识点 代码块

构造代码块(动态代码块) 初始化当前类的所有类对象,只要调用构造方法,【一定】会执行对应的构造代码块

代码语言:javascript
复制
执行顺序【成员变量之后  构造方法之前】

格式
{
    
}

静态代码块 初始化程序,只要类文件加载,静态代码块中所有内容全部执行

代码语言:javascript
复制
格式:
static {
// 静态代码块
}

只要【类文件】加载,当前静态代码块中的内容就一定会执行,并且有且只【执行一次】。 注意: 是.class文件加载,不是文件加载,如果主类中没有用到这个类,那么就不会加载这个类中的静态代码块。

作用:整个类的初始化过程

局部代码块 提高效率,解决内存,让JVM回收内存的效率提升。

代码语言:javascript
复制
for () {
	{
		int num
	}
}
1.5 静态题
代码语言:javascript
复制
public class Demo3 {
	static Demo3 demo1 = new Demo3();
	static Demo3 demo2 = new Demo3();
    
    {
        System.out.println("构造代码块"); // 1
    }
    
    static {
        System.out.println("静态代码块"); // 2
    }
    
    public Demo3() {
        System.out.println("构造方法"); // 3
    }
    
    public static void main(String[] args) {
        Demo3 demo1 = new Demo3();
    }
    
}

请问输出结果应该是什么呢?做题,不是写代码实践,思考…

答案:

代码语言:javascript
复制
//答案
/*
构造代码块
构造方法
构造代码块
构造方法
静态代码块
构造代码块
构造方法
*/
//解释
//首先代码执行static Demo3 demo1 = new Demo3();  是new一个对象,是new构造方法,所以执行
//构造代码块和构造方法
//然后执行static Demo3 demo2 = new Demo3();是new一个对象,是new构造方法,所以执行
//构造代码块和构造方法
//然后执行 
	static {
        System.out.println("静态代码块"); // 2
    }
//然后执行
 	public static void main(String[] args) {
        Demo3 demo1 = new Demo3();
    }
//又是创建新的类对象,所以执行构造代码块和构造方法

那么接下来我们将上边两个代码去掉static,结果会怎样? 如下:

代码语言:javascript
复制
public class Demo3 {
	 Demo3 demo1 = new Demo3();
	 Demo3 demo2 = new Demo3();
    
    {
        System.out.println("构造代码块"); // 1
    }
    
    static {
        System.out.println("静态代码块"); // 2
    }
    
    public Demo3() {
        System.out.println("构造方法"); // 3
    }
    
    public static void main(String[] args) {
        Demo3 demo1 = new Demo3();
    }
    
}

结果:

执行“静态代码块” 无限递归,栈堆内存满,报错

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. static关键字
    • 1.1 static修饰成员变量
      • 1.1.1 static修饰成员变量的需求
      • 1.1.2 静态成员变量使用注意事项
      • 1.1.3 为什么静态成员变量和对象无关
    • 1.2 static修饰成员方法
      • 1.2.1 静态成员方法的格式
      • 1.2.2 静态成员方法注意事项 【FFF社】
      • 1.2.3 静态成员方法特征解释
    • 1.3 类变量和类方法
      • 1.4 静态代码块
        • 1.5 静态题
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档