1、多态概念
定义:某一类事物的多种表现形式。可以理解为事物存在的多种体现形态。
2、多态-扩展性
多态的体现:父类的引用指向了自己的子类对象。父类的引用也可以接受自己的子类对象。 如:Father father=new Sun();
多态的好处:多态的出现大大的提高了程序的扩展性。
多态的前提:必须是类与类之间的关系,要么继承,要么实现。通常还有一个前提,存在覆盖。
多态的弊端:提高了扩展性,但只能使用父类的引用访问父类中的成员。
interface Animal {
void eat();
}
public class Dog implements Animal {
/*重写父类的方法*/
public void eat() {
System.out.println("狗吃骨头");
}
}
public class Pink implements Animal {
/* 重写父类的方法 */
public void eat() {
System.out.println("猪吃猪饲料");
}
}
public class DuoTaiDemo {
public static void main(String[] agrs) {
animalEat(new Dog());
animalEat(new Pink());
}
/**
* 用父类来接受子类,那么就可以调用子类和父类相同的方法
*/
public static void animalEat(Animal animal) {
animal.eat();
}
}
结果:
狗吃骨头
猪吃猪饲料
3、多态-转型
如果想要操作子类特有的方法,怎么办?
强制将父类的引用转成子类类型。如:Father father=new Son();Son son=(Son)father;
但不能这么做:(将父类对象转成子类类型)
Father father=new Father();
Son son=(Son)father;
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。多态自始自终都是子类对象在做着变化。
判断一个实例是不是某个类型时:a instanceof Son;a是实例名,Son是类名
4、多态-示例
interface Animal {
void eat();
}
public class Dog implements Animal {
/* 重写父类的方法 */
public void eat() {
System.out.println("狗吃骨头");
}
/* 自独有的方法 */
public void seeDoor() {
System.out.println("看门");
}
}
public class Pink implements Animal {
/* 重写父类的方法 */
public void eat() {
System.out.println("猪吃猪饲料");
}
/* 自独有的方法 */
public void DongDi() {
System.out.println("猪,gongdi");
}
}
public class DuoTaiDemo {
public static void main(String[] agrs) {
animalEat(new Dog());
animalEat(new Pink());
}
/**
* 用父类来接受子类,那么就可以调用子类和父类相同的方法
*/
public static void animalEat(Animal animal) {
animal.eat();
/*instanceof 是判断是否是此类对象,十寸与此类存在某种关系
* 一般情况下,只有在子类比较少的情况下,才使用此比较的方式,
* 父类不能调用子类自己独有的方法,必须强制转换成子类对象*/
if(animal instanceof Dog){
Dog dog=(Dog)animal;
dog.seeDoor();
}else if(animal instanceof Pink){
Pink p=(Pink)animal;
p.DongDi();
}
}
}
结果;
狗吃骨头
看门
猪吃猪饲料
猪,gongdi
5、多态中成员的特点
在多态中成员函数(非静态)的特点:
在编译时期:参阅引用型变量所属的类是否有调用的方法,如果有,编译通过,如果没有,编译失败。
在运行时期,参阅对象所属的类是否有调用方法。
简单总结:成员函数在多态调用时编译看左边,运行看右边。
public class Fu {
public int num=5;
/*静态成员*/
public static void show(){
System.out.println("父类的静态的show()方法");
}
public void print(){
System.out.println("父类的非静态的print()方法");
}
}
public class Zi extends Fu {
public int num=10;
public static void show(){
System.out.println("子类的静态的show()方法");
}
public void print(){
System.out.println("子类的非静态的print()方法");
}
public static void main(String[] agrs) {
Fu fz = new Zi();
fz.show();//父类的,因为是静态的方法
System.out.println(fz.num);//父类的,因为是常量
fz.print();//子类的,因为不是静态的
}
}
结果:
父类的静态的show()方法
子类的非静态的print()方法
涉及面试的环节:
在多态中成员变量和静态函数的特点:无论编译和运行,都参考左边(引用变量所属的类)
6、多态的主板示例
需求:电脑运行实例,电脑运行基于主板。
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("mainboard run ");
}
public void usePCI(PCI p)//PCI p = new NetCard()//接口型引用指向自己的子类对象。
{
if(p!=null)
{
p.open();
p.close();
}
}
}
class NetCard implements PCI
{
public void open()
{
System.out.println("netcard open");
}
public void close()
{
System.out.println("netcard close");
method();
}
}
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCard open");
}
public void close()
{
System.out.println("SoundCard close");
}
}
class DuoTaiDemo5
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run();
mb.usePCI(null);
mb.usePCI(new NetCard());
mb.usePCI(new SoundCard());
}
}
7、多态的扩展示例
需求:数据库操作,数据是用户信息
(1)连接数据库,
(2)操作数据库,增删改查
(3)关闭数据库连接。
interface UserInfoDao
{
public void add(User user);
public void delete(User user);
}
class UserInfoByJDBC implements UserInofDao
{
public void add(User user)
{
1,JDBC连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
public void delete(User user)
{
1,JDBC连接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class UserInfoByHibernate implements UserInfoDao
{
public void add(User user)
{
1,Hibernate连接数据库。;
2,使用sql添加语句添加数据。;
3,关闭连接。
}
public void delete(User user)
{
1,Hibernate连接数据库。;
2,使用sql添加语句删除数据。;
3,关闭连接。
}
}
class DBOperate
{
public static void main(String[] args)
{
//UserInfoByJDBC ui = new UserInfoByJDBC();
// UserInfoByHibernate ui = new UserInfoByHibernate();
UserInfoDao ui = new UserInfoByHibernate();
ui.add(user);
ui.delete(user);
}
}
8、Object类
Object是所有对象的直接或者间接父类,传说中的上帝。该类定义的肯定是所有类都具备的功能。
Object已经提供了对对象是否相同的比较方法,如果自定义类中也有比较相同的功能,没有必要重新定义,只要沿袭父类中的功能,建立自己特有的比较内容即可,这就是覆盖。
9、内部类访问规则
定义:将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类)。
内部类特点:
内部类可以直接访问外部类中的成员,也包括私有。
外部类要访问内部类必须建立内部类对象。
在另一个类中访问内部类方式:外部类.内部类 名称=new 外部类(). new 内部类();
private可以修饰内部类的class前面。
如果内部类和外部类有相同的变量名,则在外部类访问内部类变量时方式:外部类.this.变量名;
10、静态内部类
总结访问格式:
1当内部类定义在外部类的成员位置上,而且非私有,可以再外部其它类中,可以直接建立内部类对象。
格式:外部类名.内部类名 变量名=外部类对象.内部类对象;
如:Outer.Inner in=new Outer().new Inner();
2当内部类在成员位置上,就可以被成员修饰符所修饰,比如:private,将内部类在外部类中进行封装。还有static,内部类就具备static的特性。
当内部类被static修饰后,只能直接访问内部类中的static成员,出现了访问权限。
在外部其它类中,如何直接访问静态内部类呢?
方式:new 外部类名.内部类().函数名(参数);如:new Outer.Inner().Function();
如果内部类的成员函数也是静态的,访问方式是:Outer.Inner.Function();
注意:当内部类中定义了静态成员,该内部类必须是静态的。
当外部类中的静态方法访问内部类时,内部类也必须是静态的。
11、内部类定义原则
当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事务在使用外部事物的内容。
12、匿名内部类
在成员方法中也可以定义局部类,但该局部类不能被private和static修饰
内部类定义在局部时,不可以被成员修饰符修饰,可以直接访问外部类中的成员,因为还有外部类中的引用,但是不可以访问他所在的局部中的变量,只能访问final修饰的局部变量。
匿名内部类:
1.匿名内部类其实就是内部类的简写格式。就是没名字的内部类。
2.定义匿名内部类的前提:内部类必须继承一个类,或者实现接口。
3.匿名内部类的格式:new 父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,可以理解为带内容的内部对象。
在成员方法中定义匿名内部类的方法:
public void 成员方法()
{
new 外部接口或类名()
{
重写或覆盖外部类或接口中的方法或抽象方法;
}.重写或自己特有的方法或覆盖的方法名();
}