多态概述
多态成员方法的使用
多态成员变量的使用
多态好处
成员内部类
静态内部类
局部内部类
匿名内部类
多态
多态概述
- 继承或是实现是多态的前提
- 多态是指对象的多态性(仔细体会)
- 代码中体现多态:父类引用指向子类对象
- 多态:通过父类引用不同的子类
- Java实现多态的三个必要条件
- 继承、重写、向上转型
多态中方法的使用
- 使用规则:new 谁 则调用谁的方法,没有则向上找
- 成员方法:编译看左边,运行看右边
class Animal {
//父类方法
public void bark() {
System.out.println("动物叫!");
}
}
class Dog extends Animal {
//子类重写父类的bark方法
public void bark() {
System.out.println("汪、汪、汪!");
}
//子类自己的方法
public void dogType() {
System.out.println("这是什么品种的狗?");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
Animal b = new Dog();
Dog d = new Dog();
a.bark(); //动物叫!
b.bark(); //汪、汪、汪!
//b.dogType();
//b.dogType()编译不通过
d.bark(); //汪、汪、汪!
d.dogType(); //这是什么品种的狗?
}
}
- 注意:这里b是父类的引用,指向子类的对象,因此不能获取子类的方法(dogType()方法),当调用back()方法时,因为子类覆盖了父类的back()方法,因此会调用子类的back()方法
- 因此,向上转型在运行时会遗忘子类对象与父类不同名的方法,也会覆盖与父类中相同的方法(方法名,参数列表都相同)
多态中成员变量的使用
- 只有方法可以重写,成员变量不可以重写
- 直接通过对象名称访问成员变量,看等号左面是谁,优先使用谁,没有则想上找
- 间接通过成员方法访问成员变量,看方法属于谁,优先用谁,没有则想上找
public class Fu {
int num = 10;
public void shouNum() {
System.out.println(num);
}
}
public class Zi extends Fu{
int num = 5;
@Override
public void shouNum() {
System.out.println(num);
}
}
/**
* 多态成员变量的使用
* 只有方法可以重写,成员便令不可以重写
* 1、直接通过对象名称访问成员变量,看等号左面是谁,优先使用谁,没有则想上找
* 2、间接通过成员方法访问成员变量,看方法属于谁,优先用谁,没有则想上找
* */
public class MutiField {
public static void main(String[] args) {
Fu obj = new Zi();
System.out.println(obj.num); //10
obj.shouNum(); //5
}
}
使用多态好处
- 无论等号右面new哪个子类对象,等号左面的调用方法都不会改变
多态总结:
- 在调用变量是,看等号左面是谁,则优先使用谁,没有则向上找
- 在调用方法时,看new 谁则优先使用谁,没有则想上找
- 调用变量时,编译时看左边,运行时也看左边
- 调用方法时,编译时看左边,运行时看右边
成员内部类
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之外,不允许同一个包中的其他类访问该类
- 内部类方法可以直接访问外部类的所有数据,包括私有数据
- 内部类所有实现功能使用外部类同样实现
- 内部类运训继承多个非接口类型
- 内部类在外部类中相当于一个成员变量
- 内部类里可以直接访问外部类的属性和方法反之不行
- 必须使用外部类对象来创建内部类对象
- 内部类 对象名 = 外部类对象.new 内部类();
- 内部类不能由static变量和方法,因为成员内部类需要在创建外部类之后才能创建它
- 内部类和外部类成员变量和方法重名时,内部类默认访问自己的,外部类使用this访问
// People.java
//外部类People
public class People {
private String name = "LiLei"; //外部类的私有属性
//内部类Student
public class Student {
String ID = "20151234"; //内部类的成员属性
//内部类的方法
public void stuInfo(){
System.out.println("访问外部类中的name:" + name);
System.out.println("访问内部类中的ID:" + ID);
}
}
//测试成员内部类
public static void main(String[] args) {
People a = new People(); //创建外部类对象,对象名为a
Student b = a.new Student(); //使用外部类对象创建内部类对象,对象名为b
// 或者为 People.Student b = a.new Student();
b.stuInfo(); //调用内部对象的suInfo方法
}
}
静态内部类
- 静态内部类不能直接访问外部类的非静态成员,可以通过new 外部类().成员 的方法访问
- 如果外部类的静态成员与内部类的成员名称相同,可通过 类名.静态成员 访问外部类的静态成员;如果外部类的静态成员与内部类的成员名称不相同,则可通过 成员名 直接调用外部类的静态成员。
- 创建静态内部类的对象时,不需要外部类的对象,可以直接创建 内部类 对象名 = new 内部类();
// People.java
//外部类People
public class People {
private String name = "LiLei"; //外部类的私有属性
/*外部类的静态变量。
Java 中被 static 修饰的成员称为静态成员或类成员。它属于整个类所有,而不是某个对象所有,即被类的所有对象所共享。静态成员可以使用类名直接访问,也可以使用对象名进行访问。
*/
static String ID = "510xxx199X0724XXXX";
//静态内部类Student
public static class Student {
String ID = "20151234"; //内部类的成员属性
//内部类的方法
public void stuInfo(){
System.out.println("访问外部类中的name:" + (new People().name));
System.out.println("访问外部类中的ID:" + People.ID);
System.out.println("访问内部类中的ID:" + ID);
}
}
//测试成员内部类
public static void main(String[] args) {
Student b = new Student(); //直接创建内部类对象,对象名为b
b.stuInfo(); //调用内部对象的suInfo方法
}
}
局部内部类
- 局部内部类,是指内部类定义在方法和作用域内
// People.java
//外部类People
public class People {
//定义在外部类中的方法内:
public void peopleInfo() {
final String sex = "man"; //外部类方法中的常量
class Student {
String ID = "20151234"; //内部类中的常量
public void print() {
System.out.println("访问外部类的方法中的常量sex:" + sex);
System.out.println("访问内部类中的变量ID:" + ID);
}
}
Student a = new Student(); //创建方法内部类的对象
a.print();//调用内部类的方法
}
//定义在外部类中的作用域内
public void peopleInfo2(boolean b) {
if(b){
final String sex = "man"; //外部类方法中的常量
class Student {
String ID = "20151234"; //内部类中的常量
public void print() {
System.out.println("访问外部类的方法中的常量sex:" + sex);
System.out.println("访问内部类中的变量ID:" + ID);
}
}
Student a = new Student(); //创建方法内部类的对象
a.print();//调用内部类的方法
}
}
//测试方法内部类
public static void main(String[] args) {
People b = new People(); //创建外部类的对象
System.out.println("定义在方法内:===========");
b.peopleInfo(); //调用外部类的方法
System.out.println("定义在作用域内:===========");
b.peopleInfo2(true);
}
}
匿名内部类
- 匿名内部类,顾名思义,就是没有名字的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写。但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
// Outer.java
public class Outer {
public Inner getInner(final String name, String city) {
return new Inner() {
private String nameStr = name;
public String getName() {
return nameStr;
}
};
}
public static void main(String[] args) {
Outer outer = new Outer();
Inner inner = outer.getInner("Inner", "NewYork");
System.out.println(inner.getName());
}
}
interface Inner {
String getName();
}