static关键字

本文详细介绍了Java中的static关键字,包括其理解、使用场景、静态变量与静态方法、空引用访问静态变量的特性、静态代码块与实例代码块的执行顺序。通过实例分析了何时使用静态变量和静态方法,以及它们与实例变量和实例方法的区别。此外,还讨论了静态代码块和实例代码块在类加载和对象构建过程中的执行时机。
摘要由CSDN通过智能技术生成

目录

🏀static关键字

🥅static关键字理解

🥅什么时候使用static关键字

🥅空引用访问静态不会空指针

🥅关于实例方法的调用

🥅静态代码块

🥅实例代码块


🏀static关键字

🥅static关键字理解

  ❤️static:
        1、static翻译为“静态”
        2、所有static关键字修饰的都是类相关的,类级别的。
        3、所有static修饰的,都是采用“类名.”的方式访问。
        4、static修饰的变量:静态变量
        5、static修饰的方法:静态方法   
  ❤️ 变量的分类:
       ⭐️变量根据声明的位置进行划分:
          (1)在方法体当中声明的变量叫做:局部变量。
          (2)在方法体外声明的变量叫做:成员变量。     
      ⭐️成员变量又可以分为:
            实例变量
            静态变量

class VarTest{
//1. 以下实例的,都是对象相关的,访问时采用“引用.”的方式访问。需要先new对象。
	// 实例相关的,必须先有对象,才能访问,可能会出现空指针异常。

	int i;	// 成员变量中的实例变量
	public void m2(){ // 实例方法
		// 局部变量
		int x = 200;
	}


//2. 以下静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象。
	// 不需要对象的参与即可访问。没有空指针异常的发生。
	
	static int k;// 成员变量中的静态变量
	// 静态方法
	public static void m1(){ // 局部变量	
		int m = 100;
	}
	
}

🥅什么时候使用static关键字

   ❤️什么时候变量声明为实例的,什么时候声明为静态的?
    ⭐️如果这个类型的所有对象的某个属性值都是一样的,不建议定义为实例变量,浪费内存空间。建议定义为类级别特征,定义为静态变量,在方法区中只保留一份,节省内存开销。
    ⭐️一个对象一份的是实例变量。
    ⭐️所有对象一份的是静态变量。

❤️例1:不使用static

public class StaticTest02{
	public static void main(String[] args){
//1.创建一个c1对象
		Chinese c1 = new Chinese("1231456456456456","张三","中国");
		System.out.println(c1.idCard);
		System.out.println(c1.name);
		System.out.println(c1.country);
//2.创建一个c2对象
		Chinese c2 = new Chinese("7897897896748564","李四","中国");
		System.out.println(c2.idCard);
		System.out.println(c2.name);
		System.out.println(c2.country);
	}
}

//3. 定义一个类:中国人
class Chinese{
	// 每一个人的身份证号不同,所以身份证号应该是实例变量,一个对象一份。
	String idCard; 
	// 姓名也是一个人一个姓名,姓名也应该是实例变量。
	String name;

	// 对于“中国人”这个类来说,国籍都是“中国”,不会随着对象的改变而改变。
	// 显然国籍并不是对象级别的特征。
	// 国籍属于整个类的特征。整个族的特征。
	// 假设声明为实例变量,内存图是怎样的?
	// 假设声明为静态变量,内存图又是怎样的?
	String country;

// 无参数构造方法
	public Chinese(){
	
	}
// 有参数构造方法
	public Chinese(String s1,String s2, String s3){
		idCard = s1;
		name = s2;
		country = s3;
	}
}

⭐️内存图

❤️例2:使用static

 ⭐️加static的变量叫做静态变量
      (1)静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了。
      (2)静态变量存储在方法区。

 ⭐️不加static的变量叫做实例变量
      (1)实例变量在new创建对象,实例变量的空间就开出来了。
      (2)实例变量存储在堆区。

⭐️记住一句话:静态变量在方法区,在类加载时初始化!

