您的位置:首页 > 编程语言

2017 - 10 -16 面向对象 多态 抽象类 接口 形参和返回值 链式编程 包 访问修饰符 内部类

2017-10-17 22:04 453 查看
1 多态

(1)同一个对象(事物),在不同时刻体现出来的不同状态

  举例:

     猫是猫,猫是动物。

     水(液态,固态,气态)。

(2)多态的前提:

       A:要有继承关系。

       B:要有方法重写。

             其实没有也是可以的,但是如果没有这个就没有意义。

             动物 d = new 猫();

             d.show();

             动物 d = new 狗();

             d.show();

       C:要有父类引用指向子类对象那个。
               父 f = new 子类;

(3)多态中的成员访问特点:

       A:成员变量

           编译看左边,运行看左边

       B:构造方法

           创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化

       C:成员方法

           编译看左边,运行看右边(成员方法存在重写)

       D:静态方法

           编译看左边,运行看左边

           (静态和类相关,算不上重写,所以访问还是左边的)

         

       由于成员方法存在方法重写,所以它看右边

class Fu{

      public int num =100;

      public void show(){

        System.out.println("show Fu");

}

      public static void function(){

        System.out.println("function Fu");

           }

}

class Zi extend Fu{

       public int num =1000;

       public int num2 =2000;

       public void show(){

        System.out.println("show Zi");

}

       public static void function(){

        System.out.println("function Zi");

}

}

class DuoTaiDemo{

      public static void main(String[] args){

        Fu f = new Zi();

        System.out.println(f.num);

        //报错 父类中找不到num2

        //System.out.println(f.num2);

        f.show();

        f.function();

}

}               

     输出结果:100 show Zi function Fu

(4) 多态的好处

    A:提高了代码的维护性(继承保证)

    B:提高了代码的扩展性(调用时,直接调用父类名,而不用直接调用子类名)

   例如:

    Dog a = new Dog();

    Cat b = new Cat();

    Pig c = new Pig();

    AnimalTool.useDog(a);

    AnimalTool.useCat(b);

    AnimalTool.usePig(c);

----------------------------------------

    Dog a = new Dog();

    Cat b = new Cat();

    Pig c = new Pig();

    AnimalTool.useAnimal(a);

    AnimalTool.useAnimal(b);

    AnimalTool.useAnimal(c);

(5) 多态的弊端

    不能使用子类的特有功能,只能使用父类中定义了的功能。

    那如何使用子类的特有功能?

      A:创建子类对象调用特有功能。(可以,但是很
4000
多时候不合理,而且太占内存了)

      Fu f = new Zi();

      f.show();

      //f.method(); 无法调用子类的method

      //所以创建另一个子类对象

      Zi z = new Zi();

      z.show();

      z.method();

      B:把父类的引用强制转换为子类的引用。(向下转型)

      Zi z = (Zi)f;

      z.show();

      z.method();

 -----------------------------------------

      对象间的转型问题:

        向上转型:

          Fu f = new Zi();

        向下转型:

          Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

(6) 继承的时候:

       子类中有和父类一样的方法,叫做重写。

       子类中没有父亲中出现过的方法,方法就被继承过来了

2 抽象类

(1)抽象类的概述:

      动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。

      我们把一个不是具体的功能成为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类。

   

(2)抽象类的特点:

     A:抽象类和抽象方法必须用abstract关键字修饰

     B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类

     C:抽象类不能实例化

          因为它不是具体的

          抽象类有构造方法,但是不能实例化?构造方法的作用是什么呢?

          用于子类访问父类数据的初始化

     D:抽象的子类

          a:如果不想重写抽象方法,该子类是抽象类

          b:重写所有的抽象方法,这个时候子类是一个具体的类

   **抽象类的实例化其实是靠具体的子类实现的,是多态的方式。

     Animal a = new Dog();
     a.eat();

abstract class Animal{

        //抽象方法

        //public abstract void eat(){} //空方法体,这个会报错,抽象方法不能有主体

        public abstract void eat();

}

  

