Java——变量作用域和生命周期

发布于:2024-06-16 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、作用域

1、作用域简介

在Java中,作用域(Scope)指的是变量、方法和类在代码中的可见性和生命周期。理解作用域有助于编写更清晰、更高效的代码。

2、作用域

块作用域(Block Scope):

块作用域是指在大括号 {} 内定义的变量的作用域。变量只在其定义的块内可见和有效,包括循环、条件语句和代码块。

方法作用域(Method Scope):

方法作用域指的是在方法内定义的变量的作用域。变量在整个方法内可见和有效。

类作用域(Class Scope):

类作用域指的是在类中定义的成员变量的作用域。成员变量在整个类内可见和有效。

二、全局变量和局部变量

1、全局变量

全局变量在Java中通常指的是类级别变量,或者说是类的属性。包括实例变量和静态变量。这些变量的作用域在整个类内,它们可以在类的所有方法中访问和修改。

1)实例变量

实例变量是类的非静态成员变量。它们属于类的每个实例,每个实例都有自己的一份实例变量。实例变量也是全局变量,在这个类的每一个方法中都能访问:

class Person {
	//全局变量,类的属性
	String name;
	int age;

	//构造方法
	public Person(String name, int age) {
		this.name = name;//在每个方法中都能访问到这个全局变量
		this.age = age;//在每个方法中都能访问到这个全局变量
	}
	//获取年龄
	public int getAge() {
		return age;//在每个方法中都能访问到这个全局变量
	}
	//设置年龄
	public void setAge(int age) {
		this.age = age;//在每个方法中都能访问到这个全局变量
	}
	//获取名字
	public String getName() {
		return name;//在每个方法中都能访问到这个全局变量
	}
	//设置名字
	public void setName(String name) {
		this.name = name;//在每个方法中都能访问到这个全局变量
	}
}

可以看到这里的属性或者说是全局变量在这个类的每一个方法中都能访问到。

2)静态变量

静态变量是使用static关键字声明的类变量。它们属于整个类,而不是任何特定实例。所有实例共享同一个静态变量。类的静态变量在这个类的每一个方法中都能访问:

public class MyClass {
    // 静态变量
    private static int staticVariable = 0;

    public MyClass() {
        staticVariable++;
    }

    public void printStaticVariable() {
        System.out.println(staticVariable);
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass obj1 = new MyClass();
        MyClass obj2 = new MyClass();

        obj1.printStaticVariable(); // 输出:2
        obj2.printStaticVariable(); // 输出:2
    }
}

2、局部变量

局部变量是在方法、构造函数或块中声明的变量。它们的作用域仅限于声明它们的方法、构造函数或块内,方法或块的执行结束后,局部变量将被销毁。

public class MyClass {
    public void myMethod() {
        // 局部变量
        int localVar = 100;
        System.out.println(localVar);
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.myMethod(); // 输出:100

        // System.out.println(localVar); // 错误,localVar在myMethod方法完成调用后就会被销毁
    }
}

这里就体现了对于定义在某个方法内的局部变量在方法调用结束后,就会被销毁。

class Cat {
	int age;

	//猫叫方法
	public void mewing() {
		String mew = "Mewing~";//这个mew就是局部变量,在mewing方法中定义,只能在mewing方法中使用
		System.out.println(mew);
	}

	//吃东西方法
	public void eat() {
		//System.out.println(mew);//在这里使用mewing方法中的局部变量mew是错误的
		//对于mew这个局部变量只能在mewing这个方法中使用
		
		//...
	}
}

这段代码体现了,定义在某个方法中的局部变量,只能在这个方法中使用,不能在其他方法中使用。

三、补充细节

1、全局变量和局部变量的赋值

全局变量可以不赋值,直接使用,因为它们有默认赋值,但是对于局部变量不赋值(不初始化)是不能使用的。

未初始化的全局变量:

public class Test {
	public static void main(String[] args) {
		Example example = new Example();
		example.foo();
	}
}

class Example {
	int a;//未赋值(未初始化)的全局变量,会被默认初始化为这个类型的默认值

