Java—(多态、内部类)

我与影子孤独终老i 提交于 2019-12-15 20:14:09

一、多态

多态:可以理解为同一个事物在不同的场合具有不同的形态

分为两种:

  • 编译时多态:在编译期间编译器根据函数实参的类型确定要调哪个函数(这个我们之前已经接触过了,和函数重载差不多,是同名函数,但是参数不同)编译时的多态性是通过函数重载或运算符重载来实现的。

  • 运行时多态:在程序运行期间才会去判断到底会调用哪个函数。这里我们主要讲的就是动态多态。运行时的多态性是通过虚函数与基类指针共同作用实现的。

作用:

  • 静态多态的作用:减少了名字(比如:函数名)的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。

  • 动态多态的作用:多态技术允许将基类指针或基类引用指向子类对象,根据对象的动态类型来决定调用的是哪个子类中的这个同名方法,从而解决了同名覆盖问题,写出了通用的代码,即扩展性优秀的代码,以适应需求的不断变化。

简单举个例子:

    猫 x=new 猫();
 
    动物 y=new 猫();

1.多态的体现

  • 父类的引用指向自己的子类对象;
  • 父类的引用也可以接收自己的子类对象。

2.多态的前提

必须是类与类之间的关系,要么是继承(extends),要么是实现(implements),通常还有一个前提,就是存在覆盖(重写)。

3.多态的好处

多态的出现大大的提高了程序的可扩展性。但是只能使用父类的引用,访问父类的成员。

4.类型转换(向上转型,向下转型)

  • Anmial a=new Cat();//类型提升,向上转型
  • Cat c=(Cat)a;//强制将父类的引用转成子类的类型,向下转型
/*
Anmial a=new Anmial();
Cat c=(Cat)a;
此段代码有误;
原因:不能将以前有的东西强制转为现有的东西。
*/

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

5.多态的应用

instanceof-------一般用于子类的类型有限,当传的类型需要进行其他操作时,必须要确定它的类型,即用到它的特有方法,这时用instaceof进行比较。

多态示例一:

abstract class Animal{
    public abstract void eat();
}
 
class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
    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){
        funcation(new Dog());
        funcation(new Cat());
        public static void funcation(Animal a){
            a.eat();
            if(a instanceof Cat){
                Cat c=(Cat)a;
                c.catchMouse();
            }else if(a instanceof Dog){
                Dog d=(Dog)a;
                d.kanJia();
            }
        }
    }
 
}

输出结果为:

狗吃骨头

狗看家

猫吃鱼

猫抓老鼠

多态示例二:

描述笔记本,笔记本使用USB鼠标,USB键盘,移动硬盘
定义USB接口,笔记本要使用USB设备,即笔记本在生产时需要预留可以插入USB
设备的USB接口,即就是笔记本具备使用USB设备的功能,但具体是什么USB设备,笔记本
并不关心,只要符合USB规格的设备都可以。鼠标、键盘和移动硬盘要能在电脑上使用,那么鼠标、键
盘和移动硬盘也必须遵守USB规范,不然生产出来无法使用

class DuoTai02{
    public static void main(String[] args){
        Computer c=new Computer();
        c.getUSBConnect1(new Mouse());
        c.getUSBConnect2(new KeyBoard());
        //好处 降低耦合性
    }
}
interface USB{
    public void doSometing();
}
class Computer {
    public void getUSBConnect1(USB usb){
        usb.doSometing();
    }
    public void getUSBConnect2(USB usb){
        usb.doSometing();
    }
}
class Mouse implements USB{
    public void doSometing(){
        System.out.println("鼠标激活可用!");
    }
}
class KeyBoard implements USB{
    public void doSometing(){
        System.out.println("键盘激活可用!");
    }
}
class MobleHardDisk implements USB{
    public void doSometing(){
        System.out.println("移动硬盘激活可用!");
    }
}

