成员变量的定义与使用

成员变量又称为成员属性,它是描述对象状态的数据,是类中很重要的组成成分。本节详细讨论如何来定义成员变量、成员变量的访问权限,以及静态成员变量与实例成员变量之间的区别。

成员变量的定义

定义成员变量的语法如下:
[变量修饰符] 类型说明符变量名
类的成员变量和在方法中所声明的局部变量都是用户标识符,它们的命名规则相同。变量修饰符是可选项,一个没有变量修饰符的变量定义如下:

public class Cuber{
double width,height;
int number;
}

  

成员变量的类型可以是Java中的任意数据类型,包括基本类型、数组、类和接口。在一个类中,成员变量应该是唯一的,但是成员变量的名字可以和类中某个方法的名字相同,例如:

public class Point{
int x, y;
int x(){
return x;
}
}

  

其中,方法x()和变量x具有相同的名字,但笔者不赞成这样写,因为这会引起不必要的混淆。
可以用成员变量修饰符来规定变量的相关属性,这些属性包括:
● 成员变量的访问权限。一共有4种访问权限可供选择,在3.3.2节将详细介绍。
● 成员变量是否为静态。默认情况下,成员变量是实例成员,在外部需要通过对象才能操作。如果用static修饰,就成为了静态成员,也称为类变量,无需通过对象就可以操作。
● 是否为常量。默认的是变量,如果前面加上final关键字,它就是一个常量。
这些修饰符可以任意组合使用。加上修饰符的成员变量如下所示:

public class Cuber{
private double width,height; //定义两个私有的成员变量
public static int count; //定义一个公共的静态类变量
public static final int COLORE=1; //定义一个公共的整型静态常量
}

  

虽然Java并没有规定,成员变量必须定义在类的开始部分,不过在实际编程中,多数程序员将成员变量定义在成员方法的前面。
3.3.2 成员变量的访问权限
访问权限修饰符声明了成员变量的访问权限。Java提供的显示的访问权限修饰符有3种,分别是:私有(private)、保护(protected)和公共(public)。除此之外,还有一种默认的访问权限:friendly,它并不是Java的关键字,只有当变量前面没有写明任何访问权限修饰符时,就默认以friendly作为访问权限。为了表达上的方便,省略了其中“成员”两字,将被这些修饰符所修饰的变量分别称为私有变量、保护变量和公共变量。下面分别讨论各个修饰符的用法。
1.公共变量
凡是被public修饰的成员变量,都称为公共变量,它可以被任何类所访问。即允许该变量所属的类中所有方法访问,也允许其他类在外部访问。如例3.2所示。
【例3.2】 公共变量使用示例。

//-----------文件名declarePublic.java,程序编号3.2------------------
public class declarePublic{
public int publicVar=10; //定义一个公共变量
}


  

在类declarePublic中声明了一个公共变量publicVar,它可以被任何类所访问。下面这段程序中,类otherClass可以合法地修改变量publicVar的值,而无论otherClass位于什么地方。

1 //-----------文件名otherClass.java,程序编号3.3------------------
2 public class otherClass{
3 void change(){
4 declarePublic ca=new declarePublic(); //创建一个declarePublic对象
5 ca.publicVar=20; //通过对象名来访问它的公共变量,正确
6 }
7 }

用public修饰的变量,允许任何类在外部直接访问,这破坏了封装的原则,造成数据安全性能下降,所以除非有特别的需要,否则不要使用这种方案。
2.私有变量
凡是被private修饰的成员变量,都称为私有变量。它只允许在本类的内部访问,任何外部类都不能访问它。
【例3.3】 私有变量使用示例。

1 //-----------文件名declarePrivate.java,程序编号3.4------------------
2 public class declarePrivate{
3 private int privateVar=10; //定义一个私有变量
4 void change(){
5 privateVar=20; //在本类中访问私有变量,合法
6 }
7 }

如果企图在类的外部访问私有变量,编译器将会报错。

1 //-----------文件名otherClass.java,程序编号3.5------------------
2 public class otherClass{
3 void change(){
4 declarePrivate ca=new declarePrivate(); //创建一个declarePrivate对象
5 ca.privateVar=20; //企图访问私有变量,非法
6 }
7 }

为了让外部用户能够访问某些私有变量,通常类的设计者会提供一些方法给外部调用,这些方法被称为访问接口。下面是一个改写过的declarePrivate类。

 1 //-----------文件名declarePrivate.java,程序编号3.6------------------
 2 public class declarePrivate{
 3 private int privateVar=10; //定义一个私有变量
 4 void change(){
 5 privateVar=20;
 6 }
 7 public int getPrivateVar(){ //定义一个接口,返回私有变量privateVar的值
 8 return privateVar;
 9 }
10 public boolean setPrivateVar(int value){ //定义一个接口,可以设置privateVar
11 的值
12 //可以在这里先检测value是否在允许的范围内,然后再执行下面的语句。
13 privateVar = value;
14 return true;
15 }
16 }

