Java多态大乱炖

一 UML(统一建模语言)类的关系

在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)

① 泛化extends:子类继承父类,一般表示有说 “子类  is  a 父类”

 

② 现实implements,在java中表示实现类和接口的关系

 

③ 关联:是一种拥有的关系,它使一个类知道另一个类的属性和方法。

 

扫描二维码关注公众号,回复: 2733186 查看本文章

④ 聚合:是整体与部分的关系,且部分可以离开整体而单独存在。

 

⑤ 组合:是整体与部分的关系,且部分不可以离开整体而单独存在。

 

⑥依赖:是一种使用的关系,即一个类的实现需要另一个类的协助,

所以要尽量不使用双向的互相依赖.

二 抽象类和接口

抽象方法:是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的声明格式为:abstract void fun();

抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。

如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。抽象类不能被直接实例化。

抽象类可以不含抽象方法(无意义),也可以有普通方法和静态方法。

如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

2.1抽象类的间接实例化(匿名内部类)

//抽象类
public abstract class One {
//抽象方法 public abstract void ok1(); }

public class Two extends One{
//实现父类全部抽象方法 @Override

public void ok1() { System.out.println("two ok1...."); } }

public class Test {
    public static void main(String[] args) {
       // One x=new One(){};
//匿名内部类:相当于又创建了一个类,这个类的父类是One,也要重写抽象父类one的抽象方法,先使用{}创建了类的身体,通过{前面的最
//近的类名告诉编译器我的父类是One,由于使用new关键字在堆中按自定义的{}中语句生成内存;
        One y=new One(){
//重写
            public void ok1(){
                System.out.println("ok1...");
            }

// 父类(one)中没有OK2,不能调用,可以将父类理解为模板
            public void ok2(){
                System.out.println("ok2");
            }
        };
//        y.ok2();报错
y.ok1();//成功调用        
//多态
        y=new Two();
//          y.ok2();报错,由于two继承了one,但模板one中没有该方法
    }
}

多态:instanceof

父类引用指向子类对象:

public class MyNum {
    public void show(){
        System.out.println("我是父类的show...");
    }
}
public class MyOne extends MyNum{
    public void show() {
        System.out.println("One show....");
    }

}
public class MyTwo extends MyNum{
    public void show() {
        System.out.println("two show....");
    }
    public void fly(){
        System.out.println("飞....");
    }
}
public class Test {
    //方法参数的类型是父类,这是多态的主要应用
    public static void say(MyNum ni){
        ni.show();调用指向的对象内的方法。前提是父类即模板中有该方法
        ni.fly();//报错,父类中无该方法。需要转换
        //判断对象的真实类型  对象引用 instanceof 类型
        if(ni instanceof MyTwo){
            //将ni引用的对象,强制类型转换
            MyTwo t=(MyTwo) ni;
            t.fly();
        }
    }
  //  public static void say(MyOne ni){ ni.show();}类型不匹配,不被调用

    public static void main(String[] args) {
        //引用多态语法
        MyNum x=new MyTwo();//x的类型是MyNum
        x.show();
        x=new MyOne();
        x.show();
        say(x);//x按类型匹配,与指向的对象无关。   
    }
}
(生成setter方法快捷键  alt+insert)

JavaOOP三大特性:封装、继承和多态;

封装:使用类封装自定义属性和方法;包封装多个类等等;

继承:子类继承父类;

多态:一个父类或接口类型的变量,能够存储多个子类或实现类对象引用;

多态作用,提高代码可以重用性;

多态语法:一个变量引用多种对象(有关联关系);

多态用法:主要用于在方法的参数上使用多态语法,提高代码可重用性;

        注意:可以instanceof判断变量的具体类型,通过强制转换;

四 java的interface

java中引入接口弥补java单继承,父子类必须血缘关系特点;现实中多个不同种类的对象在方法上有相似之处,引入抽取相同方法接口(interface)

用法:一个类可以实现一个或多个接口,但是要求必须重写所有抽象方法;

注意: java中类和接口(除了内部类外),访问修饰符只支持public和默认;

//java中接口可以扩展多个接口:public interface IAction extends  Isky,ILand

接口变量默认添加以下三个关键字 public static final 称常量变量。

接口中的抽象方法,默认有public  abstract关键字   

jdk1.8中接口中可以使用default method,可以被调用   public default String nihao ( ){  return "你好!"; }

面试题,抽象类和接口区别?

.语法层面上的区别

  1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

  2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

  3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

  4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

2.设计层面上的区别

  1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。从这里可以看出,继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

  2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

举例:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念,但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?

从这里可以看出, Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。

4.2 java中关键字

  static, 修饰代码块,变量,方法,内部类;

  final,表示最终不能修改,可以修饰类(该类不能继承)、变量(常量变量)、方法(不能重写,即不能修饰接口中的方法,可以重载)

 面试题:  多态存在的三个必要条件?

  ①要有继承,或实现;②要有重写;③父类引用指向子类对象

5 java中内部类:

1.成员内部类:与类中属性和方法并列内部类;

实例化成员内部类,首先先实例化外部(MTree是外部类,node是内部类)

MTree mt=new MTree()

MTree.Node n=mt.new Node();      //错误的 MTree.Node node=mt.new MTree.Node();

2.静态内部类:静态内部类 static表示当前类的实例化 脱离外部类存在

调用其中的方法也需要new。

3.局部内部类:位于方法或代码块里

4.匿名内部类:

通常用于异步控制上,图形编程,多线程编程;特点,提供抽象类或接口作为模板,然后在方法中的参数指定该抽象类或接口;

当方法执行时,直接在方法中使用匿名内部类

public class Demo03 extends JFrame {

    private JButton btn;

    public Demo03(){

        this.setTitle("我是一个窗口");

        this.setSize(350,300);

        btn=new JButton();

        btn.setSize(100,30);

        btn.setText("你点击我了吗?");

        Container panel = this.getContentPane();

        panel.add(btn);

 

        //向按钮添加点击事件

        btn.addActionListener(new ActionListener() {

            @Override

            public void actionPerformed(ActionEvent e) {

                JOptionPane.showMessageDialog(Demo03.this,"你敢点我!");

            }

        });

    }

    public static void main(String[] args) {

        Demo03 d3=new Demo03();

        d3.setVisible(true);

    }

}

世界上第一位程序员一个妹子,名叫阿达·洛芙莱斯(Ada Lovelace)是英国著名诗人拜伦的女儿。       

猜你喜欢

转载自blog.csdn.net/skylibiao/article/details/81225990