1、3.1 面向对象概述 面向过程方法是围绕实现处理功能的“过程”来构造系统的。然而,用户需求的变化大部分是针对功能的,因此,这种变化对于基于过程的设计来说是灾难性的。用这种方法设计出来的系统结构常常是不稳定的,用户需求的变化往往造成系统结构的较大变化,从而需要花费很大代价才能实现这种变化。3.1 面向对象概述 面向对象的基本思想是认为世界是由各种各样具有自己的功能和内部状态的对象所组成;不同对象之间的相互作用和通信构成了完整的现实世界。因此,软件系统也是由一些具有若干内部状态和功能的对象组成,对象之间通过合作(调用对方的功能)来完成系统功能。3.1.1 面向对象的三要素 类、对象和继承是面向对象
2、的三要素。1、对象、对象例如:一个时钟对象例子对象的属性:属性名 属性值时 18分 30秒 10对象的行为:设置时、设置分、设置秒、显示时间。3.1.1 面向对象的三要素 2、类、类图3-1 时钟类的抽象3.1.1 面向对象的三要素+setHour()+setMinute()+setSecond()+dispTime()-run()-hour:int-minute:int-second:intClock图3-2 时钟类的类图hour:int=18minute:int=30second:int=10北京时钟:Clockhour:int=6minute:int=30second:int=10纽约时
3、钟:Clock图3-3 时钟类的两个对象图3.1.1 面向对象的三要素 3、继承、继承表示继承关系图3-4 类的继承体系人人教教师师学学生生任任课课教教师师教教辅辅人人员员本本科科生生研研究究生生父类子类3.1.2 面向对象的特性 1、封装性、封装性3.1.2 面向对象的三大特性 2、继承性、继承性 继承(Inheritance)是一种联结类与类的层次模型。继承性是指特殊类的对象拥有其一般类的属性和行为。继承意味着“自动地拥有”,即特殊类中不必重新定义已在一般类中定义过的属性和行为,而它却自动地、隐含地拥有其一般类的属性与行为。3.1.2 面向对象的三大特性 3、多态性(、多态性(Polymo
4、rphism)多态有编译时多态和运行时多态。编译时多态是通过方法重载实现;运行时多态是通过方法覆盖实现(子类覆盖父类方法)。通常说的多态是指运行时多态性,是指同一个继承体系中不同类的对象收到相同的消息时产生多种不同的行为方式。3.2 类和对象 3.2.1 类的定义及构成类定义的一般形式类定义的一般形式public class /下面是属性定义public|protected|private ;/其它属性定义/下面是方法定义 public|protected|private 方法名(类型 参数1,类型 参数2,)/方法体/其它方法定义3.2.1 类的定义及构成示例:定义一个简单的示例:定义一个简
5、单的Person类类 class Person private String name;private int age;public void setName(String name)this.name=name;public void setAge(int age)this.age=age;public void speak()System.out.println(I am+name);System.out.println(I am+age+years old);3.2.2 对象的生成生成对象一般有两种方式:方式方式1:类名 对象引用名=null;/声明对象引用对象引用名=new 类名();
6、/实例化对象 例如:Person p1=null;p1=new Person();方式方式2:类名 对象引用名=new 类名();/声明对象引用和实例化对象一步完成 例如:Person p1=new Person();注意:注意:对象引用不是对象,声明对象引用只是分配一个引用空间(用来存放对象的地址)。3.2.3 对象的使用public class ObjectCreateDemopublic static void main(String args)Person p1=new Person();p1.setName(张三);p1.setAge(20);p1.speak();/p1.name=
7、张三;/错误,不能访问对象的 非public成员/p1.age=20;/错误,不能访问对象的 非public成员3.2.3 对象的使用3.2.4 对象的清除public class ObjectCreateDemopublic static void main(String args)Person p1=new Person();/p1指向一个新建的对象Person p2=new Person();/p2指向一个新建的对象p1.setName(张三);p1.setAge(20);p2.setName(李四);p2.setAge(30);System.out.println(p1指向地址:+p1
8、);System.out.println(p2指向地址:+p2);p2=p1;/让p2指向p1所指向的对象,p2原来所指向的对象成为了垃圾对象System.out.println(在p2=p1后,p2指向地址:+p2);3.2.4 对象的清除3.2.4 对象的清除程序的运行结果如下:p1指向地址:Person5c8da962p2指向地址:Person512ddf17在p2=p1后,p2指向地址:Person5c8da962 3.3 成员方法3.3.1 成员方法的定义public|protected|private 方法名(类型 参数1,类型 参数2,)/方法体例如:public void pr
9、int()System.out.println(你好!);3.3.2 成员方法的调用class A public void print()System.out.println(print 被调用了);public class MethodInvokeDemopublic static void main(String args)A a=new A();System.out.println(a对象的print 被调用前);a.print();/调用a对象的print()方法System.out.println(a对象的print 被调用后);程序执行结果如下:a对象的print 被调用前prin
10、t 被调用了a对象的print 被调用后3.3.3 使用return语句返回一个值 当方法需要返回值的时候,方法体中必须有相应的return语句向方法的调用者返回和返回类型一致的数据。return语句只能返回一个值。当方法体中有return语句时,遇到return语句方法执行就结束了。3.3.4 访问器getter方法和更改器setter方法class Person private String name;private int age;public Person()public String getName()return name;public int getAge()return age
11、;public void setName(String name)this.name=name;public void setAge(int age)this.age=age;提示提示:getter方法和setter方法在Eclipse中可以自动生成。3.3.5 成员方法的参数及传值【实例实例3-5】简单数据类型参数传递class A public void setX(int x)/x是形参System.out.println(传进来的值 x=+x);x=5;/形参改变了System.out.println(设置后 x=+x);3.3.5 成员方法的参数及传值public class Meth
12、odArgumentDemo1 public static void main(String args)int m=2;A a=new A();System.out.println(调用setX方法前:m=+m);a.setX(m);/m是实参System.out.println(调用setX方法后:m=+m);3.3.5 成员方法的参数及传值程序执行结果如下:调用setX方法前:m=2传进来的值 x=2设置后 x=5调用setX方法后:m=23.3.5 成员方法的参数及传值【实例实例3-6】引用数据类型参数传递class A private int intValue;public int g
13、etIntValue()return intValue;public void setIntValue(int x)intValue=x;3.3.5 成员方法的参数及传值public class MethodArgumentDemo2 public static void change(A a)/a是形参a.setIntValue(100);public static void main(String args)A a1=new A();a1.setIntValue(50);System.out.println(调用change方法前 a1中intValue的值为:+a1.getIntValu
14、e();change(a1);/a1是实参是实参System.out.println(调用change方法后 a1中intValue的值为:+a1.getIntValue();3.3.5 成员方法的参数及传值程序执行结果如下:调用change方法前 a1中intValue的值为:50调用change方法后 a1中intValue的值为:1003.3.5 成员方法的参数及传值3.3.6 方法重载(Overload)【实例实例3-7】方法重载的例子class MethodOverloading void receive(int i)System.out.println(Receive one in
15、t data:);System.out.println(i=+i);void receive(int x,int y)System.out.println(Receive tow int datas:);System.out.println(x=+x+y=+y);void receive(double d)System.out.println(Receive one double data:);System.out.println(d=+d);void receive(String s)System.out.println(Receive a string:);System.out.print
16、ln(s=+s);3.3.6 方法重载(Overload)public class MethodOverloadingDemo public static void main(String args)MethodOverloading mo=new MethodOverloading();mo.receive(1);/1是int型,匹配上了void receive(int i)mo.receive(2,3);/2和3是int型,匹配上了void receive(int x,int y)mo.receive(12.56);/12.56是double型,匹配上了void receive(doubl
17、e d)mo.receive(very interesting,isnt it?);3.3.6 方法重载(Overload)程序执行结果如下:Receive one int data:i=1Receive tow int datas:x=2 y=3Receive one double data:d=12.56Receive a string:s=very interesting,isnt it?3.4 构造方法3.4.1 构造方法的作用和特点 构造方法是一类特殊得成员方法,构造方法的作用是对对象进行初始化,构造方法是在构造方法是在new一个对象时被自动调用一个对象时被自动调用的的,避免了在生成
18、对象后每次都要调用对象的初始化方法(例如给属性赋值的setter方法)。构造方法的特点:1、构造方法具有和类名相同的名称。原因很简单,自动调用时就靠这一点来找到它。2、构造方法不能声明返回类型。注意不是没有返回类型,而是不能声明返回类型。3、构造方法中除了初始化对象属性的语句外,不应该有其它语句。3.4.2 构造方法的使用【实例实例3-7】通过构造方法来为对象的属性赋初值class Person private String name;private int age;public Person(String name,int age)/构造方法this.name=name;this.age=a
19、ge;/其它成员省略public class ConstructorDemopublic static void main(String args)Person p1=new Person(张三,20);/给对象分配空间后,立刻自动调用构造方法p1.speak();程序执行结果如下:I am 张三I am 20 years old提示提示:构造方法在eclipse中可以自动生成。3.4.3 构造方法重载【实例实例3-8】构造方法的重载class Date private String year;private String month;private String day;/无参构造方法用固定
20、日期值初始化属性public Date()year=“2000;month=1;day=1;/本构造方法用三个参数初始化属性public Date(String year,String month,String day)this.year=year;this.month=month;this.day=day;3.4.3 构造方法重载/本构造方法用一个参数初始化属性public Date(String date)/split是String类的一个方法,用来分割字符串,参数是分隔符String s=date.split(-);year=s0;month=s1;day=s2;public void
21、printDate()System.out.println(year=+year+month=+month+day=+day);3.4.3 构造方法重载public class ConstructorOverloadingDemopublic static void main(String args)Date d1=new Date();/会调用无参构造方法 d1.printDate();Date d2=new Date(2010,10,1);/会调用三个String参数的构造方法 d2.printDate();Date d3=new Date(2020-12-1);/会调用一个String参
22、数的构造方法 d3.printDate();程序执行结果如下:year=2000 month=1 day=1year=2010 month=10 day=1year=2020 month=12 day=13.4.4 缺省构造方法如果程序中没有定义类的构造方法,例如:class Person Java编译器在编译上面的Person类时,会自动添加一个无参数的,什么都不做的构造方法,如下所示:class Person public Person()3.5 this引用3.5.1 什么是this引用 每个类的非静态成员方法(没有被static修饰)中都隐含一个this引用,在通过一个对象调用成员方法
23、时,这个对象我们称为当前对象,这时,当前对象的地址会被赋值给this引用,所以,this引用指向当前对象,也就是调用成员方法的这个对象。class Point private int x,y;public Point(int x,int y)this.x=x;this.y=y;public void setX(int x)this.x=x;public class PointTest public static void main(String args)Point p1=new Point(0,0);Point p2=new Point(1,1);p1.setX(2);p2.setX(5);
24、public Point(Point this,int x,int y)this.x=x;this.y=y;编译器改变了成员方法的定义,在每个类成员方法中添加了this引用。编译后编译后编译后编译后Point p1=new Point(p1,0,0);Point p2=new Point(p2,1,1);编译器改变了成员方法的调用,加上一个额外的实参,即被调用对象的引用。public void setX(Point this,int x)this.x=x;p1.setX(p1,2);p2.setX(p2,5);3.5.2 使用this引用区分对象属性与方法形参class Person priv
25、ate String name;private int age;public Person(String name,int age)this.name=name;this.age=age;3.5.3 使用this引用调用其它构造方法class Date private String year;private String month;private String day;/无参构造方法用固定日期值初始化属性public Date()this(1900,1,1);/调用下面带三个参数的构造方法/本构造方法用三个参数初始化属性public Date(String year,String month
26、,String day)this.year=year;this.month=month;this.day=day;3.5.4 使用this引用表示当前对象class MyDate private String year;private String month;private String day;public MyDate(String year,String month,String day)this.year=year;this.month=month;this.day=day;public boolean compare(MyDate date)if(this=date)return
27、true;/比较当前对象的地址和参数对象的地址 if(this.year=date.year&this.month=date.month&this.day=date.day)return true;else return false;3.6 静态(static)成员 在Java类中用static关键字修饰的成员称为静态成员,静态成员包括静态属性(或类属性)和静态方法(或类方法)。3.6.1 静态属性或类属性静态属性或类属性的特点如下:静态属性或类属性的特点如下:1、静态属性不在对象中,也不是对象状态的一部分,或者说它和对象无关。2、静态属性是与类有关的,整个类只有一份,第一次使用类时(如通过“
28、类名.静态属性”方式访问类属性或第一次把类实例化对象时等)在类的公共区给类属性分配存储空间。3、使用静态属性无需创建类的对象,虽然可以通过“对象名.静态属性”方式访问静态属性,但建议通过“类名.静态属性”方式访问静态属性。3.6.1 静态属性或类属性【实例实例3-9】静态属性的例子class Person public static int count=0;/这是一个静态属性public Person()count+;public class StaticFieldDemopublic static void main(String args)System.out.println(Person
29、.count);Person p=new Person();new Person();new Person();System.out.println(Person.count);/System.out.println(p.count);/不建议使用对象访问静态属性3.6.1 静态属性或类属性静态属性有下面两种用途:1、这个类的所有对象所共享的变量,通常声明为、这个类的所有对象所共享的变量,通常声明为private访问访问方式。方式。2、用、用final声明为常量,并且声明为声明为常量,并且声明为public访问方式,可以通过访问方式,可以通过“类名类名.类属性类属性”方式在程序的任意位置使用它
30、。方式在程序的任意位置使用它。其中,上面第二种用途使用得更多一些,例如Java系统类库java.lang包中的Math类,包含了一些常用的静态属性,如:public static final double E=2.7182818284590452354;public static final double PI=3.14159265358979323846;3.6.2 静态方法或类方法静态方法的特点如下:1、静态方法属于一个类而不是属于实例对象。2、静态方法与类对象无关,在创建对象之前就可以使用“类名.静态方法”来调用静态方法。3、静态方法中没有this引用,所以在静态方法中不能使用this引
31、用,也就不能直接使用对象属性和调用对象方法。4、静态方法中可以访问静态属性和其它静态方法。5、静态方法使用“类名.静态方法”方式在类外来调用,所以应该定义为public访问方式。3.6.2 静态方法或类方法【实例实例3-10】静态方法的例子class A public static int i=0;/这是一个静态属性public int j=0;/这是一个对象属性public static void f1()System.out.println(“我是一个静态方法);i+;/可以直接访问静态属性/j+;/对象属性不能直接访问/f2();/对象方法不能直接访问public void f2()Sy
32、stem.out.println(我是一个对象方法);3.6.2 静态方法或类方法public class StaticMethodDemopublic static void main(String args)A.f1();/在创建对象之前就可以使用“类名.静态方法”来调用类方法A a=new A();a.f1();/可以,但不建议使用对象访问静态方法3.6.2 静态方法或类方法 常常把常常把静态方法作为工具来使用。方法作为工具来使用。许多Java系统类库中的类包含这样的方法,典型的如java.lang包中的Math类,它包含了完整的数学函数,如sin、cos等三角函数、指数函数exp、对数
33、函数log,平方根函数sqrt等等,我们可以通过Math类直接使用,例如:double x=Math.sin(12);double y=Math.sqrt(24);3.6.3 理解main方法与主类public class MainArgumentsDemo public static void main(String args)String name1=args0;/第一个命令行参数String name2=args1;/第二个命令行参数System.out.println(你们好 +name1+和+name2);一般把程序入口main方法单独定义在一个public类中(类中除了main方法
34、没有其它成员),习惯上把这个类称为主类或应用程序类。3.6.4 单例(Singleton)设计模式 单例模式确保某一个类只有一个对象,而且自行实例化并向整个系统提供这个对象,这样的类称为单例类。1、单例类的用途、单例类的用途 系统中的一些公用的数据结构包括一些链表、队列、表格,或软件中的属性文件等应该由一个对象来管理,以避免同时操作带来的错误。例如:Windows的回收站3.6.4 单例(Singleton)设计模式 2、如何实现单例类、如何实现单例类 我们知道,类是生成对象的模版,每次用new操作符就可以生成类的一个对象。那么如何让类只有一个对象呢?3.6.4 单例(Singleton)设计
35、模式【实例实例3-11】一个单例类的例子class Singleton/定义一个单例类/类属性,在类内自己 new 一个本类对象private static Singleton instance=new Singleton();public static Singleton getInstance()/返回对象的静态方法return instance;public String printMessage()return 我代表一个功能,已完成!;private Singleton();/私有构造方法3.6.4 单例(Singleton)设计模式public class SingletonDem
36、o/利用SingletonDemo 类实现单例类的测试public static void main(String args)/调用单例类的静态方法获取对象Singleton s1=Singleton.getInstance();/调用对象的方法System.out.println(s1.printMessage();/再调用单例类的静态方法获取对象Singleton s2=Singleton.getInstance();/测试两回返回的对象是否为同一个对象System.out.println(s1=s2 +(s1=s2);/下面这样是错误的,编译会出错!/Singleton s3=new S
37、ingleton();程序运行结果如下:我代表一个功能,已完成!s1=s2 true3.7 内部类 定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类的特性:内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类命和$符号。内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。3.7.1 成员内部类成员内部类一般只是在外部类内实例化使用。例如:class Outer private int i=10;public void makeInner()Inner in=ne
38、w Inner();in.seeOuter();class Inner public void seeOuter()System.out.print(i);3.7.2 匿名内部类 匿名内部类,顾名思义,没有名字的内部类。在窗口应用编程中特别常见,主要用来事件的处理。3.7.2 匿名内部类(1)继承式的匿名内部类 class Car public void drive()System.out.println(Driving a car!);class Test public static void main(String args)Car car=new Car()public void dri
39、ve()System.out.println(Driving another car!);car.drive();结果输出了:Driving another car!3.7.2 匿名内部类(2)接口式的匿名内部类 interface Vehicle public void drive();class Test public static void main(String args)Vehicle v=new Vehicle()public void drive()System.out.println(Driving a car!);v.drive();3.7.2 匿名内部类(3)参数式的匿名内
40、部类 class Bar void doStuff(Foo f)interface Foo void foo();class Test static void go()Bar b=new Bar();b.doStuff(new Foo()public void foo()System.out.println(foofy););3.8 包(package)一个Java源文件中定义了A类、B类、C类、D类,那么编译后,会在这个Java源文件所在文件夹下生成A.class、B.class、C.class、D.class字节码文件。如果多个Java源文件中有相同名字的类,那么编译后生成的类的字节码文件
41、会发生命名冲突问题。3.8.1 理解包的作用 为了便于管理大型软件系统中数目众多的类,解决类命名冲突问题,Java引入了包(package)。包其实就对应于文件系统中的文件夹,包的作用如下:u解决类命名冲突问题。u把类分门别类地组织到相应的包中,方便管理、维护和保护。JDK类库中提供了大量的类,就采用包进行管理的。3.8.2 如何创建包在Java中用关键字package来创建包。【格式】package pkg1.pkg2.pkg3;例如:package com.my.util;【注意注意】程序中如果有package语句,该语句一定是源文件中的第一条可执行语句,它的前面只能有注释或空行。另外,一
42、个文件中最多只能有一条package语句。3.8.3 编译使用包的程序例如,在MyClass.java 源程序中有如下语句:package com.my.util;编译生成的字节码文件将放在目录pathcommyutil 下。path在编译时指定:C:javac -d path MyClass.java例如:C:javac -d D:MyJavaFile MyClass.java编译生成的字节码文件将放在D:MyJavaFilecommyutil 下。3.8.4 使用import引入包中的类使用不在一个包中的类,需要使用import语句引入这个类。【格式】import package1.pac
43、kage2.(classname|*);【说明】1、编译import语句时,编译器会从系统classpath环境变量所设置的类路径中去查找package1package2。2、classname指明所要引入的类,例如:import java.awt.Button;3、“*”表明要从一个包中引入所有类,例如:import java.awt.*;【注意注意】Java编译器为所有程序自动引入包java.lang,因此不必用import语句引入它包含的所有类,但若需要使用其它包中的类,必须用import语句引入。3.8.5 包访问控制方式 package除了有避免命名冲突的问题外,还引申出一个包访问控
44、制方式,Java访问控制方式有4种:public,protected,private,另外加上一个缺省的包访问控制方式。在类中定义成员时,如果没有加上public或protected或 private这三种修饰符来修饰的,就是包访问控制方式。3.9 字符串类 Java语言中,把字符串作为对象来处理。Java类库中的类String和StringBuffer、StringBuilder分别用于处理不变字符串和可变字符串。3.9.1 String类【实例实例3-12】String对象的不变性public class TestStringDemo public static void main(Str
45、ing args)String s=Hello;s=Java;String s1=Java;String s2=new String(Java);System.out.println(s);System.out.println(s=s1);System.out.println(s=s2);程序运行结果如下:Javatruefalse表表3-1 String类中一些比较常用的方法类中一些比较常用的方法序号序号方法方法描述描述1public int length()返回此字符串的长度2public char toCharArray()将此字符串转换为一个新的字符数组3public char cha
46、rAt(int index)返回指定索引处的字符4public byte getBytes()将此字符串转换为一个byte 数组5public String trim()返回字符串的副本,去除前导空白和尾部空白6public String substring(int beginIndex)从指定索引处的字符开始截取,直到此字符串末尾。7public String substring(int begin,int end)截取从begin 处开始,直到索引 end-1 处的字符串8public int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引9publi
47、c int indexOf(String str,int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始10public String split(String regex)根据给定正则表达式的匹配拆分此字符串11public String toLowerCase()将此 String 中的所有字符都转换为小写12public String toUpperCase()将此 String 中的所有字符都转换为大写13public boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始14public boolean
48、 endsWith(String suffix)测试此字符串是否以指定的后缀结束15public boolean equals(String str)将此字符串与指定的字符串比较16public boolean equalsIgnoreCase(String str)将此字符串与指定的字符串比较,不考虑大小写17public String replaceAll(String regex,String replacement)使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串3.9.1 String类获取字符串的长度:public class LengthDemo
49、 public static void main(String args)String str=string length;/定义一个字符串 System.out.println(+str+的长度是:+str.length();程序运行输出:string length 的长度是:133.9.1 String类字符串的比较:public class EqualsDemo public static void main(String args)String str1=hello;/定义一个字符串String str2=new String(hello);System.out.print(“str1
50、=str2”+(str1=str2);/比较地址/比较内容System.out.println(“,str1 equals str2+(str1.equals(str2);程序运行输出:str1=str2:false,str1 equals str2:true3.9.1 String类字符串和字符数组的转换:public class ToCharArrayDemo public static void main(String args)String str=ABCDEFG;/定义一个字符串char chars=str.toCharArray();/将字符串变为字符数组for(int i=0;i