6.多态中成员的特点

  • 多态成员变量
    当子父类中出现同名的成员变量时,多态调用该变量时:
    编译时期:参考的是引用型变量所属的类中是否有被调用的成员变量。没有,编译失败。
    运行时期:也是调用引用型变量所属的类中的成员变量。
    简单记:编译和运行都参考等号的左边。编译运行看左边。

  • 多态成员函数
    编译时期:参考引用变量所属的类,如果没有类中没有调用的函数,编译失败。
    运行时期:参考引用变量所指的对象所属的类,并运行对象所属类中的成员函数。
    简而言之:编译看左边,运行看右边。

  • 多态静态函数
    多态调用时:编译和运行都参考引用类型变量所属的类中的静态函数。
    简而言之:编译和运行看等号的左边。其实真正调用静态方法是不需要对象的,静态方
    法通过类直接调用。

结论: .】
1.对于成员变量和静态函数,编译和运行都看左边。
2.对于成员函数,编译看左边,运行看右边。

二、内部类

1.内部类由来:

在我们描述一个事物的时候(类) 发现,该事物当中又存在一个其他的事物
那么外面的这个事物叫做外部类, 里面的事物叫做内部类

2.内部类的作用:

  • 内部类提供了更好的封装,不允许外部类之外的类访问外部内中的内部类的对象(但可以获取外部类.内部类.class),内部类只有在外部类中才有效,离开外部类后没有任何意义。
  • 内部类可以访问外部的的成员变量(包括私有变量)
  • 匿名内部类适合用于创建那些只需要使用一次的类。

内部类比外部类多了三个修饰符(都有的是public-共有访问权限,default-包访问权限):private(当前类访问权限),protected(子类访问权限),static,final。因为外部类只有两个作用于包、任何位置。而内部类有四个作用域:同一个类、同一个包、父子类、任何位置。
  
3.内部类分类
   
1.静态内部类(static inner class):

只能访问外部类的静态成员变量和静态方法,生成静态内部类的方式为:StaticInner.Inner inner=new StaticInner.Inner();

2.成员内部类(member inner class):

A)可以当做成员变量来看待理解,可以访问外部类的静态与非静态方法和成员变量,

  生成成员内部类的方式:Member.MemberInner m=new Member().new MemberInner();

B)若想在成员内部类中访问外部类的变量,语法为:OutClass.this.a

3.局部内部类(local inner Class):

a) 定义在方法里面,只能访问方法中声明的final类型的变量;

b) 这个类要定义成final类型的;

c) 只能在这个方法中new出其对象,对其进行操作。

d) 注意:方法内部的局部变量或局部类都是final类型的。

4.匿名内部类(Anonymous Inner Class):

a) 没有类名,没有构造方法,但是隐式地继承一个父类或者实现一个接口。

b) 通常作为方法参数,在swing中注册监听者用的较多。
class InnerClassDemo{
    public static void main(String[] args){
        //1.成员内部类 如何调用该内部类中的其他成员
        //num想要被访问 必须先创建Inner对象
        //Inner对象想创建 必须先存在Inner类
        //Inner类又是Outter的一个成员 必须先创建Outter对象
        /*
        Outter out=new Outter();
        Outter.Inner in=out.new Inner();
        */
        /*
        Outter.Inner in=new Outter().new Inner();
        System.out.println(in.num);
        in.show();
        */
        //成员内部类中无法创建静态成员
        //为什么?
        //因为静态优先于对象加载进静态方法区
        //但是 内部类的静态成员想要进方法区 前提是该类得存在
        //该内部类的存在前提是外部类创建对象
        //创建外部类的对象之前 静态都已经加载完毕了
        //矛盾!
        //2.静态内部类当中 如何访问非静态成员
        Outter.Inner in=new Outter.Inner();
        in.show();
        //3.静态内部类当中 如何访问静态成员?
        System.out.println(Outter.Inner.haha);
        /* 
        内部类当中如果出现静态 则内部类也必须是静态的
        */
    }
}
class Outter{
    //类的内容 成员变量 成员函数 静态变量 静态函数
    //成员类 静态类
    int num=10;
    static int haha=30;
    public void show(){
        System.out.println("Outter show");
    }
    //this

    static class Inner{
        //此处 this只能是Inner对象
        int num=20;
        static int haha=40;
        public void show(){
            System.out.println("Inner show"+num);
            System.out.println(haha);
            //Outter.this.show();
            System.out.println(Outter.haha);
        }
    }
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!