0
点赞
收藏
分享

微信扫一扫

this和static关键字

凯约 2022-04-29 阅读 85

文章目录

1.this关键字

1) this关键字在内存中的位置

先看一段代码

public class Customer {
	private String name;
	public Customer(){
	}
	public Customer(String _name){
		name = _name;
	}
	public void setName(String _name){
		name = _name;
	}
	public String getName(){
		return name;
	}
}
public class CustomerTest {
	public static void main(String[] args) {
		Customer jack = new Customer("jack");
	}
}

以上代码在内存中的活动图为(16进制以0x开头,2进制以0b开头,8进制以0开头)

在这里插入图片描述

在图中可以看出,this是一个引用,它存储在Java虚拟机堆内存的对象内部,this这个引用保存了当前对象的内存地址,指向自身。任何一个堆内存的Java对象都有一个this。即this代表当前对象,this可以使用在实例方法和构造方法中,this不能出现在带有static的方法中。

2) this在实例方法和实例变量中的使用

  1. static的方法中不能使用this

    被static修饰的方法称为静态方法,静态方法调用时使用-类名.方法名-调用,不需要创建对象,而this关键字代表的是当前对象,此处冲突。

    为什么set、get方法设计为实例方法呢?(不被static修饰)

    因为set、get方法操作的是实例变量,"不同对象"调用get方法得到的数据是不同的,强调的是对象,显然调用该方法不能用类名.方法名调用,必须先创建对象,再通过引用去访问

  2. this可以出现在实例方法中,它指向当前调用这个方法的对象

    因为通过对象名.方法名调用实例方法,此时一定会提前创建对象,用对象去触发实例方法,实例方法一定要对象才可以调用,而恰好this关键字又代表当前对象,存储在Java虚拟机堆内存的对象内部,即对象的内部。

  3. 在实例方法中可以直接访问当前对象的实例变量,而this是可以省略的,而在set、get方法中的不能省略。

    public class Customer{
        private String name;
        public Customer(String name){
            this.name=name;
        }
        public void setName(String name){
            this.name=name;
    //this.name代表的是实例变量,而那么、代表的是局部变量,如果this省略根据就近原则,省略this后的name为局部变量
        }
        public String getName(){
            return this.name;
        }
        public voif shopping(){
            System.out.println(name);
            System.out.println(this.name);
        }
            
    }
    public class Test{
        public static void main(String[] args){
            Customer c=new Customer("jack");
            c.shopping();
        }
    }
    
    //输出的结果是
    jack
    jack
    

从以上代码可知,name和this.name输出的结果是想等的。即当实例方法中要访问实例变量时,可直接通过实例变量名来访问,也可以使用"this."来访问,也就是说在实例方法中访问实例变量时"this."可以省略

  1. 在一个实例方法中可以直接调用其他的实例方法("this."省略),也可以使用this.方法名调用,相当于对象.方法名.

    public class Customer{
        private String name;
        public Customer(String name){
            this.name=name;
        }
        public void setName(String name){
            this.name=name;
        }
        public String getName(){
            return this.name;
        }
        public void shopping(){
            System.out.println(name);
            System.out.println(this.name);
            System.out.println("调用其他的实例方法"+this.pay());
              System.out.println("调用其他的实例方法"+pay());
        }
        public void pay(){
            System.out.println("支付方法");
        }
            
    }
    public class Test{
        public static void main(String[] args){
            Customer c=new Customer("jack");
            c.shopping();
        }
    }
    
  2. 在main方法中无法直接访问实例方法和实例变量

    实例方法要通过对象.方法名或变量名调用(通过引用去访问),而main方法为static类型的,属于类,在类加载的时候执行。在执行main方法时,如对象还没有被创建,所以就还没有"this",因为"this"代表当前对象,没有对象所以不能用this,也就不能直接访问实例方法或变量 。

    public class Test{
        public void M(){
            System.out.println("实例方法");
        }
        public static void main(String[] args){
          M();//次数出现编译错误,因为不能直接使用实例方法
          new Test().M();//正确调用
        }
    }
    
    
    
    
    
    public class Test{
        int i=10;
        public static void main(String[] args){
          System.out.println(i);//次数出现编译错误,因为不能直接使用实例变量
          System.out.println(new Test().i);//正确调用
        }
    }
    

