全局变量+静态全局变量+局部变量+简单类型数据传值调用演示

本文详细介绍了Java中的全局变量、静态全局变量(类变量)、实例全局变量(成员变量)和简单类型数据的传值调用。讲解了它们的定义、作用范围、生命周期以及内存分配,并通过代码示例展示了它们的使用和影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

全局变量+静态全局变量+局部变量+简单类型数据传值调用演示


全局变量

**定义:**在类里定义的变量,就是全局变量,该类所有方法都可以使用
变量默认初始值
**

静态全局变量(类变量)

**
语法:static [类型] [变量名];
§ 定义位置:类的内部,方法外部;
§ 开辟时间:一加载含有静态全局变量的类,就开辟空间;
§ 开辟空间位置:方法区的静态数据区,自动与类关联;
§ 开辟次数:只开辟一次(因为类只加载一次);
§ 默认初始化;
§ 作用范围:该类里所有的对象(所有方法也可以)使用;(Java当中作用范围最大的变量);
§ 生存周期:与类相同,与整个程序相同,生存周期特别长,但浪费空间,内存效率低;
§ 开辟方法:开辟空间,初始化,关联;
§ 该类所有对象共享§ 优点: 作用范围大□
§ 缺点: 增加该类所有对象的耦合性,尽量少用(单例使用)□ 如:假设有1000个对象都有静态全局变量的引用,只要有一个对象改变了静态全局变量引用的值,剩下999个对象都会受 到影响。

代码示例:

class GlobalVar {
	static int i;// 静态全局变量(类变量)
	double k;// 实例全局变量(成员变量或属性) //k=12.0;

	public int methodA() {
		return this.i;
	}

	public double methodB() {
		return this.k;
	}
}

public class TestGlobalVar {
	// static int c;
	public static void main(String[] args) { // 可以不实例化GlobalVar就可以使用全局类变量
		GlobalVar.i = 100;
		System.out.println(GlobalVar.i);// 100
		System.out.println(k); // 必须实例化GlobalVar后才可以访问全局实例变量
		GlobalVar gv1 = new GlobalVar();
		gv1.k = 20.5;
		GlobalVar gv2 = new GlobalVar();
		gv2.k = 45.6;
		System.out.println(k);
		System.out.println(gv1.methodB());// 20.5
		System.out.println(gv1.k);// 20.5
		System.out.println(gv1.methodA());// 100
		gv2.i = gv1.i / 2;
		System.out.println(gv1.i);// 50
		System.out.println(gv2.methodB());// 45.6
		System.out.println(gv2.k);// 45.6
		System.out.println(gv2.methodA());// 50
		System.out.println(gv2.i);// 50
	}
}

内存图
内存图
□ javac 编译生成字节码文件TestGlobalVar.class和GlobalVar.class放在根目录下

□ 执行有主方法的字节码文件TestGlobalVar.class,并把字节码文件加载到方法区的类代码区;

□ 通过该类找到与之关联的主方法;□ 加载GlobalVar.class到方法区的类代码区;

□ 发现静态全局变量:static int i;
a) 在方法区的静态数据区给静态全局变量i开辟空间(int类型 4个字节);
b) 给i默认初始化(0);
c) 建立与GlobalVar类的关联;

□ 继续执行主方法,给i赋值100;

□ 创建GlobalVar类型的对象,并把对象的地址传给与之类型相同的变量gv1;

□ 在堆中为Global对象开辟空间:
属性: i;自动拥有该类静态全局变量的引用,并且名称与静态全局变量相同 k;实例全局变量
方法: methodA();methodB()

□ 调用gv1所指对象的属性k,并赋值20.5;

□ 创建GlobalVar类型的对象,并把对象的地址传给与之类型相同的变量gv2;

□ 在堆中为Global对象开辟空间:
属性: i:(与gv1里的i不是同一个i,也不是静态全局变量的i) k:实例全局变量
方法: methodA();methodB();

□ 调用gv2所指对象的属性k,并赋值45.6;

□ 调用gv1所指对象的方法methodB(),输出k=20.5;

□ gv1.k:输出gv1所指对象的属性k的值=20.5;

□ 调用gv1所指对象的方法methodA(),返回该对象的属性i,i存放着静态全局变量的地址,所以输出静态全局变量i的值 =100;

  类似于调用对象的方法,
  真正的方法代码存放在方法区的共享代码段,例如:methodA(),
  在堆中存放的其实是 methodA()的引用,
  通过引用在方法区的共享代码段找到这段代码,提高效率 

□ gv2.i=gv1.i/2; 调用gv1所指对象的属性i,i属性存放着静态全局变量i的地址,所以是把静态全局变量的i/2,把该值赋给 gv.2所指对象的属性i,i同样存放着静态全局变量i的地址,所以就是把静态全局变量的i/2,并赋值给自己本身,i=50;

□ gv1 i;输出gv1所指对象的属性i所指的静态全局变量i,为50;

