Java内部类

在一个类的内部定义的类称为内部类。
1、内部类的基本语法
这里写图片描述
顶层类只能处于public和默认访问级别,而内部类可以是public,protected,默认,private这四种访问级别。

package visitcontrol;

public class Outer {
    public class Inner {
        public int add(int a, int b) {
            return (a + b);
        }
    }

    Inner inner = new Inner();

    public int add(int a, int b, int c) {

        return inner.add(inner.add(a, b), c);

    }
}
public class Tester {

    public static void main(String[] args) {

        Outer outer = new Outer();
        System.out.println(outer.add(1, 2, 3));
        Outer.Inner inner = new Outer().new Inner();
        System.out.println(inner.add(1, 2));

    }

}

输出结果:
6
3
1.1、实例内部类
实例内部类具有以下特点:
●在创建实例内部类的实例时,外部类的实例必须已经存在。
Outer.Inner inner=new Outer.new Inner();
等价于:
Outer outer=new Outer();
Outer.Inner inner=outer.new Inner();
●实例内部类的实例自动持有外部类的实例的引用。在内部类中可以直接访问外部类的所有成员。

package outerref;

public class A {
    public int a1;
    protected int a2;
    static int a3;

    public A(int a1, int a2) {

        this.a1 = a1;
        this.a2 = a2;
    }

    protected int method() {
        return a1 * a2;
    }

    class B {
        int b1 = a1;
        int b2 = a2;
        int b3 = a3;
        int b4 = new A(3, 4).a1;
        int b5 = method();
    }

    public static void main(String[] args) {
        A.B b = new A(1, 2).new B();
        System.out.println("b.b1=" + b.b1);
        System.out.println("b.b2=" + b.b2);
        System.out.println("b.b3=" + b.b3);
        System.out.println("b.b4=" + b.b4);
        System.out.println("b.b5=" + b.b5);
    }

}

输出结果:
b.b1=1
b.b2=2
b.b3=0
b.b4=3
b.b5=2
●外部类实例与内部类实例之间是一对多的关系,一个内部类实例只会引用一个外部类实例,而一个外部类实例对应零个或多个外部类实例。在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问。
●在实例内部类中不能定义静态成员,而只能定义实例成员。
●如果实例内部类B与外部类A包含同名的成员(比如成员变量v),那么在类B中,this.v表示类B的成员,A.this.v表示类A的成员。

package differnames;

public class A {
    int v = 1;

    public class B {
        int v = 2;

        public void test() {
            System.out.println("v=" + v);
            System.out.println("this.v=" + this.v);
            System.out.println("A.this.v=" + A.this.v);
        }
    }

    public static void main(String[] args) {
        new A().new B().test();

    }

}

输出结果:
v=2
this.v=2
A.this.v=1
1.1.2、静态内部类
静态内部类具有以下特点:
●静态内部类的实例不会自动持有外部类的特定实例的引用,在创建外部类的实例时,不用创建外部类的实例。

public class A{
public static class B{
int v;
}
}
class Tester{
public void test(){
A.B b=new A.B();
b.v=1;
}
}

●静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例来访问。
●在静态内部类中可以定义静态成员和实例成员。
●客户类可以通过完整的类名直接访问静态内部类的静态成员。
1.1.3、局部内部类
局部内部类是在一个方法中定义的内部类,它的可见范围是当前方法,和局部变量一样,局部内部类不能用访问控制符修饰(public ,private,protected)及static修饰符修饰。局部内部类具有以下特点:
●局部内部类只能在当前方法中使用
●局部内部类和实例内部类一样,不能包含静态成员。
●在局部内部类中定义的内部类也不能被public,protected和private这些控制修饰符修饰。
●局部内部类和实例内部类一样,可以访问外部类的所有成员,此外局部内部类还可以访问所在方法中的final类型的参数和变量。
2、内部类的继承

package inherit;

public class Outer {
    public int a ;//外部类的实例变量

    public Outer(int a) {

        this.a = a;
    }

    public class Inner {
        public Inner() {
        };

        public void print() {
            System.out.println("a=" + a);// 访问外部类的实例变量
        }
    }

}

public class Sample extends Outer.Inner {
    public Sample(Outer o) {
        o.super();
    }

    public static void main(String[] args) {
        Outer outer1 = new Outer(1);
        Outer outer2 = new Outer(2);
        Outer.Inner in = outer1.new Inner();
        in.print();
        Sample sample1 = new Sample(outer1);
        Sample sample2 = new Sample(outer2);
        sample1.print();
        sample2.print();
    }

}

输出结果:
a=1
a=1
a=2
3、子类与父类中的内部类同名

package nooverride;

public class Outer {
    Inner in;

    public Outer() {
        in = new Inner();
    };

    public class Inner {
        public Inner() {
            System.out.println("Inner of Outer");
        }
    }
}

public class SubOuter extends Outer {
    public class Inner {
        public Inner() {
            System.out.println("Inner of SubOuter");
        };

    }

    public static void main(String[] args) {
        SubOuter.Inner subin = new SubOuter().new Inner();
        Outer.Inner in = new Outer().new Inner();


    }

}

输出结果:
Inner of Outer
Inner of SubOuter
Inner of Outer
Inner of Outer
4、匿名类

package noname;

public class A {
    public A(int v) {
        System.out.println("another constructor");
    }

    public A() {
        System.out.println("default constructor");
    }

    void method() {
        System.out.println("from A");
    }

    public static void main(String[] args) {
        new A().method();
        // 定义了一个继承类A的匿名类
        A a = new A() {
            void method() {
                System.out.println("from anonymous");
            }
        };
        a.method();
    }

}

输出结果:
default constructor
from A
default constructor
from anonymous

匿名类的特点:
●匿名类本身没有构造方法,但是会调用父类的构造方法
●匿名类虽然没有构造方法,但是可以在匿名类中提供一段实例初始化代码,Java虚拟机会在调用了父类的构造方法后执行这段代码。实例化初始化代码不允许被重载,匿名类的实例只能有一种初始化方式。

public static void main(String[] args) {
        int v=1;
        // 定义了一个继承类A的匿名类
        A a = new A(v) {
        {System.out.println("initialize instance");}
            void method() {
                System.out.println("from anonymous");
            }
        };
        a.method();
    }

输出结果:
another constructor
initialize instance
from anonymous
●除了可以在外部类的方法内定义匿名类外,还可以在声明一个成员变量时定义匿名类
●匿名类除了可以继承之外,还可以实现接口
●匿名类和局部内部类一样,可以访问外部类的所有成员,如果匿名类位于一个方法中,还能访问所在方法的final类型的参数和变量。
●局部内部类的名字在方法外是不可见的,因此和匿名类一样,可以起到封装类型名字的作用。局部内部类与匿名类的区别:
①匿名类的程序代码比较简洁
②一个局部内部类可以有多个重载的构造方法,并且客户类可以多次创建局部内部类的实例。而匿名类没有重载构造方法,并且只能创建一次实例。
5、内部接口及接口中的内部类
6、内部类的用途
①封装类型
②直接访问外部类的成员
③回调外部类的方法
。。。未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值