Skip to content

面向对象

面向对象编程

1.结构化开发(面向过程)

面向功能划分的软件结构
从上到下,按步执行
最小的粒度是方法
步骤繁琐,制约了软件的可维护性和可扩展性
代码一次成型,后续修改非常麻烦

2.面向对象开发

把软件系统看成各种对象的集合
系统结构稳定
子系统相对独立
软件的可维护性,可扩展性强

面向过程编程关注点在于每一个细节,每一步的具体操作。 面向对象关注点在于整个事件的参与对象,将系统中的 参与者全部看成模块化的对象。 汽车 司机 北京 天津

面向对象程序设计(Object Oriented Programming)OOP 就是把世间万物都看成一个个对象, OOP是一种编程思想,思维模式,将程序中的所有参与者 模块化为对象,然后通过各种对象之间的相互作用关系来 完成程序的需求。

3.类和对象

类是对象的模版,抽象化的对象。类是构成Java程序的单位,Java程序通过类来组织其结构,是指在开发期间,静态。 对象是Java程序在运行时的单位,运行期间的Java程序是通过多个对象之间的相互作用关系来完成需求,动态。

开发代码时,是通过编写类来完成程序的需求。 程序在运行期: 1.将编写好的类加载到JVM中,有了模版。 2.根据需求通过模版(类)来创建对应的对象,完成业务需求。

类是静态的,写完之后就存在于硬盘中。 对象是动态的,随着程序的运行而创建,同时随着程序的关闭而销毁。

JVM中类只有一份,对象有多份。

类的静态特征通过属性来描述 类的动态功能通过方法来描述

举例:Scanner工具类

Scanner scanner = new Scanner(System.in); scanner.next(); Scanner scanner2 = new Scanner(System.in);

对象是类的具体实例化,具体化的类 scanner对象

4.属性和方法

每个对象的每个属性都拥有特定值。

属性是描述对象的特征的,是静态的 车的品牌,颜色,排量都是静态的,是属性

让车跑到北京,是动态的功能,程序中用方法来描述对象执行的操作,即其动态功能。

程序中使用方法来描述对象的动态功能,使用属性来描述对象的静态特征,所以,对象是由一组属性和方法构成,用来描述客观存在的一个实体。

与对象密不可分的另外一个概念是类。 类:具有相同属性和方法的一组对象的集合,类是对象 的抽象化描述,对象是类的具体实例。

虽然属性和方法是在类中定义的,但是如果需要访问属性或者调用方法,必须通过对象来完成,不能通过类来完成。

方法调用需要注意的事项: 参数的数据类型,顺序必须与类中方法定义时的列表一致。

5.具体的开发步骤:

对象和类是面向对象编程的核心。 所有的Java程序都是以类class为组织单元,一个Java文件就是一个类 真正执行程序是通过类的具体化对象来完成的。

1)定义类

public class 类名(首字母大写){ //定义属性,属性名符合驼峰式命名法 访问权限修饰符(public) 数据类型 属性名; 访问权限修饰符(public) 数据类型 属性名; ...

//定义方法,方法名符合驼峰式命名法
访问权限修饰符 返回值类型 方法名(参数列表){
	方法体
}
...

}

java
public class Car {
	//定义属性
	public String color;
	public int age;
	public String brand;
	public float width;
	public float height;
	//定义方法
	public void start() {
		System.out.println("将车开到北京");
	}
	public float getSpeed(float hour,float km) {
		float speed = km/hour;
		return speed;
	}
	public Car() {
		
	}
	public Car(String color,int age,String brand,float width,float height) {
		this.color = color;
		this.age = age;
		this.brand = brand;
		this.height = height;
		this.width = width;
	}
	public Car(String brand) {
		this.brand = brand;
	}
}

2)根据类来创建对象

通过调用类的构造函数/构造方法来创建 每一个类都有一个默认的无参构造方法,该方法不需要创建,由类自动生成。

构造方法语法: 访问权限修饰符 方法名/必须跟类名一模一样(参数列表){ 方法体 }

