多态、接口、内部类与单例模型

多态

概念:

意味着允许不同类的对象对同一消息做出不同的响应

必要条件:

1、满足继承关系

2、父类引用指向子类

编译时多态(设计时多态)

运行时多态(运行时多态)

向上转型(隐式转型、自动转型):
        父类引用指向子类实例,可以调用子类重写父类的方法以及父类派生的方法,无法调用子类独有的方法,是小类转大类
Animal one = new Animal();
Animal two  = new Cat();
Animal three = new Dog();
one.eat();
two.eat();
three.eat();

结果:

动物都有吃东西的能力
猫吃鱼~~
狗吃肉~~
向下转型(强制类型转换)
    子类引用指向父类对象,此处必须进行强转。可以调用子类特有的方法,必须满足转型条件才能转换
Cat temp = (Cat)two;
temp.eat();
temp.run();

结果:

猫吃鱼~~
小猫在快乐的奔跑

instanceof运算符:

作用:判断对象是否满足某个特定类型,判断左边的对象是否是右边类型的实例

返回true或false
if(two instanceof Cat){
    Cat temp = (Cat)two;
    System.out.println("two可以转换为Cat类型");
}
if(two instanceof Dog){
    Dog temp2 = (Dog)two;
    System.out.println("two可以转换为Dog类型");
}
if(two instanceof Animal){
    System.out.println("Animal");
}
if(two instanceof Object){
    System.out.println("Object");
}

结果:

two可以转换为Cat类型
Animal
Object

由此结果我们可知two满足Cat的类型的特征,也满足Cat类型的父类Animal和Object类型的特征

Master案例:

需求:

  • 喂宠物
  • 喂猫咪:吃完东西后,主人会带着去玩线球
  • 喂狗狗:吃完东西后,主人会带着狗狗去睡觉
  • 主人时间充足的条件下养狗狗
  • 主人时间不充足的条件下养猫咪

Cat.java

//方法:吃东西(重写父类方法)
@Override
    public void eat() {
        System.out.println("猫吃鱼~~");
    }
//方法:玩线球
public void playBall() {
        // TODO Auto-generated method stub
        System.out.println("小猫喜欢玩线球");
    }

Dog.java

//方法:吃东西(重写父类方法)
    @Override
    public void eat() {
        System.out.println("狗吃肉~~");
        
    }
//方法:睡觉
    public void sleep(){
        System.out.println("小狗有午睡的习惯");
    }

Master.java

//方案:编写方法传入动物的父类,方法中通过类型转换,调用指定子类的方法
public void feed(Animal obj){
        obj.eat();
        if(obj instanceof Cat){
            Cat temp=(Cat)obj;
            temp.playBall();
        }else if(obj instanceof Dog){
            Dog temp=(Dog)obj;
            temp.sleep();
        }
    }
//
public Animal raise(boolean isManyTime){
        if(isManyTime){
            System.out.println("主人休闲时间比较充足,适合养狗狗");
            return new Dog();
        }else{
            System.out.println("主人平时比较忙碌,适合养猫咪");
            return new Cat();
        }
    }

MasterTest.java

Master master=new Master();
Cat one=new Cat();
Dog two=new Dog();
master.feed(one);
master.feed(two);
System.out.println("=============");
        boolean isManyTime=false;
        Animal temp=master.raise(isManyTime);
        System.out.println(temp);

结果:

猫吃鱼~~
小猫喜欢玩线球
狗吃肉~~
小狗有午睡的习惯
=============
主人平时比较忙碌,适合养猫咪
com.imooc.animal.Cat@15db9742

接口:

定义接口:interface
package com.imooc.tel;

/**
 * 具有照相能力的接口
 * @author imooc
 *
 */
public interface IPhoto {
    //具有拍照的能力
    public void photo();
    }
    
//  void network();
}

实现接口:implements

一个类去实现一个接口使用到的关键字是implements

一个类去实现一个接口的时候需要去实现这个接口当中的方法

Camera.java

package com.imooc.tel;

public class Camera implements IPhoto{

