黑马程序员_Java面向对象下

------- android培训java培训java博客、java学习型技术博客、期待与您交流! ----------

 抽象类 abstract  

概念:有抽象方法的类叫做抽象类

抽象类的特点 :

1.抽象方法一定在抽象类中。

2.抽象方法和抽象类都必须被abstract关键字修饰。

3.抽象类不可以用new创建对象。因为调用抽象方法没意义。

4.抽象类中的方法要被使用,必须由子类覆写其所有的抽象方法后,建立子类对象调用。

   如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

对抽象类的应用:

  假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性:

  姓名、工号、以及工资。经理也是员工,除了含有员工的属性外,另外还有一个奖金属性。

  请使用继承的思想设计出员工类和经理类。要求类中提供必要的方法进行属性访问。

abstractclass Employee{

    private Stringname;//private修饰,范围只能在本类中访问,所以必须在此类中进行初始化

    private Stringid;

    privatedouble pay;

    Employee(String name,String id,double pay){

        this.name=name;

        this.id=id;

        this.pay=pay;

    }

    publicabstract void work();

}

//经理类

class Managerextends Employee{

    privateint bonus;

    Manager(String name,String id,double pay,int bonus){

        super(name,id,pay);//子类中构造函数初始化方式,即访问父类构造函数(必须)

        this.bonus=bonus;

    }

    publicvoid work(){//实现父类中的抽象方法

        System.out.println("我是经理职责");

    }

}

//员工类

class Proextends Employee{

    Pro(String name,String id,double pay){

        super(name,id,pay);

    }

    publicvoid work(){

        System.out.println("普通员工职责");

    }

}

模板方法设计模式--抽象类应用

  需求:获取一段程序运行的时间。

  原理:获取程序开始和结束的时间并相减即可。

  获取时间:System.currentTimeMillis();

  这种方式------>模板方法设计模式

  什么是模板方法?

  在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分。

  那么这时就将不确定的部分暴露出去。由该类的子类去完成。

abstractclass GetTime{

    publicfinal void getTime(){//final修饰后此方法不可以被覆写(确定部分)

        long start=System.currentTimeMillis();

        runCode();

        long end=System.currentTimeMillis();

        System.out.println("毫秒:"+(end-start));

    }

    publicabstract void runCode();//(不确定部分)留给子类去实现此抽象方法

}

class SubTimeextends GetTime{//要用来测试的程序

    publicvoid runCode(){

        for(int x=0;x<2000;x++){

            System.out.println(x);

        }

    }

}

publicclass DateDemo {

    publicstatic void main(String[] args) {

        SubTime st=new SubTime();

        st.getTime();

    }

}

5、接口 interface 

/*接口:初期理解可以认为是一个特殊的抽象类。

 *     当抽象类中的方法都是抽象的时,那么该类可以通过接口的形式来表示。

 * class用于定义类

 * interface用于定义接口

 * 接口定义时,格式特点:

 * 1、接口中常见定义:常量、抽象方法

 * 2、常量:public static final

 * 3、方法:public abstract

 * 接口中的成员都是public的。

 * 接口:是不可以创建对象的,因为有抽象方法。

 * 需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化。

 * 否则子类是抽象类。

 * */

interface Inter{

    publicstatic finalint NUM=3; //最终变量,不可以重新赋值

    publicabstract void show();

}

class Test1implements Inter{

    publicvoid show(){}//实现

}

publicclass InterfaceDemo {

    publicstatic void main(String[] args) {

        Test1 t=new Test1();

        System.out.println(t.NUM);

        System.out.println(Test1.NUM);

        System.out.println(Inter.NUM);

    }

}

接口的特点:

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

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

3.接口可以用来多实现。

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

5.接口与接口之间可以有继承关系。

8.1多态

定义:某一类事物的多种存在形态。

例:动物中的猫,狗。

l 猫这个对象对应的类型是猫类型

       猫  x=new 猫();

l 同时猫也是动物的一种,也可以把猫称为动物。

 动物 y=new 猫();

动物是猫和狗具体事物中抽取出来的父类型。

父类型引用指向子类对象。

多态的体现

   父类的引用指向了自己的子类对象。

   父类的引用也可以接收自己的子类对象

