Java三大特性【继承、封装、多态】

JAVA学习网 2020-09-13 21:59:02

一、封装

  • 概念:尽可能的隐藏对象内部的事先细节,控制对象的修改及访问权限,使得程序不能被外部随意访问,提高了安全性。
  • 封装使用访问修饰符private(可将属性修饰为私有,仅在本类中可访问)
  • 封装以后提供get、set方法让外界调用,我们也可以在get和set方法中指定相应规则来规范程序
    //////////////////////////////未封装的代码////////////////////////////////////////////////
    public class Demo01 {
    	public static void main(String[] args) {
    		
    		Stu stu01 = new Stu();
    		stu01.name = "张三";
    		stu01.age = 23;
    		stu01.show();
    		
    		Stu stu02 = new Stu();
    		stu02.name = "李思思";
    		// 年龄的范围符合语法,但是不符合生产需求
    		stu02.age = 2444;
    		stu02.show();
    	}
    }
    
    class Stu{
    	// 属性
    	String name;
    	int age;
    	String gender;
    	String addr;
    	
    	// 方法
    	public void show() {
    		System.out.println("我的名字是" + name + ",我今年" + age);
    	}
    }
    
    //////////////////////////////封装后的代码////////////////////////////////////////////////
    public class Demo02 {
    	public static void main(String[] args) {
    		Student s01 = new Student();
    		s01.name = "王五";
    		s01.setAge(25);
    		s01.show();
    	}
    }
    
    class Student{
    	// 属性
    	String name;
    	// 私有化属性age
    	private int age;
    	
    	public void setAge(int age) {
    		this.age = age;
    	}	
    	
    	public int getAge() {
    		return this.age;
    	}
    	// 方法
    	public void show() {
    		System.out.println("我的名字叫" + name + ",我今年" + age);
    	}
    } 
  • set和get方法被绕过的情况

    • 我们创建对象的时候有可能是调用的有参数的构造方法
    • 在构造方法中可以直接给属性完成赋值的操作
    • 这样就绕过了set和get中自定义的规则
    • 如果想要set和get中的规则继续生效的话,在构造方法中调用set和get方法
    •  1 class Students{
       2     // 属性
       3     String name;
       4     private int age;
       5 
       6     // 构造方法
       7     public Students() {
       8         super();
       9     }
      10     
      11     public Students(String name, int age) {
      12         super();
      13         // 构造方法可以逃过set和get方法直接给属性赋值
      14         this.name = name;
      15         // 如果想要set中的规则继续生效就在构造方法中调用set和get方法
      16         this.setAge(age);
      17     }

       

二、继承

  • 概念:子类从父类中获取的属性和方法;子类通过关键字extends和这个类产生继承关系;类和父类需要满足一个条件【子类 is a 父类】
  • 语法格式:  class 子类 extends 父类{    子类的代码      }
  • 继承的特点:
    • Java是单继承【一个类只能有一个直接的父类,但父类中可以在有父类】
    • Java可以多级继承,子类可以获取到父类属性和方法,也可以获取到父类的父类的属性和方法
    • 优点:提高了代码的复用性,又提高代码的可扩展性
  • 不可继承:
    • 父类的构造方法不可继承【由于类的构造方法只负责本类对象,所以不可继承】
    • private修饰的属性和方法不可继承【private修饰的属性和方法作用范围只限于本类,因此不可继承】
    • 父子类不在同一个package中时,default修饰的属性和方法:【default修饰的属性和方法作用范围仅在同包下】
  • 图解【访问修饰符】
  本类 同包 非同包子类 其他
private true false false false
default true true false false
protected true true true false
public true true true true

三、方法重写\覆盖【Override】==》有继承关系

  • 概念:子类继承父类的属性和方法时,父类的方法无法满足子类的需求,可在子类中定义和父类相同的方法进行重写【Override】
  • 重写的原则【可使用@Override注解来验证是否重写】
    • 方法名称、参数列表、返回值类型必须和父类相同
    • 访问修饰符可与父类相同或比父类更广
  • 方法重写执行:
    • 子类重写父类方法后,调用时优先执行子类重写后的方法
  • 案例:
     1 public class Demo01 {
     2     public static void main(String[] args) {
     3         // 方法重写案例
     4         WeChatV1 w01 = new WeChatV1();
     5         w01.chat();
     6         
     7         WeChatV2 w02 = new WeChatV2();
     8         w02.chat();
     9         
    10     }
    11 }
    12 
    13 class WeChatV1{
    14     public void chat() {
    15         System.out.println("微信第一版跨时代产品上市,能通过网络发消息,发消息免费.");
    16     }
    17 }
    18 
    19 classs WeChatV2 extends WeChatV1{
    20     @Override
    21     public void chat() {
    22         System.out.println("微信第二版隆重上市,可以通过网络发送语音消息,每人每天可免费发出200条");
    23     }
    24 } 

四、关键字super

  • 定义:子类继承父类后,获取到父类的属性和方法有可能与子类的属性和方法重名。使用super可区分子类与父类的属性和方法
  • super调用属性和方法
    • super.方法名(参数列表)==》调用父类的方法
    • super.属性名==》调用父类的属性
  • super调用父类的构造方法
    • super(参数列表)==》调用父类构造方法
    • 案例:
       1 class Dog extends Animal{
       2     public Dog() {
       3               //调用无参构造
       4         super();
       5     }
       6 
       7     public Dog(String type, String name, int age, String gender) {
       8         // 调用父类有参数的构造方法
       9         super(type, name, age, gender);
      10     }
      11 } 
  • this和super
    • 调用属性
      • this.属性 == 》调用子类自己的属性
      • super.属性 ==》调用父类的属性
    • 调用方法
      • this.方法名(参数列表)==》调用子类自己的方法
      • super.方法名(参数列表)==》调用父类的方法
    • 调用构造方法
      • this(参数列表)==》 调用子类自己的构造方法
      • super(参数列表)==》调用父类的构造方法
    • 注意:
      • 在调用构造方法的时候,this和super不能同时存在
      • 子类的构造方法会默认调用父类的空参构造方法
      • this和super必须放在首行

五、多态

  • 概念:父类引用指向子类对象,从而产生多态
  • 语法格式:Animal a = new Dog();  ==》Animal:父类类型(引用);Dog():子类对象(对象类型)
  • 二者具有直接或间接的继承关系时,父类引用可指向子类对象,即形成多态。
  • 父类引用仅可调用父类所声明的属性和方法,不可调用子类的独有属性和方法
  • 多态使用方法和属性调用情况:
    • 调用方法:
      • 编译时候看父类中是否有这个方法,运行时看子类是否重写过该方法。【编译看左边,运行看右边】
    • 调用属性:
      • 编译时候看父类是都存在该属性,运行时候也是看父类是否存在该方法。【编译看左边,运行看左边】

六、向上转型【装箱】和向下转型【拆箱】

  • 向上转型【装箱】
    • 声明的引用是父类类型,返回比较大,引用指向了子类对象
    • 子类对象自动提升为父类类型,不会报错
    • 但是只能使用声明的父类类型中的属性和方法
    • 多态基本使用情况:Animal a = new Dog();
  • 向下转型【拆箱】
    • 声明的类型是子类类型的引用
    • 引用指向的父类类型的对象
    • 如果父类类型引用指向的子类类型的本身,代码不会出现问题,因为转了回来
    • 如果父类引用的不是子类的类型,会报错:ClassCastException
    • 例如 Dog d = (Animal)Aniimal(); Animal是Dog父类不报错;      Dog d = (Person)Person(); Person不是Dog父类 程序报错ClassCastException();

七、Instanceof

  • 定义:判断一个对象是否是指定类型的实例
  • 案例
      1 import java.util.Scanner;
      2 
      3 public class Demo06 {
      4     public static void main(String[] args) {
      5         /**
      6          * 传入一个对象,调用这个对象所有的方法
      7          */
      8         System.out.println("" instanceof String);
      9         
     10         /**
     11          * 提示用书输入一个数字,调用getPerson方法,获取这个数字对应的对象
     12          * 调用show方法,传入这个对象,展示这个对象的方法
     13          */
     14         
     15         Scanner in = new Scanner(System.in);
     16         System.out.println("请输入你希望看到的职业(1==SoftwareEngineer,,,2==DBA,,,3==ImplementationEngineer,,,其他数字==Person):");
     17         int num = in.nextInt();
     18         // 调用getPerson方法获取对象
     19         Person person = getPerson(num);
     20         
     21         // 调用show方法传入Person。展示这个职业的方法
     22         show(person);
     23         
     24     }
     25     
     26     /**
     27      * 传入数字,获取对应的Person或者其子类的对象
     28      * @param num-
     29      * @return
     30      */
     31     public static Person getPerson(int num) {
     32         Person person;
     33         switch (num) {
     34         case 1:
     35             person = new SoftwareEngineer();
     36             break;
     37             
     38         case 2:
     39             person = new DBA();
     40             break;
     41             
     42         case 3:
     43             person = new ImplementationEngineer();
     44             break;
     45 
     46         default:
     47             person = new Person();
     48             break;
     49         }
     50         
     51         return person;
     52     }
     53     
     54     
     55     /**
     56      * 展示Person或者其子类的所有方法
     57      * @param person
     58      */
     59     public static void show(Person person) {
     60         if (person == null) {
     61             System.out.println("Person为null,请重新执行代码传入正确的参数...");
     62             return;
     63         }
     64         
     65         // person非null
     66         if (person instanceof SoftwareEngineer) {
     67             SoftwareEngineer engineer = (SoftwareEngineer) person;
     68             engineer.eat();
     69             engineer.sleep();
     70             engineer.work();
     71         } else if (person instanceof DBA) {
     72             DBA dba = (DBA) person;
     73             dba.eat();
     74             dba.sleep();
     75             dba.eatBraisedChicken();
     76         } else if (person instanceof ImplementationEngineer) {
     77             ImplementationEngineer engineer = (ImplementationEngineer) person;
     78             engineer.eat();
     79             engineer.sleep();
     80             engineer.work();
     81         } else if (person instanceof Person) {
     82             person.eat();
     83             person.sleep();
     84         } else {
     85             System.out.println("您选择的职业暂无相关信息...");
     86         }
     87     }
     88 }
     89 
     90 /** 父类
     91  *     会有一些子类,子类是具体职业的人
     92  *     
     93  */
     94 class Person{
     95     public void eat() {
     96         System.out.println("人类需要吃饭...");
     97     }
     98     
     99     public void sleep() {
    100         System.out.println("人需要睡眠保持精力...");
    101     }
    102 }
    103 
    104 /**
    105  * 技术总监/经理 
    106  * 技术支持/维护 技术专员
    107  * 助理 软件工程师 
    108  * 程序员
    109  * 硬件工程师
    110  * 质量工程师
    111  * 测试工程师
    112  * 系统架构师
    113  * 数据库管理/DBA
    114  * 游戏设计
    115  * 开发
    116  * 网页设计/制作 
    117  * 语音/视频/图形 
    118  * 项目经理/主管 
    119  * 产品经理/专员 
    120  * 网站运营 
    121  * 网站编辑
    122  * 网站策划
    123  * 网络管理员 网络与信息安全工程师 实施工程师 通信技术工程师
    124  * */
    125 
    126 /**
    127  * 软件工程师类
    128  *     继承Person
    129  *     重写eat和sleep方法
    130  *     自定义work方法
    131  * @author Dushine2008
    132  *
    133  */
    134 class SoftwareEngineer extends Person{
    135     
    136     @Override
    137     public void eat() {
    138         System.out.println("我们工作很忙,外卖解决吃饭的问题...");
    139     }
    140     
    141     public void sleep() {
    142         System.out.println("我们每天坚持午睡,下午精力充沛...");
    143     }
    144     
    145     public void work() {
    146         System.out.println("我们的工作白天不怎么忙,晚上经常加班...");
    147     }
    148 }
    149 
    150 /**
    151  * DBA类
    152  *     继承Person
    153  *     重写eat和work
    154  *     自定义eatBraisedChicken方法
    155  * @author Dushine2008
    156  *
    157  */
    158 class DBA extends Person {
    159     
    160     @Override
    161     public void eat() {
    162         System.out.println("DBA数据库方面的造诣比较深厚,他们吃饭也是点外卖,靠入侵外卖平台的数据库,篡改订单信息吃饭.");
    163     }
    164     
    165     public void sleep() {
    166         System.out.println("中午不睡下午崩溃,坚持在你午睡攻陷你家的数据库.");
    167     }
    168     
    169     public void eatBraisedChicken() {
    170         System.out.println("靠技术吃黄焖鸡,吃了整整一年...");
    171     }
    172     
    173 }
    174 
    175 /**
    176  * 实施工程师
    177  *     继承Person
    178  *     重写eat和sleep方法
    179  *     自定义work方法
    180  * @author Dushine2008
    181  *
    182  */
    183 class ImplementationEngineer extends Person{
    184     @Override
    185     public void eat() {
    186         System.out.println("经常出差,可以领略各地的美食...");
    187     }
    188     
    189     @Override
    190     public void sleep() {
    191         System.out.println("一年到头就处于开房和退房的路上...");
    192     }
    193     
    194     public void work() {
    195         System.out.println("这是个根客户打交道比较多的工作...");
    196     }
    197 }

     

阅读(2606) 评论(0)