Java必备基础四——成员变量和局部变量(static修饰变量详解、this关键字)(2021/10/15更新)

一、变量定义以及其存储与访问

1.变量总类

根据Java中定义变量位置的不同,变量有两大类:成员变量和局部变量,而成员变量里面根据有无static修饰又可分为类变量和实例变量

在这里插入图片描述

2.各变量定义

(1)成员变量:类中定义的变量(方法之外),用来描述对象的属性特征。
(2)局部变量:在类的方法中方定义的变量,用来保存临时数据。
(3)类变量:成员变量中,被static修饰符修饰的变量称为类变量,也叫静态变量
(4)实例变量:成员变量中,不被static修饰符稀修饰的变量称为实例变量

3.各变量区别

类变量实例变量局部变量
定义位置在类中,方法外在类中,方法外方法中,或者方法形式的参数
初始化值有默认初始化值有默认初始化值无定义,赋值后才能使用
调用方式对象调用,类名直接调用对象调用/
存储位置方法区堆中栈中
生命周期与类共存亡与对象共存亡与方法共存亡
别名静态变量//

解释:

  • 堆:此内存区域的唯一目的就是存放实例对象,几乎所有的实例对象都在这里分配内存(所有对象实例以及数组都要在堆上分配)
  • 栈:虚拟机栈,用于存放局部变量表,局部变量表存放了编译期可知长度的各种8大基本数据类型、对象引用(reference类型,它不同于对象本身,是对象在堆内存的首地址)。方法执行完,自动释放
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据

4.各变量注意点

  • 同一方法中不允许局部变量同名,不同方法中可以有同名的局部变量
  • 局部变量必须要有最初始值,成员变量可没有,后面方法里面有赋值也可行
  • 成员变量和局部变量同名时,局部变量有更高优先级
  • 类变量独立于该类的任何对象,被类的所有实例共享,即JVM只为类变量分配一次内存,在加载类的过程中即完成类变量的内存分配,可用类名或对象名直接访问:
类名.类变量名
实例名.类变量名
  • 实例变量可以在内存中有多个拷贝,即每创建一次实例,就会为实例变量分配一次内存,通过对象访问 :
实例名.实例变量名

举个例子说明三种变量

class Text {
    static int a;//类变量(静态变量)
    int b;//实例变量
}

public class TextForVariable {
    public static void main(String[] args) {
        int a = 10;//局部变量
        int b = 11;//局部变量
        a=12;
        b=13;
        Text.a = 1;
        Text text = new Text();
        text.a = 2;
        text.b = 2;
        Text text1 = new Text();
        text1.a = 3;
        text1.b = 3;
        System.out.println(a);
        System.out.println(b);
        System.out.println(Text.a);
        System.out.println(Text.a);
        System.out.println(text.a);
        System.out.println(text1.a);
        System.out.println(text.b);
        System.out.println(text1.b);

    }
}

输出的结果为:

12
13
3
3
3
3
2
3

可以看到,所有的类变量的值都为最后一次的赋值3;而实例变量可以多次赋值;局部变量也只能有一次最终的赋值。

二、代码块

  • 基本上代码块分为三种:static静态代码块、构造代码块、普通代码块
  • 代码块执行顺序为静态代码块>构造代码块>构造函数>普通代码块
  • 继承中代码块的执行顺序:父类静态块>子类静态块>父类代码块>父类构造器>子类代码块>子类构造器

1.静态代码块

(1)定义

static代码块也叫静态代码块,是在类中独立于类成员的static代码块

  • 使用格式:
static{
}
  • 几个小点
1static代码块只执行一次
2、静态块常用来执行类属性的初始化
3、静态块优先于各种代码块以及构造函数,一个类中可以有多个静态代码块,则按照书写顺序执行
4、静态代码快要独立于类成员,可以定义在类中的任何地方除了方法体中
5、静态代码可通过对象访问普通变量
(2)举例
public class TestStatic {
    private int b;
    private static int a;

    static {
        TestStatic.a = 6;//此处可直接写成a=6
        System.out.print(a + "\t");
        TestStatic ts = new TestStatic();
        ts.show();
        ts.b=200;
        System.out.print(ts.b+"\t");
    }

    public static void main(String[] args){}

    static {
        TestStatic.a=9;
        System.out.print(a+"\t");
    }

    void show(){
        System.out.print("abc"+"\t");
    }
}

输出结果:

6	abc	200	9
(3)分析

只要含有static关键字的类被加载,Java虚拟机就能根据类名找到它们。因此,static对象可以在类的任何对象创建之前访问,无须引用任何对象。所以静态代码块的存在在类加载的时候就自动运行了,而普通方法和静态方法都不能自动运行,前者需要对象,后者需要加载类之后才能调用,故static代码块优先于所有方法之前执行。

三、this关键字

1.代表当前对象

当this出现在某个方法体中,它可以代表当前类的任何一个实例对象。Leaf类setColor方法中的this可以代表Leaf类中的任何一个对象,只有这个方法被调用时,它所代表的具体对象才能被确定下来,此时谁在调用这个方法,this就代表谁。

class Leaf {
    private String color;
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
}

public class TestThis {
    public static void main(String[] args) {
        Leaf f1 = new Leaf();
        f1.setColor("红色");//此时setColor中的this代表的是f1这个实例
        System.out.println("第一片叶子是:"+f1.getColor()+"的");
        Leaf f2=new Leaf();
        f2.setColor("黄色");//此时setColor中的this代表的是f2这个实例
        System.out.println("第二片叶子是:"+f2.getColor()+"的");
    }
}

