3.3 Java的非访问控制符 Java的非访问控制符 static 静态修饰符 修饰属性和方法 abstract 抽象修饰符 修饰类和方法 final 最终修饰符 修饰类、属性和方法 3.3.1 静态属性、静态方法与静态初始化器 static是静态修饰符。 (1)静态属性 被static修饰的属性不属于任何一个类的具体对象,是公共的存储单元。任何对象访问它时,取到的都是相同的数值。静态属性是类属性。 当需要引用或修改一个static限定的类属性时,可以使用类名,也可以使用某一个对象名,效果相同。
(2)静态方法 用static修饰符修饰的方法,是属于整个类的方法。 例如,在PhoneCard200中如果需要修改附加费,可以定义一个静态方法setAdditory( ): static void setAdditory ( double newAdd) { if(newAdd > 0) additoryFee = newAdd; } 用static修饰的方法的含义: 1)调用这个方法时应该使用类名做前缀,不用某个具体的对象名; 2)该方法属于整个类,它在内存中的代码段随着类的定义而分配和装载; 3)该方法不能操纵属于某个对象的成员变量,即static方法只能处理static属性。
(3)静态初始化器 直接用static 当名字、用{ }包起来的一段特殊代码。与构造函数类似,完成初始化工作,但两者的区别是: 静态初始化器对每个类初始化,构造函数对每个新创建的对象初始化。 静态初始化器在所属的类加载入内存时由系统调用运行,构造函数则在产生新对象时由系统自动执行。 静态初始化器不是方法,没有方法名、返回值和参数列表。 总之,静态初始化器对整个类完成初始化操作,包括给static类成员赋初值。
例 TestStatic.java //测试静态属性、静态方法与静态初始化器的综合例题 public class TestStatic { public static void main(String args[]) PhoneCard200 my200_1 = new PhoneCard200(100.0); PhoneCard200 my200_2 = new PhoneCard200(200.5); //测试静态初始化器 System.out.println("第1张200卡的卡号:"+my200_1.cardNumber); System.out.println("第1张200卡的金额:"+my200_1.balance); System.out.println("第1张200卡的附加费:"+my200_1.additoryFee); System.out.println("第1张200卡的密码:"+my200_1.password); System.out.println("第2张200卡的卡号:"+my200_2.cardNumber); System.out.println("第2张200卡的金额:"+my200_2.balance); System.out.println("第2张200卡的附加费:"+my200_2.additoryFee); System.out.println("第2张200卡的密码:"+my200_2.password);
System.out.println("---------直接操作修改静态属性:测试静态属性"); my200_1.additoryFee = 0.4; //直接操作修改对象的静态属性,可以实现对类和其它同类对象同一属性的修改 System.out.println("第2张200卡的附加费:"+my200_2.additoryFee); System.out.println("200卡类的附加费:"+PhoneCard200.additoryFee); System.out.println("第1张200卡类的附加费:"+my200_1.additoryFee); System.out.println("------调用静态方法修改静态属性:测试静态方法"); PhoneCard200.setAdditory(0.6); //调用静态方法修改类的静态属性,可以实现其所有同类对象同一属性的修改 System.out.println(“修改后第1张200卡类的附加费: "+ my200_1.additoryFee); System.out.println("修改后第2张200卡的附加费:"+ my200_2.additoryFee);
System.out.println("--------测试修改密码的各种方法"); my200_2.password=222; //用普通赋值法给对象的非静态属性赋值 System.out.println("第2张200卡的密码:"+my200_2.password); //对该对象的非静态属性操作有效 System.out.println("第1张200卡的密码:"+my200_1.password); //对其它同类对象的非静态属性操作无效 // PhoneCard200.password=333; //用普通赋值法给类的非属性赋值,编译不能通过 my200_2.changePwd(666); //调用类中的方法实现密码的修改 System.out.println("第2张200卡的密码:"+my200_2.password); //对该对象的非静态属性操作有效 }
class PhoneCard200 //定义类:PhoneCard200 { static long nextCardNumber; static String connectNumber = "200"; static double additoryFee; //静态属性 long cardNumber ; int password=111; boolean connected; double balance; PhoneCard200(double bi) //构造函数 cardNumber = nextCardNumber++; balance=bi; } static //静态初始化器 nextCardNumber = 2001800001; additoryFee=0.2;
static void setAdditory(double newAdd) //静态方法 { if(newAdd>0) additoryFee=newAdd; //password=6666; //静态方法不能操作非静态变量 } int changePwd(int pwd) //普通方法 password=pwd; return pwd;
3.3.2 抽象类与抽象方法 (1)抽象类 用abstract修饰的类或方法。 没有具体实例对象的类。 使用抽象类的优点就是可以充分利用公共属性来提高开发和维护程序的效率。 例:我们以交通工具类作为例子,它代表了所有具体交通工具的共同属性,如速度、加速、减速等。 交通工具 陆地交通工具 海上交通工具 空中交通工具 自行车 汽车
java语句可表述为: abstract class transportmeans { float speed; //速度 void start() //启动 { ... } void stop() //停止 float speedUp(float increaseSpeed) //加速 }
(2)抽象方法 用abstract声明的仅有方法头而没有具体的方法体和 操作实现的抽象方法。 方法体的具体实现由当前类的不同子类在各自的类定义中完成。 只能把abstract方法作为一个共同的接口。 所有的抽象方法必须存在于抽象类中。 使用abstract方法可以隐藏具体的细节信息。
例 TestAbstract.java public class TestAbstract //抽象类与抽象方法的使用 { public static void main(String args[]) PhoneCard200 my200 = new PhoneCard200(50.0); //用PhoneCard200的构造函数初始化对象my200 PhoneCard200 my2002 = new PhoneCard200(60.0); //用PhoneCard200的构造函数初始化对象my2002 IC_Card myIC = new IC_Card(50.0); //用IC_Card的构造函数初始化对象myIC System.out.println("200卡可以拨打 "+my200.TimeLeft()+" 次电话。"); System.out.println("IC 卡可以拨打 "+myIC.TimeLeft()+" 次电话。"); System.out.println("第1张200卡的卡号:"+my200.cardNumber); System.out.println("第2张200卡的卡号:"+my2002.cardNumber); System.out.println("第2张200卡可以拨打 "+my2002.TimeLeft()+" 次电话。"); }
abstract class PhoneCard //抽象类 { double balance; abstract void performDial(); //抽象方法,不需要定义方法体 // void performChangePwd(); //出错,要么加上abstract,要么定义方法体 double TimeLeft() //一般方法,需要定义方法体,计算可以拨打的次数 double current = balance; int times = 0; do performDial(); //调用抽象方法 times++; }while(balance>=0); balance = current; return times-1; }
class PhoneCard200 extends PhoneCard { static long nextCardNumber; static final String connectNumber = "200"; static double additoryFee; long cardNumber ; int password; boolean connected; static //静态初始化器,初始化类 nextCardNumber = 2001800001; additoryFee = 0.1; } PhoneCard200(double ib) //PhoneCard200的构造函数 cardNumber = nextCardNumber++; balance = ib; void performDial() //子类PhoneCard200实现的抽象方法 balance -= 0.5+additoryFee; //abstract void performChange(); //出错,非抽象类不可以定义抽象方法
class IC_Card extends PhoneCard { IC_Card(double ib) //IC_Card的构造函数 balance = ib; } void performDial() //子类IC_Card实现的抽象方法 balance -= 0.8;
3.3.3 最终类、最终属性、最终方法 用final最终修饰符来修饰类、属性和方法。 (1)最终类——不可能有子类 语法:static final double additoryFee=0.1; 注意: 需要说明常量的数据类型 需要同时指出常量的具体取值 为了节省空间,常量通常被声明为static
(3)最终方法——功能和语句都不能被修改的最终方法,即不能被当前类的子类重载。目的是为了预防不必要的重复定义。 例:final double getAdditoryFee() { return additoryFee; } 注意:所有已被private修饰符限定为私有的方法,以及所有包含在final类中的方法,都被缺省地认为是final的。
例:TestFinal.java //最终类、最终方法、最终属性、终结器的综合例题 public class TestFinal { public static void main(String args[]) PhoneCard200 my200_1 = new PhoneCard200(100.0); PhoneCard200 my200_2 = new PhoneCard200(200.5); System.out.println("第1张200卡的卡号:"+my200_1.cardNumber); System.out.println("第1张200卡的金额:"+my200_1.balance); System.out.println("第1张200卡的附加费:"+my200_1.additoryFee); System.out.println("第1张200卡的密码:"+my200_1.getAdditoryFee()); System.out.println("第2张200卡的卡号:"+my200_2.cardNumber); System.out.println("第2张200卡的金额:"+my200_2.balance); System.out.println("第2张200卡的连接号:"+my200_2.connectNumber); my200_1.setAdditory(0.9); System.out.println("修改后第2张200卡的连接号:"+my200_2.connectNumber); //my200_1.additoryFee = 0.4; //出错,不能给对象的最终属性赋值 //PhoneCard200.setAdditory(0.6); //出错,不能修改对象的最终属性 IC_Card myIC = new IC_Card(50.0); System.out.println("IC 卡可以拨打 "+myIC.TimeLeft()+" 次电话。"); }
final class PhoneCard //定义为final 最终类,则下面的IC卡不能定义为其子类 ,若定义为抽象类 ,IC卡可以为子类 { double balance; //abstract void performDial(); //final中不能定义抽象方法 double TimeLeft() //一般方法,需要定义方法体,计算可以拨打的次数 double current = balance; int times = 0; do // performDial(); //不能调用该方法 times++; }while(balance>=0); balance = current; return times-1; }
class PhoneCard200 //定义类:PhoneCard200 { static long nextCardNumber; static String connectNumber = "200"; static final double additoryFee=0.5; //静态最终属性,被赋值后就不可以再修改 //这里如果不赋值,可以在静态初始化器中修改 long cardNumber ; int password=222; boolean connected; double balance; PhoneCard200(double bi) //构造函数 cardNumber = nextCardNumber++; balance=bi; } static //静态初始化器 nextCardNumber = 2001800001; //additoryFee=0.2; //出错,如果定义时没有赋初值才可以
static void setAdditory(double newAdd) //静态方法 { if(newAdd>0) //additoryFee=newAdd; //不能操作最终变量 connectNumber = "300"; } final double getAdditoryFee() //最终方法 return additoryFee; void performDial() //PhoneCard200的方法 balance -= 0.5+additoryFee; /*class IC_Card extends PhoneCard //PhoneCard被定义为final则不能有子类 IC_Card(double ib) //IC_Card的构造函数 balance = ib; void performDial() //子类IC_Card的方法 balance -= 0.8; }*/