zoukankan      html  css  js  c++  java
  • 关键字之this和super

    经常会在程序中用到同名变量或方法,区分对了才能正确引用,得到所要的结果,这通常得要靠this和super了;

    在说明这两个关键字之前先做些准备:

    1、扩展类会继承基类的方法和变量,在内存中为其开辟空间;

    2、对于变量x,java的搜索顺序:局部变量 => 本类成员变量 => 直接父类成员变量 => 间接父类成员变量 => …… => java.lang.Object类变量;

    现在,来看个例子:

    class A{
        int x;
        A(int x){
            x=x;
            System.out.println(x);
        }
    }
    按照上面说的搜索顺序,构造函数体中的变量x指的都是形参,这与我们的本意可能就不相符,为了给成员变量x赋值并输出之,通常可以作如下改变:

    A(int x){
        this.x=x;
        System.out.println(this.x);
    }
    这里我们使用了关键字this,this指代的是调用本方法/变量的本类实例,这样就将成员变量跟形参进行了区分;

    既然指代的是实例,那实例自然可以调用变量以及方法,因此,this通常有如下用法:

    • 调用本类实例变量:this.x; //x为实例变量,对于类变量,通常不建议通过 “实例名.变量名” 的方式来调用;
    • 调用本类实例方法:this.f([para1,……]);   //这跟上一点是一个意思,都指代本类实例,自然可以调用方法和变量;
    • 调用构造函数:this([para1,……]);  //将构造函数单独列出,可以是无参或带参的;
    既然涉及到"实例",那有些地方就不能使用:static方法,我们都知道static方法都是属于类的,可以使用类名直接进行调用,不依赖实例而存在,二者的内存空间不一样,可以这样简单验证下:
    假设static方法可以直接引用实例变量,存在这种可能:在未建立实例前即引用类方法,这自然会产生错误;
    因此在static代码块/方法中不允许使用this;
    this在内部类中的应用也比较频繁,内部类可以共享外部类的成员变量,同样存在同名变量的可能,如下代码所示:
    class B{
        int x=1;
        class C{
            int x=2;
            void f(){
                int x=3;
                System.out.println(x);//3
                System.out.println(this.x);//2
                System.out.println(B.this.x);//1
            }
        }
    }
    其中this.x的写法等效于C.this.x,在引用外部类成员变量时可以运用该种写法,当然new出一个实例也OK;
    在涉及到继承关系时,就会使用到另一个关键字super,虽然扩展类继承了基类的变量/方法,但若扩展类中存在同名变量/方法,则在引用时自然也只能调用到扩展类的成员;
    我们直到继承时,扩展类建立对象时也在内存中为基类开辟了内存区,因此基类的同名变量/方法并没有被重写,只是被隐藏了,类似this的使用,我们通过super来调用他们;
    super通常有如下限定:
    • 用于扩展类中调用基类被隐藏的实例变量/方法(private修饰的自然是引用不到的);
    • 扩展类的构造方法须引用基类构造方法,并且super([para1,……])语句需放在执行体第一行;
    • 扩展类构造方法中若调用基类无参构造方法,则可默认省略不写;
    参考this,可知super有如下用法:
    • 调用基类实例变量:super.x;
    • 调用基类实例方法:super.f([para1,……]);
    • 调用基类构造函数:super([para1,……]);
    在《Java语言规范》中解释道,super.x,实际指代的是本类当前对象的成员变量x,若假设当前类的基类为A,则super.x会被看成犹如:((A)this).x;因此下面代码输出是一样的:
    class A{
        int x=1;
    }
    
    class B extends A{
        int x=2;
        {
            System.out.println(super.x);//1
            System.out.println(((A)this).x);//1
        }
    }
    最后还是得再强调super也是实例相关的关键字,不能用于static修饰的方法或代码块中,否则会引起编译错误;

  • 相关阅读:
    java并发容器
    五种单例模式的写法
    Java中Volatile关键字
    Future模式实例
    mysql笔记
    亚马逊EC2服务器登录方法
    RSA加密方法java工具类
    Base64Util工具类
    maven命令创建项目
    关于spring事务注解
  • 原文地址:https://www.cnblogs.com/lynxz0620/p/4384932.html
Copyright © 2011-2022 走看看