zoukankan      html  css  js  c++  java
  • 黑马程序员——【Java基础】——面向对象(一)概述、类与对象、继承、抽象类、接口、多态、内部类

    ---------- android培训java培训、期待与您交流! ---------- 

    一、面向对象概述

      1、面向对象:是一个很抽象的概念,它相对面向过程而言,是一种程序设计的思想。

      2、面向对象的特点:

      * 符合人们思考习惯的思想

      * 可以将复杂的事情简单化

      * 将程序员从执行者转换成了指挥者

      * 完成需求时:只需要寻找具备所需功能的对象或者创建所需功能的对象即可,简化开发效率并提高对象的复用性。

      3、面向对象的三个特征:封装(Encapsulation)、继承(Inheritance)、多态(Polymorphism)。

    二、类与对象

      (一)类与对象之间的关系

      1、类的定义:类是一组事物共有特征和功能的描述。类是对于一组事物的总体描述。Java用类class来描述对象的属性和行为。

      2、对象:对象是类的实例,

      3、类的定义格式:

      [修饰符] class类名{

                属性;

                构造方法;

                一般方法;

          }

      (二)成员变量和局部变量的区别

      成员变量:
      * 成员变量定义在类中,在整个类中都可以被访问。

      * 成员变量随着对象的建立而建立,存在于对象所在的堆内存中。
      * 成员变量有默认初始化值。

      局部变量:
      * 局部变量只定义在局部范围内,如:函数内,语句内等。

      * 局部变量存在于栈内存中。
      * 作用的范围结束,变量空间会自动释放。
      * 局部变量没有默认初始化值。

      (三)构造函数

      1、特点:

      (1)函数名与类名相同。

      (2)无返回值。

      2、作用:给对象进行初始化。对象一建立就会调用与之对应的构造函数。

      3、构造函数的细节:

      当一个类中没有定义构造函数时,系统就会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就没有了。

      4、构造函数和一般函数的区别?

      (1)写法上不同。

      (2)在运行上也有不同:构造函数式在对象一建立就运行,给对象初始化。而一般方法是对象调用时才执行,是给对象添加对象具备的功能。

      (3)一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。

      5、什么时候定义构造函数?

      当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。

      6、构造代码块

       System.out.println(“person code run”); } 

      作用:给对象进行初始化。对象一建立就运行,而且优先于构造函数执行。

      “构造函数”与“构造代码块”的区别总结:(1)优先级不同,构造代码块优先于构造函数;(2)初始化对象不同。构造代码块中定义的是不同对象共性的初始化内容,是给所有对象进行统一初始化。而构造函数是给对应的对象初始化。

      (四)this关键字

      1、作用:指向当前类的属性和方法。

      2、说明:在类定义中,如果“局部变量”和“成员变量”同名,则在将“局部变量”赋给“成员变量”时,可以使用this关键字,例如使用方式可以使:this.name = name 。

      3、问题:this看上去好像是为了区分变量同名,即区分局部变量和成员变量。this为什么可以解决这种区分?它到底代表什么呢?

        解答:this代表本类的对象,代表它所在函数所属的对象的引用。因为this持有本类对象的引用,所以this单独使用代表当前对象。

      4、补充:this也可以使用在构造函数中调用其他的构造函数。在构造函数中,用this调用其他构造函数,必须写在第一行,因为初始化要先执行。。

      5this关键字的基本应用(Java代码)

      需求:this关键字用于“构造函数”间调用

    1 class Person{
    2        Person (String name){
    3              this.name = name;
    4        }
    5        Person( String name , int age ){
    6              this( name );   //等价于 this.name = name,即调用上面的构造函数
    7           this.age = age;
    8        }
    9 }

      6、关于this及构造函数的总结:

      (1)用于区分同名变量的情况,说的成员和局部同名的时候;

      (2)用于构造函数间调用,this语句只能定义在构造函数的第一行。

      (3)构造函数之间相互调用,初始化动作先执行。初始化动作中的初始化要先执行;构造函数自身的初始化,最后执行。

      (4)注意:构造杉树之间的相互调用初始化,会陷入死循环。

      (五)static关键字

      1static关键字说明

      static是一个修饰符,用于修饰成员(成员变量和成员函数)。当类成员被static修饰后,就多了一个调用方式,除了可以被对象调用外,还可以直接通过类名调用。格式:类名.静态成员。

      2static的特点

      (1)随着类的加载而加载,随着类的消失而消失,其生命周期最长。

      (2)优先于对象存在。(静态是先存在。对象是后存在)

      (3)被所有对象所共享。

      (4)可以直接通过类名所调用。

      (5)static修饰的数据是共享数据。由static修饰的变量称为“静态变量”或“类变量”。可被对象调用的非静态变量称为“成员变量”或“实例变量”。

      3、实例变量和类变量(静态变量)的区别

      (1)存放位置:类变量随着类的加载而存在于“方法区”中。实例变量随着对象的建立而存在“堆内存”中。

      (2)生命周期:类变量生命周期最长,随着类的消失而消失。实例变量生命周期随着对象的消失而消失。

      4static使用注意事项

      (1)static方法只能访问“静态成员”。非static方法既可以访问static成员,也可以访问非静态成员。

      (2)static方法中,不可以定义this,super等关键字。因为静态优先于对象存在。

      (3)main函数是静态的。

      5static的利弊

      利:对对象共享数据进行单独空间的存储,节省空间;可以直接被类名调用。

      弊:生命周期过长。访问出现局限性。(静态虽好,只能访问静态)。

      6main函数是静态的

      (1)主函数是一个特殊的函数,是程序的入口,可以被JVM调用。

      (2)主函数定义:public:代表着该函数访问权限是最大的。static:代表主函数随着类的加载就已经存在了。void:主函数没有具体的返回值。main:不是关键字,但是一个特殊的单词,可以被JVM识别。String[] arr:函数的参数,是一个字符串数组。

      (3)主函数是固定格式的:被JVM识别。JVM在调用主函数时,传入的是new String[0]。可以将main函数的参数args输出查看。

      7、什么时候使用static

      (1)从两方面下手: 即“静态变量”和“静态函数”。

      (2)什么时候定义静态变量(类变量)呢?当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态,存在于堆内存中。

      (3)什么时候定义静态函数呢?当功能内部没有访问到非静态数据(对象的特有数据),那么该功能可以定义成静态的。

      8Java帮助文档的制作(Javadoc

      在类文件ArrayToolDemo.java文件中,有文档注释如下:

      /**

        这是一个可以对数组进行操作的工具类,提供了……功能。

        @ author xxx

        @ version v1.0

        @ param xxx

        @ return xxx

      */

      在dos命令行中输入命令:javadoc -d myhelp -author-version ArrayToolDemo.java,则Java中的javadoc工具就会帮我们完成帮助文档(也称API文档)的制作。

      9、静态代码块

      (1)定义格式:static { 静态代码块中的语句 }

      (2)特点:随着类的加载而执行,只执行一次。并优先先于main函数。用于对类进行初始化。

      10、对象的初始化过程

      定义一个对象,都做了什么事情?

      (1)把类名.class文件加载到内存中。

      (2)执行该类中的static代码块,如果有得话,给该类进行初始化。

      (3)在堆内存中开辟空间,分配内存地址给对象。

      (4)在堆内存中建立对象的特有属性,并进行默认初始化。

      (5)对属性进行显示初始化。

      (6)对对象进行构造代码块初始化。

      (7)对对象进行对应构造函数初始化。

      (8)将内存地址赋给栈内存中的对象名变量。

      (六)单例设计模式

      1、设计模式:解决某一问题最行之有效的方法。java有23种设计模式。

      2、单例设计模式:解决一个类在内存中只存在一个对象的问题。

      3、问题:如何保证对象的唯一呢?

      (1)为避免其他程序过多建立该类对象,先禁止其他程序建立该类对象。

      (2)为了让其他的程序可以访问到该类对象,只好在本类中自定义一个对象。

      (3)为方便其他程序对自定义对象的访问,可以对外提供一些访问方式。

      上述三步如何通过代码实现来体现呢?

      (1)将构造函数用private私有化。

      (2)在类中创建一个本类对象。

      (3)提供一个方法可以获取该类对象。

      注解:对事物该怎么描述,还怎么描述。当需要将该事物的对象保证在内存中唯一时,就加上以上三步。

      4、饿汉式、懒汉式

      (1)单例设计模式一:饿汉式

    class Single
    {
        private Single(){}
        private static Single s = new Single();
        public static Single getInstance(){
            return s;
        }
    }

      注释说明:饿汉式的特点是先初始化对象。如:Single类一进内存,就已经创建好了对象。在实际开发中,出于安全考虑,建议使用此方式。 

      (2)单例设计模式二:懒汉式(又称:延时加载)

     1 class Single
     2 {
     3      private static Single s=null;
     4      private Single(){} 
     5      public static Single getInstance()
     6      {
     7           If(s==null)
     8                s=new Single();
     9           return s;
    10      }
    11 }

      注释说明:是方法被调用时,才进行初始化。如:以上代码中,Single类进内存,对象还没有存在,只有调用了getInstance()方法时,才创建对象。在多线程同时调用时,懒汉式易出问题。 

    三、继承(extends

      (一)继承的概述

      继承是面向对象的一个重要特征。当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承抽取共同属性的类即可。这时,多个类可以称为子类,单独的这个类被称为父类或超类。

      当类与类之间就存在了继承的关系,子类可以直接访问父类中的非私有的属性和行为。在代码中通过extends关键字表示继承关系。

      继承的定义格式:格式:[修饰符] class SubClass extends SuperClass{}

      (二)继承特点

      1、提高了代码的复用性。

      2、让类之间产生关系,催生了类的多态特性。

      3、类与类之间的所属关系是is-a

      4、java语言只支持单继承,不支持多继承(因为多继承带来安全隐患,当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个)

      5、Java保留了“多继承”机制,用“接口(interface)”完成“多实现”,实现接口的关键字implements

      6、Java支持“多层继承”,也就是一个继承体系。

      (三)子父类中成员变量

      继承关系出现后,类成员包括:变量,函数,构造函数。

      1、变量

      如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量,用this。子类要访问父类中的同名变量,用super。

      super的使用和this的使用几乎一致,且两者都存在于方法区中。this表示本来对象的引用。super表示父类对象的引用。

      2、子父类中函数的特点——覆盖(重写)

      当子父类出现同名函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这种情况是函数的另一个特性:重写(覆盖)。

      当子类继承父类,沿袭了父类的功能到子类中。但子类虽具备该功能与父类不同,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。子类同时具有父类方法中的内容时,可以用super.方法()。

      注意:(1)子类覆盖父类,必须保证子类权限大于父类权限,才可以覆盖,否则编译失败。(2)静态只能覆盖静态。(3)父类中的私有方法不能被覆盖。

      重载(Overload):只看同名函数的参数列表。

      重写(Override):子父类方法要一模一样。

      3、构造函数

      在对子类对象进行初始化时,父类构造函数也会运行。那是因为子类的每一个构造函数默认第一行有一条隐式的语句super()。super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super()。

      问题:为什么子类实例化一定要访问父类中的构造函数?

      因为父类中的数据子类可以直接获取,所以子类在建立对象时,需要先查看父类是如何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造函数。

      如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。在上面的示例中已经有了很好的体现。

      注:super语句一定定义在子类构造函数中的第一行。

      构造函数结论:

      ① 子类的所有构造函数,默认都会访问父类中空参数的构造函数。因为子类的每一个构造函数内的第一行都有一句隐式super()。

      ② 当父类中没有空参数的构造函数时,子类必须手动通过supe语句形式来指定要访问父类中的构造函数。

      ③ 当然,子类的构造函数第一行也可以手动指定this语句形式来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。

      知识点:为什么this()和super()不能在同一个构造函数中?因为它们都位于够咱函数的第一行,且两不能在同一行。为什么不能再同一行?因为初始化动作要先做,而在子类构造函数中必有一个this语句或者super语句。

      (四)final关键字

      final作为一个修饰符。具有以下特点:

      1、可以修饰类、函数、变量。

      2、被final修饰的类不可以被继承,这样就可以避免被继承、被子类复写功能,打破“封装性”。

      3、被final修饰的方法不可以被覆写。

      4、被final修饰的变量是一个常量,只能赋值一次,既可以修饰“成员变量”,又可以修饰“局部变量”。(作为常量:所有的字母都大写;多个单词,用下划线连接)。

      5、内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。

    四、抽象类(abstract class

      (一)定义

      1、Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,包含抽象方法的类就是抽象类。

      2、抽象类的由来

      多个对象都具备相同的功能,但是功能具体内容有所不同,那么在抽取过程中,只抽取了功能定义,并未抽取功能主体,那么只有功能声明,没有功能主体的方法称为抽象方法。

      (二)抽象的特点

      1、抽象方法一定定义在抽象类中。

      2、抽象类和抽象方法必须用abstract关键字来修饰。

      3、 抽象类不可以被实例化,即不可以用new创建对象。

      4、抽象类中的抽象方法被使用,必须有子类覆写后,建立子类对象进行调用。如果子类只覆盖了部分抽象方法,那么子类还是一个抽象类。

      5、抽象方法只有方法声明,没有方法体,定义在抽象类中。

      注:抽象类中可以有非抽象的方法。

      6、抽象类及抽象方法的定义格式,示例代码如下:

    1 abstract class Demo{
    2     abstract void show();    //抽象方法
    3     abstract void inof();        //抽象方法
    4     void turn(){}    //一般方法
    5 }

      (三)抽象类的一些细节问题

      1、抽象类中有构造函数吗?

      答:有,用于给子类对象进行初始化。

      2、抽象类可以不定义抽象方法吗?

      答:可以,但很少见,目的是不让该类创建对象。AWT的适配器对象就是这种类。

      3、抽象关键字不可以和那些关键字共存?

      答:private(因为方法要被覆盖)、static(不用创建对象)、final(覆盖还是不覆盖?)

      4、抽象类和一般类的异同点:

      相同点:抽象类和一般类都是用来描述事物的,都在内部定义成员。

      不同点:(1)一般类有足够的信息描述事物。抽象了描述事物的信息有可能不足。(2)一般类中不能定义抽象方法,只能定义非抽象方法。抽象类中既可以定义抽象方法,又可以定义非抽象方法。(3)一般类可以被实例化。抽象方法不可以被实例化。

      5、抽象类一定是个父类吗?是的。

      (四)抽象类应用示例代码

        /* 需求:假如我们在开发一个系统时需要对员工进行建模,员工包含 3 个属性:姓名、工号以及工资。经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。 

        分析:员工类:name id pay。经理类:继承了员工,并有自己特有的bonus。*/ 

     1 //员工类,也是父类 
     2 abstract class Employee{
     3       private String name;//姓名
     4      private String id;  //工号
     5      private double pay;  //工资
     6 
     7      //自定义构造函数初始化 
     8      Employee(String name,String id,double pay){ 
     9             this.name = name;
    10             this.id = id; 
    11             this.pay = pay;
    12       }
    13       public abstract void work();//抽象的工作方法
    14 }
    15 
    16 //经理类,继承员工类
    17 class Manager extends Employee{
    18       private int bonus;//特有的奖金属性
    19       Manager(String name,String id,double pay,int bonus) {//子类的构造方法
    20       super(name,id,pay);//调用超类中的构造器
    21       this.bonus = bonus;
    22       }
    23       public void work(){//经理类的工作方法内容
    24       System.out.println("manager work");
    25       }
    26 }
    27 
    28 //普通员工类,继承员工类
    29 class Pro extends Employee{
    30       Pro(String name,String id,double pay){
    31       super(name,id,pay);
    32       }
    33       public void work(){        //普通员工类的工作方法内容
    34       System.out.println("pro work");
    35       }
    36 }
    37 
    38 class  AbstractDemo{
    39       public static void main(String[] args){
    40       new Manager("manager","001",10000,2000).work();
    41       new Pro("pro","020",5000).work(); 
    42       }
    43 }

    五、接口interface

      (一)接口的概述

      1、接口定义

      接口可以被认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。格式为:

      interface 接口名{}

      子类名 implements接口名{}

      2、格式特点

      (1)接口中常见定义:常量,抽象方法。

      (2)接口中的成员都有固定修饰符。常量:public static final。方法:public abstract

      (3)接口中的成员都是public的。

      在使用中,常量可以不写publicstatic final,方法可以不写public abstract,编译时Java会自动添加这些修饰符,因为这是固定的格式修饰符。但为了方便阅读,通常我们都写上。

      (二)接口的特点

      1、接口是对外暴露的规则。

      2、接口是程序的功能扩展。

      3、接口的出现降低耦合性。

      4、接口可以由类多实现。这也是对多继承不支持的转换形式。java支持多实现。

      5、类与接口之间是“实现关系”,而且类可以继承一个类的同时实现多个接口。

      6、接口之间可以有继承关系,而且可以多继承,因为接口没有方法体。

      注:(1)接口不可以创建对象的,因为有抽象方法。需要被子类实现(implements),子类对接口中的抽象方法全都覆盖后,子类才可以进行实例化。否则子类是一个抽象类。(2)实现多个接口时,接口中不可以有返回不同类型的同名抽象函数。这样子类实现时将不能复写。

      (三)接口与抽象类的

      相同点:都是不断向上抽取而来。

      不同点:(1)抽象类需要被继承,只能是单继承。接口需要被实现,可以使多实现。(2)抽象类中可以定义抽象方法和非抽象方法,子类继承后可以直接使用非抽象方法。接口只能是定义抽象方法,必须由子类去实现。(3)继承关系是is-a。实现关系是like。继承体系是共性内容;实现关系是额外功能。(4)抽象类中可以私有变量或方法。接口中的常量和方法都是public修饰的权限。

      (四)接口的应用示例

      /*需求:笔记本电脑使用。为了扩展笔记本的功能,但日后出现什么功能设备不知道。 

      分析:定义一个规则,只要日后出现的设备都符合这个规则就可以了。规则在java中就是接口。*/

     1 interface USB// 暴露的规则。
     2 {
     3     public void open();
     4     public void close();
     5 }
     6 class BookPC
     7 {
     8     public static void main(String[] args)
     9     {
    10         useUSB(new UPan());//功能扩展了。
    11         useUSB(new UsbMouse());
    12     }
    13     //使用规则。
    14     public static void useUSB(USB u)//接口类型的引用,用于接收(指向)接口的子类对象。//USB u= new UPan();
    15     {
    16         if(u!=null)
    17         {
    18             u.open();
    19             u.close();
    20         }
    21     }
    22 }
    23 //一年后。------------------------------
    24 //实现规则。
    25 //这些设备和电脑的耦合性降低了。
    26 class UPan implements USB
    27 {
    28     public void open()
    29     {
    30         System.out.println("upan open");
    31     }
    32     public void close()
    33     {
    34         System.out.println("upan close");
    35     }
    36 }
    37 class UsbMouse implements USB
    38 {
    39     public void open()
    40     {
    41         System.out.println("UsbMouse open");
    42     }
    43     public void close()
    44     {
    45         System.out.println("UsbMouse close");
    46     }
    47 }

     

    六、多态

      (一)多态的概述

      1、对多态的理解:指同一个实体同时具有多种形式,也可以理解为事物存在的多种体现形态。例如动物中猫和狗。猫这个对象对应的类型是猫类型,如:猫 cat1 = new 猫()。同时猫也是动物的一种,因此也可以把猫称为动物。动物 cat1 = new猫()。那么动物就是从猫和狗等具体事物中抽取出来的父类型。

      2、多态在代码中的体现:父类或接口的引用指向其子类对象。如Animal a = new Dog()。

      3、多态的好处:提高代码的扩展性,前期定义的代码可以使用后期的内容。

      4、多态的弊端

      (1)前期定义的内容,不能使用后期特有内容。

      (2)只能使用父类中的引用访问父类中的成员。也就是说使用了多态,父类型的引用在使用功能时,不能直接调用子类中的特有方法。如Animal a = new Cat(); 这代码就是多态的体现,假设子类Cat中有特有的抓老鼠功能,父类型的 a就不能直接调用。这上面的代码中,可以理解为Cat类型提升了,向上转型。如果此时父类的引用想要调用Cat中特有的方法,就需要强制将父类的引用转成子类类型,向下转型。如:Catc = (Cat)a;

    注:如果父类可以创建对象,如Animal a = new Animal()。此时就不能向下转型,Cat c = (Cat)a这样的代码就变得不容许,编译时会报错。所以千万不能出现这样的操作,就是将父类对象转成子类类型。我们所说的能够转换指的是父类引用指向自己的子类对象时,该引用可以被提升,也可以被强制转换。多态始终都是子类对象在做着变化。

      5、多态的前提

      (1)类与类之间必须有关系,要么继承,要么实现。

      (2)存在覆盖。父类中有方法被子类重写。

      6、多态的类型判断

      instanceof用于判断对象的具体类型。

      (二)多态中成员的特点

      1、多态中成员变量的特点

      无论编译和运行,都参考左边(引用变量所属的类)。如:多态中的父类引用调用成员变量时,如果父类和子类有同名的成员变量,那么被调用的是父类中的成员变量。

      2、多态中非静态成员函数的特点

      在编译时期:参考引用型变量所属的类中是否有调用成员函数。如果有,编译通过,如果没有编译失败。

      在运行时期:参阅对象所属的类中是否有调用的方法。这就是说,如果父类中有一个非抽象的方法,而子类继承后又将其覆写,在多态运行时,父类的引用调用这个同名函数时,被运行的将是父类中的方法。

      简单总结就是:成员函数在多态调用时,编译时看左边,运行时看右边。

      3、多态中静态成员函数的特点

      无论编译和运行,都参考左边。也就是父类引用在调用静态同名函数时,被调用的是父类中的静态函数。这是因为,当类一被加载,静态函数就随类绑定在了内存中。此时,不需要创建对象,就可以使用类名直接调用。

      注:类在方法区中的分配,分为静态区和非静态区,而关键字this和super在非静态区。

      (三)多态应用的代码示例

      /* 电脑的运行实例。电脑的运行由主板控制,假设主板只是提供电脑运行,但是没有上网,听歌等功能。而上网、听歌需要硬件的支持。而现在主板上没有网卡和声卡,这时可以定义一个规则,叫PCI,只要符合这个规则的网卡和声卡都可以在主板上使用,这样就降低了主板和网卡、声卡之间的耦合性。用程序体现。*/ 

     1 // 接口PCI
     2 interface PCI{
     3       void open();
     4       void close();
     5 }
     6 
     7 //网卡实现接口
     8 class NetCard implements PCI{
     9       public void open(){
    10             System.out.println("NetCard_open");
    11       }
    12       public void close(){
    13             System.out.println("NetCard_close");
    14       }
    15 }
    16 
    17 //声卡实现接口
    18 class SoundCard implements PCI{
    19       public void open(){
    20             System.out.println("SoundCard_open");
    21       }
    22       public void close(){
    23             System.out.println("SoundCard_close");
    24       }
    25 }
    26 
    27 class Mainboard{
    28       //电脑运行
    29       public static void run(){
    30             System.out.println("Mainboard_run");
    31       }
    32       //使用扩展功能
    33       public static void usePCI(PCI p) {//接口型引用指向自己的子类对象。//PCI p = new NetCard()
    34             if(!(p==null)){
    35                   p.open();
    36                   p.close();
    37             }
    38       }
    39 }
    40 
    41 class Demo{
    42       public static void main(String[] args) {
    43             Mainboard m =new Mainboard();
    44             //电脑运行
    45             m.run();
    46             //m.usePCI(null);
    47             //电脑上网
    48             m.usePCI(new NetCard());
    49             //电脑听歌
    50             m.usePCI(new SoundCard());
    51       }
    52 }

    七、内部类 

      (一)概述

      将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。编译时,如果代码中有内部类,生成的class文件中会含有这样的文件:Test$1.class。编译器将会把内部类翻译成用$(美元符号)分隔外部类名和内部类名的常规类文件。

      (二)内部类的访问规则

      1、内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this。

      2、外部类要访问内部类,必须建立内部类对象。

      (三)访问格式

      1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部类的方法中,创建内部类的对象,然后调用。格式:Outer.Inner in = new Outer().new Inner();

      2、当内部类在外部类中的成员位置上时,可以被成员修饰符private所修饰,private将内部类在外部类中进行封装。 访问格式:Outer.this.x。

      3、static静态内部类:static内部类具备static特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现访问局限。

      4、在外部类中,直接访问static内部类的非静态函数。格式:new Outer.Inner().function。

      5、在外部其他类中,直接访问static内部类的静态成员。格式为:Outer.Inner.function();

      注意:(1)当内部类中定义了静态成员时,则内部类必须是static的。(2)当外部类中的静态方法访问内部类时,内部类也必须是static的。(3)在实际应用中,内部类通常被定义为private,而很少定义为public。

      6、内部类定义的原则

      当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。

      (三)局部内部类(内部类定义在局部时)

      内部类定义在外部类中的某个方法中,创建了这个类型的对象时,且仅使用了一次,那么可在这个方法中定义局部内部类。

      1、不可以被成员修饰符(如public、private、static等)修饰。其作用域被限定在了声明这个局部类的代码块中

      2、可以直接访问外部类中的成员,因为还持有外部类中的引用。内部类在局部位置上,不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

      (四)匿名内部类

      1、匿名内部类其实就是内部类的简写格式。

      2、定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。

      3、匿名内部类的格式:  new父类或者接口(){定义子类的内容}

      4、其实匿名内部类就是一个匿名子类对象。可以理解为带内容的对象。

      5、匿名内部类中定义的方法最好不要超过3个。

      (五)匿名内部类的应用示例 

     1 interface Inter{
     2       void method();
     3 }
     4 
     5 class InnerClassTest{
     6       public static void main(String[] args){
     7             show( new Inter(){
     8                   public void method(){
     9                         System.out.println("method show run");
    10                   }
    11             });
    12       }
    13       public static void show(Inter in){
    14             in.method();
    15       }
    16 }

    ---------- android培训java培训、期待与您交流! ----------

  • 相关阅读:
    java 正则 二次转义
    HDU1789 Doing Homework again 【贪心】
    扣丁学堂笔记第22天多媒体播放
    [Python]BeautifulSoup—HTML解析包
    Android高级控件(三)—— 使用Google ZXing实现二维码的扫描和生成相关功能体系
    Business Process and SAP ERP
    HTML基础知识总结一
    控制器View是怎样创建的?
    cocos2d-x 3.0 场景切换特效汇总
    LeetCode 3Sum
  • 原文地址:https://www.cnblogs.com/jianxingjianyuan2014/p/3998571.html
Copyright © 2011-2022 走看看