public class StaticTest02{
	public static void main(String[] args){
		// 访问中国人的国籍
		// 静态变量应该使用类名.的方式访问
		System.out.println(Chinese.country);

		Chinese c1 = new Chinese("1231456456456456","张三");
		System.out.println(c1.idCard);
		System.out.println(c1.name);

		Chinese c2 = new Chinese("7897897896748564","李四");
		System.out.println(c2.idCard);
		System.out.println(c2.name);

		// idCard是实例变量,必须先new对象,通过“引用.” 访问
		// 错误: 无法从静态上下文中引用非静态 变量 idCard
		//System.out.println(Chinese.idCard);
	}
}

// 定义一个类:中国人
class Chinese{
    // 每一个人的身份证号不同,所以身份证号应该是实例变量,一个对象一份。
	String idCard; 
    // 姓名也是一个人一个姓名,姓名也应该是实例变量。
	String name;
    // 重点重点五颗星:加static的变量叫做静态变量
	// 静态变量在类加载时初始化,不需要new对象,静态变量的空间就开出来了。
	// 静态变量存储在方法区。
	static String country = "中国";//当时就进行赋值初始化

	// 无参数
	public Chinese(){
	
	}

	// 有参数
	public Chinese(String s1,String s2){
		idCard = s1;
		name = s2;
	}
}


⭐️内存图

java中一共有三大变量:

(1)静态变量:定义在类体中,用static修饰,属于类级别的;存储在方法区

(2)实例变量:定义在类体中,不用static修饰,属于对象级别的;存储在堆区

(3)局部变量:定义在方法体中,存储在栈区

🥅空引用访问静态不会空指针

  ⭐️实例的:一定需要使用“引用.”来访问。

  ⭐️静态的:建议使用“类名.”来访问,但使用“引用.”也行(不建议使用"引用.")。    
  ⭐️结论:空指针异常只有在“空引用”访问“实例”相关的,都会出现空指针异常。使用“引用.”访问“静态”不会出现空指针异常。

public class StaticTest03{
	public static void main(String[] args){
//1. 通过"类名."的方式访问静态变量
		System.out.println(Chinese.country);
		// 创建对象
		Chinese c1 = new Chinese("1111111", "张三");
		System.out.println(c1.idCard); // 1111111
		System.out.println(c1.name); // 张三
//2. 通过"引用."的方式访问静态变量也是可以的
		System.out.println(c1.country); // 中国

//3. c1是空引用,访问实例变量会空指针异常!访问静态变量不会空指针异常!
		c1 = null;
		//访问静态变量不会出现空指针异常。
		// 因为静态变量不需要对象的存在。
		// 实际上以下的代码在运行的时候,还是:System.out.println(Chinese.country);
		System.out.println(c1.country);// 实际上运行时会把c1替换成Chinese

//4. 这个会出现空指针异常,因为name是实例变量。
		//System.out.println(c1.name);
	}
}

class Chinese{

	// 实例变量
	String idCard;
	String name;

	// 静态变量
	static String country = "中国";

	//构造方法
	public Chinese(String x, String y){
		idCard = x;
		name = y;
	}
}

🥅关于实例方法的调用

⭐️static修饰的统一都是静态的,都是类相关的,不需要new对象。直接采用“类名.”访问。
⭐️当一个属性是类级别的属性,所有对象的这个属性的值是一样的,建议定义为静态变量。

 ❤️例1

public class StaticTest04{
	public static void main(String[] args){

//1. 对于静态变量:这是比较正规的方式,静态方法采用“类名.”
		StaticTest04.doSome();

//2. 对于实例变量,先new对象;用“引用.”访问
		StaticTest04 st = new StaticTest04();
		st.doSome();

//3. 空引用
		st = null;
		// 对于静态变量,不会出现空指针异常
		st.doSome(); // 这个代码在最终执行的时候还是会转变为:StaticTest04.doSome();

		// 实例方法doOther()
		// 对象级别的方法(先new对象,通过“引用.”来访问)
		//错误: 无法从静态上下文中引用非静态 方法 doOther()
		//StaticTest04.doOther();

		StaticTest04 st2 = new StaticTest04();
		st2.doOther();

		// 空引用
		st2 = null;
		// 空引用调用实例方法会出现什么问题?空指针异常。
		//st2.doOther();

	}

//1. 静态方法(静态方法不需要new对象,直接使用“类名.”来访问)
	// 但是也可以使用“引用.”来访问,不建议用。(因为其他程序员会感到困惑。)
	public static void doSome(){
		System.out.println("静态方法doSome()执行了!");
	}

//2. 实例方法(实例相关的都需要new对象,使用"引用."来访问。)
	public void doOther(){
		System.out.println("实例方法doOther执行了!");
	}
}

