我是认为"成员变量包含实例变量和静态变量(静态变量也是类变量)",但学习过程中遇到说"成员变量仅仅指实例变量",所以下面具体研究一下成员变量的定义、包含关系
1、认同"成员变量包含实例变量和静态变量"的说法汇总
说法一
java中,成员变量是指在类体的变量部分中定义的变量,也称为属性。成员变量声明在类中、方法体之外,在创建对象时实例化。成员变量可被类中的方法、构造方法以及特定类的语句块访问。如果声明成员变量时没对其初始化则系统会使用默认值初始化成员变量
声明成员变量的语法如下[public|protected|private] [static][final] <type> <variable_name>
各参数的含义如下
-
public
、protected
、private
:用于表示成员变量的访问权限 -
static
:表示该成员变量为类变量,也称为静态变量。 -
final
:表示将该成员变量声明为常量,其值无法更改。 -
type
:表示变量的类型 -
variable_name
:表示变量名称
说法2
成员变量是在类体中定义的变量,即全局变量。成员变量用于定义对象的状态。例如Student类有name、age、sex等成员变量分别表示姓名、年龄、性别等状态
注意是类体中的变量,不是其他方法中的。其他方法中的变量是局部变量,互相之间不能使用
->成员变量有新名是全局变量
成员变量是给对象使用的。每个对象被创建以后都会有属于自己的属性,即成员变量。通过修改这些属性从而改变对象的某个状态->"成员变量如果包含静态变量和实例变量",那么"静态变量是类级别的"应该和"对象都会有自己的属性"是矛盾的,但是对象是可以点静态属性
说法3
成员变量,类里定义的变量;局部变量,方法里定义的变量
其中成员变量又分为:实例变量和类变量->这里明确告知了
代码中的实例变量、类变量、常量都属于成员变量
类变量:static修饰的变量
实例变量、类变量、常量,三者不同是由于变量的修饰符
成员变量是定义在类里面并和方法处于同一层次。定义成员变量的语法如下
[变量修饰符] 类型说明符 变量名
成员变量的类型可以是Java中的任意数据类型,包括基本类型、数组、类和接口。在一个类中,成员变量应该是唯一的,但是成员变量的名字可以和类中某个方法的名字相同,如方法x()和变量x具有相同的名字,但这会引起不必要的混淆所以不建议
注:如果局部变量和成员变量的名称相同,那么成员变量被隐藏,即方法内失效。方法中如需要访问该类中的成员变量则需要加上关键字this
成员变量是否为静态
默认情况下,成员变量是实例成员,在外部需要通过对象才能操作。如果用static修饰,就成为了静态成员,也称为类变量,无需通过对象就可以操作->所以是一般情况下是会将"实例变量"说成"成员变量"的
说法4
类体的内容分为变量的声明和方法的定义,声明变量部分所声明的变量被称为成员变量或域变量
成员变量在整个类内都有效,其有效性与它在类体中书写的先后位置无关。但是不提倡把成员变量的声明分散地写在方法之间,人们习惯先介绍属性再介绍行为
注:虽然Java并没有规定成员变量必须定义在类的开始部分。不过在实际编程中,多数程序员将成员变量定义在成员方法的前面
说法5
java成员变量有:1、实例变量【String id、private String colorType】;2、类变量【private static String depart】;3、常量【final String design=yang】
局部变量也称内部变量,是指在一个函数内部或复合语句内部定义的变量
public class Clothes{String id; 实例变量private String colorType; 实例变量private int size; 实例变量private static String depart; 类变量final String design="yangzi"; 常量public void a(int num){ } 局部变量
}
说法6
变量的作用域规定了变量所能使用的范围,只有在作用域范围内变量才能被使用。根据变量声明地点的不同,变量的作用域也不同
所以可以根据作用域的不同来区分变量,一般将变量分为不同的类型:成员变量和局部变量
成员变量有两种,分别是全局变量和静态变量(类变量)。定义在方法体和语句块之外,不属于任何一个方法,作用域是整个类
名称 | 修饰 | 访问 | 生命周期 |
---|---|---|---|
全局变量(实例变量) | 无 static 修饰 | 对象名.变量名 | 只要对象被当作引用,实例变量就将存在 |
静态变量(类变量) | 用 static 修饰 | 类名.变量名或对象名.变量名 | 其生命周期取决于类的生命周期。类被垃圾回收机制彻底回收时才会被销毁 |
假设在一个类中声明了 4 个变量
public class DataClass {String name; 成员变量、实例变量int age; 成员变量、实例变量static final String website = "C语言中文网"; 成员变量、静态变量(类变量)static String URL = "http://c.biancheng.net"; 成员变量、静态变量(类变量)
}
用 static final 修饰的变量必须赋予初始值
说法7、java的成员变量和局部变量
在java中,成员变量是指在类内方法外定义的变量;而局部变量是指在方法中定义的变量,作用范围是其所在的方法
public class Student { 这是一个类name和age是成员变量,作用范围是整个类private String name;private int age;public void do(int age) {这个age是方法的形式参数,是局部变量task是定义在方法do内部的变量,作用范围是do方法内,所以是局部变量String task;}}
不同
1、在类中位置不同:局部变量在方法中,成员变量在方法外
2、在内存中位置不同:局部变量在栈内存中,成员变量在堆内存中
3、生命周期不同
局部变量随方法的调用而存在:当方法被执行时局部变量被创建、当方法执行完毕出栈,局部变量跟随方法消失
成员变量随对象的存在而存在:当对象被创建之后,成员变量作为对象的属性会与对象一同被存储在堆内存中,一直到对象消失才跟着消失
4、初始化值不同
局部变量定义之后必须主动赋值初始化才能被使用
成员变量作为对象的一部分,当对象被创建后,成员变量会被自动赋默认值(一般基本数据类型赋0,引用数据类型赋null)
5、作用范围不同:局部变量只在其所在的方法内部生效,成员变量在其所在的整个类中生效
思维导图
列出前面的7种说法
1、成员变量是指在类体的变量部分中定义的变量,也称为属性
2、成员变量是在类体中定义的变量,即全局变量。成员变量是给对象使用的。每个对象被创建以后都会有属于自己的属性,即成员变量
3、成员变量又分为:实例变量和类变量。类变量:static修饰的变量。代码中的实例变量、类变量、常量都属于成员变量,一般情况下说"成员变量"实际是在说"实例变量"
4、类体的内容分为变量的声明和方法的定义,声明变量部分所声明的变量被称为成员变量或域变量
5、java成员变量有:1、实例变量【String id、private String colorType】;2、类变量【private static String depart】;3、常量【final String design=yang】;局部变量也称内部变量
6、可以根据作用域的不同来区分变量,一般将变量分为不同的类型:成员变量和局部变量
成员变量有两种,分别是全局变量和静态变量(类变量)
7、成员变量是指在类内方法外定义的变量
尽管都是赞成"成员变量包含实例变量、静态变量"的说法,但是读完都不能明确成员变量究竟包含哪些及成员变量是否是属性/全局变量/域变量的说法更是第一次听说
继续看下一节不认同的说法,会在第三节给出答案
2、不认同"成员变量包含实例变量和静态变量"的说法汇总
说法1
成员变量的生命周期(在内存中存在的时间)
出生: new对象的时候,开辟内存空间
死亡: 堆内存地址没有引用,变成垃圾被垃圾回收器回收后
局部变量,也叫本地变量
方法的形式参数以及在方法中定义的变量
作用范围
形参:在方法体中任何位置都可以访问
方法中定义变量:从定义处开始,直到所在代码块结束
生命周期(在内存中存在的时间)
出生:运行到创建变量的语句时
死亡:超过了其作用范围
静态变量的生命周期(在内存中存在的时间)
出生:类加载时,类变量就分配内存空间。
死亡:JVM退出
没有明确告知是不同的
说法2
成员变量和局部变量的区别
成员变量
成员变量定义在类中,在整个类中都可以被访问
成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中
成员变量有默认初始化值
局部变量
局部变量只定义在局部范围内,如:函数内,语句内等,只在所属的区域有效
局部变量存在于栈内存中,作用的范围结束,变量空间会自动释放
局部变量没有默认初始化值
成员变量和静态变量的区别
两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象被回收而释放
静态变量随着类的加载而存在,随着类的消失而消失
调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用,还可以被类名调用
别名不同
成员变量也称为实例变量
静态变量也称为类变量
数据存储位置不同
成员变量存储在堆内存的对象中,所以也叫对象的特有数据
静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据
相当于是"完善的说法一",可以看出"成员变量/实例变量不同于静态变量/类变量"
说法3
变量的定义格式
[修饰符] [static] 数据类型 变量名称 = 变量的值;
变量的三个重要属性:变量名、变量类型、变量的值
成员变量
类中直接定义的变量成为成员变量。 对于成员变量也有叫作实例变量(instance variable),也有称为对象中的属性,都是同一个意思。 这里通常指非 static 进行修饰的变量
需要注意的是, 成员变量最好使用私有修饰符进行权限的控制, 保证成员属性不往外暴漏属性值,而是给一个行为或者动作去触发修改属性
下面的例子其实就是想说构造代码块在构造函数前执行这回事
静态变量
静态变量就是在类中定义的 static 的变量,也有叫类变量(class variable)
一个静态变量可以在非静态方法中进行使用,但是静态方法中不能使用非静态的变量
一般情况下对于静态变量的用法有两种情况:1. 方便调用可以直接通过类进行调用;2. 对象之间值的共享
局部变量
分为两种,一种是方法内的局部变量, 另外一种是块中的变量
不管是块也好 或方法也好,定义的局部变量就只有对应的花括号的作用域
3、结论
尝试统一说法不现实,所以还是查阅书籍靠谱
3.1、查了《java语言程序设计》,得到下图知识点
可以跳过这一节看最终总结,毕竟又是重新梳理要点了
得知"命名常量"简称是我们熟悉的"常量"
"静态变量"也可称为"类变量"
"常量应当被类的所有对象共享,所以要加final static修饰"
那么我们实际一般所说的常量,严格来说也当叫静态常量,是static final 数据类型 常量名;这种形式
静态变量、实例变量作用域都是整个类,这里又说"静态变量和实例变量统称为类变量或数据域"
提出要点
1、"命名常量"简称是我们熟悉的"常量"
2、"静态变量"也可称为"类变量"
3、"常量应当被类的所有对象共享,所以要加final static修饰"
那么我们实际一般所说的常量,严格来说也当叫静态常量,是static final 数据类型 常量名;这种形式
4、静态变量、实例变量作用域都是整个类,这里又说"静态变量和实例变量统称为类变量或数据域"
4的后半句和2是矛盾的、所找到的不足以解释成员变量,所以还是需要结合前面说法找出较为认可的点综合而成下面的最终总结
最终总结
1、类体的内容分为变量的声明和方法的定义,变量声明的位置在类内方法外
2、声明变量部分所声明的变量被称为成员变量或域变量
按理声明的静态变量和实例变量等都算成员变量内了。但"成员变量随着对象的建立而建立,随着对象的消失而消失,存在于对象所在的堆内存中,所以也叫对象的特有数据;静态变量随着类的加载而存在,随着类的消失而消失, 静态变量数据存储在方法区(共享数据区)的静态区,所以也叫对象的共享数据"所以成员变量应当只是指代实例变量
3、前面4和2的矛盾,所以一般情况就还是不要管"静态变量"叫"类变量"了,避免混淆。所以我认为是"类变量包含静态变量和实例变量",再之后只谈实例变量和静态变量,像成员变量、全局变量、类变量的概念还是不要讲了
4、成员变量不是属性,属性是成员变量(下一节解释)
5、常量(final static修饰)应该算类变量内
3.2、属性和成员变量的区别
很多人都认为java中属性就是成员变量,其实不然。那他们有什么区别呢?通过以下代码来理解
public class Person {private String name;private int age;private String gender;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public float getHeight() {return 1.75f;}public void setHeight(float height) {}}
Person类中定义了3个字段 age、name、gender。它们是成员变量但它们不全是属性,那什么是属性?
属性的定义规则是:set/get方法名去掉set/get后,将剩余部分首字母小写得到的字符串就是这个类的属性
所以name、age、height就是Person类的属性
注:尽管这个height不是成员变量,但当外部类调用Person对象时还会有height这个属性
4、拓展
4.1、局部变量
局部变量是指在方法或者方法代码块中定义的变量,其作用域是其所在的代码块。可分为以下三种
- 方法参数变量(形参):在整个方法内有效
- 方法局部变量(方法内定义): 从定义这个变量开始到方法结束这一段时间内有效
- 代码块局部变量(代码块内定义):从定义这个变量开始到代码块结束这一段时间内有效
局部变量在使用前必须被程序员主动初始化值
1)方法局部变量
声明两个局部变量并输出其值,其实现代码如下
public class Test2 {public static void main(String[] args) {int a = 7;if (5 > 3) {int s = 3; 声明一个 int 类型的局部变量System.out.println("s=" + s);System.out.println("a=" + a);}System.out.println("a=" + a);}
}
上述实例中定义了 a 和 s 两个局部变星,其中 int a 的作用域是整个 main() ,而 int s 的作用域是 if 语句的代码块内。其执行结果是
s=3
a=7
a=7
如果在 if 方法外调用变量 s 则会报无法解析该变量的错误
2)方法参数变量
作为方法参数声明的变量,作用域是整个方法
声明一个方法参数变量,实现代码如下
public class Test3 {public static void testFun(int n) {System.out.println("n=" + n);}public static void main(String[] args) {testFun(3);}
}
在上述实例中定义了一个 testFun() ,该方法中包含一个 int 类型的参数变量 n,其作用域是 testFun() 方法体内。当调用方法时传递进了一个参数 3,因此其输出控制台的 n 值是 3
3)代码块局部变量
代码块局部变量常用于 try catch 代码块中,成为异常处理参数变量
异常处理参数变量的作用域是在异常处理块中,该变量是将异常处理参数传递给异常处理块,与方法参数变量类似
声明一个异常处理语句,实现代码如下
public class Test4 {public static void test() {try {System.out.println("Hello!Exception!");} catch (Exception e) { 异常处理块,参数为 Exception 类型e.printStackTrace();}}public static void main(String[] args) {test();}
}
在上述实例中定义了异常处理语句,异常处理块 catch 的参数为 Exception 类型的变量 e,作用域是整个 catch 块
4.2、权限修饰符
public,protected,private 以及不写之间的区别
- public : 表明该成员变量或者方法是对所有类或者对象都是可见的,所有类或者对象都可以直接访问
- private : 表明该成员变量或者方法是私有的,只有当前类对其具有访问权限,除此之外其他类或者对象都没有访问权限.子类也没有访问权限
- protected : 表明成员变量或者方法对类自身,与同在一个包中的其他类可见,其他包下的类不可访问,除非是他的子类
- default :表明该成员变量或者方法只有自己和其位于同一个包的内可见,其他包内的类不能访问,即便是它的子类
总结
public | protected | default | private | |
---|---|---|---|---|
当前类可访问 | 是 | 是 | 是 | 是 |
同包的其他类可访问 | 是 | 是 | 是 | 否 |
其他包下的类可访问 | 是 | 子类可以 | 否 | 否 |
4.4、看一个例子
有一点我们应该知道,局部变量存储在栈中,实例变量存储在堆中,静态变量存储在方法区中
public class staticTest {public static void main(String[] args) {Person per1 = new Person();Person per2 = new Person();per1.name = "小韩";per1.age = 18;per1.print();per2.print();Person.country="日本";per1.print();per2.print();System.out.println(Person.country);}
}
class Person {实例变量,成员方法,必须通过该类的对象来访问String name;int age;String sex;静态成员变量,不属于对象,属于类,保存在方法区中调用时通过 类名称.country来进行访问static String country = "中国";void print(){System.out.println("name:"+name+", age:"+age+", country:"+country);}
}
猜测结果
我漏看了country赋值"中国",所以我得出的结果是
小韩,18,null
null,0,null
小韩,18,日本
null,0,日本实际结果/现在发现country赋值"中国",则结果为
小韩,18,中国
null,0,中国
小韩,18,日本
null,0,日本
例子不难,主要是想讲per1赋值name、age后直接打印输出,输出方法是对象级别的,可里面还有静态属性未赋值但还是能打印成功不报错,这点考的是"类属性没有对象也能调用"
再看
Person per = null;System.out.println(per.country); 相当于Person.country
一眼看去是不是会报空指针异常,但实际不会。首先一点:空指针异常是空引用访问实例相关;再static属性是类属性,通过类名称直接访问,此时没有对象也能调用(包含该类的null引用)
4.5、了解
为什么main()是一个静态方法?
因为主方法是程序的入口,在进入主方法前没有对象。如果主方法是一个成员方法,需要通过对象调用就会产生矛盾。要使程序开始执行,只有通过类名称直接调用静态方法,无须产生对象
静态方法能否访问成员变量和成员方法?
不能。 静态方法可以通过类名直接访问,此类中没有对象也可以访问;成员方法和成员变量必须要通过类中的对象来访问。没有对象的方法去调用必须通过对象访问的变量和方法,二者之间矛盾。或者简单说,静态方法内没对象,所以对象相关的变量、方法都不能调用
成员方法能否访问静态变量和静态方法?
可以
static方法只能调用静态变量和静态方法等,static家族的成员可以相互调用
普通的类能否使用static关键字修饰(不是内部类)?
类定义出来是要产生对象的,用static关键字修饰一个类,这个类不需要对象就能调用,矛盾