java
public class Test {
	public static void main(String[] args) {
		//创建一辆车,调用无参构造
		Car car = new Car();
		//给对象的属性赋值
		car.age = 6;
		car.brand = "奥迪";
		car.color = "黑色";
		car.height = 1.5f;
		car.width = 2f;
		//创建第二辆车,调用有参构造
		Car car2 = new Car("红色",3,"宝马",2.2f,1.6f);
		float speed = car.getSpeed(2f,200f);
		float speed2 = car2.getSpeed(1.5f, 200f);
		System.out.println(car.brand+"-"+car.color+"-时速:"+speed);
		car.start();
		System.out.println(car2.brand+"-"+car2.color+"-时速:"+speed2);
		car2.start();
	}
}

有参构造需要手动创建。 无参构造只创建对象,不完成对属性的赋值,需要在外部手动进行赋值。 有参构造边创建对象边完成对属性的赋值。

每个类都会有一个默认的无参构造, 如果手动在类中创建一个有参构造,会将默认的无参构造抹掉,如果一个类中有参和无参都需要,那么就必须手动将两种构造函数进行创建。

例1

编写学员类,创建学员对象并输出相关信息 编写教师类,创建教师对象并输出相关信息

java
public class Student {
	public int id;
	public String name;
	public int age;
	public String gender;
	public void show() {
		System.out.println("学生信息如下:");
		System.out.println("学号:"+id);
		System.out.println("姓名:"+name);
		System.out.println("年龄:"+age);
		System.out.println("性别:"+gender);
	}
	public Student(int id, String name, int age, String gender) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	public Student() {
		super();
	}
	public Student(int id, String gender) {
		super();
		this.id = id;
		this.gender = gender;
	}
}
java
public class Test2 {
	public static void main(String[] args) {
		Student student = new Student();
		student.id = 1;
		student.name = "张三";
		student.age = 22;
		student.gender = "男";
//		student.show();
		System.out.println("学生信息如下:");
		System.out.println("学号:"+student.id);
		System.out.println("姓名:"+student.name);
		System.out.println("年龄:"+student.age);
		System.out.println("性别:"+student.gender);
		Student student2 = new Student(2,"李四",18,"女");
		student2.show();
	}
}
java
public class Teacher {
	//属性:描述静态特征
	public String name;
	public int age;
	public char gender;
	//方法:描述动态功能
	public void teach() {
		System.out.println("老师上了一节课");
	}
	public String level(int score) {
		/**
		 * score>=90:优秀
		 * 80<=score<90:良好
		 * 60<=score<80:中等
		 * score<60:差
		 */
		String result = "差";
		if(score>=90) {
			result = "优秀";
		}else {
			if(score>=80) {
				result = "良好";
			}else {
				if(score>=60) {
					result = "中等";
				}
			}
		}
		return result;
	}
	public void test(int num) {
		num++;
		System.out.println("方法内部:"+num);
	}
	public void test2(Teacher teacher) {
		teacher = new Teacher();
		System.out.println(teacher);
	}
	public Teacher(String name,int age,char gender) {
		this.name = name;
		this.age = age;
		this.gender = gender;
	}
	public Teacher() {
		
	}
}

6.空指针

null指空指针,用来描述内存地址的一个值,指空,不存在。 应用类型的变量可以赋值null, 基本数据类型的变量不能赋null

7.垃圾回收

垃圾回收机制GC:是一个独立的巡查线程,GC是一个定时任务,隔一段时间执行一次。

8.栈和堆

基本数据在栈内存中开辟空间,同时直接将具体数值保存在栈中 引用类型在栈中开辟空间,同时在堆中创建对象,将堆内存的地址保存在栈中

基本数据类型传递是值,在方法内部改变变量的值,并不会影响到外部调用该方法时传入的变量值。

引用数据类型传递是地址

例2

一个景区根据游人的年龄收取不同价格的门票。 编写游人类,根据年龄段决定门票价格并输出。

