多态
概念:
意味着允许不同类的对象对同一消息做出不同的响应
必要条件:
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、当多个实例存在可能引起程序逻辑错误,如号码生成器