面向对象


面向对象

1.概述

面向对象是软件开发方法。面向对象的概念和应用已经超越了程序设计和软件开发,是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

面向对象是相对于面向过程来讲的,指的是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。

面向过程到面向对象思想层面的转变:

  1. 面向过程关注的是执行的过程,面向对象关注的是具备功能的对象.
  2. 面向对象到面向过程,是程序员思想上从执行者到指挥者的转变.

1.1 三大思想

  • OOA:面向对象分析
  • OOD:面向对象设计
  • OOP:面向对象程序

1.2 三大特征

  • 封装性:所有的内容对外部不可见
  • 继承性:将其他的功能继承下来继续发展
  • 多态性:方法的重载本身就是一个多态性的体现

2.类与对象

2.1 两者关系

类表示一个共性的产物,是一个综合的特征,而对象是一个个性的产物,是一个个体的特征。

类必须通过对象才可以使用,对象的所有操作都在类中定义。例如:类与对象的关系类似汽车图纸与汽车的关系。

2.1.1 类的组成

类由属性和方法组成:

  • 属性:特性。例如:车的特性 -> 轮胎,轴承,车壳
  • 方法:行为。例如:车的行为 -> 车能行驶,能载人

2.1.2 类的定义格式

/**
 * 格式:
 * class 类名{
 * 成员属性;
 * 成员管理;
 * }
 * 
 * 类必须编写在.java文件中
 * 一个.Java文件中,可以存在N个类,但是只能存在一个public修饰的类
 * 原因: 一个文件只能由一个主类存在
 * 
 * .java文件的文件名称必须与public修饰的类名完全一致
 * @author 孟祥宽
 *
 */
public class Demo1 {
	
	public static void main(String[] args) {
		//创建对象
		/**
		 *创建对象的格式
		 * 
		 * 类名  对象名  =  null
		 * 
		 * 类名  对象名  =  new  类名() 
		 */
		Person p1 = new Person();
		//赋值  对象名.属性名 = 值;
		p1.name = "mxk";
		p1.age = 18;
		p1.sex = '男';
		p1.say();
	}
}
/**
*表示人的类
*/
class Person {
	//属性
	String name;// 名字
	int age;// 年龄
	char sex;// 性别
	//方法
	/**
	 * void 表示没有返回值
	 * 定义格式:
	 * 返回值类型 方法名称(形参){
	 * 方法体
	 * return 返回值;
	 * }
	 * 
	 * 调用格式:
	 * 对象名.方法名称(实参);
	 */
	public void say() {
		System.out.println("我的名字:"+name+",我的年龄:"+age+",我的性别:"+sex);
	}
}

2.1.3 方法的补充

//计算
	public int sum(int x,int y) {
		int z = x + y;
		return z;
	}
	
	@SuppressWarnings("unused")
	public void fucntionA() {
		if(true) {
			//没有返回值 return 表示结束方法
			return;
		}
		System.out.println("执行完毕");
	}

2.1.4 对象创建的补充

public class Demo2 {
	
	public static void main(String[] args) {
		//两本书 b1,b2
		Book b1 = new Book();
		Book b2 = new Book();
		// 第一本书
		b1.name = "金苹果";
		b1.info = "讲述了果农种植金色苹果的辛勤路程.";
		b1.say();
		// 第二本书
		b2.name = "银苹果";
		b2.info = "讲述了果农种植银色苹果的辛勤路程.";
		b2.say();
	}
}

class Book{
	String name;
	String info;
	
	public void say() {
		System.out.println("书名《"+name+"》,简介"+info);
	}
}

2.2 对象创建内存

2.2.1 方法区

存放的是:

  • 类信息
  • 静态的变量
  • 常量
  • 成员方法

方法区中包含了一个特殊的区域(常量池) -> 存储的是使用STATIC修饰的成员。

2.2.2 PC寄存器

PC寄存器保存的是当前正在执行的JVM指令的地址。在Java程序中,每个线程启动时,都会创建一个PC寄存器。

2.2.3 本地方法栈

保存本地(native)方法的地址。

2.2.4

存储的是对象的名字和进本数据类型的值。一个线程就是一个栈,每一个栈中的元素的都是私有的,栈里的数据先进后出。数据的大小和生存期都是确定的,缺乏灵活性。但是存取速度比堆快,仅次于CPU中的寄存器。

优点:存储速度快。

存储速度快的原因:
栈内存,通过“栈指针”来创建空间与释放空间。指针向上移动释放内存,指针向下移动创建内存。

缺点:每次移动数据都要明确移动数据的大小和范围。所以为了方便指针的移动,存储的数据大小是固定的,影响程序的灵活性。

2.2.4

存放的是类的对象。Java是一个纯面向对象的语言,限制的对象的创建方式:通过new关键字创建的。

New关键字:

告诉jvm,需要明确的创建一个新的对象,去开辟一块新的堆内存空间。

