540 likes | 705 Views
第五章 Java 高级语言特征. 静态变量、方法与初始化程序块 final 关键字 抽象类 Interface package 访问控制 内部类 其它. 类变量( static /class variable). static 关键字可以用来修饰类的成员变量、成员方法 和内部类 这些类成员的创建和使用, 与类相关而与类的具体实例 不相关 因此,以 static 修饰的变量或方法又称为 类变量或者类方法. com. e2. e1. e3. com. com. com.
E N D
第五章 Java 高级语言特征 静态变量、方法与初始化程序块 final 关键字 抽象类 Interface package 访问控制 内部类 其它
类变量(static /class variable) • static 关键字可以用来修饰类的成员变量、成员方法 • 和内部类 • 这些类成员的创建和使用,与类相关而与类的具体实例 • 不相关 • 因此,以static 修饰的变量或方法又称为类变量或者类方法
com e2 e1 e3 com com com 类变量(static /class variable) 类变量在该类所有实例之间是共享的。在加载该类时, 只分配一次空间,并初始化。 例:class Employee { … static int com ; … } 则运行时,
类变量(static /class variable) 类变量可用来在实例之间进行通信或跟踪该类实例的数目。 例:public class Count{ private int serialNumber ; private static int counter = 0 ; public Count( ){ counter++ ; serialNumber = counter ; } } 程序示例
类变量(static /class variable) 类变量可以是public 或private 对于public 类型的类变量,可以在类外直接用类名调用而不需要初始化。 Public class StaticVar{ public static int number ; } public class Otherclass{ public void method(){ int x = StaticVar.number ; } }
类(class/static)方法 在类的成员方法声明中带有static关键字的方法称为类方法 或静态方法,可以直接被调用,而不需要生成任何实例 public class GeneralFunction{ public static int addUp(int x, int y){ return x+y ; } } public calss UseGeneral{ public void method(){ int c = GeneralFunction.addUp(9,10); } }
类(class/static)方法 • 类方法的编写与使用时应注意的问题: • 因为静态方法的调用不是通过实例对象进行的,所以在静态 • 方法中没有this指针,不能访问所属类的非静态变量和方法 • 子类不能重写父类的静态方法,但在子类中可以声明与父类 • 静态方法相同的方法,从而将父类的静态方法隐藏 • 子类不能把父类的非静态方法重写为静态的
类(class/static)方法 class ClassA{ public void methodOne(int i) {} public void methodTwo(int i){} public static void methodThree(int i){} public static void methodFour(int i){} } Class ClassB extends ClassA{ public static void methodOne(int i){} //错误!将ClassA中的methodOne()变成静态的 public void methodTwo(int i) {} public void methodThree(int i){} //错误!不能重写ClassA中的静态方法 public static void methodFour(int i){} //正确!将ClassA中的methodFour()方法隐蔽 }
类(class/static)方法 • Main()方法是一个静态方法 • 它是程序的入口点 • JVM不创建实例对象就可以运行该方法
静态初始化程序 没有存在于任何方法体中的静态语句块,在加载该类时执行且只执行一次。 public Class StaticInitDemo{ static int i=5; static { System.out.println(“Static code: i=”+ i++); } } public class Test { public static void main(String args[]){ System.out.println(“ Main code: i=”+ StaticInitDemo.i); } } Static code: i=5 Main code: i = 6 程序示例
final 关键字 • 被定义成final的类不能有子类。 • 例: final class Employee { • … • } • class Manager extends Employee{ …} • 被定义成final 的成员方法不能被重写。 • 定义为final的方法可以使运行时的效率优化。对于final • 方法,编译器可以直接调用方法的代码,从而阻止运行 • 时刻对方法调用的动态联编 • 被定义成final的成员变量不能改变。该变量实际上 • 是常量,一般大写,并赋值。 • final int NUMBER = 100;
抽象类 Java中允许在类中只声明方法而不提供方法的实现。 这种只有声明而没有方法体的方法称为抽象方法 包含一个或多个抽象方法的类称为抽象类。 必须在声明中增加 abstract 关键字,在无方法体的方法前 也要加上abstract。 Public abstract class Drawing{ public abstract void drawDot( int x, int y); public void drawLine(int x1, int y1, int x2,int y2) {... // 调用drawDot()方法 } } 抽象类也可有普通的成员变量或方法。
抽象类 抽象类不能直接用来生成实例。 如果抽象类的子类实现了抽象方法,可以创建子类的实例 对象,否则该子类也是抽象类,也不能创建实例。 可以生成抽象类的变量,该变量可以指向具体的一个 子类的实例。 abstract class Employee{ abstract void raiseSalary(int i) ; } class Manager extends Employee{ void raiseSalary(int i ){ ….} } Employee e = new Manager( ) ;
抽象类 抽象类不能直接用来生成实例。 如果抽象类的子类实现了抽象方法,可以创建子类的实例 对象,否则该子类也是抽象类,也不能创建实例。 abstract class Employee{ abstract void raiseSalary(int i) ; } class Manager extends Employee{ void raiseSalary(int i ){ ….} } Employee e = new Manager( ) ; //创建Employee子类Manager的对象 Employee e=new Employee(); //错误!Employee为抽象类
接口 interface Interface 是在抽象类概念的基础上演变而来的。 一个interface所有成员方法都是抽象的,并且只能 定义 static final 成员变量。
接口 interface • Public:任意类均可以使用该接口 • 缺省情况下只有与该接口定义在同一包中类才能访问该接口
Interface 的含义 • interface定义了一组行为的协议。两个对象之间通过这个协议进行通信。 • interface 不属于类层次结构。不相关的类可以实现相同的接口。
实现interface 用implements代替extends声明子类,该子类中必须实现接口(及其超类)中的所有方法。 例:interface SayHello{ void printMessage( ); } class SayHelloImpl implements SayHello{ void printMessage( ){ System.out.println(“Hello”); } }
接口与多重继承 可以通过实现接口实现多重继承:一个类可只继承 一个父类,并实现多个接口。 interface I1{ … }; interface I2{ …}; class E{ ….} ; class M extends E implements I1,I2 { …}
接口与多重继承 抽象或具体父类 interface_1 … interface_2 interface_n 父类方法 interface_1 interface_2 … interface_n 子类
Interface 示例 interface Flyer interface Sailer takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) Vehicle Airplane RiverBarge takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) SeaPlane Helicopter dock ( ) cruise ( )
Interface 示例 interface Flyer interface Sailer takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) Vehicle Airplane RiverBarge takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) SeaPlane Helicopter dock ( ) cruise ( )
Interface 示例 interface Flyer interface Sailer takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) Vehicle Airplane RiverBarge takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) SeaPlane Helicopter dock ( ) cruise ( )
Interface 示例 interface Flyer interface Sailer takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) Vehicle Airplane RiverBarge takeoff ( ) land ( ) fly ( ) dock ( ) cruise ( ) SeaPlane Helicopter dock ( ) cruise ( )
Interface的使用 • Interface可以作为一种数据类型使用。 如: public interface StockWatcher { final String sunTicker = "SUNW"; final String oracleTicker = "ORCL"; final String ciscoTicker = "CSCO"; void valueChanged(String tickerSymbol, double newValue); } public class StockMonitor { public void watchStock(StockWatcher watcher, String tickerSymbol, double delta) { ... } }
Interface 与多态 • 一个interface 可作为类名使用,实现多态。 Interface Human{ …} class Chinese implements Human{ …} class Japanese implements Human{…} ... Human e = new Chinese( ); Human e = new Japanese( ); e.showNameInNativeLanguage(); …
Interface 中注意问题 • 不能向interface定义中随意增加方法,需要通过继承扩展方法 public interface StockWatcher { final String sunTicker = "SUNW"; final String oracleTicker = "ORCL"; final String ciscoTicker = "CSCO"; void valueChanged(String tickerSymbol, double newValue); void currentValue(String tickerSymbol, double newValue); } public interface StockTracker extends StockWatcher { void currentValue(String tickerSymbol, double newValue); }
Interface 中注意问题 • 直接向接口中扩展方法可能带来的问题: 所有实现原来接口的类将因为接口的改变而不能正常工作
接口与抽象类 • 抽象类与接口有一定的相似性,但也有很大的区别 (1)接口中的所有方法都是抽象的,而抽象类可以定义带有方法体的不同方法 (2)一个类可以实现多个接口,但只能继承一个抽象类 (3)接口与实现它的类不构成类的继承体系,及接口不是类体系的一部分,不相关的类也可以实现相同的接口;而抽象类属于一个类的继承体系,并且一般位于类体系的顶层
使用接口的优点 使用接口的优点在于: (1)通过实现多个接口可以实现多重继承 (2)能够抽象出不相关类之间的相似性,而没有强行形成类的继承关系
类分组package 语句 包(package)是相关类与接口的一个集合,它提供访问控制与命名空间管理。 Java平台中的类与接口都是根据功能以包组织的。 包机制的好处: • 程序员容易确定包中的类是相关的,并且容易根据所需的功能找到相应的类。 • 每个包都创建一个新的命名空间,因此不同包中的类名不会冲突。 • 同一个包中的类之间有比较宽松的访问控制。
创建包 • 用package语句指定源文件中的类属于一个特定包: • package 包名 • 包定义语句在每个源程序中只能有一条, 即一个类只能属 • 于一个包。 • 包定义语句必须在程序的第一行(之前可有空格及注释)。 • 包名用“.” 分隔。
包成员的使用 • 包中的成员是指包中的类和接口 • 只有public类型的成员才能被包外的类访问 • 要从包外访问public类型的成员需要以下两种方法 • (1)引入包成员或者整个包,然后使用短名(类名或者接口名)引入包成员 • (2)使用长名(由包名+类名或者接口名组成)引用包成员
包成员的使用 使用短名将package 引入源程序,格式: import 包名.*; import 包名. 类名; import 语句必须在源程序之前,在package 声明之后。 [ package ….. ] //缺省是package . [import …. ] //缺省是import java.lang.* [类声明… ] ...
包成员的使用 使用长名引用包成员,格式: 包名.类名 例如:如果当前程序要访问graphics包中的Circle类,但该类并未通过import语句引入,可使用graphics.Circle来引入Circle类 graphics.Circle myCircle =new graphics.Circle(); 这种方式过于烦琐,一般只有当两个包含有同名的类时,为了对两个同名类加以区分才使用长名,如果没有这种需要,一般使用短名来引入所需要的类,然后再随后的程序中直接使用类名对类进行操作
引入其他类的静态成员 • 如果程序中需要频繁使用其他类中定义为static final的常量 或者static方法,则每次引用这些常量或者方法都要出现他们所属的类名,会使得程序显得比较混乱。 • Java中提供了static import 语句,使得程序中可以引入所需的常量和静态方法,这样程序中对他们的使用就不用再带类名 • 例如:java.lang.Math类定义了常数PI以及很多静态方法 • 引入:import static java.lang.math PI; • 或者 import static java.lang.Math.*; • 引入后可以直接使用:double r = cos (PI*theta ); • 不引用的情况下:double r=Math.cos (Math.PI * theta);
包名与包中类的存储位置 包分隔符相当于目录分隔符,包存储的路径由包根路径加上包名指明的路径组成 包的根路径由CLASSPATH环境变量指出 package abc.financeDept %CLASSPATH%\abc\ financeDept
源文件(.java)与类文件(.class)的管理 源文件可以按照包名指明的路径放置。如 类文件也将放在反映包名的一系列目录下。
源文件(.java)与类文件(.class)的管理 一般将源文件与类文件分别存放,可采用如下方式: 示例
高级访问控制 成员变量和方法有4种访问级别: public, protected, default(package), private ; 类有两种访问级别:public 或default。 修饰符的作用范围: Modifier Same class Same Package Subclass Universe public Yes Yes Yes Yes protected Yes Yes Yes default Yes Yes private Yes
高级访问控制--private class Alpha { private int iamprivate; private void privateMethod() { System.out.println("privateMethod"); } } class Beta { void accessMethod() { Alpha a = new Alpha(); a.iamprivate = 10; a.privateMethod(); } } // illegal // illegal
高级访问控制——protected 允许类本身、它的子类、以及同一个包中其余的类访问这些成员。 package Greek; public class Alpha { protected int iamprotected; protected void protectedMethod() { System.out.println("protectedMethod"); } } package Greek; class Gamma { void accessMethod() { Alpha a = new Alpha(); a.iamprotected = 10; a.protectedMethod(); } } // legal // legal
高级访问控制——protected package Greek; public class Alpha { protected int iamprotected; protected void protectedMethod() { System.out.println("protectedMethod"); } } package Latin; import Greek.*; class Delta extends Alpha { void accessMethod(Alpha a, Delta d) { a.iamprotected = 10; d.iamprotected = 10; a.protectedMethod(); d.protectedMethod(); } } X √ X √
高级访问控制——package package Greek; class Alpha { int iampackage; void packageMethod() { System.out.println("packageMethod"); } } package Greek; class Beta { void accessMethod() { Alpha a = new Alpha(); a.iampackage = 10; a.packageMethod(); } } √ √
内部类 内部类是在一个类的声明里声明的类。 Class A { … class B { … } … } 内部类可作为类的一个成员使用。一般只在包容类中 调用。 内部类可以访问外包类的所有成员。
= = 运算符与equals( )方法 equals() 和 = = 比较两个引用是否指向相同的对象。 equals()方法在String, Date, File, 所有Wrapper类都重 写了该方法,改为比较内容。
Wrapper类 Wrapper将基本类型表示成类。 每个wrapper类对象都封装了基本类型的一个值。 Primitive Data Type Wrapper Class boolean Boolean byte Byte char Character short Short int Integer long Long float Float double Double
Wrapper类 Wrapper类中包含了很多有用的方法和常量。 如数字型Wrapper类中的MIN_VALUE 和 MAX_VALUE 常量,定义了该类型的最大值与最小值。byteValue, shortValue方法进行数值转换,valueOf 和 toString 实现字符串与数值之间的转换。 例:Wrapper类对象的创建: Integer quantity = new Integer(123456); Double amount = new Double(345987.246);
JDK1.6中的自动装箱与拆箱 • 装箱(Box):把基本类型的数据通过相应Wrapper类形成对象 • 拆箱(Unbox):把一个Wrapper类对象中的基本数据类型提取出来。 • 自动装箱与拆箱 Integer i = 10; int j = i;
Collection API -- 集合类(请注意作业) 一个集合类对象表示了一组对象,相当于一个容器。