面向对象
面向对象
1.概述
面向对象是软件开发方法。面向对象的概念和应用已经超越了程序设计和软件开发,是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
面向对象是相对于面向过程来讲的,指的是把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
面向过程到面向对象思想层面的转变:
- 面向过程关注的是执行的过程,面向对象关注的是具备功能的对象.
- 面向对象到面向过程,是程序员思想上从执行者到指挥者的转变.
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)完成的。
垃圾回收器 回收规则:
当栈内存不存在此对象引用时,则视其为垃圾,等待垃圾回收器回收。
/**
* 对象创建的内存细节
*
* @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);
}
}
运行结果:
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);
}
}
运行结果:
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);
}
}
运行结果:
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);
}
}
运行结果:
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);
}
}
运行结果: