第6章 面向对象编程基础

6.1 面向对象概述

        在程序开发初期人们使用结构化开发语言,但随着软件的规模越来越庞大,结构化语言的弊端也逐渐暴露出来,开发周期被无休止地拖延,产品的质量也不尽如人意,结构化语言已经不再适合当前的软件开发。这时人们开始将另一种开发思想引入程序中,即面向对象的开发思想。面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,同时了解这些对象具有哪些相应的属性以及行为,以解决这些对象面临的一些实际问题,这样就在程序开发中引入了面向对象设计的概念,面向对象设计实质上就是对现实世界的对象进行建模操作。

  1. 方法:将具有独立功能的代码块组成一个整体,使其具有特殊功能的代码集
  2. 方法必须先创建才能使用,该过程称为方法定义
  3. 方法创建后并不是直接运行,需要手动使用后才执行,该过程称为方法调用

6.1.1对象

        在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机、高楼大厦等。人类解决问题的方法总是将复杂的事物简单化,于是就会思考这些对象都是有哪些部分组的。通常都会将对象划分为两个部分,及静态部分与动态部分。静态部分,顾名思义,就是不能动的部分,这个部分被称为“属性”,任何对象都具备其自身属性,如一个人,其属性包括高矮、胖瘦、性别、年龄等。然而具有这些属性的人会执行哪些动作也是一个值得探讨的部分,这个人可以哭泣、微笑、说话、行走,这些是这个人具备的行为(动态部分),人类通过探讨对象的属性和观察对象的行为了解对象。

        在计算机的世界中,面向对象程序设计的思想要以对象来思考问题,首先要将现实世界的实体抽象为对象,然后考虑这个对象具备的属性和行为。例如,现在面临一只大雁要从北方飞往南方这样一个实际问题,试着以面向对象的思想来解决这一实际问题。步骤如下:
(1)首先可以从这一问题中抽象出对象,这里抽象出的对象为大雁。 
(2)然后识别这个对象的属性。对象具备的属性都是静态属性,如大雁有一对翅膀、黑色的羽毛等。
(3)接着识别这个对象的动态行为,即这只大雁可以进行的动作,如飞行、觅食等,这些行为都是这个对象基于其属性而具有的动作。
(4)识别出这个对象的属性和行为后,这个对象就被定义完成了,然后可以根据这只大雁具有的特性制定这只大雁要从北方飞向南方的具体方案以解决问题。

        究其本质,所有的大雁都具有以上的属性和行为,可以将这些属性和行为封装起来以描述大雁这类动物。由此可见,类实质上就是封装对象属性和行为的载体,而对象则是类抽象出来的一个实例。

6.1.2 类

不能将所谓的一个事物描述成一类事物,有一只鸟不能称为鸟类,如果需要对同一类事物统称,就不得不说明类这个概念.

类是封装对象属性和行为的载体。反过来说,具有相同属性和行为的一类实体被称为类。

6.1.3 面向对象程序设计的特点

面向对象程序设计具有以下特点:封装性、继承性、多态性。
1.封装
封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。

2.继承
类与类之间同样具有关系,如一个百货公司类与销售员类相联系,类之间的这种关系被称为关联。

3.多态
上面介绍了继承,了解了父类和子类,其实将父类对象应用于子类的特征就是多态,多态的实现并不依赖具体类,而是依赖于抽象类和接口。

6.2 类与对象

  • 成员变量:可以是变量,可以是常量
  • 构造方法:有构造方法但是本身不能实例化,用于子类访问父类数据初始化(多态的方式实例化)
  • 成员方法
    1,可以是抽象方法,限定子类必须重写
    2,还可以上非抽象方法,提高代码的复用性

java中定义类使用class关键字,语法如下:

class   类名称{

//类的成员变量

//类的成员方法

}

6.2.1 成员变量

在Java中对象的属性也称为成员变量,成员变量的定义与普通变量的定义一样,语法如下:

数据类型   变量名称  [  =值] ;

数据类型

默认值

说明

byte、short、int、long

0

整形零

float、double

0.0

浮点零

char

‘’

空格字符

boolean

false

逻辑假

引用类型,例如:string

null

空值

6.2.2 成员方法

定义成员方法的语法格式如下:

