多态和内部类
虽然java这些知识点都是很基础的东西,但是等我到用的时候,总是模棱两可的回忆起大概,这就是我java基础不牢固的表现,每天坚持写一篇java基础,以此来打牢自己的基础。坚持~坚持,关于这篇自己的总结是看了下面的博客,加上自己的理解https://blog.csdn.net/m366917/article/details/52124604
在说内部类之前,我觉得先要了解一下什么是多态,因为对于后面匿名内部会比较好理解。多态通俗一点就是,子类可以持有父类的引用,父类也可以向下转型成子类,使用子类的方法,(Fu fu = new ZI(); 或者 Fu fu = new Fu(); ZI zi = (ZI)fu)
下面看一段代码
定义一个父类(A.java)
public class A {
public int numA = 100;
public void Ashow() {
System.out.println("show A");
}
public static void Afunction() {
System.out.println("function A");
}
}
定义一个子类(B.java)
public class B extends A{
public int numB =10;
public int numA = 10;
public void Ashow(){
System.out.println("修改的Ashow");
}
public void Bshow() {
System.out.println("show B");
}
public static void Bfunction() {
System.out.println("function B");
}
}
测试一下
public class C {
public static void main(String[] args){
//成员
A a = new B();
System.out.println(a.numA); //只能调动A的成员变量
a.Ashow(); //只能调用A中Ashow方法,但是请看运行结果
a.Afunction(); //同上
}
}
//这里注意一下输出结果:
100
修改的Ashow
function A
结果说明了什么,
对于成员变量来说 :编译看左边,运行看左边,所以只能调用A的成员变量。
对于成员方法来说:编译看左边,运行看右边,也就是new B();B中有Ashow方法,相当于重写了A中的Ashow方法,这里其实调用了B中的Ashow方法。
之后a.Afunction,看B中没有Afunction方法,所以只能使用A中的成员方法。
所以多态的弊端不能使用子类特有的功能。
如果想使用子类的方法,看下面的代码
public class C {
public static void main(String[] args){
//成员
A a = new B();
System.out.println(a.numA);
a.Ashow();
a.Afunction();
//向下转型
B b = (B) a;
b.Bshow();
b.Bfunction();
}
}
//输出结果:
100
修改的Ashow
function A
show B
function B
============================多态就复习到这里==========================================
下面就来说说内部类
成员和局部内部类
看代码
定义一个成员和局部内部类都存才的类(AOuter.java)
public class AOuter {
private int num = 100;
//成员位置定义一个类,就是成员内部类
class BInner{
private int num = 200;
public void Bshow(){
System.out.println(num);
}
}
public void method(){
//在方法里定义类,就是局部位置--局部内部类
class CInner{
public void Cshow(){
System.out.println("Cshow");
}
}
//在方法类创建局部内部类对象,然后使用其功能
CInner c = new CInner();
c.Cshow();
}
}
测试一下方法
public class Test {
public static void main(String[] args){
AOuter.BInner b = new AOuter().new BInner();
b.Bshow();
AOuter a= new AOuter();
a.method();
}
}
//输出的结果:
200
Cshow
从上面的代码结果可以总结出两点,一个是内部类可以直接访问外部类的成员变量,二是局部内部类要是用时,可以在方法体内定义对象,那个这个类的生命周期就跟方法一致了。
接下来修改一下method中的代码
public void method(){
int Cnum = 300;
//在方法里定义类,就是局部位置--局部内部类
class CInner{
public void Cshow(){
System.out.println("Cshow");
System.out.println("Cnum"+Cnum);//访问局部变量
System.out.println("num"+num); //访问外部类的变量
}
}
//在方法类创建局部内部类对象,然后使用其功能
CInner c = new CInner();
c.Cshow();
}
注意这里我们是可以访问到局部变量Cnum的值得,但是为什么局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final,原因就是内部类对象的生命周期比局部变量的生命周期长,
就会报错,(在jdk8.0能编译通过,那是因为它检测到局部内部类访问了 x,会默认给 x 的前面加上隐式的final,如果我在int Cnum = 300后面加一句Cnum = 10;编译器将会报错,因为final不允许 x 的值改变)
静态内部类
看代码
定义一个静态内部类(BOuter.java)
public class BOuter {
private int num = 10;
private static int num2=100;
public static class CInner{
public void show(){
// System.out.println("show static"+num);
System.out.println("show static"+num2);
}
}
}
测试一下
public class Test {
public static void main(String[] args){
new BOuter.CInner().show();
}
}
结果:
show static100
匿名内部类
一般是定义一个接口,也可以定义一个抽象类
然后new 一个接口或者抽象类,并且实现其中的方法,这个new 出的接口或者抽象类可以想象成是一个没有名字的子类,继承了这个接口或抽象类,看代码
//使用匿名内部类访问局部变量
//定义一个接口或者抽象类
public abstract class D {
public abstract void Dshow();
}
//用匿名内部类的方法来实现
new D(){
@Override
public void Dshow() {
}
};
其实这个new D()可以想象成 new 匿名 extend/implements D(){实现方法}