Java内部类
1.内部类:
我们知道一个文件中只能有一个public类,如果还要定义一个类(包括接口)只能是默认的不能带有修饰符。而内部类则不然,内部类是指在一个类中(外部类)再定义一个类(内部类),内部类这是相当于外部类的一个属性,类似的内部类分为成员内部类,局部内部类,静态内部类,匿名内部类;内部类的定义不像外部类一样必须使用public或这默认的,他的修饰符可以像所有变量一样可以用public,default,protected和private修饰,也可以是静态的。它的命名也不用担心会和外部类产生冲突,可以自己定义。
内部类平时使用的不多,最多的还是用在事件监听的过程中。
2.成员内部类:
在内部类中可以随意的使用外部类的成员方法和成员变量,尽管这些类的成员被修饰为private.
内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类的对象,那么内部类对象就会绑定在外部类的对象上。
public class OuterClass {
innerClass in = new innerClass(); // 在外部类实例化内部类对象引用
public void ouf() {
in.inf(); // 在外部类方法中调用内部类方法
}
class innerClass {
innerClass() { // 内部类构造方法
}
public void inf() { // 内部类成员方法
}
int y = 0; // 定义内部类成员变量
}
public innerClass doit() { // 外部类方法,返回值为内部类引用
// y=4; //外部类不可以直接访问内部类成员变量
in.y = 4;
return new innerClass(); // 返回内部类引用
}
public static void main(String args[]) {
OuterClass out = new OuterClass();
// 内部类的对象实例化操作必须在外部类或外部类中的非静态方法中实现
OuterClass.innerClass in = out.doit();
OuterClass.innerClass in2 = out.new innerClass();
}
}
注意:
1.内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现,如果在这之外(静态方法、外部类)中则需要使用外部类的实例对象来进行,如上面的main函数中。
2.当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:(外部类.
this表示外部类对象
)内部类被实例化后也存放在堆中,而 外部类.
this可以活动外部类在堆中的对象。
外部类.
this
.成员变量
外部类.
this
.成员方法
public class Test {
public static void main(String args[]) {
OuterClass2 out = new OuterClass2(); // 实例化一个OuterClass2对象
// 调用doit()方法,返回一个OutInterface接口
OutInterface outinter = out.doit();
outinter.f(); // 调用f()方法,这样你根本不知道f方法是如何实现的,很好的进行了封装,这是内部类的最基本用途。
}
}
interface OutInterface { // 定义一个接口
public void f();
}
class OuterClass2 {
// 定义一个内部类实现OutInterface接口
private class InnerClass implements OutInterface {
InnerClass(String s) { // 内部类构造方法
System.out.println(s);
}
public void f() { // 实现接口中的f()方法
System.out.println("访问内部类中的f()方法");
}
}
public OutInterface doit() { // 定义一个方法,返回值类型为OutInterface接口,对InnerClass进行了自动向上转型
return new InnerClass("访问内部类构造方法");
}
}
输出:访问内部类的构造方法 访问内部类中的f()方法
interface OutInterface { // 定义一个接口
}
public class OuterClass {
public OutInterface doit(final String x) { // doit()方法参数为final类型
// 在doit()方法中定义一个内部类
class InnerClass implements OutInterface {
InnerClass(String s) {
s = x;
System.out.println(s);
}
}
return new InnerClass("doit");
}
}
我们会发现doit()的参数设置为final类型。如果需要在方法体中使用局部变量,该局部变量需要被设置为final类型(该方法中的内部类只能访问方法中final类型的局部变量),因为在方法中定义的局部变量相对于该类来说是一个常量,我们不能对它进行改变。它的生命周期超过方法运行的生命周期(该方法被销毁了,但方法的返回对象还要存在),如果可以改变的话可能造成一个变量到时可能被两个拥有,但他们对应的值又不相同。所以该局部变量被设置为final。所以不能在内部类中该局部变量的值(这点和成员内部类中也不能改外部类的属性值一样)。
interface E{
public void A();
}
public class B{
public E creat(final int a ){
return new E(){ //声明一个内部类,默认继承E接口
private int i = a;
public int getvalue(){
return i;
}
@Override
public void A() {
// TODO Auto-generated method stub
}
};
}
}
public class B {
int x=100;
static class Inner{
void doitInner(){
System.out.println("外部类"+x); //这里会编译报错
}
//进行程序测试时,如果在每个Java文件中都设置一个main方法,
//将出现很多额外的代码,而程序本身不需要这些方法时可以将main函数写入内部类中,这样只要用外部类.内部类就可以调用main函数了,测试完成时只要把这给类给删除就可以了。
public static void main(String args[]){
System.out.println("a");
}
}
}
public class C extends ClassA.ClassB{ //继承内部类ClassB
public C(ClassA a){
a.super();
}
}
class ClassA{
class ClassB{
}
}
7.内部类的编译:
2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
3.方便编写事件驱动程序及线程的编码