[权限修饰符][返回值类型]方法名([参数类型 参数名])[throws 异常类型]{
…//方法体
return 返回值;

例6.1定义一个add方法,用来计算两个数的和,该方法中有两个形参,但在方法体中,对其中的一个形参x执行加y操作,并返回x;在main方法中调用该方法,为该方法传入定义好的实参;最后分别显示调用 add 方法计算之后的x值和实参x的值。
代码

public class Book_1 {//创建主类

	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		Book_1 book = new Book_1();//创建Book对象
		int x = 30;//定义实参变量x
		int y = 40;//定义实参变量y
		System.out.println("运算结果:" + book.add(x, y));//输出运算结果
		System.out.println("实参x的值:" + x);//输出实参x的值
	}
	private int add(int x,int y)//计算两个数的和
	{
		x = x + y;//对x进行加y操作
		return x;//返回x
	}
}

结果


例6.2定义一个change方法,该方法中有一个形参,类型为数组类型,在方法体中,改变数组的索引0、1、2这3处的值;在main方法中定义一个一维数组并初始化,然后将该数组作为参数传递给 change 方法,最后输出一维数组的元素。
代码

public class RefTest_2 {//创建主类

	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		RefTest_2 refTest = new RefTest_2();//创建对象
        	int[] i = { 0, 1, 2 }; //定义一维数组,作为方法的实参
        	//输出一维数组的原始元素值
        System.out.print("原始数据:");//输出“原始数据”
        for (int j = 0; j < i.length; j++)//for循环语句
        {
            System.out.print(i[j]+" ");//输出结果
        }
        refTest.change(i);//调用方法改变数组元素的值
        System.out.print("\n修改后的数据:");//换行输出修改后的数据
        for (int j = 0; j < i.length; j++)//for循环语句
        {
            System.out.print(i[j]+" ");//输出结果
        }
	}
	public void change(int [] i)//定义一个方法,方法的参数为一维数组(形参)
    {
        i[0] = 100;//数组0的值为100
        i[1] = 200;//数组1的值为200
        i[2] = 300;//数组2的值为300
    }
}

结果 


例6.3定义一个add方法,用来计算多个int类型数据的和,在具体定义时,将参数定义为int类型的不定长参数;在main方法中调用该方法,为该方法传入多个int类型的数据,并输出计算结果。
代码

public class MultiTest_3 {//创建主类

	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		MultiTest_3 multi = new MultiTest_3();//创建MultiTest对象
	    System.out.print("运算结果:" + multi.add(20, 30, 40, 50, 60));
	    //输出结果
	}
	int add(int... x)//定义add方法,并指定不定长参数的类型为int
	{
		int result = 0;//记录运算结果
		for (int i = 0; i < x.length; i++)//遍历参数
	    {
			result += x[i];//执行相加操作
	    }
		return result;//返回运算结果
	}
}

结果


例6.4创建猎豹类,用成员方法实现猎豹的行为。
代码

public class Leopard_4 {//创建主类
	public void gaze(String target) {// 凝视。目标是参数target
		System.out.println("猎豹凝视:" + target);//输出结果
	}
	public void run() {// 奔跑
		System.out.println("猎豹开始奔跑");//输出结果
	}
	public boolean catchPrey(String prey) {// 捕捉猎物,返回捕捉是否成功
		System.out.println("猎豹开始捕捉" + prey);//输出结果
		return true;// 返回成功
	}
	public void eat(String meat) {// 吃肉,参数是肉
		System.out.println("猎豹吃" + meat);//输出结果
	}
	public void sleep() {// 睡觉
		System.out.println("猎豹睡觉");//输出结果
	}
 
	public static void main(String[] args) {//主方法
		Leopard_4 liebao = new Leopard_4();//创建一个liebao对象,通过new实例化
		liebao.gaze("羚羊");//输出羚羊
		liebao.run();//输出run
		liebao.catchPrey("羚羊");//输出羚羊
		liebao.eat("羚羊肉");//输出羚羊肉
		liebao.sleep();//输出sleep
	}
}

结果 


6.2.3 构造方法

构造方法的特点如下:
(1)构造方法没有返回类型,也不能定义为 void。
(2)构造方法的名称要与本类的名称相同。
(3)构造方法的主要作用是完成对象的初始化工作,它能把定义对象的参数传给对象成员。

例6.5创建一个图书类,将构造方法设为私有,这时如果需要创建图书类的对象,只能通过定义一个static方法,并调用该静态方法生成图书类的对象。
代码