优点:创建对象不用考虑需要多少空间,也不用考虑占用时长。堆的内存释放是由垃圾回收器(GC)完成的。

垃圾回收器 回收规则:
    当栈内存不存在此对象引用时,则视其为垃圾,等待垃圾回收器回收。

img

/**
 * 对象创建的内存细节
 * 
 * @author 孟祥宽
 *
 */
public class Demo3 {

	public static void main(String[] args) {
		Animal a1 = new Animal();
		a1.name = "狮子";
		a1.info = "百兽之王";
		a1.say();
		
		Animal a2 = a1;// 复制? 并不是
		/**
		 * a1和a2是变量名称 指向的是同一个对象
		 */
		a2.name = "老虎";
		
		a1.say(); // 发现动物名字由狮子变成老虎
	}
}

class Animal {
	String name;
	String info;
	
	public void say() {
		System.out.println("动物名字:"+name+",动物介绍:"+info);
	}
}

运行结果:image-20211027024913489

Day17.面向对象_堆与栈

3.构造方法(构造器)

Person p = new Person();// <-构造方法

特点:所有java类都至少存在一个构造方法;如果一个类中没有明确的编写构造方法,则编译器会自动生成一个无参的构造方法,构造方法中没有任何代码。如果自行编写了构造方法则不会自动生成无参的构造方法。

作用:用于对象初始化。

执行时机:在创建对象的时候自动调用。

3.1 定义格式

与普通方法基本相同,区别在于方法名称必须与类名相同,没有返回值类型声明

修饰词 类名 ( 参数 ) {

方法体

/**
 * 构造方法
 * @author 孟祥宽
 *
 */
public class Demo1 {

	
	public static void main(String[] args) {
		// TODO 调用构造方法 初始化对象
		Person p = new Person("孟祥宽","男");
	}
}

class Person {
	//姓名
	private String name;
	//性别
	private String sex;
	
	//构造方法
	/*
	 * 与普通方法基本相同,区别在于:
	 * 方法名称必须与类名相同,没有返回值类型声明
	 * 
	 */
	public Person(String name ,String sex) {
		System.out.println("这个人的名字是:"+name+",这个人的性别是:"+sex);
	}
}

运行结果:image-20211106003323139

3.2 构造方法的重载

public class Demo3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Animal a = new Animal();
		Animal a2 = new Animal("老鼠","打洞");
		Animal a3 = new Animal("狗", 2, "吃骨头");
		
	}

}

class Animal {
	private String name;
	private String thing;
	
	Animal() {
		System.out.println("猫正在抓老鼠");
	}
	
	Animal(String name, String thing) {
		System.out.println(name + "正在" + thing);
	}
	
	Animal(String name, int amount, String thing) {
		System.out.println(amount + "只" + name + "正在" + thing);
	}
}

运行结果:image-20211106012234221

4.方法的重载

一个类中是允许方法重载,但是要满足以下条件:

  • 方法名称相同
  • 方法参数的类型不同 或者 参数列表的长度不同 或者 参数类型顺序不同
  • 是否重载与返回值类型无关!!!
class Math {
	
	/**
	 * 同一个类中的方法允许有相同的函数名,但是参数列表长度 或 参数的类型 或 参数类型顺序不同
	 * @param a
	 * @param b
	 * @return
	 */
	public int getSum(int a , int b) {
		return a+b;
	}
	
	public double getSum(double a, double b) {
		return a+b;
	}
    
    public double getSum(double a , int b) {
        return a+b;
    }
    
    public double getSum(int a , double b) {
        return a+b;
    } 
}

public class Demo2 {

	public static void main(String[] args) {
		Math m = new Math();
		m.getSum(1.5, 2.1);
		m.getSum(3, 5);
	}
}

运行结果:

image-20211106010543000

5.匿名对象

public class Demo4 {
	public static void main(String[] args) {
		Math2 m = new Math2();
		int num = m.getSum(1, 2);
		System.out.println(num);

		/**
		 * 匿名对象:没有名字
		 */
		int num2 = new Math2().getSum(1, 3);
		System.out.println(num2);
	}
}

class Math2 {
	
	public int getSum(int a, int b) {
		return a+b;
	}
}
public class Demo5 {

	public static void main(String[] args) {
		/**
		 * 如果一个对象准备使用两次或以上一定要给对象创建对象名
		 */
		new Person5().setName("孟祥宽");
		new Person5().setAge(5);
		new Person5().say();// null的年龄是:0    三次使用new关键字代表开辟了三次堆内存
	}
}
class Person5 {
	private String name;
	private int age;
	
	public String setName(String name) {
		return this.name = name;
	}
	public int setAge(int age) {
		return this.age = age;
	}
	public void say() {
		System.out.println(name+"的年龄是:"+age);
	}
}

运行结果:image-20211106154313759