Java 多态和内部类的使用方法
Java 多态和内部类
1. 多态
1.1 概述
多态是继封装、继承之后,面向对象的第三大特征。
在生活中,例如跑的动作,不同的动物跑起来也是不一样的;再比如飞的动作,鸟类、昆虫等都是不一样的。由此可见,同一种行为,不同的动物可以体现出不同的形式。多态就是这样一种状态。
多态:是指同一种行为,不同的表现形式。一般应用于继承和实现。
1.2 使用格式
多态的使用格式:
父类变量 变量名 = new 子类对象 ;
变量名.方法名();
Fu fu = new Zi();
接口 变量名 = new 实现类对象();
变量名.方法名();
技巧:
编译器看 = 左边类型, 运行时JVM 看 = 右边类型
左边类型决定了变量 能调用哪些方法,
右边类型决定了最终使用的方法是哪个 - 优先调用自己重写过的
口诀: 编译看左边, 运行看右边
1.3 多态的基础代码演示
public class Fu {
int age =10;
int num = 100;
int score = 1000;
public void m1 (){
System.out.println("Fu m1");
}
public void m2 (){
System.out.println("Fu m2");
}
public int getAge() {
return age;
}
}
public class Zi extends Fu {
int age = 20;
int num = 999;
int score =9999;
@Override
public void m1() {
System.out.println("Zi m1");
}
public void m3 (){
System.out.println("Zi m3");
}
public int getAge() {
return age;
}
}
/**
* 多态的表现方面:成员变量的调用,字符类中拥有相同的成员
* 并且都有一对 get/set方法
*
* 如果通过引用直接调用成员变量的时候 -f.age 看左边类型
* 通过方法调用成员变量的时候 - f.getAge 看右边对象
*/
public class Main1 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.age);
System.out.println(f.getAge());
}
}
/**
* 多态的表现方面,成员方法的调用
* 最终调用的是哪个方法,优先调用子类重写过的,
* 子类中如果没有重写,那就调用父类的方法
*/
public class Main2 {
public static void main(String[] args) {
Fu f = new Zi();
System.out.println(f.age);
System.out.println(f.num);
System.out.println(f.score);
f.m1();
f.m2();
System.out.println(f.getAge());
System.out.println();
Zi zi = (Zi) f;
System.out.println(zi.age);
System.out.println(zi.num);
System.out.println(zi.score);
zi.m1();
zi.m2();
zi.m3();
}
}
1.4 向上转型
向上转型:多态本身是子类类型向上转换的过程,这个过程是默认的。
当父类引用指向一个子类对象时,便是向上转型。
Animal c= new Cat();
c.eat();
1.5 向下转型
向下转型:父类类型想子类类型向下转换的过程,这个过程是强制的。
一个已经向下转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型
Cat cat = (Cat) c;
cat.catchMouse();
1.6 转型异常
为了避免出现ClassCastException类型转换异常,可以使用instanceof 加粗样式 关键字,在转换之前先将引用变量和类型做效验,防止出现不符合类型转换的定义。
//编译器看c是Animal类型,和Dog是父子关系
//Dog dog = (Dog) c;
//运行时,发现c实际上Cat,不能转换为Dog 。解决方法,instanceof判断是不是存在 避免出现异常
//ClassCastException 类型转换异常!
if(d instanceof Dog){
Dog dog = (Dog) d;
dog.watchHouse();
}
2. 内部类
2.1 概述
将一个类A定义在另一个类B里,里面的那个类A就称为内部类,B则称为外部类。
种类: 成员内部类,静态内部类,局部内部类[匿名内部类]
使用方法:
内部类中, 可以随意使用外部类成员
外部类中, 使用内部类成员时需要创建内部类对象
无关类中, 使用内部类成员
1.间接调用, 在外部类方法中调用内部类方法
main方法中, 调用外部类方法
2.直接调用, 需要创建内部类对象
外部类.内部类 a = new 外部类().new 内部类();
内部类和外部类有同名成员变量
外部类的成员变量: 外部类.this.变量
内部类的成员变量: this.变量
2.2 成员内部类
成员内部类:定义在类中,方法外的类。
访问特点:
内部类可以直接访问外部类的成员,包括私有成员。
外部类要访问内部类的成员,必须要建立内部类对象。
代码举例:
public class Body {
private int a =100;
public void walk(){
System.out.println("身体在行走!");
//外部类,直接创建内部类对象
Heart heart = new Heart();
heart.beat();
System.out.println(heart.num);
}
//成员内部类
public class Heart{
int num =100;
int a = 99;
public void beat(){
System.out.println("心脏跳动!"+a);
//调用内部类的a
System.out.println(this.a);
//调用外部类的a
System.out.println(Body.this.a);
}
}
}
public class Main {
public static void main(String[] args) {
Body body = new Body();
//间接调用内部类
body.walk();
//直接调用内部类,通过外部类对象创建内部类对象
Body.Heart heart = body.new Heart();
heart.beat();
}
}
注:内部类仍然是一个独立的类,在编译之后内部类会编译成独立的.class文件,但是前面会冠以外部类的类名和$符号。
例如:Person$Heart.class
2.3 匿名内部类(重点内容)
匿名内部类:是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的子类对象。
在开发中,最常用到的内部类就是匿名内部类了。
以接口举例,当你使用一个接口时,需要做以下几个步骤:
1.定义子类
2.重写接口中的方法
3.创建子类对象
4.调用重写后的方法
匿名内部类的作用就是将这几个步骤进行简化。
前提
匿名内部类必须继承一个父类或者实现一个父接口。
代码部分:
public interface InterfaceA {
void methodA();
void methodB();
}
public class Main {
public static void main(String[] args) {
/**
* 匿名内部类的本质:实现接口或者继承抽象类
*
* new InterfaceA(){....}
* new:创建InterfaceA的实现类对象
* InterfaceA:想要实现的接口名字或抽象类
* {....}:真正的类,没有名字
* 弊端:只能使用一次,只能创建一次对象
*/
InterfaceA impl = new InterfaceA() {
@Override
public void methodA() {
System.out.println("方法A");
}
@Override
public void methodB() {
System.out.println("方法B");
}
};
impl.methodA();
impl.methodB();
}
}
输出结果:
2.4 静态内部类
public class Outer {
// 成员方法
public void m1() {
new Inner();
new InnerField();
}
// 静态方法
public static void m2() {
new Inner();
// new InnerField();
}
// 成员内部类
public class InnerField {
}
// 外部类的成员变量
int a = 10;
// 外部类的静态成员变量
static int b = 20;
// 静态内部类, 属于类的
public static class Inner {
public void m3() {
// 不能使用非静态成员
// System.out.println(a);
System.out.println(b);
}
}
}
public class Main {
public static void main(String[] args) {
// 成员内部类创建对象, 需要外部类对象
Outer.InnerField inner1 = new Outer().new InnerField();
// 静态内部类创建对象
Outer.Inner inner2 = new Outer.Inner();
// 简化 -> 需要import
Inner inner3 = new Outer.Inner();
}
}
本文地址:https://blog.csdn.net/weixin_44191224/article/details/107360691
推荐阅读
-
java内部类的格式和访问规则
-
Java 多态和内部类的使用方法
-
Java基础知识(三)面向对象、类和对象、封装继承多态、构造方法、内部类、包装类
-
Java静态内部类和非静态内部类的区别与限制
-
JAVA 在外部类外部访问内部类,静态内部类和非静态内部类的区别
-
统计方格区域内正方形和长方形的个数(洛谷P1548题题解,Java语言描述)
-
java基础:详解break和continue的使用及在循环内switch中使用
-
Java和ABAP里的外部类和内部类 ABAPJava外部类内部类SAP Cloud Platform
-
Java中静态内部类和内部类的区别
-
对继承与多态、成员变量的隐藏和方法重写、super关键字、final关键字、对象的上转型对象、抽象类的学习理解(java)