【Java基础篇】第十一章 this和static

有时候,不是因为你没有能力,也不是因为你缺少勇气,只是因为你付出的努力还太少,所以,成功便不会走向你。而你所需要做的,就是坚定你的梦想,你的目标,你的未来,然后以不达目的誓不罢休的那股劲,去付出你的努力,成功就会慢慢向你靠近。

导读:本篇文章讲解 【Java基础篇】第十一章 this和static,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

⭐⭐⭐Java基础篇目录⭐⭐⭐


🍁 第一章 Java开发环境搭建
🍁 第二章 标识符与关键字
🍁 第三章 变量
🍁 第四章 数据类型
🍁 第五章 运算符
🍁 第六章 控制语句
🍁 第七章 方法
🍁 第八章 认识面向对象
🍁 第九章 对象的创建和使用
🍁 第十章 封装
🍁 第十一章 this和static
🍁 第十二章 继承
🍁 第十三章 方法的覆盖和多态
🍁 第十四章 super

在这里插入图片描述

1、static关键字

关于static关键字:

  • static 静态的,所有static修饰的,都是类相关的,类级别的
  • 所有static修饰的,都采用 类名. 的方式访问
  • static修饰的变量为静态变量,存储在方法区
  • static修饰的方法是静态方法
    在这里插入图片描述

2、静态变量

被static修饰的变量即静态变量,存储在方法区,在类加载时完成初始化,不需要new对象,其空间就开辟出来了。

静态变量的使用场景:

  • 若某个属性一个对象一份,则用实例变量,存堆区,如姓名、身份证号
  • 若某个属性所有对象都相同,则用静态变量,存方法区,如国籍
    这样只在方法区保存一份,可避免不必要的内存空间浪费

在这里插入图片描述
在这里插入图片描述
静态变量的访问:

//正确访问姿势是通过类名.
Chinese c1 = new Chinese();
System.out.println(Chinese.country);

//使用引用.来访问静态变量也不会报错,但不建议这样用
//这里不会出现空指针异常,会转化成类名.xx
c1 = null;
System.out.println(c1.country);

空指针异常只有在“空引用”访问“实例”相关的时候,才会出现。

在这里插入图片描述
在这里插入图片描述

什么时候定义的是实例方法?什么时候定义的是静态方法?

如果方法体中需要访问实例变量,则这个方法只能定义成实例方法。如果写成静态方法,而此时无对象,无法去访问实例变量—error:无法从静态上下文中引用非静态变量。
在这里插入图片描述

3、静态代码块

关于静态代码块:

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

static {
	java语句1;
	java语句2;
}

  • 静态代码块在类加载时执行,且执行一次,存方法区(方法区中存.class等代码片段)
  • 静态代码块在main方法执行之前就执行,多个静态代码块则从上而下执行
  • 静态代码块是SUN公司给的一个特殊实际–类加载时机,如可用于记载类加载的日志信息
    在这里插入图片描述
public class StaticTest {
    static int var = 1;
    static{
        System.out.println(var);
    }

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

执行结果:
在这里插入图片描述

适当改一下静态变量和静态代码块的定义顺序

public class StaticTest {

    static{
        System.out.println(var);
    }
    //后定义静态变量,而先定义的静态代码块中已经访问了它
    static int var = 1;

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

}

运行结果:
在这里插入图片描述
😉

静态变量和静态代码块都在类加载时执行,谁先谁后,看代码顺序自上而下。

在这里插入图片描述

截至目前,有自上而下顺序要求的有:

  • 对于一个方法,方法体中的代码自上而下(两个方法的定义是无先后顺序的)
  • 静态代码块1和静态代码块2自上而下
  • 静态代码块和静态变量自上而下

4、实例代码块

实例代码块的定义:

{
  java语句1;
  java语句2;
}

构造方法执行之前,实例代码块必然在构造方法之前自动执行一次。

这是SUN公司准备的又一个特殊时机—-对象构建时机

在这里插入图片描述
在这里插入图片描述

5、this

this的总结:

  • this是一个关键字,全部小写。
  • 一个对象,一个this,this是一个变量,是一个引用。
  • this保存当前对象的内存地址,指向自身,所以严格意义上来说,this代表的就是当前对象。
  • this存储在堆内存当前对象内部。
  • this只能出现在实例方法中,哪个对象(的引用)调用这个实例方法,this就是谁,所以,this代表的是当前对象。(所以static方法中无this一说)
    在这里插入图片描述
//定义一个顾客类,此处再回味:类=属性+方法
public class Customer {
    String name;

    public Customer(){
        
    }

    public Customer(String name) {
        this.name = name;
    }
    
    //定义用户购物的方法
    public void shopping(){
        System.out.println(name+"正在购物");
        //实例变量name的访问为何没使用引用.xx
    }
}

程序分析:
实际此处省略了this,this用于实例方法中,代表当前对象。

System.out.println(this.name+"正在购物");

当对象(的引用)c1调用实例方法shopping,则this就是c1,当对象c2调用shopping时,this就是c2。不用this,你直接写c1.name+“正在购物”,且不论c1是局部变量,这样写一个本来所有对象都能用的实例方法就被写死了。

在这里插入图片描述

到此也就解释了为啥直接的Setter和Getter不能是静态方法,里面要return 属性或者set 属性,即访问实例变量,有对象的概念,this.name=name;

在这里插入图片描述

//创建男人类
public class Man {
    String idCard;
    String name;
    static boolean sex = true;
    //引用数据类型.未初始化时,值为null.实例变量
    Woman woman;

    public Man() {
    }

