java学习-面向对象
一、 面向对象
1面向对象思想
(1) 面向对象:Java语言中的一种开发思想、编程思想
(2)面向过程与面向对象
1)面向过程:如果需求或者功能要进行实现,应该怎么去实现代码。强调事物的实现过程
2)面向对象:如果需求或者功能要进行实现,应该找谁去实现。强调谁去解决问题
举例:打扫卫生
面向过程:摆凳子,摆桌子、扫地、拖地……自己实现
面向对象:让小明去打扫、
面向对象基于面向过程,面向过程是面向对象实现的基础;面向对象是比较高级的编程思维
(3) 面向对象的好处
1)面向对象思维更加符合人类的思考方式;
2) 简化程序设计难度;
3) 由事件的实施者变成事件的指挥者
(4) 面向对象的三大特征
1)封装
2)继承
3)多态
二、类与对象
2.1类与对象之间的关系
1. 类表示对于事物的抽象概念,事物的抽象表现形式
举例:人物玩具模型
2. 对象是事物的具体体现
举例:葫芦娃
2.2 类的定义
1. 类:一系列的属性和行为定义的集合
2. 类中的属性:表示对事物的特征描述
类中的属性,以成员变量的形式存在,与定义一个普通的变量一致,成员变量需要定义在类方法的外面。
举例: 人类:姓名、年龄、性别
3. 行为:表示方法的功能
举例:人类:吃饭、学习
代码举例
public class Person { // 1. 定义出成员变量,作为Person人类的属性,人类的特征 // 成员变量定义时 : 可以赋值也可以不赋值 // 姓名 String name; // 年龄 int age; // 2. 定义出人类中的方法功能 public void eat() { System.out.println(name + "正在吃饭"); } public void sleep() { System.out.println(name + "人,目前已经睡觉"+ age + "年"); } }
2.3对象的创建和使用
1. 对象的创建:
数据类型 对象名 = new 数据类型();
类名 对象名 = new 类名();
1)类名:表示对象变量属于什么类型、类属于引用数据类型
2)对象名:符合标识符规则
2)=:赋值运算符,将对象在内存中占有的空间地址赋值给对象名
4)new ;关键字,表示新建,为引用数据类型在内存中开辟空间
5)类名:与前面类名保持一致
6) ( ):表示调用类中指定的构造方法
3. 方法功能的调用
对象名.调用方法(实际参数);
代码举例
public class TestPerson { public static void main(String[] args) { // 1. 定义出一个对象,对于人类的具体表现形式 // 类名 对象名 = new 类名(); Person p = new Person(); // 2. 给当前对象p中的成员变量进行赋值 p.name = "张三"; p.age = 25; // 3. 方法中的使用的成员变量也有值 p.eat(); p.sleep(); }
练习 :
定义一个汽车类, 汽车有颜色(color), 轮胎个数(num), 跑(run : 显示当前汽车的颜色和轮胎个数)
在测试类中, 创建2个汽车对象, 给两个汽车对象的成员进行赋值, 并分别调用两个对象中的run方法
public class Car { // 颜色 String color; // 轮胎个数 int num; // 方法功能 : 跑 public void run() { System.out.println(color + "颜色的小汽车,有" + num + "个轮子,正在路上跑"); } }
public class TestCar { public static void main(String[] args) { // 1. 定义出一个小汽车对象 // 数据类型 对象名 = new 数据类型(); Car c = new Car(); c.color = "红"; c.num = 4; c.run(); Car c1 = new Car(); c1.color = "黑"; c1.num = 8; c1.run(); } }
2.4创建对象在内存中的理解
1. 栈内存:方法的调用在栈内存中开辟的空间,运行完毕出栈,释放内存
2. 堆内存:引用数据类型通过new创建出对象,在堆内存中开辟空间;举例:数组,类
3. 方法区:类型对应的.class 字节码文件,静态成员,常量
如图:
创建对象在内存的理解:
1:Car.class字节码文件先进入到方法区,.class中包含了类型在的所有内容(成员变量、方法)
2: main方法作为程序的唯一执行入口,被JVM虚拟机主动调用,进入栈内存执行
3: main方法中的第一句代码是: Car c = new Car();
1) new关键字,为Car类型对象在堆内存中开辟空间
2) JVM虚拟机将Car类型对象中的所有的非静态的成员变量加载进堆内存中, 并且为每一个成员进行默认赋初值动作
3) 将堆内存中对象内存地址,返回到栈内存中变量c位置处
4:当通过对象名.调用方法,方法中需要记录当前对象的内存地址, 后期才能通过这个内存地址找到方法中的成员使用出处
2.5 成员变量和局部变量的区别
1. 成员变量的局部变量的区别:
1) 定义不同
a: 成员变量:定义在类中方法以外的变量
b: 局部变量:定义在类方法的变量
2)在内存中存储区域不同
a: 成员变量:跟着对象存储在堆内存中
b: 局部变量:跟着方法存储在栈内存中
3)生命周期不同
a: 成员变量:随着对象的创建而出生,随着对象不再进行任何使用而消亡
b: 局部变量 : 随着方法调用进栈出生, 随着方法运行完毕而消亡
4) 值的初始化:
a : 成员变量 :JVM虚拟机会自动进行默认的赋初值动作
b : 局部变量 : JVM虚拟机不会自动赋值, 导致局部变量不赋值不能使用
2.6 匿名对象的使用
1. 创建对象时,这个对象没有名,称为匿名对象
Person p = new Person(); // p表示对象名,表示对象在内存中占有的空间地址
new Person(); // 匿名对象, 正常在堆内存中开辟空间, JVM虚拟机正常给成员变量赋值, 匿名对象的内存地址,没有任何变量去承接
2.匿名对象的使用:
1) 匿名对象只能使用一次, new Person().属性或者方法;
匿名对象在内存中存在的时间非常短暂, new创建对象,堆内存中开辟空间, 当一次属性或者方法调用完毕,这个匿名对象再无用处, 变成内存垃圾, 等待回收掉内存空间
如果对于某一个类型中的属性或者方法只使用一次,那么可以使用匿名对象
2) 匿名对象可以作为方法的实际参数和方法的实际返回值
a : 匿名对象作为方法的实际参数后, 在调用的方法中就不再是匿名对象,当做普通对象使用
b : 匿名对象作为方法的返回值, 在方法调用时, 如果有变量将返回值接住, 那么这个返回的结果就不再是匿名对象,当做普通对象使用
案例 :
定义一个Phone手机类, 类中的品牌 brand 和 price价格两个属性, 具有show方法使用功能, 使用手机时,能展现出手机中的属性特征
要求 : 定义出使用手机方法, 方法中可以使用show方法 ;
定义出创建手机对象的方法功能
public class Phone { // 品牌 String brand; // 价格 double price; // show public void show() { System.out.println("手机品牌是:" + brand + ",价格为"+price); }
public static void main(String[] args) { // 1. 匿名对象的创建 new Phone().show(); // 2. 匿名对象作为方法的参数传递 TestPhone tp = new TestPhone(); Phone p = new Phone(); // 匿名对象作为方法参数传递, 内存地址值,作为方法传递 // 在方法内部,这个地址值作为参数保存下来 // tp.usePhone(p); // new Phone()--->0xab tp.usePhone(new Phone());// 0xab // 测试匿名对象作为方法的返回值类型 Phone ph = tp.createPhone();// Phone ph = new Phone(); System.out.println(ph.price); } // 1. 创建功能,使用手机 public void usePhone(Phone p) {//实际传递的应该是一块空间地址Phone p = new Phone(); p.show(); } // 2. 创建功能, 创建出一个手机对象 public Phone createPhone() { // Phone p = new Phone(); // 3. 匿名对象作为方法的返回值类型 return new Phone(); } }
案例 :
定义一个数组容器,数组中存放5个小汽车
public static void main(String[] args) { Person p = new Person(); // 匿名对象调用方法 new Person().eat(); // 定义一个数组容器,数组中存放5个小汽车 // 数据类型[] 数组名 = new 数据类型[5]; Car[] carArr = new Car[5]; carArr[0] = new Car(); carArr[1] = new Car(); for(int index = 0; index < carArr.length; index++) { System.out.print(carArr[index] + " "); } }
三、封装
3.1封装的概念
- 封装: 面向对象中的一大特征, 隐藏事物中的属性和实现细节,对外提供公共的访问方式、
- 封装的好处:
1) 封装提高代码的复用性
2) 封装提高代码的安全性
3.2 private关键字
- private : 关键字, 表示私有的,私密的
- private 关键字可以修饰:
1) 修饰成员变量(使用最多,实体类型中的成员变量,通常都是使用private修饰,提供对应的set和get方法)
2) 修饰方法
3) 修饰内部类
4) 修饰构造方法
3.使用private 私有关键字修饰的成员, 只能在当前类型中使用
4.private关键字是封装的其中一种表现形式
3.3 Setter和Getter方法
使用private修饰的成员,需要对外提供公共的访问方式, 间接的使用私有成员
- Setter 方法 : 用于给私有的成员变量进行赋值, 在赋值的方法中,可以对成员变量进行赋值规则的限定, Setter方法让指定什么规则赋值,外界就只能如何赋值, 从而提高代码的安全性
- Getter方法 : 用于获取私有成员变量的值
public class Student { // 学生编号 , 学生姓名 , 学生年龄 String id; String name; // 为了防止外界直接给age赋值错误的值 // 使用private修饰age成员变量, // 导致age只能在Student类型中使用,其他所有外类不能直接使用 private int age; // 1. 为私有成员变量age,提供对外的公共赋值的方法 // 想让外界如何赋值,将规则写入到setAge方法中 public void setAge(int a) { if(a >= 0 && a <= 200) { age = a; }else { System.out.println("提供的年龄"+a+"不符合实际情况,使用年龄默认值20"); age = 20; } } // 2. 为私有的成员变量age,提供对外的公共的取值的方式 public int getAge() { return age; } }
public class TestStudent { public static void main(String[] args) { Student s = new Student(); s.id = "1001"; s.name = "小明"; // 赋值数据不安全,提高数据的安全性 // s.age = -19; // s.age = 19; // 调用给成员变量age赋值的方法 s.setAge(-80); // 调用获取成员变量age值的方法 System.out.println(s.getAge()); }
3.4 Set方法给成员变量赋值的过程
3.5 变量访问原则和this关键字
- 变量访问原则 : 就近当使用某个变量时, 使用的是离这个变量最近的定义结果, 如果局部变量有,优先使用局部变量; 如果没有局部变量, 再使用成员变量...
2.this关键字: 第一种使用方式,区分成员变量和局部变量重名问题
1) this 关键字 : 表示本类对象的引用(当前类型对象的引用)
2) this : 哪个对象调用了带有this关键字的方法,那么this关键字就代表哪个对象
3) this关键字区分成员和局部变量,最常使用在给私有成员变量赋值的Setter方法上
public class Demo03_变量的访问原则和this关键字 { // 成员变量 int i = 10; public void useI() { // 局部变量 // 1. 当成员变量和局部变量重名, 但是不报错; 原因 : 成员变量随着new对象进入到堆内存中 // 局部变量跟随着当前方法进入到栈内存中; 堆和栈两块内存区域,没有交集 int i = 99; // 2. i输出结果为99,因为使用了变量的就近访问原则 System.out.println("局部变量, 就近原则:"+i); // 3. 带有this关键字的变量,表示成员变量的使用 // this可以理解为 : new Demo03_变量的访问原则() . i; System.out.println("成员变量"+this.i); System.out.println("this地址:"+this); }
public class TestDemo03 { public static void main(String[] args) { Demo03_变量的访问原则和this关键字 demo3 = new Demo03_变量的访问原则和this关键字(); // useI方法带有this关键字的方法 // demo3对象调用了带有this关键字的方法useI // useI中的this关键字就表示demo3对象 demo3.useI();// 99 System.out.println(demo3.i); System.out.println("demo3地址:"+demo3); }