write:2022-4-28
前文我们学习了Java的数据类型:Java之数据类型,本文我们学习变量的作用域和初始化,文中有大量使用实例讲解分析,需耐心解读代码。
1. 变量和参数的概念
仔细分析一下代码:
public class Cat{
private String **name**; //name:属性
public Cat(String **name**){ //name:方法的参数
this.name=name;
}
public void speak(){
System.out.println(name+":喵喵喵");
}
public static void main(String args[]){
Cat cat=new Cat("朵拉");
cat.speak();
}
}
可以发现在不同的地方,变量name代表的含义不同,有不同的作用。
2. 变量的作用域
成员变量:在类中定义,它的作用域是整个类。
局部变量:在一个方法的内部定义,它的作用域是整个方法。
方法参数:方法的参数,它的作用域是整个方法。
eg:
public class Scope{
int x; //成员变量,作用域是整个类
Scope(int x){
this.x=x; //此方法与类同名,this.x(成员变量x)=x(方法参数x),用this关键字就是引用与方法参数同名成员变量
int y=2; //局部变量,作用域是这个方法
}
public void test(){
x=1;
y=1; //编译出错
}
public static void main(String args[]){
Scope s=new Scope(1);
System.out.println(s.x);
System.out.println(s.y); //编译出错
}
}
进一步理解this关键字:
eg:
public class Count{
int data; //没有显示初始化,默认值为0
public void increase(int data){
this.data=this.data+data; //把成员变量data和方法参数data相加再赋值给成员变量data
}
public static void main(String args[]){
Count c1=new Count();
Count c2=new Count();
c1.increase(2); //0+2=2
c2.increase(1); //0+1=1
System.out.println(c1.data+","+c2.data); //打印:2,1
}
}
图解:
3. 参数传递
如果参数是基本数据类型,参数传递是将数值传递给方法。
如果参数是对象或数组的引用类型,参数传递是将对象或数组的引用传递给方法。
eg:
public void methodA(){
int a=1;
String s=“Hello”
methodB(a,s); //调用methodB方法
}
public void methodB(int p1,String p2){
…
}
试一试
想一想打印输出什么结果
public class ParaTest{
public int v=0;
public static void main(String args[]){
//声明3个局部变量
int p1=0; // p1是基本数据类型
ParaTest p2=new ParaTest(); //p2 是对象引用类型
ParaTest p3=new ParaTest();//p3 是对象引用类型
//将3个局部变量作为参数传递给changeParameter ()方法
changeParameter (p1, p2, p3);
//打印3个局部变量
System.out.println("p1= " +p1);
System.out.println("p2.v= " + p2.v);
System.out.println("p3.v= " + p3.v);
}
public static void changeParameter (int p1, ParaTest p2, ParaTest p3) {
p1=1;
p2.v=1;
p3=new ParaTest();
p3.v=1;
}
}
答案:
P1=0
P2.v=1
P3.v=0
分析:
4. 变量的默认值
在创建一个对象时,JVM会自动为它的成员变量初始化为默认值。
数值型变量的默认值(0)
字符型的默认值(‘\u0000’)
布尔型的默认值(false)
引用类型的默认值(null)。
eg:
public class Sample{
int v1;
boolean v2;
Sample v3;
public static void main(String args[]){
Sample sam=new Sample();
System.out.println(sam.v1);
System.out.println(sam.v2);
System.out.println(sam.v3);
}
}
打印结果
0
false
null
5. 变量的初始化
1)成员变量会自动初始化:如果编写者显示初始化,那么成员变量的值就是赋值的值,如果没有显示初始化,则默认初始化,成员变量的值就是默认值
2)局部变量必须显式初始化再使用
eg:
6. 静态变量和实例变量
成员变量分为两种:静态变量和实例变量。
静态变量用static修饰,也叫做类变量。
eg:
public class Sample{
static int v1; //静态变量
int v2; //实例变量
public static void main(String args[]){
v1=1;
v2=1; //编译出错,在静态方法中不能直接访问v2
Sample s1=new Sample();
s1.v1=2;
s1.v2=2;
Sample.v1=3;
Sample.v2=3; //编译出错,不能通过类名访问v2
}
}
静态变量和实例变量的区别
静态变量在内存中只有一个备份,在JVM加载类时分配内存
实例变量属于特定的实例。每创建一个实例,就会为实例变量分配内存。
eg:
public class Sample{
static int v1; //静
public static void main(String args[]){
Sample s1=new Sample();
Sample s2=new Sample();
s1.v2=1;
s2.v2=2;
s1.v1=3;
s2.v1=4;
System.out.println(s1.v2+“,”+s2.v2+“,”+v1); //打印1,2,4
}
}
7. 变量的生命周期
方法的参数和局部变量只有当方法被调用时才存在
实例变量的生命周期依附于实例变量
静态变量的生命周期依附于类的生命周期
eg:用唱戏表示
变量的生命周期
eg:
8. 小结
9. 练习题
1.编译以下代码会出现什么情况?
public int test(){
int x;
int y=x+1;
return y;
}
编译出错,提示变量x必须先初始化才能被使用。
2.编译或运行以下代码会出现什么情况?
public class Sample{
static String v1;
static boolean v2;
public static void main(String args[]){
System.out.println(Sample.v1);
System.out.println(v2);
}
}
编译和运行通过,打印null和false。
3.编译或运行以下代码会出现什么情况?
public class Sample{
public int method1(){
int x=0;
return x+10;
}
public void method2(){
System.out.println(x);
}
}
编译出错,提示method2()方法中的x没有定义。
4.补充setData()方法的代码,把参数data的值赋给实例变量data?
public class Sample{
int data;
public void setData(int data){
//把参数data的值赋值给实例变量data
…
}
}
a) Sample.data=data; b) new Sample().data=data;
c) this.data=data; d) int data=data;
答案:c
5.运行以下Sample类,会得到什么打印结果?
a) 打印1,2,1 b)打印1,1,2
c)打印1,1,1 d)打印2,2,1
答案:b