Java中面向对象核心
面向对象核心
在学习Java中我们会经常会被问到,面向对象的核心是什么?
面向对象的核心即封装,继承,多态。
封装:在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。通俗点说:封装就是要访问该类的代码和数据,必须通过严格的接口控制,加强了程式码的安全性。
封装的优点(简单来说,共四点):
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
封装的示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.company; 2 3 class Test{ 4 private String name; 5 private int age; 6 private String Phone; 7 8 public String getName() { 9 return name; 10 } 11 12 public void setName(String name) { 13 this.name = name; 14 } 15 16 public int getAge() { 17 return age; 18 } 19 20 public void setAge(int age) { 21 this.age = age; 22 } 23 24 public String getPhone() { 25 return Phone; 26 } 27 28 public void setPhone(String phone) { 29 Phone = phone; 30 } 31 } 32 33 34 public class get_set_ { 35 public static void main(String[] args) { 36 Test t = new Test(); 37 t.setName("小花"); 38 t.setAge(20); 39 t.setPhone("789789789789789"); 40 System.out.println("name:"+t.getName()); 41 System.out.println("age:"+t.getAge()); 42 System.out.println("Phone"+t.getPhone()); 43 44 45 } 46 }
继承(extends):
继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
Java中的继承是单继承,但是也可以实现多继承,需要关键字(implements),
语法为: class A extends B implements .....{}
说到继承,其实生活中也有很多继承的示例,如下面这张图:
使用继承的根本原因是,减少代码的臃肿特点,提高代码的维护性。
示例 :
使用继承之后:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.company; 2 3 4 class person{ 5 private int id; 6 private String name; 7 8 public person(int id, String name) { 9 this.id = id; 10 this.name = name; 11 } 12 13 public void Eat(){ 14 System.out.println("吃饭"); 15 } 16 17 public void Sleep(){ 18 System.out.println("睡觉"); 19 } 20 21 public void introduction() { 22 System.out.println("大家好!我是" + id + "号" + name + "."); 23 } 24 } 25 26 class Boss extends person{ 27 public Boss(int MyId,String MyName){ 28 super(MyId,MyName); 29 } 30 } 31 32 class Teacher extends person{ 33 public Teacher (int MyId,String MyName){ 34 super(MyId,MyName); 35 } 36 } 37 38 public class jicehng { 39 public static void main(String[] args) { 40 Boss b = new Boss(123,"小强"); 41 b.Eat(); 42 b.Sleep(); 43 b.introduction(); 44 System.out.println("-----------------------------"); 45 Teacher t=new Teacher(456,"小明"); 46 t.Eat(); 47 t.Sleep(); 48 t.introduction(); 49 } 50 }
关于Java中继承与构造方法的关系、成员方法的关系,详见:https://blog.csdn.net/LOL_toulan/article/details/89318617
多态:
说到继承就不得不说到多态,继承与多态是相辅相成的,多态中会用到继承。
多态:简单点说就是同一事物在不同时刻展现不同状态。
多态的前提:
1.要有继承关系。
2.要有方法重写。
其实没有也是可以的,但如果没有这个就没有意义。
animal d = new cat();
d.show();
animal d = new dog();
d.show();
3.要有父类引用指向子类对象。
父 f = new 子();
多态中的成员访问特点:
1.成员变量
编译看左边,运行看左边
2.构造方法
创建子类对象的时候,访问父类构造方法,对父类对象进行初始化。
3.成员方法
编译看左边,运行看右边。
4.静态方法
编译看左边,运行看左边
(静态和类有关,所以算不上重写,所以访问还是左边的)
由于成员方法存在重写,所以运行看右边。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 2 3 class Fu{ 4 public int num=100; 5 public void show(){ 6 System.out.println("show fu"); 7 } 8 9 public static void function(){ 10 System.out.println("function Fu"); 11 } 12 13 } 14 15 class zi extends Fu{ 16 public int num=200; 17 public void show() { 18 System.out.println("show zi"); 19 } 20 public void method(){ 21 System.out.println("method zi"); 22 } 23 24 public static void function(){ 25 System.out.println("function zi"); 26 } 27 } 28 29 public class duotai { 30 public static void main(String[] args) { 31 Fu F = new zi(); 32 33 F.show(); 34 //成员变量 35 System.out.println(F.num); 36 //静态方法 37 F.function(); 38 } 39 }
运行结果:
多态的好处:
1.提高了代码的维护性
2.提高了代码的扩展性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 2 3 class Animal{ 4 public void eat(){ 5 System.out.println("eat"); 6 } 7 public void sleep(){ 8 System.out.println("sleep"); 9 } 10 } 11 12 class dog extends Animal{ 13 public void eat(){ 14 System.out.println("dog eat"); 15 } 16 public void sleep(){ 17 System.out.println("dog sleep"); 18 } 19 } 20 21 class cat extends Animal{ 22 public void eat(){ 23 System.out.println("cat eat"); 24 } 25 public void sleep(){ 26 System.out.println("cat sleep"); 27 } 28 } 29 30 class pig extends Animal{ 31 public void eat(){ 32 System.out.println("pig eat"); 33 } 34 public void sleep(){ 35 System.out.println("pig sleep"); 36 } 37 } 38 39 class AnimalTool{ 40 private AnimalTool(){} 41 // public static void userCat(cat c){ 42 // c.sleep(); 43 // c.eat(); 44 // } 45 // 46 // public static void userDog(dog d){ 47 // d.sleep(); 48 // d.eat(); 49 // } 50 // 51 // public static void userPig(pig p){ 52 // p.sleep(); 53 // p.eat(); 54 // } 55 public static void userAnimal(Animal a){ 56 a.eat(); 57 a.sleep(); 58 } 59 60 } 61 62 public class duotai { 63 public static void main(String[] args) { 64 Animal a = new dog(); 65 // cat c = new cat(); 66 //dog d = new dog(); 67 // pig p=new pig(); 68 Animal a2=new pig(); 69 Animal a1=new cat();//多态 70 AnimalTool.userAnimal(a1); 71 System.out.println("--------------"); 72 // AnimalTool.userCat(c); 73 AnimalTool.userAnimal(a); 74 //System.out.println("--------------"); 75 //AnimalTool.userDog(d); 76 //AnimalTool.userAnimal(a1); 77 System.out.println("--------------"); 78 AnimalTool.userAnimal(a2);// 79 //AnimalTool.userPig(p); 80 // System.out.println("调用猫的方法----------"); 81 // c.eat(); 82 // c.sleep(); 83 // System.out.println("调用狗的方法-----------"); 84 // d.eat(); 85 // d.sleep(); 86 } 87 }
方法重写的好处:重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
抽象类(abstract)
基本概念:普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。而拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。
抽象类的特点:
抽象类必须用abstract关键系修饰。
抽象类中不一定有抽象方法,但有抽象方法的类必须定义为抽象方法,(有抽象方法的类一定是抽象类)。
抽象类不能实例化,即无法构造对象( 如果Animal是抽象类的话,Animal a = new Animal();)。
规则:
含有抽象方法的类,一定是抽象类;
抽象类中可以声明成员变量、常量、成员方法、抽象方法,抽象类中不一定要有抽象方法;
抽象类不能被实例化;
抽象类可以被继承;
可以通过两种方式获得抽象类对象:父类引用指向子类对象、匿名内部类;
子类必须重写抽象父类的所有抽象方法,或者是把子类也定义为抽象类;
如果一个类继承的抽象父类还有上级抽象父类,那么子类中需要要重写所有抽象父类的所有抽象方法;
抽象类也可以继承非抽象类,同时继承了父类的所有非私有的属性和方法;
例如:
示例一(错误示范):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 abstract class Employee{ 2 private String name; 3 private String id; 4 private int salary; 5 6 public Employee(){} 7 8 public Employee(String name, String id, int salary) { 9 this.name = name; 10 this.id = id; 11 this.salary = salary; 12 } 13 14 public String getName() { 15 return name; 16 } 17 18 public void setName(String name) { 19 this.name = name; 20 } 21 22 public String getId() { 23 return id; 24 } 25 26 public void setId(String id) { 27 this.id = id; 28 } 29 30 public int getSalary() { 31 return salary; 32 } 33 34 public void setSalary(int salary) { 35 this.salary = salary; 36 } 37 38 public abstract void work(); 39 40 41 } 42 43 class Programmer extends Employee{ 44 45 public Programmer(){} 46 47 public Programmer (String name,String id , int salary){ 48 super(name, id, salary); 49 } 50 51 @Override 52 public void work() { 53 System.out.println("码代码"); 54 } 55 } 56 57 class Manager extends Employee{ 58 59 private int Money; //bonus 奖金 60 61 public int getMoney() { 62 return Money; 63 } 64 65 public void setMoney(int money) { 66 Money = money; 67 } 68 69 public Manager(){} 70 71 public Manager (String name,String id , int salary){ 72 super(name, id, salary); 73 this.Money=Money; 74 } 75 76 @Override 77 public void work() { 78 System.out.println("跟客户谈需求"); 79 } 80 81 } 82 83 public class chouxiang { 84 public static void main(String[] args) { 85 Employee emp = new Employee(); 86 87 88 // Employee emp = new Programmer(); 89 // emp.setId("123"); 90 // emp.setName("狗蛋儿"); 91 // emp.setSalary(123123); 92 // System.out.println(emp.getName()+"--"+emp.getId()+"--"+emp.getSalary()); 93 // System.out.println("------------------------------------"); 94 // Employee emp2 = new Manager(); 95 // emp2.setId("13"); 96 // emp2.setName("狗儿"); 97 // emp2.setSalary(12323); 98 // ((Manager) emp2).setMoney(798789); 99 // 100 // System.out.println(emp2.getName()+"--"+emp2.getId()+"--"+emp2.getSalary()+"--"+((Manager) emp2).getMoney()); 101 } 102 }
报错信息:
示例二(正确案例):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.company; 2 3 abstract class Employee{ 4 private String name; 5 private String id; 6 private int salary; 7 8 public Employee(){} 9 10 public Employee(String name, String id, int salary) { 11 this.name = name; 12 this.id = id; 13 this.salary = salary; 14 } 15 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 public String getId() { 25 return id; 26 } 27 28 public void setId(String id) { 29 this.id = id; 30 } 31 32 public int getSalary() { 33 return salary; 34 } 35 36 public void setSalary(int salary) { 37 this.salary = salary; 38 } 39 40 public abstract void work(); 41 42 43 } 44 45 class Programmer extends Employee{ 46 47 public Programmer(){} 48 49 public Programmer (String name,String id , int salary){ 50 super(name, id, salary); 51 } 52 53 @Override 54 public void work() { 55 System.out.println("码代码"); 56 } 57 } 58 59 class Manager extends Employee{ 60 61 private int Money; //bonus 奖金 62 63 public int getMoney() { 64 return Money; 65 } 66 67 public void setMoney(int money) { 68 Money = money; 69 } 70 71 public Manager(){} 72 73 public Manager (String name,String id , int salary){ 74 super(name, id, salary); 75 this.Money=Money; 76 } 77 78 @Override 79 public void work() { 80 System.out.println("跟客户谈需求"); 81 } 82 83 } 84 85 public class chouxiang { 86 public static void main(String[] args) { 87 88 89 Employee emp = new Programmer(); 90 emp.setId("123"); 91 emp.setName("狗蛋儿"); 92 emp.setSalary(123123); 93 System.out.println(emp.getName()+"--"+emp.getId()+"--"+emp.getSalary()); 94 System.out.println("------------------------------------"); 95 Employee emp2 = new Manager(); 96 emp2.setId("13"); 97 emp2.setName("狗儿"); 98 emp2.setSalary(12323); 99 ((Manager) emp2).setMoney(798789); 100 101 System.out.println(emp2.getName()+"--"+emp2.getId()+"--"+emp2.getSalary()+"--"+((Manager) emp2).getMoney()); 102 } 103 }
运行结果:
接口(interface)
在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。
初学者通常在接口这里有很大的困扰,通过一个例子来介绍一下:
接口就是个招牌。
比如说你今年放假出去杭州旅游,玩了一上午,你也有点饿了,突然看到前面有个店子,上面挂着KFC,然后你就知道今天中饭有着落了。
KFC就是接口,我们看到了这个接口,就知道这个店会卖炸鸡腿(实现接口)。
那么为神马我们要去定义一个接口涅,这个店可以直接卖炸鸡腿啊(直接写实现方法),是的,这个店可以直接卖炸鸡腿,但没有挂KFC的招牌,我们就不能直接简单粗暴的冲进去叫服务员给两个炸鸡腿了。
要么,我们就要进去问,你这里卖不卖炸鸡腿啊,卖不卖汉堡啊,卖不卖圣代啊(这就是反射)。很显然,这样一家家的问实在是非常麻烦(反射性能很差)。要么,我们就要记住,中山路108号卖炸鸡,黄山路45号卖炸鸡(硬编码),很显然这样我们要记住的很多很多东西(代码量剧增),而且,如果有新的店卖炸鸡腿,我们也不可能知道(不利于扩展)。