再回首: Java关键字 数据类型:byte boolean char double float int long short , 特殊的值: false true void null length 程序流程控制: if else 、 switch case、 break default、do – while、for 、continue、return 类的定义:class extends implements import interface package super this 非访问控制符:abstract final static native 特殊运算符: instanceof new 访问控制符:public private protected 异常处理:try catch finally throw throws 线程:thread transient synchronized
第3章 Java面向对象编程基础 3.1 面向对象程序设计的基本概念 3.2 类与对象 3.3 访问控制符与非访问控制符 3.4 继承与多态 3.5 包 3.6 接口 3.7 异常处理 3.8 Java基础类与工具类
3.1 面向对象程序设计的基本概念 面向对象程序设计是当前程序设计的主流方向,它力求按照人类的思维方式对现实世界中的客观事物进行抽象和表达,并且把对客观事物的表达和对它的操作处理结合为一个有机的整体,即“对象”。 核心思想: 用面向对象的编程语言把现实世界的实体描述成计算机能理解、可操作的、具有一定属性和行为的对象,将数据及数据的操作封装在一起,通过调用各对象的不同方法来完成相关事件。
Student 张凌=new Student () 学生 Class Student { } 对象、实体与类
对象(Object)是类的实例 面向对象的几个基本概念: 类(Class)是现实世界或思维世界中的实体在计算机中的反映,是对具有相似性质的一批对象的归纳和抽象,代表的是一类事物。 如:汽车、手机、电脑 对象(Object)是类的实例 如:路上在开的某辆车、你手里的手机、教室里的这台电脑
事件(Event)——由对象识别的一个外部动作,如:ActionEvent(动作事件),单击按钮或在文本框中回车都可以响应该事件 属性( Property )——是对象的特征,包括状态和行为 事件(Event)——由对象识别的一个外部动作,如:ActionEvent(动作事件),单击按钮或在文本框中回车都可以响应该事件 静态属性——“状态”,在计算机内用变量表示 对象 属性 动态属性——“行为”,在计算机内用方法表示
类与对象的关系 “人”类和对象“李四”的关系
对象的之间关系 包含——当对象A是对象B的属性时,称对象B包含对象A; 如:发动机与汽车, CPU与计算机 继承——当对象A是对象B的特例时,称对象A继承了对象B 如:北京大学和大学,液晶显示器和显示器 关联——当对象A的引用是对象B的属性时,称对象A和对象 B之间是关联关系。 如: 汽车与制造商
面向对象的软件开发过程 面向对象的软件开发过程可以大体划分为三个阶段: 面向对象的分析(object oriented analysis,OOA) 面向对象的设计(object oriented design,OOD) 面向对象的实现(object oriented programming,OOP) Peter Coad and Edward Yourdon,
面向对象程序设计的四个特点: 面向对象程序设计的三大优点: 抽象性——采用数据抽象的方法来构建程序的类、对象和方法 封装性——将数据和基于数据的操作封装在一起 继承性——一个类可以从其它已有的类中派生 多态性——一个程序中可以有同名的不同方法共存 面向对象程序设计的三大优点: 可重用性 可扩展性 可管理性
3. 2 类和对象 类属于一种抽象的数据类型,是Java程序的基本组成要素,其基本成分包括: 对象是由类模块创建的,其基本组成包括: 3. 2 类和对象 类属于一种抽象的数据类型,是Java程序的基本组成要素,其基本成分包括: 成员变量 成员方法 (如:人,性别,吃饭) 对象是由类模块创建的,其基本组成包括: 对象标识(对象的名字,也叫对象的引用) 状态(对象的静态属性) 行为(对象的动态属性) (如:张三,男,狼吞虎咽的吃饭) 编写Java程序就是一个编写类和创建对象的过程
类的封装 类由属性(域)和方法构成,是Java编程的基础 类既要提供与外部联系的接口,同时又要尽可能隐藏类的实现细节。 类 属性(数据) 方法(操作数据)
类定义 { 成员变量声明 //属性的声明 方法声明 } public abstract final [修饰符] class 类名 [extends 父类] [implements 接口名] { 成员变量声明 //属性的声明 方法声明 } public abstract final
属性的定义 [修饰符] 数据类型 变量名[=值]; int x = 3, y; //定义了整型变量x和y [修饰符] 数据类型 变量名[=值]; int x = 3, y; //定义了整型变量x和y Date today ; //定义了Date型类变量today char [] m ; //定义了字符型数组m
方法的定义 方法由方法头和方法体构成: { //方法体 } [修饰符] 返回值类型 方法名([参数列表]) 形参 可为各种类型, 或者空类型 void, 表示无返回值
方法的参数 形参:可以方便地从外部向方法提供信息。 编写方法时,要说明方法的所有形参名和形参的类型。 void setIncome (double d) { salary = d; }
classDemo.java 成员变量 构造方法 成员方法 public class ClassDemo { int a; int b; } void show() System.out.println(“a=”+a+”,b=”+b); public static void main(String args[]) new ClassDemo(). show(); 成员变量 构造方法 成员方法
类的完整定义示例 Person类 class Person name sex salary Age Person() getName() { String name; //姓名 int sex; //性别 private double salary; //薪水 int age; //年龄 Person类 name sex salary Age Person() getName() setIncome( ) public Person(String s1){ name=s1; } String getName() { return name; void setIncome (double d) { salary = d;
构造方法 构造方法是类的一种特殊方法,主要作用是在创建对象时,进行必要的初始化。 特点: 方法名必须与类名相同 没有返回值类型,也没有void 在用户创建对象时,由系统自动调用执行,用户不能直接调用构造方法。
引入构造方法的原因: 1) 满足面向对象程序设计中对象初始化的需要; 2) 提高灵活度,使初始化工作除赋值外有更复杂的操作; 在不定义构造方法时,系统会自动为该类生成一个默认的构造方法。
构造方法的定义 Person类的构造方法: public Person(String s1) { name=s1; }
缺省构造 类中可以不出现构造方法,如果没有构造方法,系统将为该类缺省定义一个空构造方法,也称为缺省构造方法。用缺省构造方法初始化对象时,系统用缺省值初始化类对象的数据成员。 各数据类型的缺省值如下: 数值型:0 布尔型:false 字符型:’\0’ 类:null
对象的定义 对象实例化的语法为: 下面是对象实例化的例子: Person myPerson = new Person(“孙悟空”); 类名 objectName = new 构造方法名([参数列表]); 下面是对象实例化的例子: Person myPerson = new Person(“孙悟空”); 为对象分配内存空间,同时调用类的构造方法对该对象进行初始化
firstPerson.name = “Henry”; 对象的使用 可以用点(.)操作符来调用对象实例的成员变量和方法 1.成员变量的引用 成员变量引用的形式如下: 对象名.成员变量名 例如可以通过赋值语句修改firstPerson.name的值: firstPerson.name = “Henry”;
2.方法的调用 对象的方法调用的一般形式如下: 对象名.方法名( 参数列表) 例如: firstPerson.setIncome(5000); 实参 实参
参数传递示例 值传递
参数传递 ⑴ 值传递 ⑵引用传递 调用方法时,参数是普通变量,实参将其值传给形参,调用中实参的值不受形参的影响。 调用方法时,参数的类型为复合数据类型,如:数组、类。实参随形参的变化而变化。
引用传递 public class SquareC { void square(int x[]) int s=0; for(int i=0;i<x.length;i++) x[i]=i*10; } public static void main(String args[]) int n[]=new int[5]; SquareC a=new SquareC(); for(int i=0;i<5;i++) n[i]=i; System.out.print(n[i]+" "); System.out.println(); a.square(n); 引用传递
对象的使用总结 对象是一个动态概念,具有产生、使用和消亡的生命周期 通过new操作符创建对象 对象属性的使用: 对象方法的使用: 对象名.属性 对象方法的使用: 对象名.方法名() 当对象不再使用时,将由系统的垃圾回收机制进行回收。
每个对象“总是”有不同的身份,一个类的多个对象“可能”有不同的状态 如何理解 “对象”? 对象的行为是什么?——方法 对象的状态是什么?——属性 对象的身份是什么?——名称 状态可能影响行为 每个对象“总是”有不同的身份,一个类的多个对象“可能”有不同的状态 三方面特征
变量的作用域 在方法体中定义的变量称为局部变量,它只能被定义它的方法内部访问。而成员变量可以被类中的所有方法访问。 成员变量随对象的创建而创建,局部变量在方法被调用时创建,在方法调用结束后销毁。 与成员变量不同,局部变量使用前,必须进行初始化。 局部变量的名字可以与成员变量相同 。
成员变量 不同方法中的同名局部变量互不影响 class AreaVarity { int vary1,vary2; int Multiply() int z; z=vary1*vary2; return z; } int Sum() z=vary1+vary2; 成员变量 不同方法中的同名局部变量互不影响 public static void main(String args[]){ AreaVarity a=new AreaVarity(); a.vary1=1; a.vary2=2; System.out.print(a.vary1+" "); System.out.println(a.vary2); System.out.println(a.Multiply()); System.out.println(a.Sum()); }
局部变量的名字可以与成员变量相同 public class EqualVarible{ int i=2; //此处i为成员变量 加this表达 成员变量 public class EqualVarible{ int i=2; //此处i为成员变量 void mv(){ int i=6; //此处i为局部变量 System.out.println("i="+i); } public static void main(String args[]){ EqualVarible k = new EqualVarible(); k.mv(); System.out.println("this.i="+this.i); this:指代当前对象,常用形式this.域变量,表示引用当前对象的某域变量
变量的作用域 形参名可以与类的成员变量名相同,如果相同,那么形参名将在方法体内隐藏同名的成员变量。 public class Rectangle{ double x; //成员变量 double y; //成员变量 double computeArea(double x, double y){ double s; s = x*y; return s; } } 局部变量 如何调用computeArea方法? 请编写main方法,以调用computeArea方法
课堂练习: 1.编写一个车辆类,其中包括2个成员变量:车辆类别、轮胎数量,2个成员方法:分别用来设置车辆类别和轮胎数量。 2. 编写一个Java Application程序,实现车辆对象的创建,并调用其成员方法将所创建车辆的“车辆类别”设置为“长公交”、轮胎数量设置为6,要求通过字符界面输出所创建与设置的结果。
类中的“变量”概念辨析: (1)成员变量: 在类体变量定义处定义的变量,在整个类内都有效; 成员变量包括实例变量和类变量,用static定义的变量是类变量,也叫静态变量; 所有对象独享实例变量,但共享类变量; 实例变量只能通过对象名访问,类变量既可以通过某个对象名也可以通过类名来访问。 (2)局部变量: 在类的方法中定义的变量,仅在定义它的方法内有效
类中的“方法”概念辨析: (1)实例方法: (2)类方法: 实例方法既可以操作实例变量,也可以操作类变量; 实例方法在创建类对象后才分配入口地址; 实例方法可以被类创建的任何对象访问,必须通过对象来调用;实例方法可以调用其它方法(包括类方法)。 (2)类方法: 用static修饰的方法是类方法,也叫静态方法; 类方法只能操作类变量; 类方法在类被加载到内存后就分配了入口地址; 类方法可以被类创建的任何对象调用,也可以通过类名来调用,类方法只能调用该类的类方法。
3.3 访问控制符与非访问控制符 访问控制符是一组限定类、域和方法是否可以被程序内和程序之外的部分访问和调用的修饰符 ,用来规定类、域和方法是否可以被外界访问和调用。 非访问控制符表示专门的特性,说明类或成员 的构成特点。
3.3.1 访问控制符 用于成员变量和方法的: 用于类的: 访问控制符规定的权限共有四个: public private protected 缺省 (即没有定义访问控制符)。 用于成员变量和方法的: public protected private 缺省 用于类的: public 缺省
public public——“公有的、公共的”,它不仅可以修饰类,还可以修饰变量和方法。
private private——私有的,修饰域和方法。
编译时 报错
protected 关键字protected修饰的域和方法能被以下三种类访问和调用: 域和方法所在的类。 同一个包内的其它类。 其它包(package)中该类的子类。
缺省的修饰符 如果一个类、域和方法前面没有被访问控制符修饰,说明它具有缺省的访问控制特性(包访问特性) : 域和方法所在的类。 同一个包内的其它类。
成员变量和方法的访问控制 成员变量和方法的访问控制符有: private、缺省、protected、public private √ 访问指示 本 类 本类所在包 子类 所有 private √ 缺省 protected public √
同一包内的访问示意图:
包间的访问示意图:
ClassB, ClassC, ClassD分别可以访问ClassA的哪些成员变量? 成员变量和方法的访问控制举例 包1 包2 public int v1; protected int v2; int v3; private int v4; ClassA ClassC ClassB ClassD extends ClassA ClassB, ClassC, ClassD分别可以访问ClassA的哪些成员变量?
总 结 在声明类时,通常将成员变量声明为private权限,仅允许本类的方法访问成员变量,而将方法声明为public权限,供其他类调用。 总 结 在声明类时,通常将成员变量声明为private权限,仅允许本类的方法访问成员变量,而将方法声明为public权限,供其他类调用。 构造方法一般声明为public权限。
3.3.2 Java的非访问控制符 Java的非访问控制符 static 静态修饰符:属性和方法 abstract 抽象修饰符:类和方法 final 最终修饰符:类、属性和方法
对比: 未加static修饰的成员变量叫实例变量 静态属性不属于任何一个类的具体对象,是公共的存储单元。任何对象访问它时,取到的都是相同的值。 引用static修饰的类变量时,既可以使用类名,也可以使用某一个对象名,效果相同。 对比: 未加static修饰的成员变量叫实例变量
public Student(String m, String s) name=m; sex=s; id+=1; count=id; } public class TestStudent { public static void main(String args[]) Student s1=new Student(“张华”, “女”); Student s2=new Student(“丁一”, “男”); System.out.println(s1.count); System.out.println(s2.count); System.out.println(Student.id); } class Student { String name; //实例变量 String sex; //实例变量 static int id=0; //类变量 int count; //实例变量 public Student(String m, String s) name=m; sex=s; id+=1; count=id; } s1.id ?
总 结 实例变量属于对象,只能通过对象名引用 如: s1.count 类变量属于类,既可以通过类名访问,也可以通过对象名访问 总 结 实例变量属于对象,只能通过对象名引用 如: s1.count 类变量属于类,既可以通过类名访问,也可以通过对象名访问 如: Student.id s1.id
(2)静态方法(类方法) 被static修饰的方法,是属于整个类的方法。 类方法的使用: 相对于:实例方法 (2)静态方法(类方法) 被static修饰的方法,是属于整个类的方法。 类方法的使用: 1)调用类方法时可以使用类名做前缀,也可以用对象名作前缀,但后者不推荐; 2)类方法属于整个类,它在内存中的代码段随着类的定义而分配和装载,类方法可以看做是一个类的所有对象的公共行为; 3)类方法中只能调用类方法,不能调用实例方法(可以利用对象名进行调用);实例方法既可以调用类方法,也可以调用实例方法。
能否通过编译? double perimeter(double x, double y) //实例成员方法 如果将print_messgae()更改为静态方法,是否能通过编译? double perimeter(double x, double y) //实例成员方法 { return 2*(x+y);} static double area(double x, double y) //类成员方法 { returen x*y; } void print_message() //实例成员方法 { System.out.println(perimeter(2.1,3.5)); System.out.println(area(2.1,3.5)); } static void print_message( )
static int square (int x){ int s; s=x*x; return(s); } int n=5; public class SquareC{ static int square (int x){ int s; s=x*x; return(s); } public static void main(String args[]){ int n=5; int result=square(n); System.out.println(result); int result=square(n);
4)类方法只能访问本方法中的局部变量和静态域(类变量),不能访问实例变量和方法。 class TestStaticFunc{ int x; //实例成员变量 static int getx(){ return x; } static void setx(int t){ x=t; } }
class TestStaticFunc{ static int x; //类成员变量 static int getx(){ //类成员方法 System.out.println(“the value of x is ”+x); return x; } static void setx(int x){ //类成员方法 x=t; public static void main(String args[]){ TestStaticFunc ts=new TestStaticFunc(); ts.x=40; TestStaticFunc.getx(); ts.getx(); TestStaticFunc.x=78;
static { } (3)静态初始化器 与构造函数类似,完成初始化工作,但两者的区别是: 静态初始化器对每个类初始化,构造函数对每个新创建的对象初始化。 静态初始化器在所属的类加载入内存时由系统调用运行,构造函数则在产生新对象时由系统自动执行。 静态初始化器不是方法,没有方法名、返回值和参数列表。
//测试静态初始化器 class PhoneCard200 //定义类:PhoneCard200 { static long nextCardNumber; //起始编号 long cardNumber ; //卡号 double balance; //卡上金额 static //静态初始化器 nextCardNumber = 2001800001; } PhoneCard200(double bi) //构造函数 cardNumber = nextCardNumber++; balance=bi; 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("第2张200卡的卡号:"+my200_2.cardNumber); System.out.println("第2张200卡的金额:"+my200_2.balance);
最终修饰符 final final可修饰类、属性和方法。 1)最终类 用final修饰的最终类不能有子类。 2)最终属性 用final修饰的最终属性在整个执行过程中都不会变,一般用来修饰常量。修饰常量时需要说明常量的数据类型和常量的具体取值。为了节省空间,常量通常还同时被声明为static。 3)最终方法 用final修饰的最终方法其功能和语句都不能再被修改,即不能被当前类的子类重载。目的是为了预防不必要的重复定义。
用final修饰的类不能被继承; 用final修饰的成员方法不能被覆盖; 用final修饰的成员变量不能被修改。
例 继承final类 final class C1 { int i; public void print() System.out.println("i="+i); } public class C2 extends C1 double x; public double getX() { return x; }
抽象修饰符abstract abstract可修饰类或方法。 1)抽象类 抽象类是没有具体实例对象的类,主要用来实现类之间的继承关系。 使用抽象类的优点就是可以充分利用公共属性来提高开发和维护程序的效率。 2)抽象方法 抽象方法仅有方法头而没有具体的方法体,方法体的实现由当前类的不同子类在各自的类定义中完成。抽象方法只能存在于抽象类中。
抽象类示例 Shape circumference area getArea() getGirth() Square Triangle width height getArea( ) getGirth( ) Triangle A b c getArea( ) getGirth( ) Circle r getArea( ) getGirth( )
抽象类与抽象方法的关系 抽象类中可以有0个或多个抽象方法,也可以包含非抽象的方法。 抽象类中可以没有抽象方法,但是,有抽象方法的类必须是抽象类。 抽象类派生的子类中必须实现抽象类中定义的所有抽象方法。
修饰符混用注意事项 abstract不能与final并列修饰同一个类。 abstract不能与private、static、final并列修饰同一个方法。
基本类型的参数传递——值传递 换 x ? public class Change { static int i=5; public static void main(String args[]) System.out.println("Bfore change i is "+i); change(i); System.out.println("After change i is "+i); } public static void change(int i) i=10; } 程序执行后,显示结果是什么?为什么? 换 x ?
对象类型的参数传递——引用传递 class Employee { private String name; private double salary; Employee(String name,double income) { this.name=name; salary=income;} void raiseSalary(double d) salary=salary+d; } public String toString() return name+"的工资是:"+salary; public class TestReference { public static void Value(Employee e) e.raiseSalary(200); } public static void main(String args[]) Employee zhang=new Employee("张三” ,6000); Value(zhang); System.out.println(zhang.toString()); 黑板图示。
3.5 继承与多态 3.5.1 类的继承 3.5.2 类的多态性
3.5.1 类的继承 继承是一种由已有的类创建新类的机制。 3.5.1 类的继承 继承是一种由已有的类创建新类的机制。 在类的继承中,被继承的类称为父类,继承而来的类则称为子类。父类和子类之间反映的是“一般与特殊”的关系。 子类继承父类所有非private的属性和方法,同时也可以在父类的基础上添加新的属性和方法。 Java中,一个父类可以同时拥有多个子类,但一个类只能继承一个父类,称为单重继承。
在 Java 中,类的层次结构为树型结构,其中Object为树型结构的根类,所有其他类都直接或间接地继承自Object类。 …… 父类 Person Teacher Student Employee …… …… 子类
1 继承的实现 定义子类的形式为: public、abstract、final [修饰符] class 类名 extends 父类名 { 类体 } public、abstract、final
1 继承的实现 类的继承原则如下: 子类继承父类的非私有成员变量,包括实例成员变量和类成员变量。 子类继承父类的非私有成员方法,包括实例成员方法和类成员方法。 子类可以重新定义父类成员。
子类的派生 class Base1 { int x=3; } class Base2 extends Base1 { int y=5; class Ext extends Base2 { int z=7; public class ExtDemo1 { public static void main(String args[]) { Ext ext=new Ext(); System.out.println(“x=”+ext.x+”y=”+ext.y+”z=”+ext.z);
1 继承的实现 class Employee { String name; char sex; int age; protected double salary; public double getSalary() return salary; } public void modiSalary(double a) salary=salary+a; class Teacher extends Employee { String speciality; public String getSpeciality() return speciality; } public void setSpeciality(String s) speciality=s;
1 继承的实现 Employee Teacher getSalary() getSalary() modiSalary() String name char sex int age double salary getSalary() modiSalary() Teacher String name char sex int age double salary String speciality getSalary() modiSalary() getSpeciality() setSpeciality()
类在继承时会遇到的问题: 如何处理同名变量? 如何处理同名方法?
属性的继承与隐藏 (1)属性的继承:子类可以从父类直接继承属性,无需复制定义。 (2)属性的隐藏:如果子类重新定义了与父类同名的属性变量,此时将出现子类变量对同名父类变量的隐藏。 对同名属性的处理原则: 子类执行继承自父类的方法时,处理的是继承自父类的变量。 子类执行自己所定义的方法时,操作的是子类定义的变量,而把继承自父类的变量“隐藏”起来。如果要操作继承自父类的同名变量时,可使用super引导。
属性的隐藏 子类可以定义与父类同名的属性,以此来实现对父类属性的隐藏。 class Base { int x = 3; public void m() { x++; System.out.println("Base的x值为:"+x); } class Derived extends Base { double x = 20; public void n() { x--; System.out.println("Derived的x值为"+x); public class TestFieldHide{ public static void main(String[] args){ Derived d = new Derived(); System.out.println("Derived对象的域x的值为:"+d.x); 子类可以定义与父类同名的属性,以此来实现对父类属性的隐藏。
2 super 与 this super 引用父类成员变量 引用父类成员方法 引用父类构造方法 super.成员变量名
2 super 与 this this 引用当前对象的成员变量 引用当前对象的成员方法 引用当前对象的构造方法 this.成员变量名
3.5.2 多态性 多态性指同一名字的方法可以有多种实现,即不同的方法体。 多态表现为: 重载(overload) 覆盖(override) 重载:①同一类中有多个同名方法(形参表不同) ②子类和父类中存在同名方法(形参表不同)。 覆盖:子类和父类中存在同名方法(同名、同形参表、同返回值类型)。 多态性指同一名字的方法可以有多种实现,即不同的方法体。 多态表现为: 重载(overload) 覆盖(override)
(2)多态 多态是指一个程序中同名的不同方法共存的情况。 实现多态的途径: 1)覆盖( override )——在子类中对从父类继承的方法进行重新定义,即重写。 2)重载( overload )——在同一个类中定义多个同名的定义内容不同但最终功能相同的方法。 比如,程序中定义多个名为 print方法,用来打印不同类型的数据,如字符型、数值型等。 区分同名方法的措施:采用不同的形式参数列表,包括形式参数的个数、类型、顺序的不同。 注意:只是改变方法的返回值类型不改变参数是不行的。
1 方法的重载 重载是指在同一类中、父类与子类中,多个方法具有相同的方法名,但采用不同的形式参数列表,包括形参的个数、类型或顺序不同。 调用方法时,系统是通过方法名和参数列表(包括类型、顺序和数目)来区分不同的方法,确定所调用的具体方法。
1 方法的重载 正确的重载方法头: 错误的重载方法头: public double area(double r) public double area(int a, double b) public double area(double a, int b) 错误的重载方法头: public int volume(int a, int b) public void volume(int x, int y)
1 方法的重载 例如,计算圆、三角形和长方形的面积,可以定义具有以下方法头的3个重载方法: public double area(double r) public double area(double a, double b, double c) public double area(double a, double b)
方法重载例子 public class TestPoly1 { int add(int a,int b) { return a+b; } double add(double a,double b) { public static void main(String args[]) { TestPoly1 tp=new TestPoly1(); System.out.println(“Sum is:”+tp.add(8,5)); System.out.println(“Sum is:”+tp.add(8.3,4.2)); 不仅普通方法可以重载,构造方法也可以重载。一个类中定义几个构造方法,只要构造方法的参数列表不同即可。构造方法重载可以方便灵活地为对象进行初始化。
3.5.3 final类和final成员 用final修饰的类不能被继承; 用final修饰的成员方法不能被覆盖;
1 final类 出于安全性考虑,有些类不允许被继承,不能有子类,称为final类。 在下列情况下,通常将类定义为final类: 具有固定作用,用来完成某种标准功能的类。 类的定义已经很完美,不需要再生成其子类。 final class 类名 { 类体 }
例 继承final类 final class C1 { int i; 程序编译时的错误信息如下: public void print() System.out.println("i="+i); } public class C2 extends C1 double x; public double getX() { return x; } 程序编译时的错误信息如下: 无法从最终 C1 进行继承 public class C2 extends C1 ^ 1 错误
2 final成员方法 有些方法不允许被覆盖,也就是不能在子类的内部重写该方法,称为final方法。
例 覆盖final方法。 编译出错 class Mother{ int x=100,y=20; public final void sum() { int s; s=x+y; System.out.println("s="+s); } public class Children extends Mother int m=20,n=30; public void sum() int f; f=m+n; System.out.println("f="+f); public static void main(String arg[]) { Children aa=new Children(); aa.sum(); } 编译出错
3 final成员变量 如果一个变量被final修饰,则其值不能改变,成为一个常量。如果在程序中企图改变其值,将引起编译错误。如: final int i=23; 在程序中不能再给i赋值,否则产生编译错误。 一般都结合static修饰符进行修饰。 final static int i=23;
3.5.4 抽象类和抽象方法 在面向对象程序设计中,越是处在继承结构的顶层的类,就越概括、越抽象。我们常常需要定义一些表示抽象概念的类,这些类为子类提供一个实现框架,本身却不能提供具体的实例,这称为抽象类。
abstract double getArea(参数表 ); 3.5.4 抽象类和抽象方法 用 abstract 关键字修饰的类,称为抽象类。 抽象类只能被继承,不能实例化。 若A是抽象类,则以下语句错误: A a=new A( ) ; 用abstract 关键字修饰的方法,称为抽象方法。 抽象方法只写出其方法名和类型,不写其方法体。 abstract double getArea(参数表 );
3.5.4 抽象类和抽象方法 抽象类中可以有0个或多个抽象方法,也可以包含非抽象的方法。 3.5.4 抽象类和抽象方法 抽象类中可以有0个或多个抽象方法,也可以包含非抽象的方法。 抽象类中可以没有抽象方法,但是,有抽象方法的类必须是抽象类。 抽象类派生的子类中必须实现抽象类中定义的所有抽象方法。
抽象类示例 Shape width height getArea() getGirth() Square width height Triangle width height c getArea( ) getGirth( ) Shape width height getArea() getGirth() Circle width height r getArea( ) getGirth( )
3.5.4 抽象类和抽象方法 abstract不能与final并列修饰同一个类。 3.5.4 抽象类和抽象方法 abstract不能与final并列修饰同一个类。 abstract不能与private、static、final并列修饰同一个方法。
5.3 Java的字符串 5.3.1 String类 Java中字符串常量用String类的对象表示,对所有用双引号括起的字符串常量,系统都会创建一个无名的String类。 (1)创建字符串常量String对象 创建String对象时,通常需要向String类的构造函数传递参数来指定所创建的字符串的内容。 String类的构造函数: 1)public String()——创建一个空的字符串常量 2)public String(String value)——利用一个已经存在的字符串常量创建一个新的String对象,该对象的内容与给出的字符串常量一致。
3)public String(StringBuffer buffer)——利用一个已经存在的StringBuffer对象为新建的对象String初始化。 4)public String(char value[ ])——利用已经存在的字符数组的内容初始化新建的String对象。 创建实例: ① String s; //声明一个对象s s=new String(“ABC”); //为s赋值 ② String s=new String(“ABC”); //声明的同时赋值 ③ String s= “ABC”; //简化的直接赋值方法
(2)字符串常量的操作 求字符串的长度的方法: public int length(); 例: String s=“Study”,s1=“学习”; System.out.println(s.length( ));//显示5 System.out.println(s1.length( ));//显示2 注意:在java中,每个字符(不论中文还是西文)都是占用16个比特的Unicode字符,故都只要一个字符表示。 (3)判断字符串的前缀和后缀 public boolean startsWith(String prefix); public boolean endsWith(String suffix); 这两个方法分别用来判断当前字符串的前缀和后缀是否为指定的字符子串。
例:String s=User.getID(); if (s.startsWith(”320705”)) { System.out.println(“此人是连云港的”); } (4)字符串中单个字符的查找 public int indexOf(int ch); 从前往后查找字符ch在当前字符串中第一次出现的位置,并返回字符ch出现的位置,若找不到返回-1。 public int indexOf(int ch,int fromIndex); 在当前字符串中自fromIndex位字符之后向后查找,并返回该字符首次出现的位置。 与上面对应的从后往前找的方法: public int lastindexOf(int ch); public int lastindexOf(int ch,int fromIndex);
(5)字符串中子串的查找 public int indexOf(String str); public int indexOf(String str,int fromIndex); public int lastindexOf(String str); public int lastindexOf(String str,int fromIndex); 获取字符串中某个(index表示位置)字符的方法: public char charAt(int index); (6)连接字符子串 public String concat(String str); 将参数字符串连接在当前字符串的尾部。 例:String s=“早上好,”; System.out.println(s.concat(”同学们”));
(7)比较两个字符串 public int compareTo(String anotherString); 若当前字符串与参数字符串完全相同/大于/小于时,则返回0/1/-1。 public boolean equals(Object anObject); 比较两个字符串,区分大小写,相同时返回真值,否则为假。 public boolean equalsIgnoreCase(String anotherString); 比较两个字符串,忽略大小写,相同时返回真值,否则为假。 例:String s1=“Hello”, s2=“hello”; boolean b1=s1.equals(s2); //返回假 boolean b1=s1.equalsIgnoreCase (s2); //返回真
5.3.2 StringBuffer类 用来存放字符串变量的对象属于StringBuffer类。 构造函数: public StringBuffer( ); 创建一个空StringBuffer对象,需要扩充后才可以使用。 public StringBuffer(int length); 创建一个长度为length的StringBuffer对象。 public StringBuffer(String str); 利用一个已存在的字符串String对象来初始化StringBuffer对象。
(2)字符串变量的扩充、修改与操作 追加的方法: public StringBuffer append(参数对象类型 参数对象名); 将指定的参数对象转化成字符串,附加在原StringBuffer字符串对象之后。 插入的方法: public StringBuffer insert(int 插入位置,参数对象类型 参数对象名); 在指定位置插入给出的参数对象所转化而得的字符串。 附加或插入的参数对象可以是各种数据类型的数据。 如果希望将StringBuffer在屏幕上显示出来,则必须首先调用toString方法把它变成字符串常量。
修改的方法: public void setCharAt(int index, char ch); 将指定位置处的字符用给定的另一个字符来替换。 (3)字符串的赋值和加法 String MyStr=“Hello,”; MyStr = MyStr +”World”; 相当于: String MyStr= new StringBuffer(). append(“Hello,”).toString(); MyStr= new StringBuffer(). append(MyStr) .append(“World,”).toString();