目录
多态
什么是多态?
定义:某一类事物的多种存在形态。
例如:动物中猫,狗。
猫这个对象对应的类型是猫类型:猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物类型:动物 y = new 猫();
我们发现:动物是猫和狗具体事物中抽取出来的父类型。
也就是父类型引用指向了子类对象。
多态的体现:
父类或者接口的引用指向或者接收自己的子类对象 。
多态的作用:
多态的存在提高了程序的扩展性和后期可维护性。
多态的使用前提:
(1)需要存在继承或者实现关系,就是类与类之间要有关系。要么继承,要么实现;
(2)要有覆盖操作
多态的特点:
- 成员函数:
(1)编译时:要查看引用变量所属的类中是否有所调用的方法。如果有,编译通过,如果没有编译失败;
(2)在运行时:要查看对象所属的类中是否有所调用的方法.
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
- 成员变量
只看引用变量所属的类。
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。
例子:猫和狗的多态例子
//猫和狗的多态例子
public class Demo {
public static void main(String[] args) {
Animal a=new Cat(); //类型提升。 向上转型。父类的引用指向了自己的子类对象
Animal a1=new Dog();
a.eat();
a1.eat();
//如果想要调用猫的特有方法时,如何操作?
Cat c=(Cat)a; //强制将父类的引用转成子类类型。为向下转型。
c.catchMouse();
}
}
//将Animal定义为抽象类
abstract class Animal
{
abstract void eat(); //抽象方法
}
class Cat extends Animal
{
//抽象方法的实现
public void eat()
{
System.out.println("Fish");
}
public void catchMouse()
{
System.out.println("Catch Mouse");
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("Bone");
}
}
例2:多态中成员函数的运行特点:
public class Demo {
public static void main(String[] args) {
Fu f=new Zi();
//在多态中,静态成员函数的特点:无论编译和运行,都参考做左边。
System.out.println(f.num); //访问的是父类中的静态成员num,
f.method1(); //因为method1是非静态函数,访问的是子类中的方法method1
f.method2(); // method2是静态方法,访问的是父类中的方法method2
Zi z=new Zi();
z.method2(); //访问子类中的method2
}
}
class Fu
{
static int num=5;
void method1()
{
System.out.println("Fu method1");
}
static void method2()
{
System.out.println("Fu method2");
}
}
class Zi extends Fu
{
static int num = 8;
void method1()
{
System.out.println("Zi method1");
}
static void method2()
{
System.out.println("Zi method2");
}
}
例3:电脑运行实例,电脑运行基于主板。主板通过PCI来连接声卡,网卡。
public class Demo {
public static void main(String[] args) {
MainBoard m=new MainBoard();
m.run();
m.usePCI(new NetCard());
m.usePCI(new SoundCard());
}
}
//定义接口
interface PCI
{
public void open();
public void close();
}
class MainBoard
{
public void run()
{
System.out.println("MainBoard run");
}
public void usePCI(PCI p) //接口型引用指向自己的子类对象。
{
if (p != null) {
p.open();
p.close();
}
}
}
//声卡实现接口
class SoundCard implements PCI
{
public void open()
{
System.out.println("SoundCard open");
}
public void close()
{
System.out.println("SoundCard close");
}
}
//网卡实现接口
class NetCard implements PCI
{
public void open()
{
System.out.println("NetCard open");
}
public void close()
{
System.out.println("NetCard close");
}
}
内部类
定义:将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)
内部类的访问特点:
- 内部类可以直接访问外部类中的成员,包括私有成员;
之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
- 而外部类要访问内部类中的成员必须要建立内部类的对象
内部类的位置:
内部类定义在成员位置上:
- 可以被private static成员修饰符修饰;
- 被static修饰的内部类只能访问外部类中的静态成员
内部类定义在局部位置上:
- 也可以直接访问外部类中的成员;
- 同时可以访问所在局部中的局部变量,但必须是被final修饰的
例子: 外部类访问内部类成员
public class Demo {
public static void main(String[] args) {
Outer otr=new Outer();
otr.show();
}
}
class Outer
{
private int i=3;
//定义内部类
class Inner
{
void method()
{
System.out.println("Inner:"+i);
//访问的i值其实是Outer.this.i,内部类中持有了一个外部类的引用
}
}
void show()
{
//外部类要访问内部类,必须建立内部类对象
Inner ir=new Inner();
ir.method();
}
}
例2:静态内部类的应用
- 当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。
格式:
外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inner in = new Outer().new Inner();
- 当内部类在成员位置上,就可以被成员修饰符所修饰.比如,private:将内部类在外部类中进行封装。 static:内部类就具备static的特性。当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限。
- 在外部其他类中,如何直接访问static内部类的非静态成员呢? new Outer.Inner().function();
- 在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.function();
//内部类定义在外部类成员位置上
public class Demo {
public static void main(String[] args) {
Outer ot=new Outer();
ot.show();
}
}
class Outer
{
private static int x=3;
//定义静态内部类
static class Inner
{
//当内部类中定义了静态成员,该内部类必须是static的
static void method()
{
System.out.println("Inner:"+x);
//访问的i值其实是Outer.this.i,内部类中持有了一个外部类的引用
}
}
static class Inner2
{
void method2()
{
System.out.println("Inner2");
}
}
public static void show()
{
//在外部其他类中,直接访问static内部类的非静态成员时:
//格式:new Outer.Inner().function();
new Outer.Inner2().method2();
//在外部其他类中,直接访问static内部类的静态成员
//格式:Outer.Inner.function();
Outer.Inner.method();
}
}
例3:内部类定义在局部时的情形
当内部类定义在局部时:
- 内部类不可以被成员修饰符修饰 ;
- 可以直接访问外部类中的成员,因为还持有外部类中的引用;
- 不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
//内部类定义在局部时的情形
public class Demo {
public static void main(String[] args) {
Outer ot=new Outer();
ot.method();
}
}
class Outer
{
int x = 3;
void method()
{
final int y =5;
class Inner
{
void function()
{
//只能访问被final修饰的局部变量
System.out.println(y);
}
}
new Inner().function();
}
}
匿名内部类
什么是匿名内部类?
就是内部类的简化写法。
匿名内部类的前提: 内部类可以继承或实现一个外部类或者接口。
格式: new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
简单理解:就是建立一个带内容的外部类或者接口的子类匿名对象。
例1:内部类定义在
public class Demo {
public static void main(String[] args) {
new Outer().function();
}
}
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x=3;
public void function()
{
//创建匿名内部类
AbsDemo d=new AbsDemo()
{
int num=8;
void show()
{
System.out.println("num="+num);
}
}; //不要忘了这个分号
d.show();
}
}
public class Demo {
public static void main(String[] args) {
new Outer().function();
}
}
abstract class AbsDemo
{
abstract void show();
}
class Outer
{
int x=3;
public void function()
{
//匿名内部类
new AbsDemo()
{
//实现父类的抽象方法
int num=8;
void show()
{
System.out.println("num="+num);
}
}.show(); //记住.前面的内容为匿名类对象,然而再调用自己的成员
}
}