	public void foo() {
		System.out.println(a);//使用这个未初始化的全局变量,它的值是默认值
	}
}

运行结果:

未初始化的局部变量:

public class Test {
	public static void main(String[] args) {
		Example example = new Example();
		example.foo();
	}
}

class Example {
	public void foo() {
		int a;//未赋值(未初始化)的局部变量
		System.out.println(a);//使用这个未初始化的局部变量,会报错
	}
}

运行结果:

2、全局变量和局部变量可以重名

在Java中,全局变量(类级别变量,包括实例变量和静态变量)和局部变量(方法、构造函数或块内声明的变量)是可以重名的,在访问时,遵循就近原则。尽管如此,这样做可能会导致代码混淆和难以维护,因此通常建议避免这种做法。

例如:

public class Test {
	public static void main(String[] args) {
		Example example = new Example();
		example.foo();
	}
}

class Example {
	int a = 6;
	public void foo() {
		int a = 16;
		System.out.println(a);//就近原则,会使用foo方法内的变量a
	}
}

运行结果:

可以发现全局变量和局部变量是可以重名的,在使用时遵循就近原则。

3、同一个作用域内不能重名

在同一个作用域中不能重名,例如在同一个方法中不能定义同名的变量,即使是不同类型同名也不行。

    public void foo() {
		int a = 16;
		double a = 0.0;
	}

这里就会报错:

4、局部变量只能用final修饰符

对于全局变量可以使用所有修饰符,但是对于局部变量就只能使用final这个修饰符,其他的都能用。

全局变量修饰符使用情况:

全局变量包括实例变量和静态变量,它们可以使用各种修饰符来指定访问权限、状态和其他特性。常用的修饰符有:

  • 访问修饰符

    • public: 变量可以被所有类访问。
    • protected: 变量可以被同一包中的类和子类访问。
    • private: 变量只能被声明它的类访问。
    • 默认(无修饰符): 变量只能被同一包中的类访问。
  • 状态修饰符

    • static: 将变量定义为类变量,共享给所有实例。
    • final: 将变量定义为常量,初始化后不能修改。
    • transient: 序列化时忽略该变量。
    • volatile: 提示线程对该变量的修改操作是可见的,多线程环境中保证变量的可见性。

局部变量修饰符修饰符使用情况:

局部变量包括方法内部、构造函数内部或代码块内部定义的变量。局部变量的作用范围仅在其声明的块内。局部变量只能使用final修饰符。

class Example {

	public void foo() {
		final int num = 0;//使用final修饰符修饰,表示这个局部变量的值不能再被改变
	}
}

与全局变量不同,局部变量不能使用访问控制修饰符(如 publicprotectedprivate)和一些状态修饰符(如 statictransientvolatile)。

class Example {
	
	public void foo() {
		public int a = 0;
		private int b = 0;
		protected int c = 0;
		static int d = 0;
		transient int e = 0;
		volatile int f = 0;
	}
}

这里就会报错:

四、变量的生命周期

在Java中,变量的生命周期决定了变量存在的时间范围。根据变量的类型和定义位置,可以将Java中的变量分为以下几类:局部变量全局变量(包括实例变量静态变量)。下面详细介绍每种变量的生命周期及特点。

1、局部变量生命周期

当局部变量所在的方法被调用时,局部变量的生命周期从它们声明开始,到包含它们的块(方法、构造函数、代码块等)结束。当方法、构造函数或代码块执行完毕后,局部变量将不再存在,内存也将被释放。

局部变量存储在栈区中。

2、全局变量生命周期

1)实例变量生命周期

实例变量的生命周期从创建对象(调用构造函数)开始,到这个对象被垃圾回收器回收时结束。实例变量在对象存在期间都可以访问。

实例变量存储在堆区中。

2)静态变量生命周期

静态变量的生命周期从类加载时开始,到类卸载时结束。静态变量在整个程序运行期间都存在,直到JVM结束。

静态变量存储在方法区(Method Area)中。