    @Override
    public void photo() {
        // TODO Auto-generated method stub
        System.out.println("相机可以拍照");
    }

FourthPhone.java

package com.imooc.tel;

public class FourthPhone extends ThirdPhone implements IPhoto,INet{

    public void game(){
        System.out.println("手机可以玩游戏");
    }
    @Override
    public void photo() {
        // TODO Auto-generated method stub
        System.out.println("手机可以拍照");
    }

PhoneTest.java

package com.imooc.test;

import com.imooc.tel.Camera;
import com.imooc.tel.FourthPhone;
import com.imooc.tel.INet;
import com.imooc.tel.IPhoto;
import com.imooc.tel.SmartWatch;

public class PhoneTest {

    public static void main(String[] args) {
        IPhoto ip=new FourthPhone();
        ip.photo();
        ip=new Camera();
        ip.photo();
        
    }

}

结果:

相机可以拍照
手机可以拍照
default:默认方法,可以带方法体
    //default:默认方法 可以带方法体 jdk1.8后新增
    //可以在实现类中重写,并可以通过接口的引用调用
    default void connection(){
        System.out.println("我是接口中的默认链接");
    }
    

default实现类的重写:

系统自动加上public访问权限

INet.super.connection();//接调用接口中默认的方法

如果不填super的话,通过接口名打点调用的是当前接口的静态成员

static:静态方法 可以带方法体 ,通过接口名去调用

INet.java

    //static:静态方法 可以带方法体 jdk1.8后新增
    //不可以在实现类中重写,可以同接口名调用
    static void stop(){
        System.out.println("我是接口中的静态方法");
    }

PhoneText.java

INet.stop();

一个类可以实现多个接口,但注意去实现接口中待重写的方法,否则这个类也会变成抽象类

当一个类实现多个接口,接口中有多个同名的方法时,实现类必须要重写一个满足自己特征的同名方法,如果这个实现类中的父类有同名方法时,默认情况下会调用父类的同名方法, 但属性则不同,父类没有优先权

接口的继承:

1、Java中的接口也可以实现接口,且可以有多个父接口

2、当父接口中存在同名方法时,需要在自己的接口李创建自己的同名方法,不用任何一个父接口里的方法

内部类:

定义:

在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类

分类:

  • 成员内部类(普通内部类)
  • 静态内部类
  • 方法内部类(局部内部类)
  • 匿名内部类
成员内部类:
* 内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化 
* 内部类的访问修饰符,可以任意,但是访问范围会受到影响
* 内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中定义的
* 可以使用外部类.this.成员的方式,访问外部类中同名的信息 
* 外部类访问内部类信息,需要通过内部类实例,无法直接访问 
* 内部类编译后.class文件命名:外部类$内部类.class
* 内部类中是否可以包含与外部类相同方法签名的方法?以及如何调用?



如何获取内部类实例对象:

方法一:

//获取成员内部类对象实例,方式1:new 外部类.new 内部类
Person.Heart myHeart=new Person().new Heart();
System.out.println(myHeart.beat());

方法二:

 //获取成员内部类对象实例,方式2:外部类对象.new 内部类
myHeart=lili.new Heart();
System.out.println(myHeart.beat());

方法三:

//获取成员内部类对象实例,方式3:外部类对象.获取方法
myHeart=lili.getHeart();
System.out.println(myHeart.beat());
静态内部类:
  • 静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例

    static class Heart {
         int age = 13;
         int temp = 22;
    
         public String beat() {
                //对象实例
             new Person().eat();
             return new Person.age + "岁的心脏在跳动";
         }
     }
    
  • 静态内部类对象实例时,可以不依赖于外部类对象

  • 可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员

  • 当内部类属性与外部类属性同名时,默认直接调用内部类中的成员;

  • 如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式;