public class BookTest_5 {//创建主类
	private BookTest_5() {//私有构造方法
	}
	//静态公开方法,向图书馆借书
	static public BookTest_5 libraryBorrow(){//创建静态方法,返回本类实例对象
		System.out.println("通过调用静态方法创建对象");//输出结果
		return new BookTest_5();//返回新的BookTest_5
	}
	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		//创建一个书的对象,不是new实例化的,而是通过方法从图书馆借来的
		BookTest_5 book = BookTest_5.libraryBorrow();//输出new实例化的结果
	}
}

结果 


6.2.4 局变量

如果在成员方法内定义一个变量,那么这个变量被称为局部变量。
局部变量在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。

6.2.5 局部变量的有效范围

可以将局部变量的有效范围称为变量的作用域局部变量的有效范围从该变量的声明开始到该变量的结束为止
 

6.2.6 对象的创建

在6.1节中曾经介绍过对象,对象可以认为是在一类事物中抽象出某一个特例,可以通过这个特例来处理这类事物出现的问题。在Java语言中通过new操作符来创建对象。前文在讲解构造法时介绍过,每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程准确地说,可以在Java 语言中使用 new 操作符调用构造方法创建对象。
语法如下:

Test test=new Test();
Test test=new Test("a"); y
Test:类名。test:创建 Test类对象。 new:创建对象操作符。 a:构造方法的参数。

test 对象被创建出来时,就是一个对象的引用,这个引用在内存中为对象分配了存储空间,6.2.3节中介绍过,可以在构造方法中初始化成员变量,当创建对象时,自动调用构造方法,也就是说在 Java 语言中初始化与创建是被捆绑在一起的。

例6.6在项目中创建CreateObject类,在该类中创建对象并在主方法中创建对象。
代码

public class CreateObject_6 {//创建主类
	public CreateObject_6() { // 构造方法
		System.out.println("创建对象");//输出“创建对象”
	}

	public static void main(String args[]) { // 主方法
		new CreateObject_6(); // 创建对象

	}

}

结果



6.2.7 访问对象的属性和行为

用户使用 new 操作符创建一个对象后,可以使用“对象.类成员”来获取对象的属性和行为。前文已经提到过,对象的属性和行为在类中是通过类成员变量和成员方法的形式来表示的,所以当对象获取类成员时,也相应地获取了对象的属性和行为。
 

例6.7在项目中创建TransferProperty类,在该类中说明对象是如何调用类成员的。
代码
 

public class TransferProperty_7 {//创建主类
	int i = 47; // 定义成员变量
	 
	public void call() { // 定义成员方法
		System.out.println("调用call()方法");//输出“调用call()方法”
		for (i = 0; i < 3; i++) {//开始for循环,循环i从0到2输出
			System.out.print(i + " ");//输出结果
			if (i == 2) {//判断i的值是否等于2
				System.out.println("\n");//换行
			}
		}
	}

	public TransferProperty_7() { // 定义构造方法
	}

	public static void main(String[] args) {//主方法
		TransferProperty_7 t1 = new TransferProperty_7(); // 创建一个对象
		TransferProperty_7 t2 = new  TransferProperty_7(); // 创建另一个对象
		t2.i = 60; // 将类成员变量赋值为60
		System.out.println("第一个实例对象调用变量i的结果:" + t1.i);// 使用第一个对象调用类成员变量
		t1.call(); // 使用第一个对象调用类成员方法
		System.out.println("第二个实例对象调用变量i的结果:" + t2.i);// 使用第二个对象调用类成员变量
		t2.call(); // 使用第二个对象调用类成员方法
	}
}

结果 


6.2.8 对象的销毁

每个对象都有生命周期,当对象的生命周期结束时,分配给该对象的内存地址会被回收。在其他语言中需要手动回收废弃的对象,但是Java拥有一套完整的垃圾回收机制,用户不必担心废弃的对象占用内存,垃圾回收器将回收无用的但占用内存的资源。
在谈到垃圾回收机制之前,首先需要了解何种对象会被 Java 虚拟机视为垃圾。主要包括以下两种情况:
(1)对象引用超过其作用范围,这个对象将被视为垃圾。
(2)将对象赋值为null。

6.2.9 this 关键字

例6.8创建Book2类,定义一个成员变量name并赋值,在定义一个成员方法showName(String name),输出方法中name的值。
代码

public class Book2_8 {//创建主类
		String name="abc";//定义一个String类型的name为abc值
		public void showName(String name) {//定义一个showName类并从传入一个参数
			System.out.println(name);//输出name
		}
 
