`
小驴变黑马
  • 浏览: 12020 次
文章分类
社区版块
存档分类

黑马学习日记_面向对象编程

阅读更多
---------------------- android开发java培训、期待与您交流! ----------------------
 
1.面向对象概念
            什么是面向对象,面向对象与面向过程的区别?
                      面向对象是相对面向过程而言,面向过程和面向对象都是一种思想,面向过程注重的是过程, 强调的是功能行为,面向对象就是将功能封装进对象,强调的是具备了功能的对象。面向对象 简单地说就是站在对象的角度考虑问题。
 
         面向对象的几个例子:(比较重要一定要理解)
               a.账户的存取
                      面向对象简单地说就是站在对象的角度考虑问题,比如说有一个账户,我们可以对其进行存款和取款的操作,以面向过程的思想考虑就是我们操作此账户,来手动的完成存和取的动作。而以 面向对象的思想来考虑的话,就是我们可以把存款和取款这两个功能封装在账户中,每当我们要存或取的时候,就直接调用账户就行了。
               b.冰箱的开关
                      要把大象放进冰箱,要分为三个步骤,把冰箱门打开,把大象放进去,把冰箱门关上。首先开门,放东西进去,关门,这三步都是过程吧,以面向过程的思想就是我们要去执行这三个过程,每一次往里放东西都要执行这三个步骤,这样是比较麻烦的,这样考虑下,加入我们把这三个 功能的方法装进冰箱里,就是说冰箱具有自动开关等功能,我们再需要往冰箱里放东西,是不是就可以直接找冰箱这三个步骤让它来做(因为它具有了这三个功能)就行啦。
 
                     再简单点说就是,比如有一个大筐里面放了编写程序所需要的所有功能(也就是函数),再假如 说此时我们要做一件事,过程中需要调用好多功能,这时我们是不是就需要在那个大筐里找我们所 需要的功能啊,这样是比较麻烦的。然后我们再想是不是可以这样,这个大筐中的功能肯定有好多共性的,并且同属于一个事物的(比如说冰箱的开关等),这时我们是不是就可以把这些共性的功能放到另一个小筐里啊,等下次再用的时候直接找这个小框就行了,反正那些功能是小筐特有的,那就直接让它做就ok了,这样是不是就省了很多事儿啊。    
             
面向对象的特点有哪些?
                1、 面向对象是一种思想
2、可以将复杂的事情简单化
3、将程序员从执行者转换成了指挥者
 
为什么需要面向对象?
面向对象与人们习惯的思维方法一致,使程序代码更加容易让人理解和接受,开发效率高,并且有利与后期修改和维护;面向对象能提高代码的复用性,而面向过程就不行,好比有一个功能, 面向过程的程序设计时如果有很多地方都用到这个功能,那好多地方的代码肯定都是重复的,而用面向对象的话,就直接调用(对象.功能) 就行了,够简洁吧。
   
2.类与对象的区别
                 在开发的过程中其实就是在找对象用,比如说要用一个功能,就找其对应的对象,如果没有的话,就 自己造一个对象,把功能封装进去。然后再指挥该对象做事情。
类:就是具体事物的描述,就是描述对象的,类是抽象的,就像一张图纸。
对象:就是实实在在具体的事物,类就是描述它的。new一个类就出来一个对象实体在java中,描述就是class定义的类,对象就是java堆内存中new出来的实体。因为一个对象里含有很多数据,我们说含有很多数据的就用实体来存储,就像数组一样
 
怎么定义一个类?
定义一个类其实就是在描述一个事物,而一个事物通常都会有属性与行为,就像一只鸭子,眼睛 腿就是 属性,游泳就是行为。属性对应的就是类中的变量,行为对应的就是类中的函数。 一个类要想独立运行的前提是要有主函数,而建立一个类不需要独立运行的话可以不写主函数
   
类中的成员有:成员变量和成员函数
成员变量与局部变量的区别是什么?
成员变量作用于整个类中,而局部变量作用于函数中或语句中,用过后空间会被自动释放。成员变量在栈内存中,而局部变量存在于堆内存中,因为它是因对象存在而存在的,你说人都没了定义人的年龄有什么用。局部变量没有默认初始化值,而成员变量有默认初始化值。
 
                定义一个类:
                              class Car//对Car这类事物进行描述
                              {
                                       String color = "red";//在整个类中有效
                                       int num = 4;
                                       void show()
                                       {
                                              System.out.println("color="+color+"..num="+num);
                                       }
                              }
                             class CarDemo
                             {
                                      public static void main(String[] args)
                                      {
                                             Car c = new Car();//new一个汽车实体
                                             c.color = "black";//对对象(汽车)的属性进行修改
                                             c.show();//使用对象的功能。
                                      }
                              }
 
             匿名对象
                   什么是匿名对象?
                       匿名对象是对象的简化形式
                      例如:Car c = new Car();c.show();可以写成new Car().show;这就是匿名对象直接调用show方法
 
                  什么情况下使用匿名对象?
                          1.当对对象的方法只调用一次时(调用变量没意义),可以用匿名对象来完成,这样写比较简化。
                             如果对一个对象进行多个成员调用,必须给这个对象起个名字。
 2.可以将匿名对象作为实际参数进行传递。
                         代码:
                          
 class Car
                           {
                                   String color = "红色";//描述颜色
                                   int num = 4;//描述轮胎数
 
                                   void run()//运行行为。
                                   {
                                            System.out.println(color+".."+num);
                                   }
 
                           }
 
                           class  CarDemo
                           {
                                    public static void main(String[] args) 
                                    {
                                             //创建一匿名对象调用属性
                                               new Car().num = 5;
                                             //又创建一匿名对象,此时上面创建的堆内存中的实体已经成垃圾了
                                               new Car().color = "blue";
                                               new Car().run();//创建匿名对象调用属性没意义,因为调过来了没人用
         
 
                                               Car q = new Car();
                                               show(q);//创建一有名对象,调用show方法
                                               //上面两步可以简化成这样:
                                                show(new Car());//匿名对象当参数传入
                                    }
 
 
                                    public static void show(Car c)//传入一个car类型的参数
                                    {
                                                c.num = 3;
                                                c.color = "black";
                                                c.run();
                                    }
                          }
  
          对象与匿名对象在内存中的结构如下图:
黑马程序员——面向对象之封装 - hm_yong_jie - hm_yong_jie的博客
 
 3.封装
什么是封装?
面向对象三大特征之一,是指隐藏对象的属性和实现细节,仅对外提供 公共访问方式。就是说我们如果调用一个功能的话,我们要的就是它的结果,而它怎么实现的和我们没关系。函数就是最小的封装体。
1、比如说我们使用的电脑,什么上网啊,玩游戏啊,我们使用的只是它的功能,有必要直到它内部是怎么实现的吗?有必要打开机箱看看里面都是什么吗?即使打开看了也不懂,还有可能把电脑给捯饬坏。
 
使用封装有什么好处呢?
1.提高安全性  把主板啊,cpu啊封装在机箱内,避免我们这些不懂的人乱碰乱改,是不是安全了?
2.提高重用性  
3.将变化隔离  这次机箱里面的部件是这样,等过些日子又出来一新电脑,里面的东西是不是变啦, 怎么变得我们知道,也不需要知道,这就是将变化隔离               
4.便于使用   我们不需要知道电脑的内部结构了,直接拿过来就能用,是不是很方便
              
private(私有)关键字
封装的目的就是限制对类里面成员的访问,隐藏类的实现细节,那么要限制类的外部对类成员的访问,可以用访问修饰符private来修饰属性。
1.private是一个权限修饰符
2.用于修饰成员(成员变量和成员函数)
3.被私有化的成员只在本类中有效用private将成员变量私有化,对外提供对应的set,get方法对其进行访问,提高对数据访问的安全性。
 
                    代码:
                          
class Person
                          {
                                 //把person类中的age属性私有化,在其他类中将不能访问它,像new Person().age是不行的
                                     private int age;
                               //在这个类中不让访问age,但是你得提供一个让别人访问的方法啊,就是下面这样
                                     public void setAge(int a)
                                     {
                                              if(a>0 && a<130)
                                               {
                                                        age = a;
                                                        speak();
                                               }
                                              else
                                                    System.out.println("feifa age");
                                     }
 
                                     public int getAge()
                                     {
                                              return age;
                                     }
                                   //类中的方法被私有化,在别的类中也是访问不到的,只在本类中有效
                                     private void speak()
                                     {
                                              System.out.println("age="+age);
                                     }   
                           }
  
  4.构造函数
什么是构造函数?
构造函数是类中一种特殊的函数,它方法名誉类名相同,没有返回值类型,也不需要void,构造 函数的作用在于创建对象的时候初始化对象,给实例化对象的成员变量赋初始值。
 
构造函数的特点是什么?
1.函数名与类名相同   
2.不用定义返回值类型(void也是一种返回值类型)
3.不可以写return语句   函数中连返回值类型都没有还用得着把return语句吗?
 
构造函数与一般函数有什么区别?
1.首先在写法上就不同,然后在运行上也有不同。构造函数是在对象一建立就运行。给对象初始化。而一般方法是对象调用才执行,是给对象添加对象具备的功能。
2.一个对象建立,构造函数只运行一次。而一般方法可以被该对象调用多次。可以理解为构造函数就是为了创建对象,对象一创建完它的使命就完成了
  
什么时候用构造函数?
当分析事物时,该事物存在具备一些特性或者行为,就是该食物一定具备哪些行为(就像小孩 一出生就哭)那么将这些内容定义在构造函数中。然后再考虑写构造函数的时候是否需要未知参数参与运算。
 
构造函数有什么用?
构造函数是用来给对象进行初始化的,对象一建立就会调用与之对应的构造函数,
注意:
说是对象一初始化就要调用构造函数,那前些日子写代码也没斜构造函数啊?这是因为当 一个类中没写构造函数时,系统会帮你自动加一个空参数的构造函数,方便于对象初始化, 否则对象是建立不出来的。总之要记着,一个类中如果没有构造函数,那这个对象是肯定new不出来的。如果new对象时,类中没有与它对应的构造函数,这样也是创建不出对象的。 如果你自己建立了一个构造函数,那默认的构造函数就没了。
                  
部分代码:
                         
 class Person
                          {
                                    private String name;
                                    private int age;
                                 
                                  //所以对象一创建就会按下面与之对应的构造函数来初始化对象
                                     Person()
                                     {
                                              System.out.println("A: name="+name+",,age="+age);
                                     }
                               //构造函数也是函数它也可以重载
                                    Person(String n)
                                    {
                                              name = n;
                                              System.out.println("B: name="+name+",,age="+age);  
                                    }
 
                                   Person(String n,int a)
                                   {
                                              name = n;
                                              age = a;
                                              System.out.println("C: name="+name+",,age="+age);
                                   }
                         }
 
                         class  PersonDemo2
                         {
                                    public static void main(String[] args) 
                                    {
                                            //对应第一种构造函数new出来的人什么都没有
                                               Person p1 = new Person();
                                            //对应第二种构造函数new出来的人有名字没年龄
                                               Person p2 = new Person("lisi");
                                            //对应第三种构造函数new出来的人有年龄有姓名
                                               Person p3 = new Person("lisi",0);
  
                                    }
                         }
  
构造代码块:
作用:给对象进行初始化,对象一创建就运行,并且优先于构造函数
疑问:构造函数不就是给对象进行初始化的吗,为什么还要用构造代码块啊?和构造函数的区别:                        上面不是说有很多种构造函数吗,就是说创建对象的时候能创建很多种类型的对象,每一种构造函数都是给其对应的那类对象初始化,而构造代码块是给所有种类的对象都初始化,也就是说把所有类型对象的共同点给抽出来写在构造代码块里,这样就不用在每种构造函数都写了,比如每一种小孩生下来都哭,那么这样就可以把哭的行为写进构造代码块,是不是比在每个构造函数里都写显得轻松啊,就像是以前说的如果好几段代码里都有相同代码的时候,那就把这些相同的抽出来写进一个函数中,不就 省的来回的重复写啦。                                                                                                     
 
5.this关键字
                  class Person
                  {
                            private String name;//此name是成员变量 
                            public void String setName(String name)//此name是往函数中传的参数是局部变量
                            {
                                          //this.成员变量 = 局部变量
                                           this.name  =  name;
                            }
                 } 
从以上代码看出this是用来解决成员变量和局部变量同名似的问题。
this:看上去,是用于区分局部变量和成员变量同名情况。
this:就代表本类的对象,到底代表哪一个呢?
this代表它所在函数所属对象的引用。
简单说:哪个对象在调用this所在的函数,this就代表哪个对象。
                
类中成员之间的互相调用的时候其实都是对象完成的,只不过是省略了this.。
                    class Person
                    {
                              private String name;
 
                              public void speak()
                              {
                                        System.out.println("name="+this.name);//省略了this.     
                              }
                    }
 
 this的应用:
当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象。
但凡本类功能内部使用了了本类对象,都用this表示。
 
          this语句 :用于构造函数之间进行互相调用。
          this语句只能定义在构造函数的第一行。因为初始化要先执行。
部分代码:  
                           
 class Person
                            {
                                      private String name;
                                      private int age;
                                      Person(String name)
                                      {
                                               this.name =name;
                                      }
                                      Person(String name,int age)
                                      {
                                               this(name);//调用上一种构造函数,不过要写在第一行
                                               this.age = age;
                                      }
                            }
  
 6.static关键字
                     static用于修饰成员(成员变量和成员函数),static修饰的是把所有new出来的对象共性的东西。
          参看下图:
黑马程序员——面向对象之封装 - hm_yong_jie - hm_yong_jie的博客
 
被修饰后的成员具备以下特点:
1.随着类的加载而加载 说明它的生命周期和类一样长,而一般成员是随着对象的存在而存在的
2.优先于对象存在  静态是先存在的,对象是后存在的。
3.被所有对象所共享
4.可以直接被类名调用
使用static时要注意:
1.静态方法只能访问静态成员
2.静态方法中不可以写this,super关键字,静态修饰的对象先于构造函数存在,
3.主函数是静态的
 
什么时候使用静态?
因为静态修饰的内容有成员变量和函数。那就分两步下手:
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。对象中的特有数据要定义成非静态存在于堆内存中。
什么时候定义静态函数呢?
当功能内部没有访问到肺静态数据(对象的特有数据),那么该功能可以定义成静态的。
 
  静态代码块。
                         格式:
                                 static
                                 {
                                            //静态代码块中的执行语句。
                                 }
 
                         特点:随着类的加载而执行,只执行一次,并优先于主函数。用于给类进行初始化的。
                         优先级  高----------------------------------->低        
                          静态代码块----  构造代码块----构造函数   
                        class StaticCode
                        {
                                   StaticCode()
                                   {
                                            System.out.println("b");
                                   }
 
                                   static//静态代码块,先于构造代码块和构造函数
                                   {
                                             System.out.println("a");
                                   }
                                    //构造代码块,先于构造函数
                                   {
                                             System.out.println("c");
                                   }
 
                                   StaticCode(int x)
                                   {
                                             System.out.println("d");
                                   }
                       }
                      class StaticCodeDemo 
                      {
                                public static void main(String[] args) 
                                {
                                          new StaticCode(4);
                                
                      }
                      打印结果:a  c  d
 
实例变量(成员变量)和类变量(static修饰的变量)的区别:
1,存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
2,生命周期:
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
使用静态有哪些利弊?
利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。可以直接被类名调用。
弊端:生命周期过长。访问出现局限性。(静态虽好,但是只能访问静态。)
    
对象初始化过程:                                                                                                                                                              
Person p = new Person("zhangsan",20);                                            
该句话都做了什么事情?                                                          
1,因为new用到了Person.class.所以会先找到Person.class文件并加载到内存中。
2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。
3,在堆内存中开辟空间,分配内存地址。
4,在堆内存中建立对象的特有属性。并进行默认初始化。
5,对属性进行显示初始化。
6,对对象进行构造代码块初始化。
7,对对象进行对应的构造函数初始化。
8,将内存地址付给栈内存中的p变量。                                                
  
7.单例设计模式
单例设计模式:解决一个类在内存只存在一个对象。
想要保证对象唯一新需要三步:
1,为了避免其他程序过多建立该类对象。先禁止其他程序建立该类对象
2,还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象。
3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式。
       这三部怎么用代码体现呢?
  1,将构造函数私有化。
2,在类中创建一个本类对象。
3,提供一个方法可以获取到该对象。
 
                     饿汉式
                             这个是先初始化对象。Single类一进内存,就已经创建好了对象。
                            
class Single
                            {
                                     private static Single s = new Single();
                                     private Single(){}
                                     public static Single getInstance()
                                     {
                                               return s;
                                     }
                            }
  
 
                     懒汉式
                                对象是方法被调用时,才初始化,也叫做对象的延时加载。Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。
 
                               
  class Single
                                  {
                                             private static Single s = null;
                                             private Single(){};
                                             public static Single getInstance()//双重判断 先判断是否为空,再判断锁,然后再判读是否为空
                                             {
                                                     if(s==null)
                                                      {
                                                                synchronized(Single.class)
                                                                {    
                                                                        if(s==null)
                                                                                 s = new Single();
                                                                }
                                                     }
                                                                return s;
                                             }
                                }
  
1.继承
      1、什么是继承?
             多个类中存在相同属性和行为时,将这些内容抽取到 单独一个类中,那么多个类无需再定
          义这些属性和行 为,只要继承单独的那个类即可。多个类可以称为子类,单独这个类称为父类
          超类。子类可以直接访问父类中的非私有的属性和行为。通过extends 关键字让类与类之间产生
          或者继承关系。如:class SubDemo extends Demo{}
-------------------------------------------------------------------------------------------------
          举个例子,比方说俩兄弟去露营,那这时候是不是要带帐篷,救生箱,睡袋什么的啊。但是哥俩
          每个人都带一份是不是就显得累赘啊,这个时候父亲看到了:"说我也去,我拿帐篷,救生箱什么
          的“。这样兄弟俩是不是就轻松了许多啊,不用每个人都拿那么多东西了,晚上睡觉的时候或者
          需要救生箱的时候到父亲那拿就行了。  这个父亲就相当于父类,俩兄弟就是子类,父类中都是
          子类所共有的,所以子类中就没必要再挨个定义了。只要不是父类私有的东西,子类都可以继承
          过来用,父类与子类之间通过 extends 来实现继承。
-------------------------------------------------------------------------------------------------
          通过继承可以使用其他类里的功能,但是千万不要为了使用其他类里的功能而随便继承,必须是
          类与类之间存在所属关系才能够继承,就像是你露营的时候不可能别人拿了个游戏机你为了玩个
          游戏,就随便认别人为父亲吧。像燕子麻雀等都能继承鸟类,但你不可能为了吃的功能去继承哺
          乳动物那一类吧。所属关系是 is a才能继承。is a(谁是谁里面的一员)。
 
-------------------------------------------------------------------------------------------------
      2、继承的特点是什么?
          Java只支持单继承,不支持多继承。一个类只能有一个父类,不可以有多个父类。因为多继承容
           易带来安全隐患:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一
           个。但是java保留这种机制。并用另一种体现形式来完成表示。可以多实现接口。
             class SubDemo extends Demo{} //正确
             class SubDemo extends Demo1,Demo2...//错误
 
          Java支持多层继承(继承体系),就类似父亲-儿子-孙子的关系
             class A{}
             class B extends A{}
             class C extends B{}
 
          定义继承需要注意:
              不要仅为了获取其他类中某个功能而去继承
 
          类与类之间要有所属( " is a " )关系才能继承,xx1是xx2的一种。
-------------------------------------------------------------------------------------------------
      3.如何使用一个继承体系中的功能呢?
          在使用一个继承体系中的功能时,可以看一下这个体系中父亲类的功能是什么,因为父亲类中
          肯定是这个体系中最共性的东西,通过了解共性功能,就了解到这个体系的基本功能是什么了。
          但是在具体调用时,要创建最子类的对象,为什么呢?
          一是因为有可能父类不能创建对象,
          二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。
 
        简单一句话:查阅父类功能,创建子类对象使用功能。 
-------------------------------------------------------------------------------------------------
      4.聚集关系
          java类与类之间的其它关系:
          聚集或者叫关联: 分为聚合和组合两部分
          聚合:has a 一个班级由很多学生组成,学生与班级的关系就是组合。
          组合:事物的联系程度更紧密,例如心脏是人身体中的一部分,班级少一个人行,人缺了心脏不行。
-------------------------------------------------------------------------------------------------
      5.子父类中成员的特点
             类中成员包括:1,变量。2,函数。3,构造函数。
         a.那么子父类中的变量特点是什么呢?
             继承的时候,当子类和父类之间存在相同的成员变量时,子类要访问本类中的变量,用this,
             子类要访问父类中的同名变量,用super。比方说你本来有一个苹果,又从父亲那继承过来一
             个苹果,这个时候你要吃的话,就是吃自己的(this)还是父亲的(super);
           super 的使用和this的使用几乎一致。this代表的是本类对象的引用。super代表的是父类对象的引用。
   
         b.子父类中函数的特点
             当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。
             如同父类的函数被覆盖一样。就像孩子从父亲那继承过来说话的行为(函数),运行的时候,是
             自己说话的功能,而不是父亲的。
    
             这种情况是函数的另一个特性:重写(或覆盖)
             当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却
             和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重
             写功能内容。
 
    
             比如说你写了一个类,类中的功能(函数)什么的都很符合当时的需求,但是过了一段时间功能
             例的内容又改变了怎么办?不可能一遍又一遍的修改源代码,这时就可以再写一个类来继承这
             各类,然后再写一个与父类方法名一样的函数,来更新函数的功能,这就用到了覆盖。
             部分代码:
                 class Tel//比如这个程序的功能当时就能打电话发信息
                 {
                     void show()
                     {
                         System.out.println("打电话");
                         System.out.println("发信息");
                     }
       
                 }
                  //一段时间后,又需要加一个上网的功能,这时不可能去改源代码或重新写一个程序这时只
                  //需要再写个类继承上个类,然后重写父类的功能就行了,如果这个新功能用着不好,还可以
                  //接着在用父类的
                class NewTel extends Tel//继承上个类
                {
                    void show()//覆盖父类的方法
                    {
                        System.out.println("打电话");
                        System.out.println("发信息");
                        System.out.println("上网");
                    }
                }
 
 
          使用覆盖时需要注意哪些问题?
             1,子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
             2,静态只能覆盖静态。
 
 
          重载与重写的区别:
             重载:只看同名函数的参数列表。
             重写:子父类方法要一模一样。就方法里面的内容不一样
 
   c.子父类中的构造函数的特点。
           在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第
           一行有一条隐式的语句 super();super():是访问父类中空参数的构造函数。而且子类中
           所有的构造函数默认第一行都是super();
 
           super关键字
           1.super和this的用法相同    
           2.this代表本类应用,super代表父类引用
           3.当子父类出现同名成员时,可以用super进行区分
           4.子类要调用父类构造函数时,可以使用super语句。
-------------------------------------------------------------------------------------------------
         为什么子类一定要访问父类中的构造函数呢?
             因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如
             何对这些数据进行初始化的。所以子类在对象初始化时,要先访问一下父类中的构造
             函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
-------------------------------------------------------------------------------------------------
         子类的实例化过程:
 
            子类的所有的构造函数,默认都会访问父类中空参数的构造函数。因为子类每一个构造函数内的第一行都有一句隐式super();当父类中没有空参数的构造函数时,子类必须手 动通过super语句形式来指定要访问父类中的构造函数。子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。
        部分代码:
            class Fu 
            {
                int num ;//1.子类继承它之后,这个成员就能直接拿过去用了
                Fu()
                {
                    num= 60;//2.但是拿过去之前得先看下父类是怎么初始化的啊
                    System.out.println("fu run");
                }
                Fu(int  x)
                {
                    System.out.println("fu ...."+x);
                }     
            }
 
            class Zi extends Fu
            {
                Zi()
                {
                  //3.如果父类已经初始化过num=60了,那再在子类中初始化就有点多余了不是
                     //num = 60 
                 //4.所以子类初始化之前要先看下父类是怎么初始化的,默认是父类空参数的构造函数
                      super();  
                 //super(4);5.但是也可以自己指定用父类的哪个构造函数,无论哪种都必须在第一行
                      System.out.println("zi run");
                }
                Zi(int x)
                {
                    this();//6.子类中的构造函数也可用this语句访问本类的构造函数
               //super();7.有6的话,就不用再写父类的构造函数了,因为this()里已经做了这个的动作了
                    System.out.println("zi..."+x);
                }
            }
 
           class  ExtendsDemo4
           {
               public static void main(String[] args) 
               {
                   Zi z = new Zi(0);
                   System.out.println(z.num);
               }
           }
-------------------------------------------------------------------------------------------------
    6.final关键字
 
         继承的缺点是破坏了封装性,人家本来一个类好好的,把里面的功能封装起来就是让你不用动
         里面的功能直接用就行了,你这把人家继承过来之后,不光用还能改,这样是不是封装性就打
         破了啊?要想不让别人改你的功能,可以用final来修饰类,这样别人就不能继承你了,如果一
         个类被别人继承之后觉得里面的个别功能你能重写,但是有的你不能重写,只是就可以用final
         来修饰那些不认别人重写的功能(函数)。
 
         final : 最终的意思。是一个修饰符,
         final的特点:
            1,可以修饰类,函数,变量。
            2,被final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
            3,被final修饰的方法不可以被复写。
            4,被final修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,有可以修饰局部变量。
               当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起
               个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。
               final常量:常量的书写规范所有字母都大写,如果由多个单词组成。单词间通过_连接。
                         如:public static final double PI = 3.14;
            5,内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.继承(2)
      7.抽象类
         什么是抽象?
            抽象就是不具体的东西,就是将很多事物的共性的本质的抽取出来。比如说狗和狼都属于
            犬科,那么这个犬科就是抽象的,它具有狗和狼的共性,但是它很笼统。
         什么是抽象类?
            Java中可以定义没有方法体的方法,该方法的具体实现由子类完成,该方法称为抽象方法,
            包含抽象方法的类就是抽象类。
            举个例子: 比方说父亲要教两个孩子一个运动的功能,但是具体的是什么不教,两个孩子
            从父亲那继承过来后,就要重写这个运动功能,一个孩子踢足球,一个孩子打篮球,那么
            这个父亲就是抽象类,因为他将两个孩子的共性抽取出来了,并且孩子从父亲那继承过来
            之后还必须自己重写这个功能,不然孩子也是抽象类了。
 
            当多个类中出现相同功能,但是功能主体不同,这是可以进行向上抽取。这时,只抽取功能
            定义,而不抽取功能主体。
 
            部分代码:
              abstract class Fu//抽象类必须用abstract修饰,它不能new对象,比方说你new                    
              {                // 了一个对象调用相面这个方法有意义吗?
                  abstract void sport();//抽象函数也必须用abstract修饰
              }
              class Zi1
              {
                  void sport()//要使用父类的抽象方法必须复写抽象方法
                  {
                      System.out.println("踢足球");
                  }
              }
              class Zi2
              {
                  void sport()
                  {
                      System.out.println("打篮球");
                  }
              }
-------------------------------------------------------------------------------------------------
         抽象类的特点:
              1,抽象方法一定在抽象类中。
              2.抽象方法只有方法声明,没有方法体,定义在抽象类中。
                 格式:修饰符abstract 返回值类型  函数名(参数列表) ;
              3.抽象方法和抽象类都必须被abstract关键字修饰。
              4.抽象类不可以用new创建对象。因为调用抽象方法没意义。
              5.抽象类中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对
                 象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
-------------------------------------------------------------------------------------------------
          抽象类与一般类没什么太大的区别,就是抽象类中比一般类多了个抽象方法,其他的
          还该怎么写该怎么写,抽象类中可以有好多函数,但并不意味着抽象类里面的函数都得是
          抽象的。另一个就是抽象类不能被实例化。
          抽象类中可以不定义抽象方法,加abstract的目的仅仅是不让创建该类的对象(不常见)。
 
          abstract 与final修饰的类的区别:
          用final修饰的类不能被继承,而用abstract修饰的类一定要有子类,不然里面的抽象
          方法没人复写留着有什么用。
-------------------------------------------------------------------------------------------------
          abstract 与下面三个关键字不能共存:
             final:被final修饰的类不能有子类,而被abstract修饰的类一定是一个父类。
             private: 抽象类被私有了,不被子类所知,就无法被复写,而抽象方法出现的就是
                      需要被复写。
             static:如果static修饰了抽象方法,那么连对象都省了,直接类名调用就可以了,
                     可是抽象方法运行没意义。
-------------------------------------------------------------------------------------------------
 
         抽象类和接口中是否有构造函数?
            抽象类中有,抽象类是一个父类,而子类继承父类的时候,子类的构造函数第一句一定是
            父类的构造函数(super()),如果抽象类中没有,构造函数那子类不能实例化成功;
            接口中没有构造函数,因为接口中都是方法都是抽象的,变量都是被final修饰的不能更
            改的,而构造函数中可以有方法体,这与抽象函数相违背。然后类可以实现多个接口,若
            多个接口都有自己的构造器,则不好决定子类的构造函数第一行怎么写。
-------------------------------------------------------------------------------------------------
     9. 模板方法模式
         什么是模版方法呢?
            在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不
            确定的部分,那么这时就将不确定的部分暴露出去。由该类的子类去完成。
         部分代码:
           
 abstract class GetTime//1.例如获取一个for循环遍历运行的时间
            {
               public final void getTime()//2.获取时间的方法是确定的定义开始时间在定义结束时间
                {
                   long start = System.currentTimeMillis();
                 //3.但是求那种for循环的代码是不确定的,比如说你是求打印100个数用的时间呢还是求遍
                //历出数组中最大值然后再打印的时间呢
                    runcode();//4.所以求那段代码运行的时间是不确定的
                   long end = System.currentTimeMillis();
 
                   System.out.println("毫秒:"+(end-start));
               }
               public abstract void runcode();//5.所以把这段不确定的给暴露出去,让子类继承
 
            }
 
            class SubTime extends GetTime//
            {
                public void runcode()//6.然后子类需要求谁的运行时间就复写5的功能把谁写进去
                {     
                    for(int x=0; x<4000; x++)
                    {
                        System.out.print(x);
                    }
                }
            }
 
            class  TemplateDemo
            {
                public static void main(String[] args) 
                {
                    SubTime gt = new SubTime();//创建子类对象
                     gt.getTime();
                }
            }
  
 
      10.接口
          什么是接口?
            接口:可以认为是一个特殊的抽象类当抽象类中的方法都是抽象的,那么该类可以通过接
            口的形式来表示。用interface用来定义接口。格式为 :  interface 接口名 {}
 
            接口中常见定义的有常量和抽象函数他们的默认表达方式为:
                常量:public static final
                方法:public abstract 
                接口中的成员都是public修饰。
 
         接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全都
         覆盖后,子类才可以实例化。否则子类是一个抽象类。
-------------------------------------------------------------------------------------------------
          接口的特点:
            1.对外暴露规则
            2.降低耦合度    需要举例,如usb。pci,主板。插座。
            3.接口是程序的功能扩展
            4.接口直接可以用来多实现
            5.类与接口之间是实现关系,而且类继承  类的同时可以多实现接口
            6.接口与接口之间有继承关系,并且可以多继承。
                                                                                              
       注意:java中不支持多继承类但是可以多实现接口,另外接口继承接口,接口之间存在多继承,
             类继承类的同时还能实现多个接口来进行功能扩展。
 
          接口与接口之间存在多继承,类之间不能多继承的原因是,如果两个父类中有两个相同的函数,
          方法体却不一样时,子类继承过来后,不知道该调用那个函数。而接口中因为都是抽象的方法,
          没有方法主体,所以接口之间可以继承。
-------------------------------------------------------------------------------------------------
        部分代码:
          
interface A
          {
              void methodA();   
          }
          interface B 
          {
              void methodB();
              void methodD();//类可以多实现的原因,B和D中都有methodD(),类D显现哪个都一样
          }
 
          interface C //extends B,A接口之间可以多继承
          {
              void methodC();
              void methodD();
          }
 
          class D implements B,C//类可以多实现接口
          {
              public void methodA(){}//因为接口中成员都是public权限的,所以子类要想用的话     
              public void methodC(){}//权限得大于等于public
              public void methodB(){}
          }
 --------------------------------------------------------------------------------------------------------------------------------------------------------------
2.多态
    1.什么是多态?
          多态:可以理解为事物存在的多种体现形态。
         部分代码:
            
abstract class Animal
            {
                abstract  void eat();
            }
            class Cat extends Animal//1.使用多态前提是类与类(接口)之间必须具有继承或实现关系
            {                       //因为若没有继承关系2中Animal就不能接收它
                public void eat()
                {
                    System.out.println("吃鱼");//3.通常还要有覆盖关系
                }
                public void catchMouse()//子类特有的方法
                {
                    System.out.println("抓老鼠");
                }
 
            }
            class Dog extends Animal
            {
                public void eat()
                {
                    System.out.println("吃骨头");
                }
                public void kanJia()//子类特有的方法
                {
                    System.out.println("看家");
                }
 
            }
            class DuoTaiDemo 
            {
                public static void main(String[] args) 
                {
                    function(new Dog());//相当于Animal a = new Dog();
                    function(new Cat());//相当于Animal a = new Cat();
                }
 
                public static void function(Animal a)//2.而使用Animal可以接收所有它的子类
                {
                    a.eat();//4.如果没有覆盖关系,把它接收过来又有什么用呢
                }
             
            }
     3.多态--转型
        上面代码是通过多态使用父类中的方法。因为子类中都复写了,所以可以通过把父类当参数传
        进来,然后接收它的子类,再调用父类的方法(其实就是子类的方法因为复写)就行了。
-------------------------------------------------------------------------------------------------
        但是怎么通过多态来调用子类中特有的方法呢?                                        
            Animal a = new Cat();接收一个猫类型的话,猫类型提升,向上转型就像byte提升为int   
                如果想要调用猫的特有方法时,如何操作?                                
                 强制将父类的引用。转成子类类型。向下转型。                              
                  Cat c = (Cat)a;                                                 
                   c.catchMouse();                                            
              千万不要出现这样的操作,就是将父类对象转成子类类型。如下:                    
                    Animal a = new Animal();                                       
                    Cat c = (Cat)a;                                                
         我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。     
         多态自始至终都是子类对象在做着变化。                                            
-------------------------------------------------------------------------------------------------
    
      如上面的代码:
         Animal a = new cat();//类型提升 向上转型了
         但是如和访问cat类中特有的方法呢?
         这个时候如果使用a.catchMouse();因为a被提升为动物类型了,那动物有很多种,不一定指的就是猫
        instanceof : 用于判断对象的类型。 对象 intanceof 类型(类类型 接口类型) 
 
 
           1,多态的体现
               父类的引用指向了自己的子类对象。例如:动物 x = new 猫(); 
           2,多态的前提
               必须是类与类之间有关系。要么继承,要么实现。通常还有一个前提:存在覆盖。  
           3,多态的好处
                多态的出现大大的提高程序的扩展性。
           4,多态的弊端:
               提高了扩展性,但是只能使用父类的引用访问父类中的成员。
           5,多态的应用
-----------------------------------------------------------------------------------
     4.多态中成员的特点
         多态中成员函数的特点:编译看左边运行看右边 
         成员变量的特点:无论编译还是运行都看左边 
         静态成员函数的特点:编译或运行都看左边 
-----------------------------------------------------------------------------------
         部分代码:
        
class Fu
           {
               int num = 5;
               void show1()
               {
                   System.out.println("Fu show_1");
               }
               void show2()
               {
                   System.out.println("Fu show_2");
               }
               static void show4()
               {
                   System.out.println("Fu show_4");
               }
           }
           class Zi extends Fu
           {
               int num = 8;
               int x=3;
               void show1()
               {
                    System.out.println("Zi show_1");
               }
               void show3()
               {
                   System.out.println("Zi show_3");
               }
               static void show4()
               {
                   System.out.println("Zi show_4");
               }
               static void show5()
               {
                   System.out.println("Zi show_5");
               }
           }
           class  DuoTaiTeDian
           {
               public static void main(String[] args) 
               {
                 Fu f = new Zi();
               //如果是f.Show3();则编译不通过因为父类中没有f.Show3();运行结果则是累类中的"Zi show_1";
                 f.show1();
           //如果是f.x则编译不通过,因为看左边父类中无X成员变量,运行结果也是5,因为运行也看左边父类中有num=5;
                  System.out.println(f.num);
           //因为左边父类中无show5(),所以编译不通过。如果为f.show4(),则打印结果为"Fu show_4";
                  f.show4();
               }
           }
 
     5.object类equal
          Object:是所有对象的直接后者间接父类,传说中的上帝。所以该类中定义的肯定是所有对象都
                 具备的功能。
          Object类中已经提供了对对象是否相同的比较方法。如果自定义类中也有比较相同的功能,没
          有必要重新定义。只要沿袭父类中的功能,建立自己特有比较内容即可。这就是覆盖。
   
          使用运算符"=="与equals()方法都可以进行对象的比较但是两者是有区别的?
              当使用关系运算符"=="比较两个对象时,是比较两个对象使用的内存地址和内容是否像相同,
            如果两个对象使用的是同一个内存地址,并且内容相同,则结果返回true,否则结果为false。 
              当使用equals()方法比较两个对象时,则是比较两个对象的内容是否相同,而与内存地址无关,
            如果两个对象的内容相同,则结果为true,否则结果为false。
        部分代码:
         
class  EqualDemo
         {
             public static void main(String[] args) 
             {
                 String str1 = new String("hello");
                 String str2 = new String("hell0");
                 String str3 = str2;
                 //用“==”比较str1与str2
                 System.out.println("str1与str2的比较结果为:"+(str1==str2));
                //用“==”比较str2与str3
                 System.out.println("str1与str2的比较结果为:"+(str2==str3));
                //用equals方法比较str1与str2
                 System.out.println("str1与str2的比较结果为:"+str1.equals(str2));
                //用equals方法比较str2与str3
                System.out.println("str1与str2的比较结果为:"+str2.equals(str3));
             }
         }
 ---------------------- android开发java培训、期待与您交流! ----------------------
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics