6.1 面向对象概述
6.1.1对象
面向过程:代码紧密,不易分开,可维护性差
面向对象:可维护性强
在程序开发初期人们使用结构化开发语言,但随着软件的规模越来越庞大,结构化语言的弊端也逐渐暴露出来,开发周期被无休止地拖延,产品的质量也不尽如人意,结构化语言已经不再适合当前的软件开发。这时人们开始将另一种开发思想引入程序中,即面向对象的开发思想。面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,同时了解这些对象具有哪些相应的属性以及行为,以解决这些对象面临的一些实际问题,这样就在程序开发中引入了面向对象设计的概念,面向对象设计实质上就是对现实世界的对象进行建模操作。
在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人、书桌、计算机、高楼大厦等。
(1)首先可以从这一问题中抽象出对象,这里抽象出的对象为大雁。
(2)然后识别这个对象的属性。对象具备的属性都是静态属性,如大雁有一对翅膀、黑色的羽毛等。这些属性如图6.1所示。
(3)接着识别这个对象的动态行为,即这只大雁可以进行的动作,如飞行、觅食等,这些行为都是这个对象基于其属性而具有的动作。
(4)识别出这个对象的属性和行为后,这个对象就被定义完成了,然后可以根据这只大雁具有的特性制定这只大雁要从北方飞向南方的具体方案以解决问题
6.1.2 类
不能将所谓的一个事物描述成一类事物,有一只鸟不能称为鸟类,如果需要对同一类事物统称,就不得不说明类这个概念.
类是封装对象属性和行为的载体。反过来说,具有相同属性和行为的一类实体被称为类。
6.1.3 封装
面对对象程序设计具有以下特点:封装性、继承性和多态性。
封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。
6.1.4 继承
类与类之间同样具有关系,这种关系被称为关联。关联主要描述两个类之间的一般二元关系。例如:一个百货公司类与销售员类就是一个关联,学生类与教师类也是一个关联。两个类之间的关系有很多种,继承是关联中的一种。
继承性主要利用特定对象之间的共有属性。在Java语言中,将类似于平行四边形类的类称为子类,将类似于四边形类的类称为父类或超类。值得注意的是,可以说平行四边形是特殊的四边形,但不能说四边形是平行四边形,也就是说子类的实例都是父类的实例,但不能说父类的实例是子类的实例。
6.1.5多态
展现不同多种的形态出现(将父类对象应用与子类的特征就是多态)
多态也是面向对象中一项主要的特征,多态性体现了程序的可扩展性,代码的复用性。
使用图形类来说明多态,每个图形都有拥有绘制自已的能力,这个能力可以看作该类具有的行为,将子类的对象统一看作父类的实例对象,这样子当绘制图形时,简单地调用父类也就是图形类绘制图形方法即可绘制任何图形,这就是多态的最基本思想
提到多态,就不得不提到抽象类和接口,因为多态的实现并不依赖具体类,而是依赖抽象类和接口。在多态的机制中,比抽象类更方便的是将抽象类定义为接口,由抽象方法组成的集合就是接口。
多态的条件:
1.继承或实现
2.方法的重写
3.父类引用指向子类对象
二、类
1.成员变量
对象的属性成为成员变量,可以是任意类型,整个类都是成员变量的作用范围
例6.1
public class Sixone { //类
private String name; //String类型的成员变量
public String getName() {//name的Getter方法
return name;
}
public void setName(String name) {//name的set方法
this.name=name;//将参数的值赋予成员变量
}
}
//6.1例题
静态属性和动态属性
直接写在类里的叫成员变量
6.2.2 成员方法
一个成员方法可以有参数,参数可以是对象,也可以是变量
可以有返回值也可以无返回值
需要返回值使用return关键字
无需返回值,使用void关键字
6.2.3 权限修饰符
getter:拿取和setter:设置鸟类名字 方法(自动生成)
1.右键
2.单击Source
3.单击Generate Getters and Setters
4.勾选
5.点击蓝色Generate,生成成功
6.2.4局部变量
在成员方法内定义一个变量,这个变量称为局部变量
6.2.5:局部变量的有效范围
6.2.6:this关键字
例:6.2
public class ChangeDemo{
public static int[] exchange(int[]arr) {
int tmp=arr[0];//创建局部变量tmp,保存数组第一个元素的值
arr[0]=arr[1];//第二个元素值赋给第一个元素
arr[1]=tmp;//第二个元素值改为tmp
return arr;
}
public static void main(String[]args) {
int arr[]= {17,29};
System.out.print("第一个值="+arr[0]+"第二个值="+arr[1]);
arr = exchange(arr);
System.out.print("第一个值="+arr[0]+"第二个值="+arr[1]);
}
}//例题6.2
public class Bird {//静态属性
//静态属性————成员变量去写
private String name;//名字 //default默认的意思
private String wing;//翅膀
private String mouth;//嘴
private String head;//头
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;//指这个类bird
}
public String getWing() {
return wing;
}
public void setWing(String wing) {
this.wing = wing;
}
public String getMouth() {
return mouth;
}
public void setMouth(String mouth) {
this.mouth = mouth;
}
public String getHead() {
return head;
}
public void setHead(String head) {
this.head = head;
}
运行结果如下:
6.3 :类的构造方法
产生对象但信息不全面(需要传入参数)
//构造方法:调用构造方法创造一个对象
public Bird(String name,String wing,String mouth,String head) { //传入参数//构造了鸟这个类
this.name = name;
this.wing = wing;
this.mouth = mouth;
this.head = head;
}
构造方法的特点如下:
1.构造方法没有返回值
2.构造方法的名称要与本类的名称相同
构造方法的定义语法格式如下:
public Book(){
... //构造方法体
}
public:构造方法修饰符
Book:构造方法的名称
例题6.3
public class EggCake {
int eggCount; //鸡蛋灌饼里蛋的个数
public EggCake(int eggCount) { //参数为鸡蛋灌饼里蛋的个数的构造方法
this.eggCount=eggCount; //将参数eggCount的值赋给属性eggCount
}
public EggCake() { //无参数构造方法,默认给饼加一个蛋
//调用参数为鸡蛋灌饼里蛋的个数的构造方法,并设置鸡蛋灌饼里蛋的个数为1
this(1);
}
public static void main(String[]args) {
EggCake cake1=new EggCake();
System.out.println("顾客不要求加蛋的数量,饼里会有"+cake1.eggCount+"个蛋。");
EggCake cake2=new EggCake(2);
System.out.println("顾客要求加2个蛋,饼里会有"+cake2.eggCount+"个蛋。");
}
}
运行结果如下:
6.4静态变量和静态方法
静态就是static,可以有静态常量、静态变量、静态方法和多个语句静态
静态是这个类的专属,只有这个类可以用,就是这个文件可以用,只要它们在一个文件里就行
例题6.4
package duilian;
public class staticdemo {
static double PI=3.1415926;//静态变量
static final int i=3;//静态常量
static void method() {//在类中定义静态方法
System.out.println("这是静态方法");//打印
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(staticdemo.PI);//调用静态变量
System.out.println(staticdemo.i);
staticdemo.method();
}//调用静态方法
}
注意:虽然静态成员也可以使用 ‘对象、静态成员”的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态成员和非静态成员。
静态变量与静态方法的作用通常是为了提供共享数据或方法,如数学计算公式等。尽管使用这种
方式调用静态成员比较方便,但静态成员同样遵循着public、private和protected修饰符的约束。
例题6.5
package b;
public class s {//类
static int i=0;//共享的属性,人数
String name;//名称属性
public s(String name ) {
this.name=name;//记录名称
i++;//人数递增
}
public static void main(String[] args) {
// TODO Auto-generated method stub
s c1=new s("tom");
System.out.println("我是第"+s.i+++"名顾客,我叫"+c1.name);
s c2=new s("张三");
System.out.println("我是第"+s.i+++"名顾客,我叫"+c2.name);
s c3=new s("狗蛋儿");
System.out.print("我是第"+s.i+++"名顾客,我叫"+c3.name);
}
}
运行结果如下:
如果在执行类时,希望先执行类的初始化动作,可以使用static定义一个静态区域,这块区域放
为静态代码块。当类文件被执行时,会首先执行static块中的程序,并且只会执行一次。静态代码块的
语法如下:
public class example{
static{
... //可以在这里写初始化的代码
}
}
最后总结以下使用static关键字要注意的几点:
在静态方法中不可以使用this关键字。
在静态方法中不可以直接调用非静态方法。
局部变量不可以使用static关键字声明。
主方法必须用static声明。
只有内部类可以使用static关键字声明。
6.5类的主方法
主方法的语法如下:
public static void main(String[] args){
... //方法体
}
在主方法的定义中可以看到其具有以下特性:
主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
主方法没有返回值。
主方法的形参为数且。其中,args[0]~args[n]分別代表程序的第一个参数到第n个参数,可以使用arga.length获取参数的个数。
例题6.6
package duilian;
public class maindemo {
public static void main(String[] args) {//主方法
// TODO Auto-generated method stub
for(int i=0;i<args.length;i++) {//根据参数个数做循环操作
System.out.println(args[i]);//循环打印参数内容
}
}
}
运行结果如下:
运行代码前,需要先设置运行的参数,步骤:
1.右击
2.点击蓝色处
3.选择自变量,输入参数,每个参数空格隔开
6.6对象
使用new操作符调用构造方法创建对象,语法如下:
Test test =new Test();
Test test =new Test("a");
例题6.7
package duilian;
public class people {
String name;//名字
int age;//年龄
String sex;
public people() {//构造方法
}
public people(String name,int age,String sex) {
this.name=name;//记录名称
this.age=age;
this.sex=sex;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
people p1=new people("tom",23,"男");
people p2=new people("liy",19,"女");
}
}
6.6.2访问对象的属性和行为
例题6.8
package duilian;
public class dog {
String name;//名字
String color;//颜色
String vioce;//声音
public dog(String name,String color,String vioce) {
this.name=name;
this.color=color;
this.vioce=vioce;
}
public void call() {//叫
System.out.println(vioce);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
dog d1=new dog("毛毛","白色","汪汪汪");
System.out.println(d1.name+"的颜色是"+d1.color);//对象属性
System.out.println(",叫起来的声音:");
d1.call();//对象行为
dog d2=new dog("灰灰","灰色","嗷呜");
System.out.println(d2.name+"的颜色是"+d2.color);
System.out.println(",叫起来的声音:");
d2.call();
}
}
运行结果如下:
6.6.3 对象的引用
语法:
类名 对象的引用变量
6.6.4 对象的销毁
每个对象都有生命周期,当对象的生命周期结束时,分配给该对象的内存地址需要被回收
何种对象会被Java虚拟机视为“垃圾”。主要包括以下两种情况:
对象引用超过其作用范围,这个对象将被视为垃圾,如图6.13所示
将对象赋值null,如图6.14所示
虽然Java的垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象。某些对象不是通过new操作符在内存中获取存储空间的,这种对象无法被垃圾回收机制所识别。在Java中,提供了一个finalize(方法,这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法。如果用户在类中定义了finalize)方法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。
说明:需要明确的是,垃圾回收或finalize()方法并不保证一定会发生。如果Java虚拟机内存损耗待尽,它将不会执行垃圾回收处理。
由于垃圾回收不受人为控制,具体执行时间也不确定,所以finalize()方法也就无法执行。为此,Java提供了System.gc0方法来强制启动垃圾回收器,这与给120打电话通知医院来救护病人的道理一样,主动告知垃圾回收器来进行清理。