面向对象(多态)

									面向对象(三大特性之一多态)
	3.多态(要点,难点)

一种事物的多种形态,就称为多态;
编译时跟运行时类型不一致就产生了多态
父类类型的变量,存放子类类型的对象,可能存放子类类型的对象有多种可能
多态存在的前提:必须有继承关系
多态方法调用编译运行过程:
a)编译时,看的是父类类型,会在父类类型中找对应的方法
如果没有找到,会继续向上找[编译时父类类型]
i.找到:编译通过
ii.找不到:编译报错
iii.注意:是不会向下找的[aml编译时子类类型]
2)运行时 :
a)先到运行时子类类型中找覆写的方法,如果子类有自己的特性方法,就直接用子类的,找不到或者没有的话就会去调用父类的。
2.有没有可能编译通过了,而运行找不到方法… 不可能!
编译时与运行时的几种情况分析:
父类中有一个方法,子类覆写了
那么会先运行子类的
2.父类中有一个方法,子类没有
那么会运行父类的
3.父类中没有,子类有一个方法
那么直接报错
4.父类子类都没有
那么就会默认的引用Object里边的方法
5.静态方法
6.字段没有覆写一说
静态方法也不是能被覆写的,和继承的,静态方法是单独存在的,全局共享的。
class Dog{//父类类型Dog
void eat(){
System.out.println(“吃食物”);
}
}
class DDog extends Dog{//子类类型DDog
void eat(){
System.out.println(“哈根达斯”);
}
}
class XDog extends Dog{//子类类型XDog
void eat(){
System.out.println(“吃牛排喝红酒”);
}
}
class Person{//人类:定义喂狗方法
void feedDog(Dog dog){
dog.eat();
}
}
//------------------------------测试类-----------------------------------
class Test {
public static void main(String[] args) {
Dog ddog = new DDog();
XDog xdog = new XDog();

	Person pson = new Person();
	pson.feedDog(ddog);
	pson.feedDog(xdog);
}

}
这儿及体现了多态的好处,直接不用在去定义更多的喂狗的方法了
多态体现的几种情况:
1.如上代码多态的体现的本质:都是父类类型的变量存放子类类型的对象
2.Dog dog = new XDog();//核心本质
大的数据类型兼容小的数据类型;
方法参数传递:方法形参父类类型,允许传子类类型对象
5.多态的好处:屏蔽了不同子类之间实现的差异
a)此处体现java语言设计是想,希望将现实生活中的对象与对象之间的关系在计算机系统得以体现
4.引用类型转换:
class Cat{
void eat(){}
}
class TomCat extends Cat{
void say(){}
}
class CoffeeCat extends Cat{
void drink(){}
}
//测试类
class Test {
public static void main(String[] args) {
Cat cat = new Tomcat();
CoffeeCat cc = (CoffeeCat)cat;
cc.drink();
}
}
基本语法:
1.明确:数据类型转换存在两种,情况,大转小:小转大
1)子类类型转父类类型:小转大
Cat cat = new TomCat();
double d = 1;
2)父类类型转子类类型:大转小
TomCat tc =(TomCat)cat;
2.在引用数据类型中:父类是较大的数据类型,子类是较小的数据类型
a)cat可能是传来的参数:在使用的时候不知道存放的是Tomcat,误以为存的是CoffeeCat类型
b)红色代码使用多态:绿色代码引用类型数据转换:cc.drink();
c)编译只看类型不看值,如上代码编译都不会有问题!
d)但是:运行时反应的是真实类型,绿色代码等于要将TomCat 变成 CoffeCat 显然不行!
2.因此引用数据类型转换,最好在转换之前先判断类型在转换
3.判断类型的方式
a)获得运行时类型 Object 中getClass();方法
b)类型判断运算符 instanceof
b)类型判断运算符 instanceof
Systme.out.println(cat instanceof Cat);//true
Systme.out.println(cat instanceof TomCat);//true
Systme.out.println(cat instanceof Object);//true
Systme.out.println(cat instanceof CoffeeCat);//false
System.out.println(tom instanceof CoffeeCat);////编译报错,不存在继承关系,不兼容,完全相关类型:编译器只看类型不看值
Systme.out.println(cat instanceof String);//编译报错,不存在继承关系,不兼容,完全相关类型:编译器只看类型不看值
引用数据类型转换小结:
1.为什么需要引用数据类型转
(1)明知道多态父类类型装的是子类对象,但是子类特性,父类对象访问,编译报错,需要转换成真实类型
2.数据类型转换的两种情况:
小转大 自动转换
大转小 强制转换
(3)父类大子类小 : 父类类型兼容子类类型
3.数据类型转换的注意事项
(1)在转换之前要进行类型判断
(2)两种判断方式
4.instanceof运算符的运用
(1)只看类型不看值,不存在继承关系的,编译不通过
5.final
代表最终的,不可变得
final是什么:
final : Java中的一个关键字,修饰符:表示的意思:最终的,不可变的,不可拓展的
final可以修饰的东西:
1.外部类:可以
2.普通方法:可以
3.成员字段:可以
4.局部变量:可以
5.内部类:可以 [ 暂时不学 ]
6.构造方法:不可以
1.final修饰类:最终类,不可拓展的类,太监类 :
final修饰普通方法:最终的方法,不可拓展的方法:
1.final修饰变量:表示最终的变量 : 2.final 修饰变量一般使用 public static final double PI = 3.14159265; 构成类中的全局常量仅供使用