		public static void main(String[] args) {//主方法
			Book2_8 book = new Book2_8();//在Book2类定义一个对象
			book.showName("123");//调用showName方法
}
	}		

结果 


例6.9在Book3类的showName()方法中,使用this关键字。
代码

public class Book3_9 {//创建主类

		String name = "abc";//定义一个String类型的name为abc值
 
		public void showName(String name) {//创建方法
			System.out.println(this.name);//输出“this.name”
		}
 
		public static void main(String[] args) {//主方法
			Book3_9 book = new Book3_9();//创建对象
			book.showName("123");//调用showName方法
}
}

结果 


例6.10我去买鸡蛋灌饼,我要求加几个蛋时,烙饼大妈就给饼加几个蛋,不要求的时候就只一个蛋。创建鸡蛋灌饼 EggCake类,创建有参数和无参数构造方法,无参数构造方法调用有参数实现初始化。
代码

public class EggCake_10 {//创建主类
	int eggCount;// 鸡蛋灌饼里有几个蛋
	 
	// 有参数构造方法,参数是给饼加蛋的个数
	public EggCake_10(int eggCount) {//调用方法
		this.eggCount = eggCount;//将eggCount转换为this.eggCount
		System.out.println("这个鸡蛋灌饼里有" + eggCount + "个蛋。");//输出结果
	}

	// 无参数构造方法,默认给饼加一个蛋
	public EggCake_10() {//无参数构造方法
		this(1);//加一个鸡蛋
	}

	public static void main(String[] args) {//主方法
		EggCake_10 cake1 = new EggCake_10();//创建一个新对象
		EggCake_10 cake2 = new EggCake_10(5);//创建一个新对象
	}
}

结果



6.3 static 关键字 

6.3.1 静态变量

很多时候,不同的类之间需要对同一个变量进行操作,比如一个水池,同时打开入水口和出水,进水和出水这两个动作会同时影响到池中的水量,此时池中的水量就可以认为是一个共享的变量。在Java 程序中,把共享的变量用 static 修饰,该变量就是静态变量。
可以在本类或其他类使用类名和“.”运算符调用静态变量。
语法如下:

类名.静态类成员

例6.11创建一个水池类,创建注水方法和放水方法,同时控制水池中的水量。
代码

public class Pool_11 {//创建主类
	static public int water = 0;//
	public void outlet() {// 放水,一次放出2个单位
		if (water >= 2) {//判断water是否大于等于2
			water = water - 2;//定义water的值
		} else {//water小于2
			water = 0;//水量为0
		}
	}
	public void inlet() {// 注水,一次注入3个单位
		water = water + 3;//定义water的值
	}

	public static void main(String[] args) {//主方法
		Pool_11 out = new Pool_11();//创建一个对象
		Pool_11 in = new Pool_11();//创建另一个对象
		System.out.println("水池的水量:" + Pool_11.water);//输出结果
		System.out.println("水池注水两次。");//输出结果
		in.inlet();//调用注水方法
		in.inlet();//调用注水方法
		System.out.println("水池的水量:" + Pool_11.water);//输出结果
		System.out.println("水池放水一次。");//输出结果
		out.outlet();//调用放水方法
		System.out.println("水池的水量:" + Pool_11.water);//输出结果
	}
}

结果 


例6.12创建StaticVariable类,包含一个静态成员变量和普通成员变量,在构造方法中给两个变量赋初值,然后分别实例化两个不同的对象。
代码

public class StaticVariable_12 {//创建主类
	static int x;// 静态变量
	int y;// 普通成员变量
	public StaticVariable_12(int x, int y) {// 构造函数
		this.x = x;//将类成员对象赋值为x
		this.y = y;//将类成员对象赋值为y
	}
	public static void main(String[] args) {//主方法
		StaticVariable_12 a = new StaticVariable_12(1, 2);//创建一个对象
		StaticVariable_12 b = new StaticVariable_12(13, 17);//创建另一个对象
		System.out.println("a.x的值是 = " + a.x);//输出结果
		System.out.println("a.y的值是 = " + a.y);//输出结果
		System.out.println("b.x的值是 = " + b.x);//输出结果
		System.out.println("b.y的值是 = " + b.y);//输出结果
	}
}

结果 


6.3.2 静态常量 

        有时,在处理问题时会需要两个类共享一个数据常量。例如,在球类中使用PI这个常量,可能除了本类需要这个常量之外,在另外一个圆类中也需要使用这个常量。这时没有必要在两个类中同对创建PI这个常量,因为这样系统会将这两个不在同一个类中的常量分配到不同的内存空间中,浪了系统资源。为了解决这个问题,可以将这个常量设置为静态的。PI常量在内存中被共享的布局。