1多态的前提

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

  通常还有一个前提:存在覆盖。

2多态的好处

   多态的出现大大的提高程序的扩展性。

3多态的弊端

   提高了扩展性,但是只能使用父类的引用访问父类中的成员。

4多态的应用 

代码体现形式:

abstractclass Animal{

    publicabstract void eat();//不确定的事物,提取出来

}

class Catextends Animal{

    publicvoid eat(){

         System.out.println("吃鱼");

    }

    publicvoid catchMouse(){

         System.out.println("抓老鼠");

    }

}

class Dogextends Animal{

    publicvoid eat(){

         System.out.println("吃骨头");

    }

    publicvoid houseKeeping(){

         System.out.println("看家");

    }

}

publicclass Polymorphic {

    publicstatic void main(String[] args) {

         function(new Dog());

         function(new Cat());

    }

    publicstatic void function(Animal c){//提高了扩展性

    c.eat();//只能使用父类的引用访问父类中的成员(反例动物不一定都会抓老鼠)

    }

}

结果:吃骨头,吃鱼

publicclass Polymorphic2 {

    publicstatic void main(String[] args) {

              Animal a=new Cat();//类型提升。向上转型

              A.eat();

              //如果想要调用猫的特有方法时,如何操作?

              //强制将父类的引用,转成子类类型。向下转型

              Cat c=(Cat)a;

              c.catchMouse();

    }

结果:吃鱼;抓老鼠

publicstatic void function(Animal a){

    a.eat();

    if(ainstanceof Cat){

         Catc=(Cat)a;

         c.catchMouse();

    }elseif(a instanceof Dog){

         Dogd=(Dog)a;

         d.houseKeeping();

    }

}

instanceof它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据

    结果:吃骨头

          看家

          吃鱼

      抓老鼠

分析:Animal a=new Animal();

      Cat c=(Cat)a;

分析中的操作是错误的,将父类对象转成子类类型。

我们能转换的是父类应用指向了自己的子类对象时,该应用可以被提升,也可以被强制转换。

多态自始自终都是子类对象在做着变化。 

5、在多态中成员函数的特点:(非静态)

   在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。

   在运行时期:参阅对象所属的类中是否有调用的方法。(父类中方法也是子类的方法)。

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

   代码:

   class Fu{

    void method(){

        System.out.println("Fu——1");

    }

    void method2(){

        System.out.println("Fu——2");

    }

   }

   class Ziextends Fu{

    void method(){

        System.out.println("Zi——1");

    }

    void method3(){

        System.out.println("Zi——3");

    }

  }

  publicclass TestExtends {

    publicstatic void main(String[] args) {

        Fu z=new Zi();

        z.method();z.method2();//z.method3();

    }

  }

6、在多太中,成员变量的特点:(面试)

  当子类和父类出现同名的变量时,内存中出现了两个同名变量,一个是父类的一个是子类的。

  多态情况下:

  无论编译和运行,都参考左边(引用型变量所属的类)。

  代码:

     class Fu{

       intnum=8;

     }

     class Ziextends Fu{

    intnum=9;

     }

    publicclass TestExtends {

    publicstatic void main(String[] args) {

        Fu f=new Zi();//多态中输出父类的内容,不可覆盖

        System.out.println(f.num);

        Zi z=new Zi(); //非多态中可以覆盖

        System.out.println(z.num);

    }

}

结果:8,9

7、在多态中,静态成员函数的特点:

  无论编译和运行,都参考左边

  代码:

   class Fu{

    staticvoid method(){

        System.out.println("Fu——1");

    }

}

class Ziextends Fu{

    staticvoid method(){

        System.out.println("Zi——1");

    }

}

publicclass TestExtends {

    publicstatic void main(String[] args) {

        Fu z=new Zi();//多态中

        z.method();

    }

}

结果:Fu——1

面向对象的扩展--数据库操作。

1、链接数据库

2、操作数据库,增C 、删D 、改 U、查R

   C create R read  U update  D delect

3、关闭数据库链接。

 情景描述:开始是通过JDBC来操作数据库,可是5年后需求使用Hibernate操作数据库,而又不想更改原来的操作数据库的代码,那么,我们此时可以定义一个有相同同能的接口即可:

interface UserInfoDAO{

    publicvoid add(user);

    publicvoid delete(user);

 }

 class UserInfoByJDBCimplements UserInfoDAO{

  publicvoid add(User user)

 {

    1、链接数据库;

    2、使用sql语句添加数据。;

    3、关闭链接;

 }

 publicvoid delete(User user)

 {

    1、链接数据库;

    2、使用sql语句添加数据。;

    3、关闭链接;

 }

 }

 class UserInfoByHibernateimplements UserInfoDAO{

  publicvoid add(User user)

 {

    1、链接数据库;

    2、使用sql语句添加数据。;

    3、关闭链接;

 } 

 publicvoid delete(User user)

 {

    1、链接数据库;

    2、使用sql语句添加数据。;

    3、关闭链接;

 }

 } 

publicclass test{

  publicstatic voidmain(String[] args){

    //开始很麻烦的实现方式

   /*

     UserInfoByJDBC u=newUserInfoByJDBC();

     u.add(user);

     u.add(user);

     UserInfoByHibernate u=newUserInfoByHibernate();

     u.add(user);

     u.add(user);

*/

//5年后的成果:父类接口指向子类对象   =newUserInfoByHibernate(); 

     UserInfoDAO  u=new UserInfoByJDBC();//多态的体现,降低程序之间的耦合性

     u.add(user);

     u.add(user);

  }

} 

vObject类中的方法

v 面向对象(Object-equals()

Object:是所有对象的直接或者间接父类。

该类中定义的肯定是所有对象都具备的功能。

深入理解equals():

其实父类的equals方法比较的是两个对象的地址值是否相等,在没覆写的情况下,

      Demo2 d1=new Demo2(3);

      Demo2 d2=new Demo2(3);

  System.out.println(d1.equals(d2));

 //返回的结果是false,因为两个对象的地址值是不相等的

当我们覆写父类的equals方法后让其比较的是对象中num变量的值是否相等;

      Demo2 d1=new Demo2(3);

      Demo2 d2=new Demo2(3);

  System.out.println(d1.equals(d2));

 //同样情况下返回的结果是true,因为两个对象中的num值3==3

代码体现:

class Demo2{

    privateint num;

    Demo2(int num){

        this.num=num;

    }

    publicboolean equals(Object obj){//覆写父类Object的方法

        if(!(objinstanceof Demo2))//关键字

            returnfalse;

        Demo2 d=(Demo2)obj;//向下转型,多态

        returnthis.num==d.num;

    }

}

publicclass ObjectDemo {

    publicstatic void main(String[] args) {

      Demo2 d1=new Demo2(3);

      Demo2 d2=new Demo2(4);

    System.out.println(d1.equals(d2));//两个对象的比较,比的值是地址值;结果false

    }

}

v 面向对象(Object-toString()

toString():你创建的每个类都会继承该方法。它返回对象的一个String表示,并且对于调试非常有帮助。然而对于默认的toString()方法往往不能满足需求,需要覆盖这个方法。

class Person_0{

   private Stringname;

   Person_0(Stringname){

      this.name=name;

   }

   @Override

   public String toString(){//覆盖

      return"我的名字是:"+name;

   }

}

publicclass ToStringDemo {

   publicstatic void main(String[] args){

      Person_0 p=new Person_0("king");

      System.out.println(p.toString());

   }

}

9.1内部类的访问规则:

   1、内部类可以直接访问外部类中的成员,包括私有

      之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用(默认省略)。

      格式:外部类名.this

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

  访问格式:

   1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其它类中直接建立内部类对象。

   格式:外部类名.内部类名 变量名=外部类对象.内部类对象

   2、当内部类在成员位置上,就可以被成员修饰符所修饰。

      比如,private:将内部类在外部类中进行封装。

            Static :内部类就具备static的特性。 

            当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。       

            在外部其它类中,如何直接访问static内部类的非静态成员呢?

            new Outer.Inner().function();

            在外部其它类中,如何直接访问static内部类的静态成员呢?

            Outer.Inner.function();

注意:当内部类中定义了静态成员,该内部类必须是static的。

      当外部类中的静态方法访问内部类时,内部类也必须是静态的。

代码:

class Outer{

    privateint num=9;

    class Innter{//内部类在外部类的成员位置,可以对其进行私有化,private;

                         //则就不能直接的访问内部类的成员了。

        publicvoid show(){

            System.out.println("inner:"+num);//之所以能直接访问外部成员原因:

                                      //此处省略了Outer.this;//其实是Outer.this.num;

        }

    }

    void method(){

        Innter in=new Innter();

        in.show();

    }

}

publicclass ToStringDemo {

    publicstatic void main(String[] args){   

        //外部类间接访问内部类成员

        Outer o=new Outer();

        o.method();

        //直接访问内部类中的成员

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

        oi.show(); 

    }

}

内部类与外部类的由来: 

当描述事物时,事物的内部还有事物,该事物用内部类来描述。

因为内部事物在使用外部事物的内容。

内部类就是能直接访问外部类成员的一个描述。

class Body{

   private class xinZang{

   }

   public void show(){

     new xinZang();

  }

}

9.2内部类定义在局部时

     1、不可以被成员修饰符修饰,如不可以被static修饰

     2、可以直接访问外部类中的成员,因为持有外部类中的引用。

        但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。

class Outer2{

   intx=3;

   void method(finalint a){

      finalint y=4;

      class Inner{//局部内部类只能访问被final修饰的局部变量

          void function(){

                           System.out.println(x);

             System.out.println(y+"::"+a);

          }

      }

      new Inner().function();//对内部类中函数的访问

   }

}

publicclass InnerClass {

   publicstatic void main(String[] args) {

      new Outer2().method(5);

      new Outer2().method(6);

   }

} 

//afinal修饰为什么可以为a传两次值呢?

 //因为a是局部变量a在栈内存,把5赋给a,此时a的值被锁定为5,当第一句话执行完,出栈就释放了;

 //再调用的话又是一次进栈.. 

9.3匿名内部类

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

2、定义匿名内部类的前提:

   内部类必须是继承一个类或者实现接口。

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

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

5、匿名内部类中定义的方法最好不用超过三个;

abstractclass AbsDemo{

   abstractvoid show();

}

class Outer_1{

   intx=3;

   class Innerextends AbsDemo{

      void show(){

          System.out.println("show:"+x);

      }

   }

   publicvoid function(){

      new Inner().show();

   }

}

//===演变如下===============

class Outer_2{

   intx=3; 

   publicvoid function(){

      //new Inner().show();

      new AbsDemo(){

          void show(){

             System.out.println("show:"+x); 

          }

      }.show();

   }

}

publicclass NoNameClass {

   publicstatic void main(String[] args) {  

       new Outer_2().function();

   } 

} 

//===多态===============

classOuter_3{

   intx=3; 

   publicvoid function(){

      AbsDemo a=new AbsDemo(){//父类引用指向之类对象--多态

          void show(){

             System.out.println("show:"+x); 

          }

          voidmethod(){

             System.out.println("hello");

          }

      };

      a.show();

      //a.method();看左边,父类中未定义,编译失败;如果编译通过则运行输出右边内容

   }

}

匿名内部类----接口 

interface Inter2{

   void method();

}

class Test2{

   //补充代码,通过匿名内部类。

/* static classInner implements Inter2{

      public voidmethod(){

          System.out.println("methodrun");

      }

   }*/

   static Inter2 function(){

      returnnew Inter2(){

          publicvoid method(){

             System.out.println("methodrun");

          }

      };

   }

}

publicclass InnerClassTest {

   publicstatic void main(String[] args) {

      //Test2.function():Test2类中有一个静态方法function

      //.method():function()这个方法运算后的结果是一个对象。而且是一个inter2类型的对象

      //因为只有inter2类型的对象,才可以调用method方法。

      Test2.function().method();

   }

} 

 面试题:在既没有抽象类又没有接口的情况下还能创建匿名内部类吗?

class Outerdemo{

   publicstatic void getFun(){

    new Object(){//此处不能用对象接收,因为父类Object方法中没有我们自己定义的函数,编译会失败,调用的话只能最后面.fun();

      publicvoid fun(){

          System.out.println("调用了");

      }

     }.fun();

   }

}

------- android培训java培训java博客、java学习型技术博客、期待与您交流! ---------- 

如有疑问:http://edu.csdn.net/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_wangtao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值