⭐️总结:

从第一天开始讲解HelloWorld到目前为止,一个类当中一共就写过这些东西。
类{
    实例相关的都是需要new对象的,通过"引用."访问。
    实例变量;
    实例方法;

    静态相关的都是采用“类名.”访问。也可以使用“引用.”,只不过不建议。
    静态变量;
    静态方法;
}

 ❤️例2

⭐️关于方法来说,什么时候定义为实例方法?什么时候定义为静态方法?
     参考标准:当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法。此方法一般都是描述了一个行为,如果说该行为必须由对象去触发。那么该方法定义为实例方法

⭐️我们以后开发中,大部分情况下,如果是工具类的话,工具类当中的方法一般都是静态的。(静态方法有一个优点,是不需要new对象,直接采用类名调用,极其方便。工具类就是为了方便,所以工具类中的方法一般都是static的。)

⭐️类 = 属性 + 方法
    (1)属性描述的是:状态
    (2)方法描述的是:行为动作
⭐️一个方法代表了一个动作。什么时候方法定义为实例方法?例如:
     张三考试,得分90,李四考试,得分100;不同的对象参加考试的结果不同。我们可以认定“考试”这个行为是与对象相关的行为。建议将“考试”这个方法定义为实例方法。

public class StaticTest05{
	public static void main(String[] args){
//1.getID是实例方法,必须先new对象		
        User u = new User();
		System.out.println(u.getId()); //0
//2.名字name是实例变量,必须先new对象	
		User x = new User();
		x.printName1();

	}
}


//实例变量访问的语法机制是什么?
//语法:引用.实例变量名
class User{

	// 实例变量,需要对象
	private int id;

	// 实例变量
	private String name; // 首先先分析的是,这个name是对象级别的,一个对象一份。


	// 打印用户的名字这样的一个方法。
	public void printName1(){ 
		System.out.println(name);
	}

	public void setId(int i){// 不能加static,加static就和对象没关系了
		id = i; //id是实例变量,上面必须是实例方法才行
	}
	public int getId(){// 不能加static
		return id;
	}
}

🥅静态代码块

  ⭐️使用static关键字可以定义:静态代码块
  ⭐️什么是静态代码块,语法是什么?

 static {
            java语句;
            java语句;
        }

  ⭐️static静态代码块在什么时候执行呢?
         静态代码块有这样的特征/特点:类加载时执行;并且只执行一次

 ⭐️注意:静态代码块在类加载时执行,并且在main方法执行之前执行

 ⭐️静态代码块一般是按照自上而下的顺序执行。 

 ⭐️静态代码块有啥作用,有什么用?
        第一:静态代码块不是那么常用。(不是每一个类当中都要写的东西。)
        第二:静态代码块这种语法机制实际上是SUN公司给我们java程序员的一个特殊的时刻/时机;这个时机叫做:类加载时机。
        第三:具体的业务:我们编写的程序中,只要是类加载了,请记录一下类加载的日志信息(在哪年哪月哪日几时几分几秒,哪个类加载到JVM当中了)。
       第四:思考这些记录日志的代码写到哪里呢? 写到静态代码块当中。

 ❤️例1

