zoukankan      html  css  js  c++  java
  • javaSE_10_关键字 static丶this

    static 概述

    static 是 java 语言中的关键字,表示“静态的”,它可以用来修饰变量、方法、代码块等,修饰的变量叫做静态变量,修饰的方法叫做静态方法,修饰的代码块叫做静态代码块。在 java语言中凡是用 static 修饰的都是类相关的,不需要创建对象,直接通过“类名”即可访问,即使使用“引用”去访问,在运行的时候也和堆内存当中的对象无关。

    静态变量

    java 中的变量包括:局部变量和成员变量,在方法体中声明的变量为局部变量,有效范围很小,只能在方法体中访问,方法结束之后局部变量内存就释放了,在内存方面局部变量存储在栈当中。在类体中定义的变量为成员变量,而成员变量又包括实例变量和静态变量,当成员变量声明时使用了 static 关键字,那么这种变量称为静态变量,没有使用 static 关键字称为实例变量,实例变量是对象级别的,每个对象的实例变量值可能不同,所以实例变量必须先创建对象,通过“引用”去访问,而静态变量访问时不需要创建对象,直接通过“类名”访问。实例变量存储在堆内存当中,静态变量存储在方法区当中。实例变量在构造方法执行过程中初始化,静态变量在类加载时初始化。代码举例
    /*
        static:
            1、static翻译为“静态”
            2、所有static关键字修饰的都是类相关的,类级别的。
            3、所有static修饰的,都是采用“类名.”的方式访问。
            4、static修饰的变量:静态变量
            5、static修饰的方法:静态方法
        
        变量的分类:
            变量根据声明的位置进行划分:
                在方法体当中声明的变量叫做:局部变量。
                在方法体外声明的变量叫做:成员变量。
            
            成员变量又可以分为:
                实例变量
                静态变量
    */
    
    class VarTest{
    
        // 以下实例的,都是对象相关的,访问时采用“引用.”的方式访问。需要先new对象。
        // 实例相关的,必须先有对象,才能访问,可能会出现空指针异常。
        // 成员变量中的实例变量
        int i;
    
        // 实例方法
        public void m2(){
            // 局部变量
            int x = 200;
        }
    
    
        // 以下静态的,都是类相关的,访问时采用“类名.”的方式访问。不需要new对象。
        // 不需要对象的参与即可访问。没有空指针异常的发生。
        // 成员变量中的静态变量
        static int k;
    
        // 静态方法
        public static void m1(){
            // 局部变量
            int m = 100;
        }
        
    }
    那么变量在什么情况下会声明为静态变量呢?
    • 当一个类的所有对象的某个“属性值”不会随着对象的改变而变化的时候,建议将该属性定义为静态属性(或者说把这个变量定义为静态变量),静态变量在类加载的时候初始化,存储在方法区当中,不需要创建对象,直接通过“类名”来访问。

    静态变量的调用

    • 静态的:建议使用“类名.”来访问,但使用“引用.”也行(不建议使用"引用.")。静态的如果使用“引用.”来访问会让程序员产生困惑:程序员以为是实例的呢。
    • 空指针异常只有在什么情况下才会发生呢?只有在“空引用”访问“实例”相关的,都会出现空指针异常。

    静态方法 

    方法在什么情况下会声明为静态的呢?
    • 方法实际上描述的是行为动作,我认为当某个动作在触发的时候需要对象的参与,这个方法应该定义为实例方法,例如:每个高中生都有考试的行为,但是你考试和学霸考试最终的结果是不一样的,一个上了“家里蹲大学”,一个上了“清华大学”,显然这个动作也是需要对象参与才能完成的,所以考试这个方法应该定义为实例方法。实例成员必须要创建对象才能访问。
    • 当方法体中需要直接访问当前对象的实例变量或者实例方法的时候,该方法必须定义为实例方法,因为只有实例方法中才有 this,静态方法中不存在 this。
    • 在实际的开发中,“工具类”当中的方法一般定义为静态方法,因为工具类就是为了方便大家的使用,将方法定义为静态方法,比较方便调用,不需要创建对象,直接使用类名就可以访问。

    被修饰后的成员具备以下特点:

    • 随着类的加载而加载
    • 优先于对象存在
    • 修饰的成员,被所有对象所共享
    • 访问权限允许时,可不创建对象,直接被类调用

    非静态的成员方法的访问特点

    • 能访问静态的成员变量
    • 能访问非静态的成员变量
    • 能访问静态的成员方法
    • 能访问非静态的成员方法

    静态的成员方法

    • 能访问静态的成员变量
    • 能访问静态的成员方法

    总结成一句话就是:

    • 静态成员方法只能访问静态成员

    静态代码块

    静态代码块的语法格式是这样的: 

    特点

    • 静态代码块在类加载时执行,并且只执行一次。
    • 态代码块实际上是 java 语言为程序员准备的一个特殊的时刻,这个时刻就是类加载时刻,如果你想在类加载的时候执行一段代码,那么这段代码就有的放矢了。例如我们要在类加载的时候解析某个文件,并且要求该文件只解析一次,那么此时就可以把解析该文件的代码写到静态代码块当中了。
    • 一个类当中可以编写多个静态代码块(尽管大部分情况下只编写一个),并且静态代码块遵循自上而下的顺序依次执行,所以有的时候放在类体当中的代码是有执行顺序的(大部分情况下类体当中的代码没有顺序要求,方法体当中的代码是有顺序要求的,方法体当中的代码必须遵守自上而下的顺序依次逐行执行),另外静态代码块当中的代码在 main 方法执行之前执行,这是因为静态代码块在类加载时执行,并且只执行一次。
    /*
        1、使用static关键字可以定义:静态代码块
        2、什么是静态代码块,语法是什么?
            static {
                java语句;
                java语句;
            }
        3、static静态代码块在什么时候执行呢?
            类加载时执行。并且只执行一次。
            静态代码块有这样的特征/特点。
    
        4、注意:静态代码块在类加载时执行,并且在main方法执行之前执行。
    
        5、静态代码块一般是按照自上而下的顺序执行。
    
        6、静态代码块有啥作用,有什么用?
            第一:静态代码块不是那么常用。(不是每一个类当中都要写的东西。)
            第二:静态代码块这种语法机制实际上是SUN公司给我们java程序员的一个特殊的时刻/时机。
            这个时机叫做:类加载时机。
    
        具体的业务:
            项目经理说了:大家注意了,所有我们编写的程序中,只要是类加载了,请记录一下
            类加载的日志信息(在哪年哪月哪日几时几分几秒,哪个类加载到JVM当中了)。
            思考:这些记录日志的代码写到哪里呢?
                写到静态代码块当中。
            
    */
    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!
    */

    注意:

    静态代码块在类加载时执行,静态变量在类加载时初始化,它们在同一时间发生,所以必然会有顺序要求,如果在静态代码块中要访问 i 变量,那么 i 变量必须放到静态代码块之前。

    实例代码块

    /*
    1、除了静态代码块之外,还有一种语句块叫做:实例语句块
    2、实例语句在类加载是并没有执行。
    3、实例语句语法?
        {
            java语句;
            java语句;
            java语句;
        }
    4、实例语句块在什么时候执行?
        只要是构造方法执行,必然在构造方法执行之前,自动执行“实例语句块”中的代码。
        实际上这也是SUN公司为java程序员准备一个特殊的时机,叫做对象构建时机。
    */
    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("有参数的构造方法");
        }
    
    }

    代码的执行顺序练习题

    //判断以下程序的执行顺序
    public class CodeOrder{
        
        // 静态代码块
        static{
            System.out.println("A");
        }
    
        // 入口
        // A X Y C B Z
        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");
        }
    
    }

    知识框架

    this 是什么

    • this 可以看做一个变量,它是一个引用,存储在 Java 虚拟机堆内存的对象内部,this 这个引用保存了当前对象的内存地址指向自身,任何一个堆内存的 java 对象都有一个 this,也就是说创建 100 个 java 对象则分别对应 100 个 this。
    • this 指向“当前对象”,也可以说 this 代表“当前对象”,this 可以使用在实例方法中以及构造方法中,语法格式分别为“this.”和“this(..)”。
    • this不能出现在 static的方法当中,这是为什么呢?首先static 的方法,在调用的时候是不需要创建对象的,直接采用“类名”的方式调用,也就是说static 方法执行的过程中是不需要“当前对象”参与的,所以 static 的方法中不能使用 this,因为 this 代表的就是“当前对象”。
    代码举例
    /*
        this:
            1、this是一个关键字,全部小写。
            2、this是什么,在内存方面是怎样的?
                一个对象一个this。
                this是一个变量,是一个引用。this保存当前对象的内存地址,指向自身。
                所以,严格意义上来说,this代表的就是“当前对象”
                this存储在堆内存当中对象的内部。
    
            3、this只能使用在实例方法中。谁调用这个实例方法,this就是谁。
            所以this代表的是:当前对象。
    
            4、“this.”大部分情况下是可以省略的。
    
            5、为什么this不能使用在静态方法中??????
                this代表当前对象,静态方法中不存在当前对象。
    */
    public class ThisTest01{
        public static void main(String[] args){
    
            Customer c1 = new Customer("张三");
            c1.shopping();
    
            Customer c2 = new Customer("李四");
            c2.shopping();
    
            Customer.doSome();
        }
    }
    
    // 顾客类
    class Customer{
    
        // 属性
        // 实例变量(必须采用“引用.”的方式访问)
        String name;   
    
        //构造方法
        public Customer(){
        
        }
        public Customer(String s){
            name = s;
        }
    
        // 顾客购物的方法
        // 实例方法
        public void shopping(){
            // 这里的this是谁?this是当前对象。
            // c1调用shopping(),this是c1
            // c2调用shopping(),this是c2
            //System.out.println(this.name + "正在购物!");
    
            // this. 是可以省略的。
            // this. 省略的话,还是默认访问“当前对象”的name。
            System.out.println(name + "正在购物!");
        }
    
        // 静态方法
        public static void doSome(){
            // this代表的是当前对象,而静态方法的调用不需要对象。矛盾了。
            // 错误: 无法从静态上下文中引用非静态 变量 this
            //System.out.println(this);
        }
    }
    
    
    class Student{
    
        // 实例变量,怎么访问?必须先new对象,通过“引用.”来访问。
        String name = "zhangsan";
    
        // 静态方法
        public static void m1(){
            //System.out.println(name);
    
            // this代表的是当前对象。
            //System.out.println(this.name);
    
            // 除非你这样
            Student s = new Student();
            System.out.println(s.name);
    
        }
    
        //为什么set和get方法是实例方法?
        public static void setName(String s){
            name = s;
        }
        public String getName(){
            return name;
        }
    
        // 什么时候方法定义为实例方法,什么时候定义为静态方法?
        // 如果方法中直接访问了实例变量,该方法必须是实例方法。
    }

    this 的使用

    在实例方法中,或者构造方法中,为了区分局部变量和实例变量,这种情况下:this. 是不能省略的。

    /*
    1、this可以使用在实例方法中,不能使用在静态方法中。
    2、this关键字大部分情况下可以省略,什么时候不能省略呢?
        在实例方法中,或者构造方法中,为了区分局部变量和实例变量,
        这种情况下:this. 是不能省略的。
    */
    public class ThisTest03{
        public static void main(String[] args){
    
            Student s = new Student();
            s.setNo(111);
            s.setName("张三");
            System.out.println("学号:" + s.getNo());
            System.out.println("姓名:" + s.getName());
    
            Student s2 = new Student(2222, "李四");
            System.out.println("学号:" + s2.getNo());
            System.out.println("姓名:" + s2.getName());
    
        }
    }
    
    // 学生类
    class Student{
        //学号
        private int no;
    
        //姓名
        private String name;
    
        //构造方法无参
        public Student(){
        
        }
    
    
        // 上面的有参构造方法也增强以下可读性
        public Student(int no, String name){
            this.no = no;
            this.name = name;
        }
    
    
        public void setNo(int no){ 
            //no是局部变量
            //this.no 是指的实例变量。
            this.no = no; // this. 的作用是:区分局部变量和实例变量。
        }
        public int getNo(){
            return no;
            //return this.no;
        }
        
        public void setName(String name){
            this.name = name;
        }
    
    
    
        public String getName(){ // getName实际上获取的是“当前对象”的名字。
            //return this.name; // 严格来说,这里是有一个 this. 的。只不过这个 this. 是可以省略的。
            return name;
        }
    }
    this 还有另外一种用法,使用在构造方法第一行(只能出现在第一行,这是规定,记住就行),通过当前构造方法调用本类当中其它的构造方法,其目的是为了代码复用。调用时的语法格式是:this(实际参数列表)
    /*
        1、this除了可以使用在实例方法中,还可以用在构造方法中。
        2、新语法:通过当前的构造方法去调用另一个本类的构造方法,可以使用以下语法格式:
            this(实际参数列表);
                通过一个构造方法1去调用构造方法2,可以做到代码复用。
                但需要注意的是:“构造方法1”和“构造方法2” 都是在同一个类当中。
    
        3、this() 这个语法作用是什么?
            代码复用。
        
        4、死记硬背:
            对于this()的调用只能出现在构造方法的第一行。
    */
    public class ThisTest04{
        public static void main(String[] args){
            // 调用无参数构造方法
            Date d1 = new Date();
            d1.detail();
    
            // 调用有参数构造方法
            Date d2 = new Date(2008, 8, 8);
            d2.detail();
        }
    }
    
    /*
    需求:
        1、定义一个日期类,可以表示年月日信息。
        2、需求中要求:
            如果调用无参数构造方法,默认创建的日期为:1970年1月1日。
            当然,除了调用无参数构造方法之外,也可以调用有参数的构造方法来创建日期对象。
    */
    class Date{ // 以后写代码都要封装,属性私有化,对外提供setter and getter
        //
        private int year;
        //
        private int month;
        //
        private int day;
    
        // 构造方法无参
        // 调用无参数构造方法,初始化的日期是固定值。
        public Date(){
            //错误: 对this的调用必须是构造器中的第一个语句
            //System.out.println(11);
            this(1970, 1, 1);
        }
        // 构造方法有参数
        public Date(int year, int month, int day){
            this.year = year;
            this.month = month;
            this.day = day;
        }
    
        // 提供一个可以打印日期的方法
        public void detail(){
            //System.out.println(year + "年" + month + "月" + day + "日");
            System.out.println(this.year + "年" + this.month + "月" + this.day + "日");
        }
    
        //setter and getter
        public void setYear(int year){
            // 设立关卡(有时间可以设立关卡)
            this.year = year;
        }
        public int getYear(){
            return year;
        }
        public void setMonth(int month){
            // 设立关卡(有时间可以设立关卡)
            this.month = month;
        }
        public int getMonth(){
            return month;
        }
        public void setDay(int day){
            // 设立关卡(有时间可以设立关卡)
            this.day = day;
        }
        public int getDay(){
            return day;
        }
    }

    总结一下this的用法

  • 相关阅读:
    JS中常遇到的浏览器兼容问题和解决方法
    遍历
    深度克隆和浅拷贝
    js数据类型
    js运算符
    理解js中的事件模型
    常见事件总结
    模板方法模式
    适配器模式和外观模式
    命令模式
  • 原文地址:https://www.cnblogs.com/wurengen/p/13252890.html
Copyright © 2011-2022 走看看