【Java】- 面向对象三大特征
一、面向对象和面向过程的区别
1、面向过程(Procedure Oriented 简称PO)
看名字它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和 数据(用于方法的参数) 。然后按照一定的顺序,执行完这些方法(每个方法看作一个个过程),等方法执行完了,事情就搞定了。
举例: 大象装冰箱
1、打开冰箱门
2、将大象放进冰箱
3、关闭冰箱门
2、面向对象(Object Oriented简称OO)
看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。
举例: 大象装冰箱
1、对象:冰箱
方法:打开门(),关闭门()
2、对象:大象
方法:进入()
3、demo(主方法)
4、执行:.冰箱.打开(),大象.进入(),冰箱.关闭(冰箱)
二、面向对象三大特征
1、封装
a、定义
将代码通过权限修饰符来限定甚至隐藏起来,起到部分代码不可见从而减少被外部类对象调用修改的风险。
权限修饰范围如下:
从表格中可以看出从上到下封装性越来越差
b、this关键字
this关键字代表当前对象,采取this.属性,this.方法可以来进行操作当前的属性和方法
c、内部类(Inner Class)
定义在一个类(A)中的一个类(B),可以对代码进行有效的封装,且相对于内部类(B)来说A就是外部类,内部类B可以 调用外部类中的一切属性和一切方法,不包括匿名方法,和代码块
2、继承
a、定义
类与类之间达成 "is a" 的关系,比如:A继承B,那么A就是父类(基类),B就是子类(派生类)
注:1、java中类的继承是单继承的,即一个类的父类只能有一个
2、java中类的继承可以传递,C继承B,B继承A,那么C可以间接的继承了A,C中拥有A中的属性和方法(不包括 私有)
b、继承的好处
子类可以拥有父类除了private修饰的所有的属性和方法,从而实现了代码的复用
c、继承类加载执行顺序
B继承A
0)、加载A的类模板
1)、A产生静态区,加载A的静态方法,静态属性和静态代码块即:static 修饰的属性,static修饰的方法,static修饰的代码块
2)、加载B的类模板
3)、B产生静态区,加载B的静态方法,静态属性和静态代码块即:static 修饰的属性,static修饰的方法,static修饰的代码块
4)、堆内存开辟空间,加载父类A的非静态元素(属性,方法,代码块,构造方法)
5)、执行父类A代码块/执行父类A构造函数
6)、堆内存开辟空间,加载子类B的非静态元素(属性,方法,代码块,构造方法)
7)、执行子类B代码块/执行子类B构造函数
8)、将堆内存的地址引用传递给占内存开辟的变量
d、final修饰符
修饰类:即为最终的类,不可被继承
修饰方法:即为最终的方法,不可被重写
修饰属性:即为最终的属性,
当属性为基本类型,则在声明时必须赋值,且属性不可修改。
当属性为引用类型,则声明时可以不复制,但仅保留一次赋值机会,且赋值后,属性的值(地址)不可被修改
e、super关键字
在子类对象内部使用,可以代替父类对象
super.属性-->调用父类的属性
super.方法-->调用父类的方法
备注:
子类在调用构造函数时,会默认调用super.父类构造函数(隐式构造函数)。
若是子类调用构造函数时,自己写super.父类构造函数,那么super.父类构造函数必须写在子类构造函数中的第一行
如果子类构造方法中既没有显式调用父类的构造方法,而父类没有无参的构造方法,则编译出错。
3、多态
a、定义
父类引用指向子类的对象,此时形成多态的效果
b、举例说明
定义一个animal类如下:
1 public class Animal { 2 3 /** 4 * 定义一个animal父类 5 * 添加一个属性为name 6 * 添加一个方法为eat() 7 */ 8 9 public String name; 10 11 public void eat(){ 12 System.out.println("动物正在进食"); 13 } 14 15 }
定义一个dog类,且dog类继承animal
1 public class Dog extends Animal { 2 3 /** 4 * 定义一个dog类来继承animal 5 */ 6 7 }
此时我们在主方法中进行new 一个dog对象来看下
1 public class TestMain { 2 3 /** 4 * 定义一个测试类 5 * 类中定义一个主方法 6 * @param args 7 */ 8 9 public static void main(String[] args) { 10 11 Dog dog = new Dog(); 12 dog.eat(); 13 14 } 15 16 }
执行结果为:
由此可知子类继承父类,也就继承了父类的所有的非private修饰的方法和属性,我们在dog类中重写父类的eat()方法
1 public class Dog extends Animal { 2 3 /** 4 * 定义一个dog类来继承animal 5 */ 6 7 public void eat(){ 8 System.out.println("狗狗正在进食"); 9 } 10 }
此时我们在主方法中再次运行一下,结果如下:
由此我们可以知道当子类继承父类时,子类若是重写了父类的eat()方法,运行的结果是执行子类的方法,若是子类没有重写方法,那么就会直接调用父类的eat()方法
以下为多态的演示:
我们在dog类中在定义一个方法,且new Dog对象时,我们用父类来接收,代码如下:
1 public class Dog extends Animal { 2 3 /** 4 * 定义一个dog类来继承animal 5 */ 6 7 public void eat(){ 8 System.out.println("狗狗正在进食"); 9 } 10 11 //新写一个dog类独有的方法 12 public void run(){ 13 System.out.println("狗狗正在奔跑"); 14 } 15 }
此时我们在用父类来接受子类的对象
你会发现,我们找寻不到Dog类中独有的run()方法,接着我们在执行一下eat()方法
输出的是Dog类中重写的eat()方法,是不是很神奇,那么此时我们在纵向思考下,假设我们现在有一个Cat类也继承Animal类并且重写了eat()方法,那么我们若是在定义一个Cat类继承Animal并且重写eat()方法
1 Animal animal = new Cat(); 2 animal.eat();
此时执行出的结果就会是 “猫咪正在进食”,我都是用Animal类型接受的,但是我new的对象不同,我就会输出不同的结果,这就是多态;
那我们要执行dog的独有run()方法怎么办呢?此时就要进行向下转型
进行向下转型后就会出现Dog独有的run()方法,由此我们总结以下堕胎的特性:
1、必需存在继承关系
2、子类必需重写了父类的方法
3、父类来收子类的对象 Animal animal = new Dog() 此处就是向上转型。我new出一个狗的对象,用Animal动物来接受,相当于我说狗是一种动物,这是完全合理的。 总结为接受的类的类型必需大于或者等于子类
4、父类接受子类对象后,调用的方法或者属性都是父类中拥有的方法或者属性,但是执行的结果若是子类有重写,那就执行执行子类重写的方法,若是子类没有重写方法,那么执行父类自己的方法
5、父类接受子类对象后,若是调用子类独有的方法或者属性,必需要将父类类型向下转型为子类类型
以上就是面向对象的三大特性,到此结束!!!