例6.13将π的值赋给静态常量PI,使用PI计算圆类的面积和球类的体积。
代码

public class Graphical_13 {//创建主类
	final static double PI = 3.1415926;// 创建静态常量π
	public static void main(String[] args) {//主方法
		double radius = 3.0;// 半径
      double area = Graphical_13.PI * radius * radius;// 计算面积
		double volume = 4 / 3 * Graphical_13.PI * radius * radius * radius;// 计算体积
		Circular yuan = new Circular(radius, area);//创建一个对象
		Spherical qiu = new Spherical(radius, volume);//创建另一个对象
	}
}
class Circular {//Circular 类
	double radius;// 半径
	double area;// 面积
	public Circular(double radius, double area) {//调用变量方法
		this.radius = radius;//将类成员变量赋值为radius
		this.area = area;//将类成员变量赋值为area
		System.out.println("圆的半径是:" + radius + ",圆的面积是:" + area);//输出结果
	}
}
class Spherical {//Spherical 类
	double radius;// 半径
	double volume;// 体积
	public Spherical(double radius, double volume) {//调用变量方法
		this.radius = radius;//将类成员变量赋值为radius
		this.volume = volume;//将类成员变量赋值为volume
		System.out.println("球的半径是:" + radius + ",球的体积是:" + volume);//输出结果
	}
}

结果


6.3.3 静态方法

        如果想要使用类中的成员方法,需要先将这个类进行实例化,但有些时候不想或者无法创建类的对象时,还要调用类中的方法才能够完成业务逻辑,此时就可以使用静态方法。调用类的静态方法,无需创建类的对象。
语法如下:
类名.静态方法()

例6.14不创建类对象,直接使用静态方法。
代码

public class StaticMethod_14 {//创建主类
	static public void show() {//定义静态方法
		System.out.println("静态方法无需实例化就可以调用");//输出结果
	}
	public static void main(String[] args) {//主方法
		StaticMethod_14.show();//使用类名调用静态方法
	}
}

结果 


6.3.4 静态代码块

在类中除成员方法之外,用static 修饰代码区域可以称之为静态代码块。定义一块静态代码块,可以完成类的初始化操作,在类声明时就会运行。
语法如下:
public class StaticTest { static {
//此处编辑执行语句
        }

}

例6.15创建静态代码块、非静态代码块、构造方法、成员方法,查看这几处代码的调用顺序。
代码

public class StaticTest_15 {//创建主类
	static String name;静态代码块
	static {静态代码块
		System.out.println(name + "静态代码块");//输出结果
	}
	//非静态代码块
	{
		System.out.println(name+"非静态代码块");//输出结果
	}

	public StaticTest_15(String a) {//公开类
		name = a;//定义name的值
		System.out.println(name + "构造方法");//输出结果
	}

	public void method() {//创建method()方法
		System.out.println(name + "成员方法");//输出结果
	}

	public static void main(String[] args) {//主方法
		StaticTest_15 s1;// 声明的时候就已经运行静态代码块了
		StaticTest_15 s2 = new StaticTest_15("s2");// new的时候才会运行构造方法
		StaticTest_15 s3 = new StaticTest_15("s3");// new的时候才会运行构造方法
		s3.method();//只有调用的时候才会运行
	}
}

结果 



6.4类的主方法

主方法是类的入口点,它定义了程序从何处开始住方法提供对程序流向的控制,Java编译器通过主方法来执行程序。

例6.16在项目中创建TestMain类,在主方法中编写以下代码,并在Eclipse中设置程序参数
代码

public class TestMain_16 {//创建主类

	public static void main(String[] args) {//主方法
		// TODO Auto-generated method stub
		for (int i = 0; i < args.length; i++) { // 根据参数个数做循环操作
			System.out.println(args[i]); // 循环打印参数内容
			}
	}
}

结果 

在Eclipse中设置程序参数的步骤如下:

(1)  在Eipsce,在包资源管理器的项目名称节点上单击鼠标右键,在弹出的快捷菜单中选择"Run As"  "Run Configurations" 命令,弹出Run Configurations对话框。

(2)在Run Configurations对话框中选择Arguments选择卡,在Program arguments 文本框中输入相应的参数,每个参数间按<Enter>键隔开

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值