2.目前不能被覆写的方法 有哪些?
1)使用final修饰的方法
2)使用static修饰的方法
3)使用private修饰的方法
在这里插入图片描述1 什么是单例模式
就是一种设计模式[为了解决某类问题,而提出的比较好的解决方案]
2.单利模式概念:需要设计一个类,达到的效果: 此类在整个应用中只存在一个对象
3)单利模式好处:节省了系统资源,节省了内存空间
单利模式对象怎么用 : 如果系统很多位置都会用到该对象,通过该对象的引用地址对其引用
a.设计一个类 class A{}
b.对象怎么来的?new A(); new A(); new A(); … 调用一次构造方法就得到一个对象
c.把构造方法私有化,本类的外部就不能够随意的访问创建对象了
d.思考 : 一个类的所有构造方法都被私有化,就不能够创建对象了,说法正确吗?不正确
a)外部不能创建,自己内部可以创建
e.可以在A类内部创建好一个,并保存起来,别人需要对象给它一个地址
饿汉模式:
1)构造方法私有化
2)在类的内部创建一个对象
3)使用一个字段保存起来
4)提供一个方法允许外部使用该方法访问该字段
5)提供的方法必须静态修饰,因为外部不能创建对象
6)外部通过方法访问instance 字段,方法静态修饰,所以字段必须静态修饰
7)字段不私有化,别人可以通过类名.instance修改子字段值,所以必须私有化
class A{
private A(){}
private A instance = new A();
public A getInstance(){
return instance;
}
}
单例模式的类也是一个普通的类,其中也可以有其他的字段 方法等
instance 对象是A类被加载[把类放到JVM的过程中]的时候创建的
懒汉模式;
1)明确:应用程序在第一次调用方法获取单利模式对象的时候创建对象
2)构造方法私有化
3)设置一个A类类型的字段私有化不初始化值
4)提供一个方法允许外部使用该方法访问该字段
5)外部不能创建对象,所以方法必须static修饰
6)什么时候是第一次【instance == null】
7)当第一调用的时候判断
a.如果instance == null :初始化instance
b.如果instance != null : 直接返回instance
class A{
private A(){}
private static A instance;
public static A getInstance(){
if(instance == null){
instance = new A();
}
return instance;
}
}
懒汉模式和懒汉模式存在线程安全的问题;

猜你喜欢

转载自blog.csdn.net/dkwjava/article/details/88859670