□ 调用gv2所指对象的方法methodB(),返回gv2所指对象的属性k,输出45.6;

□ 调用gv2所指对象的属性k,输出45.6;□ 调用gv2所指对象的方法method(),返回gv2所指对象的属性i,属性i存放着静态全局变量i的地址,因此该方法返回静 态全局变量i的值,50;

□ gv2 i;输出gv2所指对象的属性i所指的静态全局变量i,为50;

□ 方法调用结束,所有空间释

**

**实例全局变量(成员变量或属性)

**
§ 在类里定义的,供类里所有方法使用;
§ 开辟时间:创建对象为实例全局变量开辟空间;
§ 开辟位置:在堆里开辟;§ 开辟次数:创建几个对象开辟几次;
§ 空间名称可以相同;
§ 只能通过对象调用;
§ 构造方法给实例全局变量默认初始化;
§ 作用范围:该对象所有方法使用;
§ 生存周期:对象创建他就有,对象被GC掉就没有。
**

**

传值

**
○Java在参数传递的时候,只使用值传递
○ 当对象实例作为参数传递给方法时,这个参数的值是对象的引用,而不是对象本身

**
代码示例:

class IInt{
	   int n = 10;
	    //static int n=100; 
	   public IInt(){
	   }

	   public IInt(int n){
	        this.n =n;
	   }
	}	

public class CallByValuePri{
		void half(int n)
		{
			n=n/2;
			System.out.println("half方法n="+n);//5
		}
		
		void half(IInt n)
		{	
			n.n =n.n/2;//n.n不能单独进行加减乘除,除非对自己进行操作后又赋值了比如n.n++;
			System.out.println("half方法n="+n.n);//5 
	       n = new IInt(20);
		System.out.println(" *****n="+n.n);//20,如果有参构造没有this那么就会打印10
		}
		
	public static void main(String args[])
		{CallByValuePri cb = new CallByValuePri();
			int m=10;	
			System.out.println("Before the Invocation,m="+m);//10
			cb.half(m);
			System.out.println("After the Invocation,m="+m);//10
			IInt m1 = new IInt();
			System.out.println("Before the Invocation,m1="+m1.n);//10
			cb.half(m1);
			System.out.println("After the Invocation,m1="+m1.n);//5
		}
	}

**
执行过程
**
编译生成字节码文件 CallByValvePri.class 放入方法区的类代码区;

• 执行CallByValvePri 找到与之关联的主方法;

• 创建CallByValvePri类型的对象,并把它的引用传给相同类型的变量cb;

• 创建int 类型局部变量m,赋初值10;

• 输出该局部变量m=10;

• 调用cb所指对象的参数类型为int的half方法:
○在half(int n)方法栈帧中,开辟形参n的空间;
○ 把main方法的局部变量m所含的数值10,赋给half方法的形参变量n;
○ 把形参变量n的数值10/2=5,再赋值给n;
○ 输出half方法内的局部变量n=5;
○ 方法调用结束,空间释放;

• 回到main方法,输出main方法中的局部变量m=10;

• 在当前目录下找到IInt的字节码文件加载到方法区的类代码区;

• 创建IInt类型的对象,并调用无参的构造方法,然后该对象的引用传给相同类型的变量m1; 在堆中开辟IInt对象的空间
§ 只有属性空间n,并赋初值10;
§ 没有方法空间,因为这个是构造方法;

• 调用m1所指对象的n属性,输出10;

• 调用cb所指对象的参数类型为IInt的half方法:
○在half(IInt n)方法栈帧中,开辟形参n的工作空间;
○ 把m1的值(IInt对象的地址)赋给half方法的形参n,所以half(Iint n)方法的形参n和main方法里的局部变量m1指向同一个对象;
○ n.n =n.n/2; 调用half方法局部变量n所指对象的n属性,除2再赋给n所指对象的n属性;
○ 输出n所指对象的n属性,5;
○ n = new IInt(20); 创建一个新的IInt对象存放在局部变量n里,并调用有参的构造方法赋初值20;
○ 此时n指向新的对象,输出局部变量n所指对象的n属性为20;
○ 方法调用结束,空间释放;

• 输出m1所指对象的n属性,由于之前已经被half方法改变,所以输出的是5;

• 方法调用结束,所有空间释放。

**
补充知识点
**
贫血模型:对象只有属性没有方法
充血模型:对象既有方法又有属性

注意:
• 当全局变量和局部变量同名冲突时后采用就近原则使用局部的,为了避免这种情况加个this.
• 当碰到实例全局变量和静态全局变量冲突时,当被调用时编译会出错。
• 像{ String s =new String(‘ddsds”):}在代码块中创建对象容易产生对象游离态,堆易溢出;
• 在方法里要给静态全局变量赋值——加类名
• 实例全局变量和静态全局变量重名,会编译错误,因为引用空间和实例全局变量的空间名称冲突

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值