java中的this关键字与static关键字

this和static

1. static关键字

  • static修饰的统一都是静态的,都是类相关的,不需要 nwe 对象。直接采用"类名."访问
  • 当一个属性是类级别的属性所有对象的这个属性的值都是一样的,建议定义为静态变量。
/* file: StaticTest01.java */
/*
	static:
		1、static 翻译为 “静态”
		2、所有的static关键字修饰的都是类相关的,类级别的。
		3、所有static修饰的,都是采用 “类名.” 的方式访问。
		4、static修饰的变量:静态变量
		5、static修饰的方法:静态方法
	
	变量的分类:
		- 变量根据申明的位置进行划分:
			- 在方法体当中声明的变零叫做:局部变量。
			- 在方法体外声明的变零叫做:成员变量。

		- 成员变量又可以分为:
			- 实例变量
			- 静态变量
*/
class VarTest{

	// 一下实例的,都是对象相关的,访问时采用 "引用."的方式访问。需要先new对象。
	// 实例相关的,必须先有对象,才能访问,可能会出现空指针异常。
	// 成员变量中的实例变量
	int i;

	//实例方法
	public void m2(){
		//局部变量
		int x = 100;
	}

	// 成员变量中的静态代变量
	static int k;
	// 静态方法
	public static void m1(){
		// 局部变量
		int x = 200;
	}
}

2.什么时候变量声明为实例的,什么时候声明为静态的?

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

将属性 国籍 设置为 实例变量

/* file: StaticTest02.java */
/*
    什么时候变量声明为实例的,什么时候声明为静态的?
*/
public class StaticTest02{
    public static void main(String[] args){
        Chinese c1 = new Chinese("123423455231456241", "张三", "中国");
        System.out.println(c1.idCard);
        System.out.println(c1.name);
        System.out.println(c1.country);

        Chinese c2 = new Chinese("252345125453425234", "李四", "中国");
        System.out.println(c2.idCard);
        System.out.println(c2.name);
        System.out.println(c2.country);
    }
}

// 定义一个类:中国人
class Chinese{
    // 身份证号
    String idCard;
    // 姓名
    String name;
    // 国籍
    // 对于“中国人”这个类来说,国籍都是“中国”,不会随着对象的改变而改变。
    // 显然国籍并不是对象级别的特征。
    // 国籍属于整个类的特征。内存图的特征。
    // 假设声明为实例变量,内存图是怎样的?
    // 假设声明为静态变量,内存图又是怎样的?
    String country;

    // 无参构造
    public Chinese(){

    }

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

}
  • 内存图:
    在这里插入图片描述

将属性 国籍 设置为 静态变量


/* file: StaticTest03.java */
*/
/*
    实例的:一定要使用"引用."来访问
    静态的:建议使用"类名."来访问,但是用"引用."也行(不建议使用"引用.")。
    静态的如果使用"引用."来访问会让程序员产生疑惑:程序员以为是实例的呢。

    结论:
        空指针异常只是在什么情况下才会发生呢?
            只会在访问"实例"相关的,才会出现空指针异常。
*/
public class StaticTest02{
    public static void main(String[] args){
		// 访问中国人的国籍
		// 静态变量应该使用类名.的方式访问
        System.out.println(Chinese.country);

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

        Chinese c2 = new Chinese("252345125453425234", "李四");
        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;
    }
}
  • 内存图
    在这里插入图片描述

3.关于方法来说,什么时候定义为实例方法,什么时候定义为静态方法

  • 有没有参考标准。
  • 此方法一般都是描述了一个行为,如果说该行为必须由对象去触发。那么该方法定义为实例方法。
  • 参考标准:
    • 当这个方法体当中,直接访问了实例变量,这个方法一定是实例方法。

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

    • 什么是工具类?????
      工具类就是为了方便编程而开发的一些类。

    • 类=属性+方法

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

/* file: StaticTest04.java */
public class StaticTest04{
    public static void main(String[] args){

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

        // 对象
        StaticTest04 st = new StaticTest04();
        //用"引用."访问
        st.doOther();

        st = null;
        // 不会出现空指针异常
        st.doSome(); // 这个代码在最终执行董事时候还是会转换为:StaticTest04.doSome();

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

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

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

    }