同理,出现在构造方法中时也是一样的,例如:

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

public class TestThis {
    public static void main(String[] args) {
       Student s1 = new Student("李红",22);
       Student s2 = new Student("王明",30);
    }
}


(1)当局部变量和成员变量相同时,成员变量会被隐藏,如果此时需要使用成员变量,则必须通过this来引用成员变量

class Fruit {
    String color = "绿色";
    public void harvest() {
        String color = "红色";
        System.out.println("这种水果收割时是红色:" + color);//此时color是局部变量
        System.out.println("原来是:" + this.color);//此时color是成员变量
    }
}

public class TestFruit {
    public static void main(String[] args) {
        Fruit fruit = new Fruit();
        fruit.harvest();
    }
}

(2)通过this调用成员方法

  void sing(){
        System.out.println("我会唱歌");
    }

    void dance(){
        this.sing();//可直接写成sing(),非静态调非静态时可直接调用
        System.out.println("我也会跳舞");
    }

2.调用当前类的其它构造方法

语法格式:

this([参数])
 class People{
        String name;
        int age;
        People(String name){
        this.name=name;
        }
        People(String name,int age){
        this(name);//调用了该类的带一个参数的构造方法
        this.age=ge
        }

四、类成员与实例成员的使用规则

如果使用static修饰某个方法,这个方法就成为静态方法或类方法,通过类名可直接访问。没有static方法修饰的是实例方法,需要通过对象对其访问。那么,如果一个类的成员变量和方法前都有static修饰,就统称该成员为类成员或静态成员,否则称为实例成员。

1.使用规则

  • 类方法可以直接引用类变量,但不能直接引用非静态变量
  • 类方法中使用非静态变量,要先创建类的对象,再通过对象访问非静态变量
  • 实例方法中,可以直接访问同类的非静态和静态变量
  • 静态方法中,不能使用this关键字, this是相对于某个对象而言的,static修饰的方法是相对于类的,因此不能在静态方法中用this

2.举例

public class TextStatic {
    static String a = "abc";
    String b = "java";

    void printValue() {
        System.out.println(a);
        System.out.println(b); //正确,实例方法中能直接调用非静态变量和静态变量
        this.b="2";//正确,非静态方法中可以使用this调用非静态方法;
    }

    public static void main(String[] args) {
        System.out.println(a);//静态方法中可直接访问静态变量
//        System.out.println(b); //错误,静态方法中不能直接调用非静态变量
        TextStatic textStatic = new TextStatic();
        System.out.println(textStatic.b);//静态方法中需要实例化对象才能访问非静态变量
        textStatic.printValue();//静态方法中调用非静态方法也需要实例化对象
        this.b="2";//错误,静态方法中不能使用this
    }
}

五、final修饰变量

  • final有不可改变,最终的意思,可以用来修饰非抽象类、成员方法和变量
  • 抽象类要被引用,所以不能用final修饰
  • final修饰的变量一旦被赋值就不可再改变,变量名称定义时一般用大写字母组成

1.final修饰成员变量

final修饰的成员变量只能被赋值一次,赋值后的其值不能再改变,一般通过两种方式指定最初始值。
(1) 被final修饰的变量在定义时,一般同时赋初值

 final int FUNCTION = 7; 	//正确		
 final int FUNCTION;
 FUNCTION=7;//错误		 		

(2)被final修饰的成员变量,如果没有在定义的同时赋初值则必须在构造方法中赋值

public class ExampleDemo {
    final float FUNCTION;//PI没有在定义的同时赋初值
    
    ExampleDemo(){
        FUNCTION=3.15f;//在构造方法中完成赋值
    }
    
    public static void main(String[] args){
        ExampleDemo exampleDemo = new ExampleDemo();
        System.out.println(exampleDemo.FUNCTION);
    }
}

这种先定义再在构造方法中赋值 的方式在使用上提供了更大的灵活性,这样的final成员变量可以根据对象不同而有所不同,却又可以保持不变的特性

2.final修饰局部变量

final修饰的局部变量必须被显式的赋初值,可以在定义时赋初值,也可以在后面的代码中赋值,但只能赋值一次。

public class ExampleDemo {
    public static void main(String[] args) {
        ExampleDemo exampleDemo = new ExampleDemo();
        exampleDemo.test();
    }

    public void test() {
        final int a;//局部变量a,需要的时候赋值
        final int b = 8;//局部变量b,定义的同时赋值
        a = 5;//只能赋值一次
        System.out.println(a);
        System.out.println(b);
    }
}

3.总结

final修饰的变量在使用之前必须被初始化,而且只能显式的赋值一次。

public class ExampleDemo {
    private final String A="final";
    private final int B=30;
    public static final int C=26;
    public final int E;
     //一个对象一个新的常量值
    public ExampleDemo(int x){
        E=x;
    }
    
    public static void main(String[] args) {
        ExampleDemo exampleDemo = new ExampleDemo(2);
        exampleDemo.C=50;//错误,final变量不能再次赋值
        System.out.println(exampleDemo.A);
        System.out.println(exampleDemo.B);
        System.out.println(ExampleDemo.C);
        System.out.println(exampleDemo.E);
        ExampleDemo exampleDemo1 = new ExampleDemo(3);
        System.out.println(exampleDemo1.E);//变量E因为对象的不同而不同
        exampleDemo1.test();
    }

    public void test() {
        final int a;//局部变量a,需要的时候赋值
        final int b = 8;//局部变量b,定义的同时赋值
        a = 5;//只能赋值一次
        System.out.println(a);
        System.out.println(b);
    }
}
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值