java
public class Person {
	public String name;
	public int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
}
java
public class Test2 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.print("请输入游客姓名:");
		String name = scanner.next();
		System.out.print("请输入游客年龄:");
		int age = scanner.nextInt();
		Person person = new Person(name,age);
		Admin admin = new Admin();
		int price = admin.getPrice(person.age);
		if(price == 0) {
			System.out.println("游客"+person.name+"的年龄是"+person.age+",门票免费");
		}else {
			System.out.println("游客"+person.name+"的年龄是"+person.age+",应该收取的门票价格为"+price);
		}
		
	}
}
java
public class Admin {
	public int getPrice(int age) {
		int price = 0;
		if(age >= 18) {
			price = 20;
		}
		return price;
	}
}

例3

5位学员参加了Java知识竞赛,输出竞赛的平均成绩和最高成绩,定义一个工具类来完成。

java
public class ScoreTools {
	public void result(int[] array) {
		//1.求平均分
		int sum = 0;
		for(int score:array) {
			sum += score;
		}
		float avg = sum/array.length;
		//2.求最高分
		int max = array[0];
		for(int i = 1;i < array.length; i++) {
			int score = array[i];
			if(score > max) {
				max = score;
			}
		}
		System.out.println("平均分是:"+avg+"最高分是:"+max);
	}
}
java
public class Test3 {
	public static void main(String[] args) {
		int[] array = {70,60,80,50,90};
		int[] array2 = {66,77,99,33,78,89};
		ScoreTools st = new ScoreTools();
		st.result(array);
		st.result(array2);
	}
}

9.this关键字:指当前类

this可以来修饰类中的属性和方法,只能在方法中使用。 this.属性名 this.方法名(参数) this(参数):只能在构造方法中使用,不能在普通方法中使用,并且必须写在构造方法的第一行。

通常情况下,在类的方法中的具体代码,this可加可不加。 当方法中的参数和属性名一致时,通过参数名无法区分参数和属性时,需要通过this来修饰属性。 当方法中的参数和属性名不一致时,通过参数名可以区分参数和属性时,不需要加this。

用来描述现实生活中的具体事物的类我们把它叫做实体类,entity。

10.递归:方法自己调自己

11.static:静态

12.方法重载:

1.同一个类中 2.方法名相同 3.参数列表不同(个数或者数据类型不同) 4.与返回值,访问权限修饰符无关

java
package com.southwind.entity;

import java.util.Arrays;

public class Cal {
  // 方法重载
	public int add(int num1,int num2) {
		return num1+num2;
	}
	
	public int add(int num1,int num 2,int num3) {
		return num1+num2+num3;
	}
	
	public void add(int num1) {
		
	}

  // ### 动态参数
  // 方法的定义:动态参数,参数列表中,数据类型后添加...
  // 动态参数实质上是一个数组,当外部在调用方法时,
  // 根据外部传入的参数个数来动态生成一个数组,记录所有的参数。
	
	public int add(int... num) {
		int sum = 0;
		for(int i:num) {
			sum += i;
		}
		return sum;
	}
}

13.成员变量和局部变量

成员变量:定义在类中,方法体外的变量,属性 局部变量:定义在方法体中的变量

区别:

1.作用域不同:变量的可用范围 局部变量的作用域仅限于定义它的方法,出了方法就无法访问。 成员变量的作用域在整个类中都是可见的。 2.初始值不同 属性/成员变量都有一个初始值,初始值根据属性的数据类型来决定, 基本数据类型:byte int short long:0 double float:0.0 char:' ' boolean:false 引用类型:null(描述的是内存地址信息,表示空,不存在的地址)

局部变量没有初始值

同一个方法中,不允许有同名的局部变量。 在不同的方法中,可以存在同名的局部变量。

在同一个方法中,存在同名的局部变量和成员变量时,局部变量的优先级更高。

例4

定义带参方法根据水果的不同,输出不同的水果汁。

