6/21:抽象,多态和接口

来源:互联网 发布:闪字软件下载 编辑:程序博客网 时间:2024/06/05 14:00

一抽象

(1)抽象的作用

①在面向对象领域,抽象类主要用来进行类型隐藏;也就是使用抽象的类型来编程,但是具体运行时就可以使用具体类型。

②利用抽象的概念,能够在开发项目中创建扩展性很好的架构,优化程序。

③抽象类,抽象方法,在软件开发过程中都是设计层面的概念。也就是说,设计人员会设计出抽象类,抽象方法,程序员都是来继承这些抽象类并覆盖抽象方法,实现具体功能。

(2)抽象方法的相关概念

在某些情况下,类无法(或者没有必要)提供方法的具体实现,可以将此方法声明成抽象方法;

在类中没有方法体的方法,就是抽象方法;

含有抽象方法的类,一定是抽象类。

(3)抽象方法的语法

使用关键字abstract声明抽象方法,一般语法:

[访问权限] abstract返回值类型 方法名称(参数列表);

如:public abstract void draw();

(4)抽象类的定义

使用关键字abstract定义抽象类,一般语法

[访问权限] abstract class类名 {成员列表}

如:public abstract class Shapes {

public abstract void draw();

}

public abstract class Shapes {

public void draw(){

         //具体代码

       }

}

(5)抽象类的相关概念

abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。

抽象类可以有成员属性和非抽象的成员方法。

抽象类不能被实例化,但可以有构造函数。

抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。否则,该类也必须声明为抽象类。

(6)抽象类的注意事项

①抽象类可以有构造方法,但不能直接实例化,只能用来继承;

②抽象类的派生子类应该提供对其所有抽象方法的具体实现;如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类,只能用于继承,而不能实例化;

③抽象类中也可以包含有非抽象的方法,子类中重写非抽象方法时返回值和参数必须与父类一致;

构造方法和静态方法不可以修饰为abstract

 

,instanceof操作符

(1)instanceof 用法

result = 对象名称 instanceof  类型

参数:

result:布尔类型。

对象名称:必选项,任意对象表达式。

类型:必选项,任意已定义的类,可以是API中的类,可以是自定义的类。

 

说明:

如果对象是这个类型的一个实例,则 instanceof 运算符返回 true。如果对象不是指定类的一个实例,或者对象是null,则返回false

instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例

(2)instanceof操作符

abstract class Animal {

abstract void eat();

}

class Dog extends Animal {

                 void look ()...

}

class Cat extends Animal {

                void catch() ……

}

class InstanceofDemo {

public static void main(String[]  args ) {

                           method(new Dog());

                   }

 }