(3)抽象类的成员特点:

      成员变量:既可以是变量,也可以是常量。

      构造方法: 有。

                用于子类访问父类数据的初始化。

      成员方法:既可以是抽象的,也可以是非抽象的。

      

      抽象类的成员方法特性:

       A:抽象方法,强制要求子类做的事情

       B:非抽象方法 子类继承的事情,提高代码复用性。

(4)抽象类的几个小问题

    A:一个类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义

    a:可以

    b:不让创建对象

    B:abstract不能和哪些关键字共存

         private 冲突  (不能被继承,但抽象要求重写)

         final   冲突  (不能被重写,但抽象要求重写)

         static  无意义 (抽象无方法体,static可以直接访问方法体)

3 接口

  为了体现事物功能的扩展性,java中就提供了接口来定义这些额外功能,并不给出具体实现。

(1) 接口的特点:

        A:接口用关键字interface表示

           interface 接口名{}

        B:类实现接口用implements表示

           class 类名 implements 接口名{}

        C:接口不能实例化

             那么,接口如何实例化呢?

              按照多态的方式来实例化

        D:接口的子类

           a:可以是抽象类,但意义不大

           b:可以是具体类,要重写接口中的所有抽象方法(推荐方案)

    由此可见:

        A:具体类多态(几乎没有)

        B:抽象类多态(常用)

        C:接口多态(最常用)

//定义动物培训接口

interface AnimalTrain{

     public abstract void jump();

}       

(2)接口成员特点

       成员变量:只能是常量

                 默认修饰符 public static final

       构造方法:没有,因为接口主要是扩展功能的,而没有具体存在

       成员方法:只能是抽象方法

                 默认修饰符public abstract

(3) 类与类:

         继承关系:只能单继承,可以多层继承。

    类与接口:

         实现关系,可以单实现,也可以多实现。

         并且还可以在继承一个类的时候同时实现多个接口。

    接口与接口:

         继承关系:可以单继承,也可以多继承

4 抽象类与接口的区别

   A:成员区别

    抽象类:

         成员变量:可以变量,也可以常量

         构造方法:有

         成员方法:可以抽象,也可以非抽象

    接口:

         成员变量:只可以是常量

         构造方法:无

         成员方法:只可以是抽象

   B:关系区别

    类与类:

         继承关系:只能单继承,可以多层继承。

    类与接口:

         实现关系,可以但实现,也可以多实现。

         并且还可以在继承一个类的时候同时实现多个接口。

    接口与接口:

         继承关系:可以单继承,也可以多继承

 **C:设计理念区别

    抽象类 被继承体现的是:"is a"的关系,抽象类中定义的是该继承体系的共性功能。

    接口 被实现体现的是:"like a"的关系,接口中定义的是该继承体系的扩展功能。

5 形式参数和返回值问题

     形式参数: 

         基本类型: 8种基本类型

         引用类型: 

           类:(匿名对象的时候已经用过)需要的是该类的对象

           抽象类:需要的是该抽象类的子类的对象

           接口:跟抽象类同理

     返回值类型: 

         基本类型: 8种基本类型

         引用类型: 

           类:返回的是该类的对象

           抽象类:返回的是该抽象类的子类的对象

           接口:返回的是该接口的实现类的对象

6 链式编程

    每次调用完毕方法后,返回的是一个对象。

  class StudentDemo{

     public Student getStudent(){

           return new Student();         

          }

}

     sd.getStudent().study();//链式编程

7 包

   A:其实就是文件夹

   B:作用

      a:把相同的类名放到不同的包中

      b:对类进行分类管理

  

   举例:

      学生:增加,删除,修改,查询

      老师:增加,删除,修改,查询

      。。。

   方案1:按照功能分

        cn.itcast.add

              AddStudent

              AddTeacher

        cn.itcast.delete

              DeleteStudent

              DeleteTeacher

        cn.itcast.update

              UpdateStudent

              UpdateTeacher

    方案2:按照模块分

        cn.itcast.teacher

              AddTeacher 

              DeleteTeacher

              UpdateTeacher

        cn.itcast.student

              AddStudent

              DeleteStudent

              UpdateStudent

    包的定义

          package 包名;

              多级包用.分开即可

    注意事项:

      A:package语句必须是程序的第一条可执行的代码

      B:package语句在一个java文件中只能有一个

      C:如果没有package,默认表示无包名