java
public class Juicer {
	public void getJuice(String fruit) {
		System.out.println(fruit+"汁");
	}
}
java
public class Test {
	public static void main(String[] args) {
		Juicer juicer = new Juicer();
		juicer.getJuice("苹果");
	}
}

例5

使用带参方法实现学员信息管理,增加学员姓名,在保存了多个学生姓名的数组中,指定查找区间,查找某个学生姓名,并显示是否查找成功。

java
import java.util.Arrays;
import java.util.Scanner;

import com.southwind.entity.StudentTools;

public class StudentToolsTest {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		StudentTools studentTools = new StudentTools();
		for(int i = 0; i < 5; i++) {
			System.out.print("请输入学生姓名:");
			studentTools.array[i] = scanner.next();
		}
		System.out.println("本班学生列表");
		for(String name:studentTools.array) {
			System.out.print(name+"\t");
		}
		System.out.println("");
		System.out.print("请输入开始查找的位置:");
		int start = scanner.nextInt();
		System.out.print("请输入结束查找的位置:");
		int end = scanner.nextInt();
		System.out.print("请输入查找的姓名:");
		String name = scanner.next();
		System.out.println(name);
		boolean flag = studentTools.findName(start, end, name);
		if(flag) {
			System.out.println("找到了");
		}else {
			System.out.println("没有找到");
		}
	}
}
java
public class StudentTools {
	public String[] array = new String[5];
	
	public boolean findName(int start,int end,String name) {
		for(int i = start;i<=end;i++) {
			String val = array[i];
			if(name.equals(val)) {
				return true;
			}
		}
		return false;
	}
}

例6

定义学员类,储存学员信息(属性:姓名,成绩。方法:显示个人成绩)编写修改成绩类,使用学员对象数组作参数,实现学员成绩修改。条件为如果学员成绩小于60,集体提高两分。最终输出修改成绩后,每个学员的成绩。

java
public class Student2 {
	public String name;
	public int score;
	public void show() {
		System.out.println(name+"的成绩是"+score);
	}
	public Student2(String name) {
		super();
		this.name = name;
	}
}
java
import java.util.Scanner;

import com.southwind.entity.ScoreTools;
import com.southwind.entity.Student2;

public class Student2Test {
	public static void main(String[] args) {
		Student2 student1 = new Student2("张三");
		Student2 student2 = new Student2("李四");
		Student2 student3 = new Student2("王五");
		Scanner scanner = new Scanner(System.in);
		System.out.println(student1.name+"的成绩:");
		student1.score = scanner.nextInt();
		System.out.println(student2.name+"的成绩:");
		student2.score = scanner.nextInt();
		System.out.println(student3.name+"的成绩:");
		student3.score = scanner.nextInt();
		
		Student2[] array = {student1,student2,student3};
		ScoreTools scoreTools = new ScoreTools();
		System.out.println("修改之前的学生成绩:");
		for(Student2 stu:array) {
			stu.show();
		}
		scoreTools.update(array);
		System.out.println("修改之后的学生成绩:");
		for(Student2 stu:array) {
			stu.show();
		}
	}
}
java
public class ScoreTools {
	public void update(Student2[] array) {
		for(Student2 stu:array) {
			if(stu.score < 60) {
				for(Student2 stu2:array) {
					stu2.score += 2;
				}
			}
		}
	}
	
	public void getResult(int[] array) {
		int sum = 0;
		int max = array[0];
		for(int score:array) {
			sum += score;
			if(score > max) {
				max = score;
			}
		}
		float avg = sum/array.length;
		System.out.println("平均成绩:"+avg+",最高分是:"+max);
	}
	
}

例7

按照方法重载定义,实现简易计算。

java
public class Cal {
	public int add(int num1,int num2) {
		return num1+num2;
	}
	
	public float add(float num1,float num2,float num3) {
		return num1+num2+num3;
	}
}
java
public class CalTest {
	public static void main(String[] args) {
		Cal cal = new Cal();
		System.out.println(cal.add(3,3));
		System.out.println(cal.add(1.5f, 2.6f,3.3f));
	}
}