3) this在构造方法中的使用

  1. 在构造方法中的第一行,用来调用本类中其他的构造方法

    public class Customer{
        private String name;
        public Customer(){
            this("jack");
        }
        public Customer(String name){
            this.name=name;
        }
    }
    //根据this()的括号中传入的参数来选择相应的构造方法
    //this(实际参数列表);
    

2.static关键字

1) static介绍

  1. static 表示静态的,属于类,随着类的加载而加载,优先于对象存在
  2. 可以修饰方法、变量、代码块等,修饰的可以在它所在的类创建对象之前被访问。修饰的方法称为静态方法,修饰的变量称为静态变量,修饰的代码块称为静态代码块

2)静态变量

java中的变量分为局部变量、成员变量(实例变量)和类变量(静态变量)。局部变量存在于栈中,成员变量(实例变量)存在于堆中、静态变量存在于方法区中。实例变量在构造方法执行过程中初始化,静态变量在类加载时初始化。被static修饰的成员变量为静态变量,不需要创建对象就可以被调用(调用方式:类名.变量名)。

(1)变量在什么情况下会声明为静态变量

当一个类的所有的对象的某个变量(属性)的值不会随着对象的改变而改变时,可将该变量设定为静态变量(静态属性)

例如:有一个类它的出生年份都是2000年,每个对象的姓名和ID号都不同。

修改前:

class Student {
    private String name;
    private int id;
    private String year;

    public Student() {

    }

    public Student(String name, int id, String year) {
        this.name = name;
        this.id = id;
        this.year = year;
    }

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

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

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +'\'' +
                ", year=" + year+
                '}';
    }

    public static void main(String[] args) {
        Student s1=new Student();
        s1.setId(1);
        s1.setName("张三1");
        s1.setYear("2000");
        Student s2=new Student();
        s2.setId(2);
        s2.setName("张三2");
        s2.setYear("2000");
        Student s3=new Student();
        s3.setId(3);
        s3.setName("张三3");
        s3.setYear("2000");
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
    }
}

修改后:

class Student {
    private String name;
    private int id;
    private  static String year="2000";

    public Student() {

    }

    public Student(String name, int id, String year) {
        this.name = name;
        this.id = id;
        this.year = year;
    }

    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

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

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +'\'' +
                ", year=" + Student.year+
                '}';
    }

    public static void main(String[] args) {
        //若将年份设置为静态变量
        Student s1=new Student();
        s1.setId(1);
        s1.setName("张三1");
        Student s2=new Student();
        s2.setId(2);
        s2.setName("张三2");
        Student s3=new Student();
        s3.setId(3);
        s3.setName("张三3");
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);

    }
}

输出的结果均为

Student{name='张三1', id=1', year=2000}
Student{name='张三2', id=2', year=2000}
Student{name='张三3', id=3', year=2000}

(2) 可以用引用来访问静态变量吗?可以的话,这个访问和具体的对象有什么关系?

//使用上一例子的代码
Student s1=new Student();
System.out.println(s1.year);
//输出的结果为2000

3)静态代码块

class Student {
    static{
        System.out.println(m);//此处会报错因为静态代码块和静态变量同时执行时,执行顺序遵循从上到下依次执行的原则。所以先执行此处的代码,但是执行此处代码时m并没有被定义。
    }
    static int m=0;
    static{
        System.out.println("静态代码块1");
    }

    public static void main(String[] args) {
        System.out.println("main方法");

    }
    static{
        System.out.println("静态代码块2");
    }
}
class Student {
    static int m=0;
    static{
        System.out.println("静态代码块1");
    }
    static{
        System.out.println(m);
    }

    public static void main(String[] args) {
        System.out.println("main方法");

    }
    static{
        System.out.println("静态代码块2");
    }
}
//执行结果
/*
静态代码块1
0
静态代码块2
main方法
*/
class Student {

    static int m=0;
    static{
        System.out.println("静态代码块1");
    }

    static{
        System.out.println(m++);
    }

    public static void main(String[] args) {
        System.out.println("main方法");
        System.out.println(m);
    }
    static{
        System.out.println("静态代码块2");
    }
}
//
/*
静态代码块1
0
静态代码块2
main方法
1
*/

4)静态方法

什么情况下要将方法设置为静态方法?方法描述的是行为,当某一行为不需要对象就可以触发时,可以将该方法设置为静态方法。或者在方法中不需要使用"当前对象"这一概念时,可以设置为静态方法。

3.this与static相关案例题

小编正在补充中……
在这里插入图片描述

举报

相关推荐

0 条评论