私有变量很好地贯彻了封装原则,所有的私有变量都只能通过程序员设计的接口来访问,任何外部使用者都无法直接访问它,所以具有很高的安全性。但是,在下面这两种情况下,需要使用Java另外提供的两种访问类型:
● 通过接口访问私有变量,将降低程序的性能,在程序性能比较重要的情况下,需要在安全性和效率间取得一个平衡。
● 私有变量无法被子类继承,当子类必须继承成员变量时,需要使用其他的访问类型。
3.保护变量
凡是被protected修饰的变量,都被称为保护变量。除了允许在本类的内部访问之外,还允许它的子类以及同一个包中的其他类访问。子类是指从该类派生出来的类。包是Java中用于管理类的一种松散的集合。二者的详细情况将在第4章介绍。下面是一个简单的 例子。
【例3.4】 保护变量使用示例。
下面这个程序先定义一个名为onlyDemo的包,declarProtected类就属于这个包。

1 //-----------文件名declareProtected.java,程序编号3.7------------------
2 package onlyDemo;
3 public class declareProtected{
4 protected int protectedVar=10; //定义一个保护变量
5 void change(){
6 protectedVar=20; //合法
7 }
8 }

%说明:读者编译这个文件时,需要用这个命令(下同):
javac -d . 文件名
下面这个otherClass类也定义在onlyDemo包中,与declareProtected类同属于一个包。

1 //-----------文件名otherClass.java,程序编号3.8------------------
2 package onlyDemo;
3 public class otherClass{ //它也在包onlyDemo中
4 void change(){
5 declareProtected ca=new declareProtected();
6 ca.protectedVar=20; //合法
7 }
8 }

下面这个deriveClass类是declareProtected的子类,它并不在onlyDemo包中。它也可以访问保护变量protectedVar,但是只能通过继承的方式访问。

1 //-----------文件名declareProtected.java,程序编号3.9------------------
2 import onlyDemo.declareProtected; //引入需要的包
3 public class deriveClass extends declareProtected{ //定义一个子类
4 void change(){
5 //合法,改变的是deriveClass从declarProtected中所继承的protectedVar值
6 protectedVar=30;
7 }
8 }

%说明:import是Java中的关键字,用于引入某个包。这将在4.13节中详细介绍。
子类如果不在父类的同一包中,是无法通过“对象名.变量名”的方式来访问protected类型的成员变量,比如下面这种访问是非法的:

1 //-----------文件名deriveClass.java,程序编号3.10-----------------
2 import onlyDemo.declareProtected;
3 public class deriveClass extends declareProtected{ //定义一个子类
4 void change(){
5 declareProtected ca=new declareProtected();
6 ca.protectedVar=30; //错误,不允许访问不在同一包中的保护变量
7 }
8 }

4.默认访问变量
如果在变量前不加任何访问权修饰符,它就具有默认的访问控制特性,也称为friendly变量。它和保护变量非常像,它只允许在同一个包中的其他类访问,即便是子类,如果和父类不在同一包中,也不能继承默认变量(这是默认访问变量和保护变量的唯一区别)。因为它限定了访问权限只能在包中,所以也有人称默认访问权限为包访问权限。
【例3.5】 默认访问变量使用示例。

 1 //-----------文件名declareDefault.java,程序编号3.11------------------
 2 package onlyDemo; //本类定义在包中
 3 public class declareDefault{
 4 int defaultVar=10; //定义一个默认访问变量
 5 void change(){
 6 defaultVar=20; //合法
 7 }
 8 }
 9 onlyDemo包中的其他类,可以访问defaultVar变量:
10 //-----------文件名otherClass.java,程序编号3.12------------------
11 package onlyDemo;
12 public class otherClass{ //它也在包onlyDemo中
13 void change(){
14 declareDefault ca=new declareDefault();
15 ca.defaultVar=20; //合法
16 }
17 }

下面是它的子类,也在onlyDemo包中。它除了可以像包中其他类那样通过“对象名.变量名”来访问默认变量,还可以通过继承的方式来访问。

 1 //-----------文件名deriveClass.java,程序编号3.13------------------
 2 package onlyDemo;
 3 public class deriveClass extends declareDefault{ //定义一个子类
 4 void change(){
 5 //合法,改变的是deriveClass从declarDefault中所继承的defaultVar值
 6 defaultVar=30;
 7 }
 8 }
 9 如果子类不在onlyDemo包中,就不会继承默认变量,也就无法像上面那样来访问。