    // 静态方法(静态方法不需要 new 对象,直接使用“类名.”来访问)
    // 但是也可以使用 "引用."的来访问,不建议使用。
    public static void doSome(){
        // 用"引用."访问
        System.out.println("静态方法doSome()执行了!");
    }

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

4.static关键字定义静态代码块

  • 使用static关键字可以定义:静态代码块

  • 什么是静态代码块,语法是什么?

   static {
       	java语句;
       	java语句;
   	}
  • static静态代码块在什么时候执行呢?

    • 类加载时执行。并且只执行一次。
    • 静态代码块有这样的特征/特点。
  • 注意:静态代码块在类加载时执行,并且在main方法执行之前执行。

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

  • 静态代码块有啥用?

    • 第一:静态代码块不是那么常用。(不是每一个类当中都要写的东西。)
    • 第二:静态代码块这种语法机制实际上是sun公司给我们java程序员的一个特殊的时刻/时间
      这个时机叫做:类加载时机。
  • 具体的业务:
    项目经理说了:大家注意了,所有我们编写的程序中,只要是类加载了,请记录一下
    类加载的日志信息(在哪年哪月哪日几时几分几秒,哪个类加载到JVM当中了)。
    思考:这些记录日志信息的代码写到哪里?
    写到静态代码块中

/* file: StaticTest06.java */
public class StaticTest06{
    //静态代码块
    static{
        System.out.println("A");
    }

    //一个类中可以编写多个静态代码块
    static{
        System.out.println("B");
    }

    public static void main(String[] args){
        System.out.println("hello world!");
    }

    // 编写一个静态代码块
    static {
        System.out.println("C");
    }

    /*程序执行结果:
        A
        B
        C
        hello world!
     */
}

静态变量在什么时候初始化?类加载时初始化。静态变量存储在哪里?方法区。

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

    static{
        // 这里可以访问 i 吗?
        System.out.println("i = " + i);
    }

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

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

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

    //入口(main方法执行之前实际上执行了很多代码)
    public static void main(String[] args){
        System.out.println("main begin");
    }
}
  • 总结:
    • 到目前为止,你遇到的所有java程序,有顺序要求的是哪些?
      • 第一:对于一个方法来说,方法体中的代码是有顺序的,遵循自上而下的顺序执行。
      • 第二:静态代码块1和静态代码块2是有先后顺序的。
      • 第三:静态代码块和静态变量是有先后顺序的。

5.除了静态代码块之外,还有一种语句块叫做:实例语句块

  • 除了静态代码块之外,还有一种语句块叫做:实例语句块
  • 实例语句在类加载是并没有执行
  • 实例语句语法?
{
    java语句;
    java语句;
    java语句;
}
  • 实例语句块在什么时候执行?
    只要是构造方法执行,必然在构造方法执行之前,自动执行“实例语句块”中的代码。
    实际上这也是SUN公司为java程序员准备一个特殊的时机,叫做对象构建时机。
/* file: InstanceCode.java */
public class InstanceCode{
    // 入口
    public static void main(String[] args) {
        System.out.println("main begin");
    }

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

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

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

7.判断一下程序的执行顺序(static关键字结束)

/* file: CodeOrder.java */
//判断一下程序的执行顺序
public class CodeOrder{
    // 静态代码块
    static{
        System.out.println("A");
    }

    //入口
    public static void main(String[] args){
        System.out.println("Y");
        new CodeOrder();
        System.out.println("Z");
    }

    // 构造方法
    public CodeOrder(){
        System.out.println("B");
    }

    // 实例代码块
    {
        System.out.println("C");
    }

    //静态代码块
    static {
        System.out.println("X");
    }
}
/*
    程序执行结果:
    A
    X
    Y
    C
    B
    Z
*/

7.判断一下程序的执行顺序(static关键字结束)

/* file: CodeOrder.java */
//判断一下程序的执行顺序
public class CodeOrder{
    // 静态代码块
    static{
        System.out.println("A");
    }

    //入口
    public static void main(String[] args){
        System.out.println("Y");
        new CodeOrder();
        System.out.println("Z");
    }

    // 构造方法
    public CodeOrder(){
        System.out.println("B");
    }

    // 实例代码块
    {
        System.out.println("C");
    }

    //静态代码块
    static {
        System.out.println("X");
    }
}
/*
    程序执行结果:
    A
    X
    Y
    C
    B
    Z
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值