zoukankan      html  css  js  c++  java
  • 04_JavaSE之OOP--面向对象(封装、继承)

    对象(四)

    一、封装

      面向对象的三大特征:封装、继承、多态。

      今天呢,我们来谈谈,其中两个 ---- 封装和继承。而多态呢,如果没有继承也就没有多态一说,这个我们后续继续聊。

    1. 什么是封装?
      封装说白了,就是把对象的属性和行为给隐藏起来,仅仅对外提供公共的访问方式。
      如:将电脑的具体实现细节隐藏起来,提供键盘和一系列接口供用户使用,用户不必关心具体内部的实现细节。
    2. 封装的好处
      •  隐藏了实现细节,提供公共的访问方式
      •  提高了代码复用性
      •  提高安全性

      3. 封装的原则

      •  将不需要对外提供的内容都隐藏起来。
      •  把属性隐藏,提供公共方法对其访问。

       4 .说明

        把成员变量私有(private),提供相应的set/get方法。private仅仅是封装的一种体现形式,并不能说封装就是私有。

    二、继承
      继承,利用继承我们可以基于已经存在的类构造新的类,继承已经存在的类就可以复用(继承)这些类的方法和成员变量。同时,我们也可以添加一些自己的方法和属性,使得子类更加强大。
      如:人可以是父类,而学生是人,是人的子类。而学生又具有他自己的特性。因此,这里存在着很明显的is-a的关系,is-a关系是继承的一个很明显的特征。

      继承使用 extends 关键字。

    1. 继承的代码
       1 class Test_Animal {
       2     public static void main(String[] args) {
       3         Cat c1 = new Cat("花",4);
       4         System.out.println(c1.getColor() + "..." + c1.getLeg());
       5         c1.eat();
       6         c1.catchMouse();
       7 
       8         Dog d1 = new Dog("黑",2);
       9         System.out.println(d1.getColor() + "..." + d1.getLeg());
      10         d1.eat();
      11         d1.lookHome();
      12     }
      13 }
      14 /*
      15 * A:猫狗案例分析
      16 * B:案例演示
      17     * 猫狗案例继承版
      18     * 属性:毛的颜色,腿的个数
      19     * 行为:吃饭
      20     * 猫特有行为:抓老鼠catchMouse
      21     * 狗特有行为:看家lookHome
      22 */
      23 
      24 class Animal {
      25     private String color;                    //毛的颜色
      26     private int leg;                        //腿的个数
      27 
      28     public Animal(){}
      29 
      30     public Animal(String color,int leg) {
      31         this.color = color;
      32         this.leg = leg;
      33     }
      34 
      35     public void setColor(String color) {    //设置颜色
      36         this.color = color;
      37     }
      38 
      39     public String getColor() {                //获取颜色
      40         return color;
      41     }
      42 
      43     public void setLeg(int leg) {            //设置腿的个数
      44         this.leg = leg;
      45     }
      46 
      47     public int getLeg() {                    //获取腿的个数
      48         return leg;
      49     }
      50 
      51     public void eat() {                        //吃饭
      52         System.out.println("吃饭");
      53     }
      54 }
      55 
      56 class Cat extends Animal {
      57     public Cat() {}                            //空参构造
      58 
      59     public Cat(String color,int leg) {        //有参构造
      60         super(color,leg);
      61     }
      62 
      63     public void eat() {                        //吃鱼
      64         System.out.println("猫吃鱼");
      65     }
      66 
      67     public void catchMouse() {                //抓老鼠
      68         System.out.println("抓老鼠");
      69     }
      70 }
      71 
      72 class Dog extends Animal {
      73     public Dog() {}                            //空参构造
      74 
      75     public Dog(String color,int leg) {        //有参构造
      76         super(color,leg);
      77     }
      78 
      79     public void eat() {                        //吃肉
      80         System.out.println("狗吃肉");
      81     }
      82 
      83     public void lookHome() {                //看家
      84         System.out.println("看家");
      85     }
      86 }
      View Code

      子类拥有父类的方法,子类更加灵活。抽取共性,动物都有颜色,还有腿的个数。猫和狗继承动物类,这样可以直接使用Animal的Color和leg属性。虽说不能直接访问父类的私有属性,但是通过set/get方法依然可以进行赋值和取值。

    2. 继承的好处
      1)提高了代码的复用性(不用多些多余的代码,做重复性的工作)
      2)提高代码维护性
      3)类和类之间产生了关系,这是多态的前提
    3. 继承的弊端
      类和类之间的耦合性增加了

      开发的原则
      高内聚,低耦合
      耦合 类与类的关系
      内聚 就是自己完成某件事情的能力


        
         

    4. java继承特点
      java不支持多继承,因为会有安全性问题。
      但是支持多层继承,A extends B,C extends A ……(继承体系)

    5. 继承的注意事项=
      1)子类只能继承父类所有非私有的成员(成员方法和成员变量)
      2)子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法。
      3)
      不要为了部分功能而去继承。而是体现 is-a 的关系时使用继承。
      如果有两个类A,B。只有他们符合A是B的一种,或者B是A的一种,就可以考虑使用继承。

    6. 重写
      当子类出现了和父类同名的方法时,则子类的方法称为重写父类的方法。
      当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。这样,即沿袭了父类的功能,又定义了子类特有的内容。
       1 public class Iphone17 {
       2     //打电话
       3     public void call(){
       4         System.out.println("打电话");
       5     }
       6     
       7 }
       8 
       9 class Iphone18 extends Iphone17 {
      10     
      11     //重写父类的方法,实现更加强大的功能,如果想要调用父类的call(),可以super.call()
      12     @Override
      13     public void call(){
      14         //super.call();
      15         System.out.println("通过意念打电话");
      16     }
      17 }
      View Code
    7. 重载和重写的区别(面试问过)
      这个问题感觉很奇葩,很二的一个问题,但没办法面试问过,而且对于刚出来的学生,例如我。问到的概率还挺大的,其实他两的关系和区别是,雷锋和雷峰塔的关系,java和JavaScript的关系,印度和印度尼西亚的关系。
      罢了,简单说说他两的区别吧。

      (图1)

      (图2)

    三、代码块(局部代码块,构造代码块,静态代码块,同步代码块)

    1):代码块概述
        * 在Java中,使用 { } 括起来的代码被称为代码块。
    2):代码块分类
        * 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态代码块,同步代码块(多线程讲解)。
    3):常见代码块的应用
     * a:局部代码块 
            * 在方法中出现;限定变量生命周期,及早释放,提高内存利用率
        * b:构造代码块 (初始化块)
            * 在类中方法外出现;多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行
        * c:静态代码块 
            * 在类中方法外出现,并加上static修饰;用于给类进行初始化,在加载的时候就执行,并且只执行一次。
            * 一般用于加载驱动

    4) 例子:(面试可能会遇到,实际开发没有任何意义)

    ① 代码

     1 public class Student {
     2 
     3     static {
     4         System.out.println("Student 静态代码块");
     5     }
     6 
     7     {
     8         System.out.println("Student 构造代码块");
     9     }
    10 
    11     public Student() {
    12         System.out.println("Student 构造方法");
    13     }
    14 }
    15 
    16 class Demo_Student {
    17     static {
    18         System.out.println("Demo_Student静态代码块");
    19     }
    20 
    21     public static void main(String[] args) {
    22         System.out.println("我是main方法");
    23 
    24         Student s1 = new Student();
    25         Student s2 = new Student();
    26     }
    27 }
    View Code

    执行结果:

    首先,编译后运行,字节码文件进入方法区(即Demo_Student.class),首先执行Demo_Student静态代码块,因为静态代码块随着类的加载而加载。

    接着,主方法进栈。执行“我是main方法”。

    然后,当加载Student.class时候,执行Student 静态代码块。

    接着,再执行构造代码块,最后执行构造方法。

    ②代码

     1 class Fu {
     2     static {
     3         System.out.println("静态代码块Fu");
     4     }
     5 
     6     {
     7         System.out.println("构造代码块Fu");
     8     }
     9 
    10     public Fu() {
    11         System.out.println("构造方法Fu");
    12     }
    13 }
    14 
    15 class Zi extends Fu {
    16     static {
    17         System.out.println("静态代码块Zi");
    18     }
    19 
    20     {
    21         System.out.println("构造代码块Zi");
    22     }
    23 
    24     public Zi() {
    25         System.out.println("构造方法Zi");
    26     }
    27 }
    28 
    29 class Dmeo {
    30     public static void main(String[] args){
    31         Zi z = new Zi(); //请执行结果。
    32     }
    33 }
    View Code

    执行结果:

    同理,首先,编译后运行,字节码文件进入方法区,因为有继承关系,在执行子类之前先得完成父类的初始化加载,静态代码块随着类的加载而加载,因此先执行父类的静态代码块,然后执行子类的静态代码块。

    接着,执行父类的构造代码块,再执行父类的构造方法。

    最后执行子类的构造代码块,执行子类的构造方法。

    如有错误之处,欢迎指正。

    邮箱:it_chang@126.com

    stay hungry,stay foolish.
  • 相关阅读:
    gotour源码阅读
    CPU知识
    GCC知识
    go/src/make.bash阅读
    Go的pprof使用
    CGI的一些知识点
    STM32——C语言数据类型
    css 学习资料
    项目管理实践教程
    js 格式验证总结
  • 原文地址:https://www.cnblogs.com/csiOS/p/8508954.html
Copyright © 2011-2022 走看看