public class StaticTest06{
//1. 静态代码块(特殊的时机:类加载时机。)
	static {
		System.out.println("A");
	}
//2. 一个类当中可以编写多个静态代码块
	static {
		System.out.println("B");
	}
//3. 程序入口
	public static void main(String[] args){
		System.out.println("Hello World!");
	}
//4. main方法后再编写一个静态代码块
	static{
		System.out.println("C");
	}
}
//5. 执行结果
A
B
C
Hello World!

 ❤️例2

    栈:方法只要执行,会压栈。(局部变量)
    堆:new出来的对象都在堆中。垃圾回收器主要针对堆中的数据。(实例变量)
    方法区:类的信息,字节码信息,代码片段。(静态变量)
    总结:方法的代码片段放在方法区,但是方法执行过程当中需要的内存在栈中。

    补充:静态代码块可以访问静态变量;

               静态代码块和静态变量都在类加载的时候执行,时间相同,只能靠代码的顺序来决定谁先谁后

public class StaticTest07{
	
//1. 静态变量在什么时候初始化?类加载时初始化。
	// 静态变量存储在哪里?方法区
	static int i = 100;

//2. 静态代码块什么时候执行?类加载时执行。
	//只要是代码一定存放在代码区
	//--------------静态代码块可以访问静态变量!
	static {
		System.out.println("i = " + i);		// 这里可以访问i
	}

	// ----------------实例变量
	int k = 111; // k变量是实例变量,在new构造方法执行时内存空间才会开辟。

	static {
		// static静态代码块在类加载时执行,并且只执行一次。
		// 类加载时,k变量空间还没有开辟出来呢。
		//错误: 无法从静态上下文中引用非静态 变量 k
		//System.out.println("k = " + k);

		
	}
//3.
     static{
        //------------------这里可以访问name吗?
		//错误: 非法前向引用
		//静态代码块和静态变量都在类加载的时候执行,时间相同,只能靠代码的顺序来决定谁先谁后。
		//System.out.println("name = " + name);
    }
	// 静态变量在静态代码块下面。
	static String name = "zhangsan";


	//入口(main方法执行之前实际上执行了很多代码)
	public static void main(String[] args){
		System.out.println("main begin");
		System.out.println("main over");
	}
}

⭐️总结:到目前为止,你遇到的所有java程序,有顺序要求的是哪些?
        第一:对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行。
        第二:静态代码块1和静态代码块2是有先后顺序的。
        第三:静态代码块和静态变量是有先后顺序的。

🥅实例代码块

  ⭐️除了静态代码块之外,还有一种语句块叫做:实例语句块
  ⭐️实例语句在类加载是并没有执行。
  ⭐️实例语句语法?

   {
        java语句;
        java语句;
        java语句;
    }

 ⭐️实例语句块在什么时候执行?
      只要是构造方法执行,必然在构造方法执行之前,自动执行“实例语句块”中的代码;每次都会执行。
      实际上这也是SUN公司为java程序员准备一个特殊的时机,叫做对象构建时机。
 ⭐️当几个方法有相同的代码,就可以把他们提取出来放到实列语句块里!减少代码冗余

❤️例1

public class InstanceCode{

    //入口
    public static void main(String[] args){
        System.out.println("main begin");
        new InstanceCode();
        new InstanceCode();

        new InstanceCode("abc");
        new InstanceCode("xyz");
    }


    //实例语句块
    {
        System.out.println("实例语句块执行!");    
    }

    // Constructor
    public InstanceCode(){
        System.out.println("无参数构造方法");
    }

    // Constructor
    public InstanceCode(String name){
        System.out.println("有参数的构造方法");
    }

}
//执行结果
main begin
实例语句块执行!
无参数构造方法
实例语句块执行!
无参数构造方法
实例语句块执行!
有参数的构造方法
实例语句块执行!
有参数的构造方法

❤️例2:判断代码执行的顺序

public class CodeOrder{	
//1. 静态代码块
	static{
		System.out.println("A");
	}
//2. 程序入口
	// A X Y C B Z
	public static void main(String[] args){
		System.out.println("Y");
		new CodeOrder();
		System.out.println("Z");
	}
//3. 构造方法
	public CodeOrder(){
		System.out.println("B");
	}
//4. 实例语句块
	{
		System.out.println("C");
	}
//5. 静态代码块
	static {
		System.out.println("X");
	}

}

总结执行顺序:静态代码块---》main方法入口---》实列语句块---》new对象(构造方法)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mgh521@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值