面向对象思想,是基于面向过程而言的:
1)面向过程:实现一个功能的时候,每一个具体的步骤都需要亲力亲为,详细的处理每一个细节。
2)面向对象:实现一个功能的时候,不关心中间具体的步骤,找一个已经具有该功能的人,来帮我做事情。
1)面向过程:脱衣服—>拿一个盆—>导入洗衣液—>加水—>浸泡几分钟—>开始搓洗—>清洗泡沫—>拧干—>晾晒
2)面向对象:脱衣服—>打开全自动洗衣机(对象)—>放进衣服—>按下按钮—>取出晾晒
1)是一种更加符合人们思考习惯的思想。
2)可以将复杂的事情简单化。
3)以前的过程中的执行者,变成了指挥者。
面向对象,对象是谁?从哪里来?
1)对象:是一类事物的具体提现。是类的一种实例化,同时具备该类事物的属性和行为。比如:洗衣机、手机、小狗。。。
2)什么又是类?
类,是一组相关属性和行为的集合,可以理解为一类事物的模板。
属性:状态信息(名字、年龄。。。)
行为:能够做什么(吃、睡、玩。。。)
在Java中对于类的属性描述就是用成员变量,行为描述就是成员方法。
在面对一个问题时,首先应该分析这个问题可以由哪些对象和类来实现,
然后再分析这些对象和类应该具有哪些属性和方法,最后分析总结出:将合适的方法放在合适的类当中!
封装可以理解是一个保护屏障,防止该类的代码被外部类定义的代码随机访问。
// 定义一个学生类
class Student{
//成员变量私有化
private String name ;
private int age ;
//给name赋值
public void setName(String n){
name = n ;
}
//获取name值
public String getName(){
return name ;
}
//给年龄赋值
public void setAge(int a){
age = a ;
}
//获取年龄
public int getAge(){
return age ;
}
}
子类继承父类,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为
class 父类 {
...
}
class 子类 extends 父类 {
...
}
当一个类存在多个子类的时候,如果该类发生变化,那么这些子类也会跟着一起变化,造成类与类之间的“强耦合”!
class Fu {
int num1 = 10;
}
class Zi extends Fu {
int num2 = 20;
public void show(){
System.out.println("Fu = " + num1);// 父类成员变量
System.out.println("Zi = " + num2);// 子类成员变量
}
}
class ZiTest {
public static void main(String[] args){
Zi zi = new Zi();
zi.show();
}
}
/* 显示结果:
Fu = 10
Zi = 20
*/
class Fu {
int num = 10;
}
class Zi extends Fu {
int num = 20;
public void show(){
int num = 30;
System.out.println("Zi1 = " + num); // 子类局部变量
System.out.println("Zi2 = " + this.num);// 子类成员变量
System.out.println("Fu = " + super.num);// 父类成员变量
}
}
class ZiTest {
public static void main(String[] args){
Zi zi = new Zi();
zi.show();
}
}
/* 显示结果:
Zi1 = 30
Zi2 = 20
Fu = 10
*/
子类对象调用方法时,首先,在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法;
若子类中不存在就会向上在父类中查找有没有对应的方法,若父类中存在就会执行子类中的方法;
若不存在就会编译报错!
class Fu {
public void show(){
System.out.println("Fu类中的show方法执行");
}
}
class Zi extends Fu {
int num = 20;
public void show2(){
System.out.println("Zi类中的show2方法执行");
}
}
class ZiTest {
public static void main(String[] args){
Zi zi = new Zi();
// 子类中没有show方法,但是可以向上找到父类方法去执行
zi.show();
zi.show2();
}
}
/* 显示结果:
Fu类中的show方法执行
Zi类中的show2方法执行
*/
方法重写的应用举例
// 手机父类
class Phone {
public void sendMessage(){
System.out.println("发短信");
}
public void call(){
System.out.println("打电话");
}
public void showNum(){
System.out.println("来电显示号码");
}
}
// 新手机子类
class NewPhone extends Phone {
//重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
public void showNum(){
super.showNum(); //调用父类已经存在的功能使用
//增加自己特有显示姓名和图片功能
System.out.println("显示来电姓名");
System.out.println("显示头像");
}
}
public class PhoneTest {
public static void main(String[] args) {
NewPhone np = new NewPhone();
// 调用父类继承而来的方法
np.sendMessage();
np.call();
// 调用子类重写的方法
np.showNum();
}
}
方法覆盖重写:
子类方法返回值的范围必须【小于等于】父类方法返回值范围!
构造方法的作用是始化成员变量。
所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个super(),表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
class Fu {
private int n;
public Fu(){
System.out.println("Fu()");
}
}
class Zi extends Fu {
public Zi(){
// super(),调用父类构造方法
System.out.println("Zi()");
}
}
class ExtendsTest{
public static void main (String args[]){
Zi zi = new Zi();
}
}
/* 显示结果:
Fu()
Zi()
*/
多态指的是一类事物有多种形态,体现代码中,就是在堆内存中的形态不一样。
父类名称 对象名 = new 子类名称();
或
接口名称 对象名 = new 实现类名称();
不能够访问子类的特有功能!
编译看(等号)左,运行看(等号)左!
class Fu {
int num = 10;
}
class Zi extends Fu {
int num = 20;
}
class MultiTest{
public static void main (String args[]){
// 使用多态写法,父类引用指向子类对象
Fu fu = new Zi();
System.out.println(fu.num);
// 编译看左:父类里有num,编译通过
// 运行看左:执行父类num变量
}
}
// 输出结果:10
编译看(等号)左,运行看(等号)右!
class Fu {
int num = 10;
public void show(){
System.out.println("父类方法执行");
}
}
class Zi extends Fu {
int num = 20;
public void show(){
System.out.println("子类方法执行");
}
}
class ExtendsTest{
public static void main (String args[]){
Fu fu = new Zi();
fu.show();
// 编译看左:父类里有show(),编译通过
// 运行看右:执行子类show()方法
}
}
// 输出结果:子类方法执行
都是对对象中的数据进行初始化,仍需要遵循分层初始化!
class Animal {
public void eat(){
System.out.println();
}
}
class Cat extends Animal {
public void eat(){
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void watchDoor(){
System.out.println("狗看门");
}
}
class ExtendsTest{
public static void main (String args[]){
// 向上转型
Animal animal = new Cat();
animal.eat();// 猫吃鱼
// 向下转型,进行“还原”动作
Cat cat = (Cat) animal;
cat.catchMouse();// 猫抓老鼠
// 错误的向下转型:本来是猫,非要“还原”成狗
//Dog dog = (Dog) animal;// 编译不会报错,运行会出现异常:ClassCastException
}
}
那么问题来了,我怎么知道你之前是什么,new的对象太多,记不得了,这时,我该怎么快速的正确完成“还原”嘞?
instanceof 来解决!
instanceof :表示该引用是否能表示该类实例,也就是判断前面的对象能不能当做后面类型的实例,返回boolean类型。
格式:
对象 instanceof 类名称
class Animal {
public void eat(){
System.out.println();
}
}
class Cat extends Animal {
public void eat(){
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃骨头");
}
public void watchDoor(){
System.out.println("狗看门");
}
}
class Test{
public static void main (String args[]){
Animal animal = new Cat();
// 判断父类引用animal本来是不是Dog
if (animal instanceof Cat){
Cat cat = (Cat) animal;
cat.catchMouse();
}
// 判断父类引用animal本来是不是Cat
if (animal instanceof Dog){
Dog dog = (Dog) animal;
dog.watchDoor();
}
}
}
// 运行结果:猫抓老鼠