    public Man(String idCard, String name, Woman woman) {
        this.idCard = idCard;
        this.name = name;
        this.woman = woman;
    }

    public Man(String idCard, String name) {
        this.idCard = idCard;
        this.name = name;

    }
}
--------------------

//创建女人类
public class Woman {
    String idCard;
    String name;
    static boolean sex = false;
    Man man;
    public Woman(){

    }

    public Woman(String idCard, String name) {
        this.idCard = idCard;
        this.name = name;
    }

    public Woman(String idCard, String name, Man man){
        this.idCard = idCard;
        this.name = name;
        this.man = man;
    }
}
----------------------
//创建测试类
public class ManTest {

    public static void main(String[] args) {
        Man man = new Man("123","llg");
        Woman woman = new Woman("456","wife");
        //注意这里引用数据类型的初始化
        man.woman = woman;
        woman.man = man;
        System.out.println(man.name+"的妻子是"+man.woman.name);

    }
}


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//测试类
public class Practice {
    public static void main(String[] args) {
        Book book = new Book("Java基础",199);
        book.detail();
    }
}

//书籍类
class Book {
    private String name;
    private int page;

    public Book() {
    }

    public Book(String name, int page) {
        this.name = name;
        if (this.page < 200) {
            System.out.println("页数少于200,自动变为200");
            this.setPage(200);
            //第一次忘记加return了,结果page一直没改好
            return;
        }
        this.page = page;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
    public void setPage(int page){
        this.page = page;
    }
    public int getPage(){
        return this.page;
    }
    public void detail(){
        System.out.println("书名:"+name+",页数:"+page);
    }
}

运行结果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
Java中的三大变量整理:

变量类型 存储位置 何时初始化
局部变量 栈区 方法执行过程中开辟空间
实例变量(成员变量) 堆区 构造方法执行时,或者说对象创建时开辟空间
静态变量(成员变量) 方法区 类加载时初始化并开辟空间

在这里插入图片描述

在实例方法或构造方法中,为了区分方法中的局部变量和实例变量,this不能省略。this.name = name;

在这里插入图片描述

6、this在构造方法中的妙用

构造方法需要初始化一个固定值,可使用this(xx,xx,xx)调用有参构造方法做为这个构造方法的方法体。

//无参构造
public Date(){
	this.year = 2022;
	this.month = 10;
	this.day = 25;
}

等价于
public Date(){
	this(2022,10,25);
}

此处this的作用是代码复用,有构造方法调用构造方法的效果。注意,这种this语句必须是构造器中的第一个语句,这样自然也就只能出现一次(否在总有一个当第二行)。

//这样的写法error

public Date(){
	System.out.println("Hello World!");
	this(2022,10,25);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
😃

this的全部总结:

😃

  • this是一个关键字,是一个引用,保存了对象的内存地址,指向自身。
  • this可以使用在实例方法,也可使用在构造方法中。
  • this出现在实例方法中,代表的是当前对象。
  • this不能使用在静态方法中。(静态方法用类名.调用,无对象概念,而this与对象挂钩)
  • this在大部分情况中可以省略,如实例方法中访问实例变量不用加this。但用于区分实例变量和局部变量时不能省略。
  • this(实参列表)的语法,只能出现在构造方法中的第一行,表示当前构造方法调用本类的其他构造方法,目的是代码复用。
    在这里插入图片描述
public class Practice2 {
    public static void main(String[] args) {
        Account account = new Account(10001,2000,0.0123);
        Customers customer = new Customers("Smith",account);
        customer.getAccount().deposit(100);
        customer.getAccount().withdraw(960);
        customer.getAccount().withdraw(2000);
        //这里访问顾客对象的account属性,不能customer.account
        //因为出了Customers类了,private属性只能通过Getter
        //customer.getAccount()即account,即Account类的对象
        //属性是一个引用,这个引用又能指向另外一个对象,从而调用另外一个对象中的方法
        //这样,两个对象就可以组合起来去描述模拟现实生活中的场景了
    }

}

/**
 * 账户类
 */
class Account{
    private int id;
    private double balance;
    private double annualInterestRate;

    public Account() {
    }
    public Account(int id,double balance,double annualInterestRate){
        this.id = id;
        this.balance = balance;
        this.annualInterestRate = annualInterestRate;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public double getAnnualInterestRate() {
        return annualInterestRate;
    }

    public void setAnnualInterestRate(double annualInterestRate) {
        this.annualInterestRate = annualInterestRate;
    }

    /**
     * llg
     * 取款方法
     * @param money
     */
    public void withdraw(double money){
        System.out.println("您当前账户余额:"+balance);
        if(balance-money<0){
            System.out.println("余额不足");
            return;
        }
        balance = balance-money;
        //setBalance(this.getBalance()-money);也可以
        System.out.println("取款"+money+",余额:"+balance);

    }

    /**
     * llg
     * 存款方法
     * @param money
     */
    public void deposit(double money){
        balance = balance+money;
        System.out.println("存款成功,存款金额:"+money+",当前余额:"+balance);

    }
}

/**
 * 顾客类
 */
class Customers{
    private String name;
    private Account account;
    public Customers(String name,Account account){
        this.name = name;
        this.account = account;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }
}


注意这里,同一个类里对余额这个private属性进行访问操作,我使用了引用.xx来完成,当然使用getBalance()方法更可以了。出了本类就只能用set和get了。

执行结果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

小结:

静态方法中访问实例变量或者调用实例方法—->new对象,引用.xxx
实例方法中访问静态变量或者调用静态方法—->类名.xxx,同一个类中类名可省略

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/146122.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!