  • 如果需要访问外部类中的非静态属性,则可以通过 new 外部类().属性的方式;

获取静态内部类对象实例方法:

Person.Heart myHeart=new Person.Heart();
System.out.println(myHeart.beat()); 
方法内部类:
  • 定义在方法内部,作用范围也在方法内
  • 和方法内部成员使用规则一样,class前面不可以添加public、private、protected、static
  • 类中不能包含静态成员
  • 类中可以包含final、abstract修饰的成员
public Object getHeart() {
    
        class Heart {
            public final int age = 13;
            int temp = 22;

            public final void say() {
                System.out.println("hello");
            }

            public void eat() {

            }

            public String beat() {
                new Person().eat();
                return Person.age + "岁的心脏在跳动";
            }
        }
        return new Heart().beat();
        // new Heart().temp=12;
        //// temp=33;
        // return new Heart();
    }
##### 匿名内部类:
定义:
对某个类的实例只会使用一次,这个类的名字对于整个程序而言就可有可无了,这时我们将类的定义与累的创建放到一起 完成
  • 匿名内部类没有类型名称、实例对象名称
  • 编译后的文件命名:外部类$数字.class
  • 无法使用private、public、protected、abstract、static修饰
  • 无法编写构造方法,可以添加构造代码块
  • 不能出现静态成员
  • 匿名内部类可以实现接口也可以继承父类,但不可兼得
test.getRead(new Person(){
            {
                //构造代码块
            }
//          public static int age=12;
            @Override
            public void read() {
                // TODO Auto-generated method stub
                System.out.println("男生喜欢看科幻类书籍");
            }
            
        });
        test.getRead(new Person(){

            @Override
            public void read() {
                // TODO Auto-generated method stub
                System.out.println("女生喜欢读言情小说");
            }
            
        });

单例模式:

要点:

    1、某个类只能有一个实例
    2、必须自行创建实例
    3、必须自行向整个系统提供这个实例

实现:

    1、只提供私有的构造方法
    2、含有一个该类的静态私有对象
    3、提供一个静态的公有方法用于创建、获取静态私有对象
饿汉式:对象创建过程中实例化
package com.imooc.singleton;

//饿汉式:创建对象实例的时候直接初始化  空间换时间
public class SingletonOne {
    //1、创建类中私有构造
    private SingletonOne(){
        
    }
    
    //2、创建该类型的私有静态实例
    private static SingletonOne instance=new SingletonOne();
    
    //3、创建公有静态方法返回静态实例对象
    public static SingletonOne getInstance(){
        return instance;
    }
}
懒汉式:静态公有方法中实例化
package com.imooc.singleton;
//懒汉式:类内实例对象创建时并不直接初始化,直到第一次调用get方法时,才完成初始化操作
//时间换空间
public class SingletonTwo {
    //1、创建私有构造方法
    private SingletonTwo(){
        
    }
    
    //2、创建静态的该类实例对象
    private static SingletonTwo instance=null;
    
    //3、创建开放的静态方法提供实例对象
    public static SingletonTwo getInstance(){
        if(instance==null)
            instance=new SingletonTwo();
        
        return instance;
    }
}

优点:

1、在内存中只有一个对象,节省内存空间

2、避免频繁的创建销毁对象,提高性能

3、避免对共享资源的多重占用

缺点:

1、扩展比较困难

2、如果实例化后的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失

使用场景:

1、创建对象时占用资源过多,单同时有需要用到该类对象

2、系统内资源要求同一读写,如读写配置信息

3、当多个实例存在可能引起程序逻辑错误,如号码生成器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.什么是设计模式 设计模式(Design pattern)是一套被反复使用的、多数人知晓的、经过分类编目的、代码...
    沧海一粟谦阅读 364评论 0 1
  • 单例模式概述 滚滚历史,朝代不断更迭,但却存在着永恒定律,比如一个朝代皇帝无论怎么更换,有且只有一个,而对于军队而...
    若兮缘阅读 351评论 0 6
  • 滚滚历史,朝代更迭,永恒定律: 一个朝代皇帝只有一,军队的最高司令官只有一个,一山不容二虎 计算机系统:1、驱动程...
    西红柿盖浇面阅读 246评论 0 0
  • Lecture1 设计模式概述 设计模式:一套被反复使用、多数人知晓、经过分类编目的代码设计经验的总结(是软件开发...
    Mr董先森阅读 334评论 0 0
  • 要点 某个类只能有一个实例 必须自行创建实例 必须向整个系统提供这个实例 优点 在内存中只有一个对象,节省内存空间...
    媛猿YY阅读 140评论 0 0

友情链接更多精彩内容