一、内部类概述
内部类(一般应用子类设计)
将一个类定义在另一个类里面,内部类也称(内置类,嵌套类)访问特点:
内部类可以直接访问外部类中的成员,包括私有成员.而外部类要访问内部类必须建立内部类的对象.
在分析事物时,发现该事物描述中还有事物,而且这个事物还在访问被表述的事物的内容.这时候就将还有的事物定义成内部类来描述.
二. 内部类修饰符
以下文件编译会生成3个.class文件(Outher.class/Test.class/Outher$Inner.class)
总结一下:1.外部类要访问内部类,必需要建立内部类的对象;
//直接访问外部类中的内部类中的成员(但是一般情况下内部类会私有化,就访问不到)
Outher.Inner.function();
细节:
内部类持有外部类引用,外部类名.this,所以可以直接访问外部类.
内部类在局部位置
//直接访问外部类中的内部类中的成员(但是一般情况下内部类会私有化,就访问不到)
Outher().Inner() in = new Outher().Inner();
in.show();
2.如内部类变成了static静态,我认为它就相当于一个外部类,它随类的加载就已经存在了
Outher.Inner in = new Outher.Inner();//直接类中的静态类
in.show();
3.如果内部类成员也是静态的,那类必须为静态,静态成员方法调用的成员变量也必须是静态成员变量.
class Outher
{
private static int num = 3;//成员方法是静态,访问的成员变量也是静态
//class Inner //内部类
static class Inner//静态内部类(当内部类有静态成员,该成员的类也必须是静态)
{
void show()
{
System.out.println("show....run..."+num); //可以直接访问私有成员
}
static void function() //静态成员方法
{
System.out.println("function....run..."+num);
}
}
public void method()
{
Inner in = new Inner(); //外部类要访问内部类,必需要建立内部类的对象
in.show();
}
}
class Test
{
public static void main(String[] agrs)
{
//Outher o = new Outher();
//o.method();
//直接访问外部类中的内部类中的成员(但是一般情况下内部类会私有化,就访问不到)
Outher().Inner() in = new Outher().Inner();
in.show();
//如内部类变成了static静态,我认为它就相当于一个外部类,它随类的加载就已经存在了
Outher.Inner in = new Outher.Inner();//直接类中的静态类
in.show();
//如内部类变成了static静态,成员也是静态的
Outher.Inner.function();
}
}
细节:
内部类持有外部类引用,外部类名.this,所以可以直接访问外部类.
class Outher
{
int num =3;
class Inner
{
int num = 4;
void show()
{
int num = 5;
System.out.println(Outher.this.num);//外部类.this
}
}
void method()
{
new Inner().show();
}
}
内部类在局部位置
class Outher
{
int num = 3;
void method()
{
final int x =9; //内部类在局部位置上,想要访问局部变量,局部变量必须被final修饰
class Inner
{
void show()
{
System.out.println("show..."+x);
}
}
Inner in = new Inner();
in.show();
}
}
三.
匿名内部类
通俗的讲就是内部类的简写格式.但是简写必须有前提.就是:内部类必须继承或是实现一个外部类或接口.
为什么第一种情况可以编译通过,并能运行?而第二种情况却直接编译失败?
原因: 第一种情况:因为我创建的是子类对象,我在调用子类方法,完全没问题.第二种情况就多加了一个引用为什么就不行了?重点就在创建了这个引用对象,将我创建的new Object子类对象向上转型为了Object类型(多态),限制了子类特有方法show()的使用.这是多态结合了匿名内部类的问题.
通俗的讲就是内部类的简写格式.但是简写必须有前提.就是:内部类必须继承或是实现一个外部类或接口.
匿名内部类:其实就是一个匿名子类对象.它其实做了一个简化封装动作,按理说应该由一个类去继承父类(Demo),覆盖它的方法,再new对象.但匿名类就是一气呵成,简化了代码.
格式:new 父类or接口(){子类内容}
格式:new 父类or接口(){子类内容}
abstract class Demo
{
abstract void show();
}
class Outher
{
int num =4;
/*
class Inner extends Demo
{
void show
{
System.out.println("show..."+num);
}
}
*/
public void method()
{
//new Inner().show();
new Demo()//这就是匿名内部类,这里new了一个Demo对象吗?No,这里new了一个Demo类的子类对象
{ //因为只有子类它才有权利去覆盖父类d的show()方法,定义在了这个区间当中
void show()
{
System.out.prinln("show..."+num)
}
}.show(); //new 完了子类对象,覆盖了方法,接着调用方法.
}
}
通常使用场景之一:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递.
细节:主函数中不能直接访问非静态成员(包括非静态内部类),main主函数本身就是静态的,它也不允许通过this.来访问.唯一方法就是将非静态成员(非静态内部类)变为静态的.
经典题:这个也是面试经常会遇到的问题,挂了一片一片.....细节:主函数中不能直接访问非静态成员(包括非静态内部类),main主函数本身就是静态的,它也不允许通过this.来访问.唯一方法就是将非静态成员(非静态内部类)变为静态的.
为什么第一种情况可以编译通过,并能运行?而第二种情况却直接编译失败?
原因: 第一种情况:因为我创建的是子类对象,我在调用子类方法,完全没问题.第二种情况就多加了一个引用为什么就不行了?重点就在创建了这个引用对象,将我创建的new Object子类对象向上转型为了Object类型(多态),限制了子类特有方法show()的使用.这是多态结合了匿名内部类的问题.
class Outher
{
//第一种情况
void method()
{
new Object()
{
public void show()
{
System.out.println("show run");
}
}.show();
//第二种情况
void method()
{
Object obj = new Object()
{
public void show()
{
System.out.println("show run");
}
};
obj.show();
}
}