Java变量、作用域编程练习

执行结果截图:

 

 

 代码:

public class ClassScopes {
/* Java程序在内存中的存储分配情况:

    一、堆区、栈区、方法区
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

二、内存分区
而内存分为四个区:
stack segment,
heap segment,
data segment,
code segment

stack 区存放函数参数和局部变量;
heap 区存放对象;
data 区存放static 的变量或者字符串常量;
code 区存放类中的方法;

因此,静态变量是存放在data区的
*/
// 用static修饰符声明静态变量,静态变量(又称为类变量),存在于方法区中,随着类的加载而加载,随着类的消失而消失
// 静态变量属于类,因为它们的作用域在整个类中都是可用的,所以也被称为全局变量。
// 静态变量可以被对象调用,也可以被类名调用,具有类属性
// 静态变量不能在声明执行后再另起一行单独赋值,但可以在声明变量后接着直接赋值进行初始化
/* 静态变量为所有对象所共享,当某个对象对静态变量修改时,其他对象会受其影响。
如果类中的成员变量有类变量(即静态变量、全局变量),那么所有对象的这个类变量都分配给相同的一处内存,
改变其中一个对象的这个类变量会影响其他对象的这个类变量,也就是说对象共享类变量。
*/
static int salary = 2500;
private static String nameTest = "Stephen";

// string类型的成员变量,如果未手动初始化,那么默认初始化值为Null
public String name = "JohnnyH";

// int类型的成员变量的默认初始化值为0
int age;

//定义一个非静态的方法
public void NonStaticTest() {
// 局部变量test要先被手动初始化,之后才能打印输出
int test = 666;

// 输出666
System.out.println(test);

String name = "Tom";

// 输出Tom
System.out.println(name);

// 用this可以在非静态方法TestNonStatic里调用ClassScopes类里定义的name,值为JohnnyH
System.out.println(this.name);
}

// 定义一个静态方法
// 静态方法不能用this关键字
public static void StaticTest() {
int test = 500;
System.out.println(test);
}

/* 关于public static void main(String[] args) 每个标识符是代表什么意思?
这是java程序的入口地址,java虚拟机运行程序的时候首先找的就是main方法.跟C语言里面的main()函数的作用是一样的.
只有有main()方法的java程序才能够被java虚拟机欲行,可理解为规定的格式

对于里面的参数及修饰符————
public:表示的这个程序的访问权限,表示的是任何的场合可以被引用,这样java虚拟机就可以找main()方法,从而来运行javac程序
static:表明方法是静态的,不依赖类的对象的,是属于类的,在类加载的时候main()方法也随着加载到内存中去
void:main()方法是不需要返回值的
main:约定俗成,规定的
String[] args:从控制台接收参数
*/
// main是静态方法,不能用this关键字
public static void main(String[] args) {

// 局部变量:在某个语句块或方法中被定义,存在于栈内存,只在语句块内或方法内有效,必须声明并手动进行初始化数值
// i是局部变量,没有默认初始化值,必须手动初始化。局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放。
int i = 10;

System.out.println(i);

// 调用上面建立的静态方法TestStatic(),方法内有打印语句,输出500
ClassScopes.StaticTest();

// 实例化对象 ———— 变量类型 变量名字 = new 包名.类名();
// 在没创建实例之前可以调用类属性salary,但不能调用实例属性的age
// 实例化对象之后,就可以调用实例属性例如t1.age了
ClassScopes t1 = new com.cnblogs.base.ClassScopes();
ClassScopes t2 = new com.cnblogs.base.ClassScopes();
t1.age = 25;
t2.age = 48;

// 成员变量t1.age和t2.age之间毫无关系。
System.out.println(t1.age);
System.out.println(t2.age);

// 输出实例变量name的初始化值JohnnyH
System.out.println(t1.name);

// 打印t1.salary,这里静态变量salary没有被再次赋值,就显示初始化赋的值
System.out.println(t1.salary);

// 对象t2对t2.salary的数值进行修改
t2.salary = 50000;

// 对象t2对t2.salary进行修改后,t1.salary也会受其影响
System.out.println(t1.salary);

// 对象t2对t2.salary进行修改后,类变量salary也会受其影响
System.out.println(salary);

//注意:阿里巴巴Java开发手册规约,避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

//例如直接用类名ClassScopes访问salary,不要通过实例变量t1.salary或某个静态方法里的salary
System.out.println(ClassScopes.salary);

//对象t1调用上面建立的非静态方法TestNonStatic(),方法中有打印语句,输出666和Tom和Johnny
t1.NonStaticTest();

String nameTest = "James";

// 输出为局部变量nameTest的值James(不是成员变量nameTest的值Stephen),可见同名局部变量nameTest的值覆盖了实例变量nameTest的值
System.out.println(nameTest);

// 可以通过类名调用被覆盖的类属性的nameTest,输出Stephen
System.out.println(ClassScopes.nameTest);

{
// 代码块内定义的局部变量test只能在代码块内被打印输出
int test = 99;

// 输出99
System.out.println(test);
}

}
}
posted @   JohnnyH  阅读(109)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示