public static void method(Animal a) {

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

                if (a instanceof Cat) {

   Cat c = (Cat) a;

   c.catch();

                   }

 

,Object类

(1)Object类是所有类的父类,位于java.lang包中

数组也是Object类的子类

Object类的常用方法

 toString();

 equals();

 hashCode();

……

(2)bject类在java.lang包下,是所有类的根。任何类的对象,都可以调用Object类中的方法,包括数组对象。

:

 

    public class Example{

      public void f(Object obj){

      }    

    }

    public class Test{

      public static void main(){

         Example exam=new Example();

         int[] array=new int[4];

         ……//任何数组

         exam.f(array);

    }

    }

(3)ObjectObject[]之间的区别

方法中的形参是Object类型时,任何类型的参数都可以传进去执行。

方法中形参是Object[]类型时,只有对象数组可以传入执行。

(4)Object类中的常用方法

toString方法;

   toString方法可以将任何一个对象转换成

   字符串返回,返回值的生成算法为:getClass().getName() + '@' + Integer.toHexString(hashCode())

equals方法;

   Object类中的equals方法,用来比较两个引用的虚地址。当且仅当两个引用在物理上是同一个对象时,返回值为true,否则将返回false

任何类可以根据实际需要,覆盖toStringequals方法,实现自定义的逻辑。

打印对象时直接调用类的toString方法

  public static void main(){

    Student stu1=new Student();

    stu1.setName("张三");

    stu1.setAge(23);

    System.out.println(stu1);

    System.out.println(stu1);

  }

  打印: Student@152b6651;  

类本身重写toString方法

   重写Student类的toString方法后

  public static void main(){

    Student stu1=new Student();

    stu1.setName("张三");

    stu1.setAge(23);

    System.out.println(stu1);

}

打印: Student: name=张三,age=23;

public class Student {

    private String name = "123";// 学生姓名

    private int age;// 年龄

    public String getName() {

       return name;

    }

   public void setName(String name) {

    this.name = name;

    }

   public int getAge() {

      return age;

    }

    public void setAge(int age) {

       this.age = age;

    }

   //重写toString方法

}

 

public String toString(){

  returnStudent:+name=+name+,age=+age;

   }

(5)equals方法和“==

equals方法

   比较对象的虚地址,但是可以在类中被重写。

   :String类重写了,两个相同值的String对象相比较为   true;

    String str=new String(123);

    String str1=new String(123);

    System.out.println(str.equals(str1));à打印为true.

==

    比较的是内存中的虚地址

     String str=new String(123);

     String str1=new String(123);

     System.out.println(str==str1);à打印为false

 

(6)hashCode方法

hashCode方法

获取对象的哈希码值,为16进制

equals方法与hashCode方法关系

  如果两个对象使用equals比较返回true,那么它们的hashCode值一定要相同

   如果两个对象equals比较返回false,那么它们的hashCode值不一定不同

  覆盖equals,往往需要覆盖hashCode,可以使用Eclipse自动生成,保证equals返回true,则hashCode相同;equals返回false,则hashCode不同

Set集合部分有实际应用

,多态参数

(1)方法参数具有多态性

class  Animal{

           void eat() {}

}

class  Cat extends Animal{

            void eat() {}

}

class Dog extends Animal{

            void eat(){}

}

//方法的形式参数类型是父类类型,而传递的实际参数可以是任意子类的对象

method(Animal  animal){  

     animal .eat();                

}

方法参数多态性的好处:提高代码的扩展性

(2)多态环境下对成员方法的调用

class  Animal{

           void show() {

             System.out.println(Anmial");

          }

}

class Cat  extends Animal{

              void show() {

                    System.out.println(cat");

              }

}

…….

Animal x = new Cat()

   x.show() //调用的是子类中的方法

 简单的说:编译看左边,运行看右边。

多态环境下对静态成员方法的调用

class  Animal{

          static  void show() {

             System.out.println(Animal");

          }

}

class Cat extends Animal {

             static  void show() {

                    System.out.println(Cat");

              }

}

…….

Animal x = new Cat()

   x.show() //调用的是动物类中的静态成员方法。

简单的说:编译和运行都看左边。

多态环境下对成员变量的调用

class Animal{

       int num = 3;

}

class Cat  extends Animal {

       int  num = 4;

}

…….

Animal x = new Cat()

x.num; //调用的是动物类中的成员变量。

简单的说:编译和运行都看等号左边。

    注意:变量不存在被子类覆写这一说法,只有方法存在覆写。

(3)多态环境下对象造型

向上造型 –又称自动类型提升

class Animal{

     abstract void eat();

}

class Cat extends Animal{

      void look() {

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

 }

    }      

 ………

   Animal x=new Cat()  //向上造型,Cat对象提升到Animal对象

   x.eat()   //只能使用父类中的方法

   x.look()  //报错!不能使用子类中的方法

向上造型的作用是:提高程序的扩展性。

向下造型 –又称向下转型

class Animal{

     abstract void eat();

}

class Cat extendsAnimal{

      void look() {

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

    }

    }      

 ………

Animal x=new Cat()

Cat  m=(Cat)x;  //向下转型

   m.eat() ;

   m.look();//子父类中的方法都可以使用

向下造型的作用是:为了使用子类中的特有方法。

(4)多态性

多态性是面向对象的三大特征之一

多态的含义是:对外一种表现形式,内在有多种具体实现。

Java中多态的具体体现

方法重载

方法覆盖

多态参数(新内容,重点、难点)

,父类引用指向子类对象

当编译器类型是父类,运行期类型是子类时,被称为父类引用指向子类对象

class  Animal{

               ……

}

class Cat  extends Animal{

               ……

}

class Dog extends Animal {

               ……

}

Cat m = new Cat()

Animal x = new Cat()  //Animal 的引用指向Cat的对象

对象m可以调用猫类中的所有方法,x只能调用动物类中定义的方法,

猫类扩展的新方法不能调用。

,接口的基本语法

(1)接口定义

Java接口是一系列方法的声明,是一些抽象的集合

一个接口只有抽象方法没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。

简单地说,接口就是特殊的抽象类,即所有方法都是抽象方法的抽象类就是Java中的接口(interface

(2)接口的基本格式

[修饰符] interface接口名 [extends父接口名列表]{

[public] [static] [final] 常量;

[public] [abstract] 方法;

}

修饰符:可选,用于指定接口的访问权限,可选值为public。即使省略,也依然是public

接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写。

extends 父接口名列表:可选参数,用于指定要定义的接口继承于哪个父接口。当使用extends关键字时,父接口名为必选参数。父接口可以存在多个,用逗号隔开。

方法:接口中的方法只有定义而没有被实现。

(3)接口的特点

接口是一种特殊的抽象类

接口中没有变量,只能有public static final修饰的静态常量。三个修饰符可以省略。

接口中所有方法都是抽象方法,且默认就是public权限。

public interface Flyer {

public static final int TYPE=1;

public abstract void fly();

public abstract void land();

public abstract void takeoff();

}

(4)接口继承接口

Java接口继承接口的原则

Java接口可以继承多个接口

接口继承接口依然使用关键字extends,不要错用成implements

Java接口继承接口的形式

Interface3 extends Interface0, Interface1, interface……

(5)接口与抽象类区别

类组成及子类使用区别

对比图表

 

 

abstract class

interface

属性

不用限制

静态常量

构造方法

可有可无

没有

普通方法

可以有具体方法

必须是抽象方法

子类

单一继承

多重实现

区别总结

abstract class Java语言中表示的是一种继承关系,一个类只能使用一次继承关系。但是,一个类却可以实现多个interface.

abstract class 中可以有自己的数据成员,也可以有非abstarct的成员方法,而在interface中,只能够有静态的不能被修改的数据成员(也就是必须是static final的,不过在interface中一般不定义数据成员),所有的成员方法都是abstract的。

实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。

接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值。

接口中的方法默认都是 publicabstract类型的。

(6)类实现接口的特点

类实现接口,本质上与类继承类相似,区别在于“类最多只能继承一个类,即单继承,而一个类却可以同时实现多个接口”,多个接口用逗号隔开即可。实现类需要覆盖所有接口中的所有抽象方法,否则该类也必须声明为抽象类。

接口是抽象的,接口中没有任何具体方法和变量,所以接口不能进行实例化。接口定义的是多个类都要实现的操作,即what to do”。类可以实现接口,从而覆盖接口中的方法,实现“how to do”。

(7)实现接口的基本格式

[修饰符] class <类名> [extends父类名] [implements接口列表]{  }

修饰符:可选参数,用于指定类的访问权限,可选值为publicabstractfinal

类名:必选参数,用于指定类的名称,类名必须是合法的Java标识符。一般情况下,要求首字母大写。

extends 父类名:可选参数,用于指定要定义的类继承于哪个父类。当使用extends关键字时,父类名为必选参数。

implements 接口列表:可选参数,用于指定该类实现的是哪些接口。当使用implements关键字时,接口列表为必选参数。当接口列表中存在多个接口名时,各个接口名之间使用逗号分隔。

(8)接口的作用

接口是设计层面的概念,往往由设计师设计,将定义与实现分离

程序员实现接口,实现具体方法

面向接口编程

面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是附属于面向对象思想体系,属于其一部分。

或者说,它是面向对象编程体系中的思想精髓之一。

面向接口编程的意思是指在面向对象的系统中所有的类或者模块之间的交互是由接口完成的。

,运行期类型与编译期类型

第一种情况:编译期类型和运行期类型相同

   A  a = new A();

      a.show();

声明A的时候,使用到的类型A表示对象的类型,被称为编译期类型,在编译期,虚拟机认为a的类型是A,对于a所使用的属性和方法的有效性将到类A中去验证。

构造方法A()中的A是运行期类型,在运行期,将执行运行期类型中的方法

 

第二种情况:当有继承关系时,可能发生编译期类型和运行期类型不同的情况,即编译期类型是父类类型,运行期类型是子类类型。

//A类是B类的父类                              

A  ab = new B();

ab.show();

对象ab的编译期类型为父类A类,运行期类型为子类B类。

如果一个引用的编译期类型和运行期类型不同,那么一定是编译期类型与运行期类型有父类子类关系。

ab对象使用的方法,在编译期到类A中去校验,而运行则执行B类的方法

如果一个对象的编译期类型是父类,运行期类型是子类,可以对该对象进行强制类型转换,将其编译器类型转换为与运行期类型相同的类型,即:B b=(B)ab;