10 //-----------文件名deriveClass.java,程序编号3.14------------------
11 import onlyDemo.declareDefault;
12 public class deriveClass extends declareDefault{ //定义一个子类
13 void change(){
14 defaultVar=30; //非法,这个变量没有继承下来
15 }
16 }

3.3.3 实例成员变量和静态成员变量
1.实例成员变量
在3.3.2节中,所有的对象都是实例成员变量。它们的最大特色是:如果所属的对象没有被创建,它们也就不存在。如果在类的外部使用它,需要先创建一个对象,然后通过“对象名.变量名”来访问。前面所有的例子都遵循了这一规则。在类的内部,实例成员方法也可以直接访问实例成员变量,比如例3.5,具体原因,将在3.5节中讲述。
不同的对象,拥有不同的实例成员变量,它们互不干扰。
【例3.6】 不同对象的实例成员变量使用示例。

 1 //-----------文件名instanceVar.java,程序编号3.15------------------
 2 public class instanceVar{
 3 protected int instVar=0; //定义一个实例成员变量
 4 }
 5 下面这个类showInstVar用两个对象来访问它的实例成员变量。
 6 //-----------文件名showInstVar.java,程序编号3.16------------------
 7 public class showInstVar{
 8 public static void main(String args[]){
 9 instanceVar one = new instanceVar(); //创建对象one
10 instanceVar two = new instanceVar(); //创建对象two
11 //分别为这两个对象的成员变量赋值
12 one.instVar = 100;
13 two.instVar = 200;
14 //分别显示这两个对象的成员变量值
15 System.out.println("one.instVar="+one.instVar);
16 System.out.println("two.instVar="+two.instVar);
17 }
18 }

程序3.16输出的结果如下:
one.instVar=100
two.instVar=200
从本例中明显地看出,不同对象的成员变量是不相同的,它们互不干涉。
2.静态成员变量
在某些情况下,程序员希望定义一个成员变量,可以独立于类的任何对象,即所有的对象都共用同一个成员变量。由于Java中不能像C一样定义全局变量,因此,Java中引入了静态成员变量。
在成员变量前加上static标识符就可以定义一个静态成员变量。相对于实例成员变量,静态成员变量具有以下特点:
● 它被类的所有对象共享,因此又被称为类变量。
● 它不是属于某个具体对象,也不是保存在某个对象的内存区域中,而是保存在类的公共存储单元。因此,可以在类的对象被创建之前就能使用。
● 它既可以通过“对象名.变量名”方式访问,也可以通过“类名.变量名”的方式访问。它们是完全等价的。
【例3.7】 静态成员变量使用示例。

 1 //-----------文件名staticVar.java,程序编号3.17------------------
 2 public class staticVar{
 3 protected static int stat=0; //定义一个静态成员变量
 4 }
 5 下面这个程序使用不同的方法来访问这个静态变量。
 6 //-----------文件名showStaticVar.java,程序编号3.18------------------
 7 public class showStaticVar{
 8 public static void main(String args[]){
 9 staticVar.stat=100; //通过类名.变量名访问静态变量,无需创建对象
10 System.out.println("staticVar.stat="+staticVar.stat);
11 staticVar one = new staticVar(); //创建对象one
12 staticVar two = new staticVar(); //创建对象two
13 //分别为这两个对象的静态成员变量赋值
14 one.stat = 200;
15 two.stat = 300;
16 //分别显示这两个对象的静态成员变量值
17 System.out.println("one.stat="+one.stat);
18 System.out.println("two.stat="+two.stat);
19 //再通过类来显示静态变量的值
20 System.out.println("staticVar.stat="+staticVar.stat);
21 }
22 }

程序3.18输出结果如下:
staticVar.stat=100
one.stat=300
two.stat=300
staticVar.stat=300
从上述结果中可以看到,静态变量stat是一个公共变量,无论哪个对象改变了它的值,对其他所有该类对象都有效。静态变量的一个重要作用是当作同类各个对象之间传递信息使用,类似于C语言中的全局变量。但这样破坏了数据的封装原则,往往会留下隐患,所以使用这类变量时需要万分谨慎。
静态变量的另一个用途是定义静态常量,比如:
public static double PI = 3.1415926;
这样的静态常量可以无需创建对象就直接使用,省略了创建对象的步骤,类似于C语言中用define定义的常量。这样定义常量,不仅使用方便,而且节省内存空间。在JDK中,存在着大量的这种静态常量。
%说明:本节中所有的成员变量的类型都是基本类型,其实它们也都可以是复合类型,比如数组、类、接口等类型。

时间: 2024-10-05 11:47:21

成员变量的定义与使用的相关文章

面向对象_成员变量和局部变量的区别