8 不同包下类之间的访问

   

     第一个问题:找不到Demo       需要用包名.Demo

     第二个问题:程序包不存在     需要建立工程包

     第三个问题:Demo在包中不是公共的,无法访问    设置访问权限。

    导包:

      格式:import 包名;

      这种方式导入时到类的名称

 

   **面试题:

      package,import,class有没有顺序关系?

       有

      package>import>class

      package:只能有一个

      import:可以有多个

      class:可以有多个,以后建议是一个

9 访问修饰符

                                            public    protected     默认    private

 同一类中                               √                √              √            √

 同一包子类,其他类             √                √              √

 不同包子类                           √                √         

 不同包其他类                       √ 

10 内部类

(1)内部类概述:把类定义在其他类的内部,这个类就被称为内部类。

       举例:在类A中定义了一个类B,类B就是内部类。

(2)内部类的访问特点:

        A:内部类可以直接访问外部类的成员,包括私有。

        B:外部类要访问内部类的成员,必须创建对象。  

(3)内部类位置:

        成员位置:在成员位置定义的类,被称为成员内部类。

        局部位置:在局部位置定义的类,被称为局部内部类。(例如方法中)

(4)成员内部类:

    如何直接访问内部类的成员?

      外部类名.内部类名  对象名 = 外部类对象.内部类对象;

       Outer.Inner oi = new Outer().new Inner();

            oi.show();

(5)成员内部类的修饰符:

     **private:为了保证数据的安全性

     **static:为了方便访问数据

          注意:静态内部类访问的外部类数据必须用静态修饰

        案例:我有一个人(人有身体,身体内有心脏) 

              不能直接让外部访问,必须要保证安全性。

          class Body{

               private class Heart{

                    public void operator(){

                        System.out.println("心脏搭桥");

               } 

      }

              public void method(){

                 if(如果你是外科医生){

                     Heart h = new Heart();

                     h.operator();

                  }

          }

}

(6) 用static修饰后的内部类访问

         class Outer{

              private int num = 10;

              private static int num2 = 100;

             //内部类用静态修饰是因为内部类可以看出是外部类的成员

              public static class Inner{

                     public void show(){

                           System.out.println(num);

              }

                     public static void show2(){

                           System.out.println(num);

              }

      }

}

         //格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

          Outer.Inner oi = new Outer.Inner();

            oi.show();

            oi.show2(); 

                       

         //show2()的另一种调用方式
            Outer.Inner.show2();

静态内部类的作用:
https://www.zhihu.com/question/28197253
***11 成员内部类的面试题

       要求请填空,分别输出30,20,10

   class Outer{

         public int num = 10;

         class Inner{

            public int num = 20;

            public void show(){

                    int num = 30;

                    System.out.println(?);   // num

                    System.out.println(??);  // this.num

                    System.out.println(???); // Outer.this.num /new Outer().num

                }

        }

}     

12 局部内部类

      A:可以直接访问外部类的成员

      B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能

    ***面试题:

         局部内部类访问局部变量的注意事项?

         A:局部内部类访问局部变量必须使用final修饰

         B:为什么?

            局部变量是随着方法的调用而调用,随着调用完毕而消失。

            而堆内存的内容并不会立即消失,所以,我们加finaal修饰。

            加入final修饰后,这个变量就变成了常量,既然是常量,你消失了,我在内存中存储的数据是20,所以,我还是有数据在使用。

    (反编译之后,就是一个常量)

     class Outer{

             private int num = 10;

             public void method(){

                   final int num2 = 20;

                   class Inner{

                       public void show(){

                         System.out.println(num);

                         // 从内部类中访问本地变量num2,需要被声明为最终类型

                         System.out.println(num2);

                   }

              }

            Inner i = new Inner();

            i.show();

      }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