作用范围: 局部变量作用于函数中或者语句中(定义在函数或语句中(比如for语句),必须初始化) 成员变量作用于整个类中(定义在类中,有默认初始化值,可以定义显示初始化值) 在内存中的位置: 成员变量在堆内存中.因为对象的存在,才在内存中存在. 局部变量在栈内存中. 如果成员变量没有定义显示初始化,那么系统默认会初始化(在堆内存中的变量都会有默认初始化值)byte 0short 0int 0long 0Ldouble 0.0Dfloat 0.0fboolean false引用数据类型默认初始化值都

【IOS 开发】Object - C 面向对象 - 类 , 对象 , 成员变量 , 成员方法

. 一. 类定义 类定义需要实现两部分 : -- 接口部分 : 定义类的成员变量和方法, 方法是抽象的, 在头文件中定义; -- 实现部分 : 引入接口部分的头文件, 实现抽象方法; 1. 接口部分定义 (1) 接口部分定义格式 接口部分定义格式 : @interface className : superClassName { type _variableName; ... ... } - (type) methodName : type parameterName; @end -- 接口定义

Objective-C之成魔之路【9-类构造方法和成员变量作用域、以及变量】

重开发者的劳动成果,请勿转载 构造方法 出于初始化类中的成员变量的需要, 可以提供一个方法用于此目的, 这个方法就叫构造方法或构造方法(Constructor). 与C++和Java不同, Objective-C命名是没有限制的, 并且有返回值本身类型指针. 以音乐类举例: Song.h文件 @interface Song : NSObject { NSString *title; NSString *artist; long int duration; } //操作方法 - (void)sta

成员变量、实例变量、类变量、成员方法、实例方法、类方法的区别

简单来说:类体的定义包括成员变量的定义和方法的定义. 1.成员变量包括实例变量和类变量:而成员方法包括实例方法.类方法,当然还有一种特殊的构造方法.  2.类变量.类方法就是类中的变量.方法,必须是静态的,要加static:故其又称静态变量 .静态方法.3.成员变量.成员方法是对象或实例中的变量.方法,不加static:  类变量:静态域,静态字段,或叫静态变量,它属于该类所有实例共有的属性,在内存中只有一个地方存储这个变量.而且所有的实例都可以修改这个类变量的值(前提是这个类变量没 有被fin

类成员变量初始化

C++类对象的构造顺序是这样的:分配内存->调用构造函数时,隐式/显式的初始化各数据成员->在构造函数内部初始化数据成员. C++类初始化需注意以下几点 1.类里面的任何成员变量在定义时是不能初始化的.    2.一般的数据成员可以在构造函数中初始化.(构造初始化列表初始化和构造函数体内赋值初始化)    3.const数据成员必须在构造函数的初始化列表中初始化.(道理很简单,const成员第一次数据初始化就是发生在类构造数据初始化时,一旦过了此时就会出现问题).    4.static在类的

(转)成员变量和局部变量有什么区别?

class A { int a;//成员变量 public static void main(String[] args) { int b;//局部变量 } } ———————————————————————————————————————————————————————————————————————————————————————— 类体由2部分构成: 一部分是变量的定义; 一部分是方法的定义(一个类中可以有多个方法) 在变量定义部分定义的变量叫做类的成员变量,成员变量在整个类中都有效. (

Objective-C类成员变量深度剖析

目录 Non Fragile ivars 为什么Non Fragile ivars很关键 如何寻址类成员变量 真正的“如何寻址类成员变量” Non Fragile ivars布局调整 为什么Objective-C类不能动态添加成员变量 总结 看下面的代码,考虑Objective-C里最常见的操作之一——类成员变量访问. - (void)doSomething:(SomeClass *)obj { obj->ivar1 = 42; // 访问obj对象的public成员变量 int n = sel

Java反射机制可以动态修改实例中final修饰的成员变量吗?

问题:Java反射机制可以动态修改实例中final修饰的成员变量吗? 回答是分两种情况的. 1. 当final修饰的成员变量在定义的时候就初始化了值,那么java反射机制就已经不能动态修改它的值了. 2. 当final修饰的成员变量在定义的时候并没有初始化值的话,那么就还能通过java反射机制来动态修改它的值. 实验: 1. 当final修饰的成员变量在定义的时候就初始化了值 1 public Class Person { 2 private final String name = "damon

成员变量跟局部变量

public class Variables { /* * 成员变量跟局部变量的特点 * 成员变量:定义类中有什么,在类中定义,在整个类中都是可见的 * JAVa会给成员变量赋一个初始值 * 局部变量:类的方法中定义,用来临时保存数据,仅限于定义它的方法 * JAVA不会给局部变量赋初始值,不同方法中可以有相同名称的局部变量 * 局部变量的优先级比同名的成员变量高 */ String name;//定义一个name的成员变量不赋值 int age=19;//定义一个age的成员变量,赋值为19