java内部类.docx
《java内部类.docx》由会员分享,可在线阅读,更多相关《java内部类.docx(22页珍藏版)》请在冰豆网上搜索。
java内部类
内部类概述
内部类是编译期状态!
编译器知道,虚拟机不知道,在虚拟机处,会成为正常的类,反编译代码会失败,甚至不好还原
JVM和昨天的我一样,不知道什么叫内部类!
1 什么是内部类
把一个类定义在另一个类之内,就是内部类。
例如把B类定义在A类之内,那么我们称A类为外部类,而B类为内部类。
2 成员内部类
内部类是外部类的成员!
即被外部类类体直接包含。
classA{
classB{}
}
3 一般内部类都是私有的
可以对成员内部类使用任何访问修饰符(4种都可以修饰)
非内部类能使用public或者默认。
publicclassTest{
publicinta=10;
publicstaticvoidmain(Stringargs[]){
Testt=newTest();
t.test();
}
publicvoidtest(){
Aa=newAImpl();
Demo.func(a);
}
//不会被其他类使用,只有Test类会只用
//这个类只在外部类的范围内可见
//成员内部类通常会被修饰为private
//好处:
隐藏代码
//成员内部类,可以使用外部类的成员(不需要对象的引用,直接使用)
privateclassAImplimplementsA{
publicvoidfun1(){
syso(a);//外部类,不能使用访问内部类的内容
}
}
}
classDemo{
publicstaticvoidfun(Aa){
a.fun1();
}
}
interfaceA{
voidfunc1();
}
4 内部类访问外部类成员
内部类中可以直接方法外部类的成员(属性和方法),包含私有成员!
interfaceA{
voidfunc1();
}
classDemo{
publicstaticvoidfun(Aa){
a.fun1();
}
}
publicclassTest{
publicinta=10;//private
publicstaticvoidmain(Stringargs[]){
Testt=newTest();
t.test();
}
publicvoidtest(){
Aa=newAImpl();
Demo.func(a);
}
privateclassAImplimplementsA{
publicvoidfun1(){
System.out.println(a);//外部类,不能使用访问内部类的内容
}
}
}
5 外部类中使用创建内部类对象
外部类不能直接访问内部类成员
外部类的特权可以创建内部类对象。
因为通常成员内部类都是private的。
比较多见的信箱
6 内部类拥有外部类对象(与继承相似)
为什么是内部类中可以访问外部类成员呢?
原因:
是内部类对象有一个外部类对象。
可以理解与继承相同!
7 内部类的class文件
成员内部类的class文件:
外部类名$内部类名.class
8 非static内部类不能拥有static的属性和方法
成员内部类中不能有static的属性和方法,不然编译失败!
publicclassTest2{
privateinti=10;
publicvoidfun(){
System.out.println("你好");
}
publicstaticvoidmain(String[]args){
//Innerinner=newInner();
}
privateclassInner{
publicvoidinnerFun(){
System.out.println(i);
fun();
}
}
}
9 成员内部类限制
publicclassTest2{
publicstaticvoidmain(String[]args){
/**
*无法在上下文中使用静态变量this
*外部类只能在构造器或者实例方法中创建内部类对象
*但是,给类加static就可以以下列的方式创建对象了
*/
Innerinner=newInner();
}
privatestaticclassInner{
}
}
publicclassTest{
publicstaticvoidmain(String[]args){
//外部类只能在构造器或者实例方法中创建内部类对象。
Innerinner=newInner();
}
privateclassInner{
}
}
无法从静态上下文中引用非静态变量this、或者给类加static
在静态方法中,不能访问实例(非静态)成员!
就好比静态方法中不能访问实例属性、实例方法一样,也不能访问成员内部类一样。
范例:
publicclassTest2{
privateinti=10;
publicvoidfun(){
System.out.println("你好");
}
publicstaticvoidmain(String[]args){
//Innerinner=newInner();
}
privateclassInner{
publicstaticinta=10;
publicvoidinnerFun(){
System.out.println(i);
fun();
}
}
}
小结
●成员内部类定义在外部类的类体中,被外部类直接包含;
●成员内部类可以使用任意访问修饰符;
●成员内部类如果是private修饰的,那么只在外部类范围之内可见;
●成员内部类中可以直接访问外部类其他成员。
●成员内部类中不能定义static属性或方法;
●外部类的静态方法中不能创建成员内部类对象。
好处:
隐藏代码
与继承相似
局部内部类(很少用)
把语法了解了,也就可以了。
1 方法内部的类是局部内部类
把一个类定义在方法(构造器)中。
classOuter{
voidfun(){
classInner{}
}
}
1 局部内部类不能使用访问修饰符!
2 局部内部类只在定义的方法内可见,而且是在内部类定义的下面才能可见!
3.在相同方法内,只能定义一个局部内部类,不能有同名情况出现
publicclassTest3{
publicvoidfun(){
classInner{
}
newInner();
}
publicvoidfun1(){
classInner{
}
}
}
2 局部内部类还可以访问所在的局部中所有局部变量
局部内部类可以访问局部变量(包含形参),但有一个要求:
局部变量必须是final的。
publicclassTest3{
publicvoidfun(finalintn){
finalinta=10;
classInner{
publicvoidfunfun(){
System.out.println(a);
}
}
newInner();
}
publicvoidfun1(){
classInner{
}
}
}
3 局部内部类不能使用访问修饰符和静态修饰符
局部内部类与局部变量相似,都不能使用修饰符来修饰。
4 局部内部类只在局部可见
局部内部类只在定义处,到包含它的块结束。
5 局部内部类的class文件
外部类名$局部编号内部类名
6 多次调用局部方法,只会创建一个局部内部类
类在编译时已经生成了.class文件,在运行时已经没有内部类一说,与正常类没有区别了
那么局部内部类,和其他的区别:
1.局部内部类的可见度(存在范围),只在当前方法中存在,与局部变量一样
2.局部内部类,与成员内部类一样,可以访问外部类的属性,和外部类的方法
3.可以使用final的局部变量
4.
同样的,
7 局部内部类不能拥有静态的属性和方法
这一点与成员内部类一样。
8 小结
●局部内部类只在局部内可以!
而且还是在定义之后才可见!
●可以访问外部类的成员(所有属性和所有方法),其实成员内部类也有这个特性。
●局部内部类可以访问局部变量,但要求被访问的局部变量必须是final的。
●局部内部类不能定义static成员。
其实成员内部类也有这个特性。
局部匿名内部类
匿名内部类都是局部的,在局部内部类中,演变的一种新形式
局部匿名内部类没有名字。
一个类如果没有名字,它的构造器是什么样子的?
-------不知道构造器,能创建对象么?
创建一个类,我们的目的是什么?
不就是使用它的对象么?
1 匿名内部类的语法
创建类的同时还要创建对象,而且只能创建这一个对象!
用什么引用指向它呢?
所以匿名类在创建时要么指定一个父类,要么指定一个实现的接口。
这时就可以使用父类或实现的接口的引用来指向它。
newA(){}
上面的语句:
创建了一个A类的子类对象,这个子类没有名字。
其中大括号内容就是这个子类的类体!
范例:
publicclassTest4{
publicstaticvoidmain(String[]args){
AbA=newAb();
}
}
classAb{}
publicclassTest4{
publicstaticvoidmain(String[]args){
AbA=newAb(){};
}
}
classAb{}
publicclassTest4{
publicstaticvoidmain(String[]args){
Aba=newAb(){
publicvoidfun(){
System.out.println("你好!
");
}
};
a.fun();//出错,调用方法受到引用类型的限制
}
}
classAb{}
publicclassTest4{
publicstaticvoidmain(String[]args){
Aba=newAb(){
publicvoidfun(){
System.out.println("你好!
");
}
};
a.fun();//出错,调用方法受到引用类型的限制
}
}
classAb{publicvoidfun(){}}
publicclassTest4{
publicstaticvoidmain(String[]args){
Aba=newAb(){
publicvoidfun(){
System.out.println("你好!
");
}
};
a.fun();//出错,调用方法受到引用类型的限制
Bb=newB(){};//实现了B接口的子类,但是类没有名字
}
}
classAb{
publicvoidfun(){
}
}
interfaceB{
}
publicclassTest4{
publicstaticvoidmain(String[]args){
Aba=newAb(){
publicvoidfun(){
System.out.println("你好!
");
}
};
a.fun();//出错,调用方法受到引用类型的限制
Bb=newB(){};//实现了B接口的子类,但是类没有名字
//此时编译不通过,因为没有实现接口中的方法
}
}
classAb{
publicvoidfun(){
}
}
interfaceB{
voidfun1();
voidfun2();
}
publicclassTest4{
publicstaticvoidmain(String[]args){
Aba=newAb(){
publicvoidfun(){
System.out.println("你好!
");
}
};
a.fun();//出错,调用方法受到引用类型的限制
Bb=newB(){
publicvoidfun1(){
System.out.println("B...fun1()");
}
publicvoidfun2(){
System.out.println("B...fun2()");
}
};//实现了B接口的子类,但是类没有名字
b.fun1();
b.fun2();
}
}
classAb{
publicvoidfun(){
}
}
interfaceB{
voidfun1();
voidfun2();
}
范例:
用匿名内部类的方式,实现下列接口,在实现类中使用循环,打印1-10的数字
publicclassTest5{
publicstaticvoidmain(String[]args){
Runr=newRun(){
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println(i);
}
}
};
r.run();
}
}
interfaceRun{
voidrun();
}
publicclassTest5{
publicstaticvoidmain(String[]args){
newRun(){
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println(i);
}
}
}.run();
}
}
interfaceRun{
voidrun();
}
2 匿名内部类只能使用一次
匿名内部类只能使用一次(创建对象),因为它没有名字,不能再次创建对象。
匿名内部类是把一个类定义在一个new语句中。
new假构造器名(){匿名类的类体}
假构造器:
就是匿名类的父类名,或者是匿名类的所实现的接口类。
3 匿名内部类必须指定父类或者指定实现的接口
匿名内部类要么指定一个父类,要么指定一个实现的接口。
两者必须选择其一,而且只能选择其一。
4 匿名内部类不能同时继承和实现
匿名内部类要么指定一个父类,要么指定一个实现的接口。
两者必须选择其一,而且只能选择其一。
5 匿名内部类最多实现一个接口
匿名内部类要么指定一个父类,要么指定一个实现的接口。
两者必须选择其一,而且只能选择其一。
6 匿名内部类的实例块
匿名类的构造代码块可以用来做为匿名类的构造器来用。
publicclassTest5{
publicstaticvoidmain(String[]args){
newRun(){
{
System.out.println("构造方法");
}
publicvoidrun(){
for(inti=0;i<=10;i++){
System.out.println(i);
}
}
}.run();
}
}
interfaceRun{
voidrun();
}
publicclassTest5{
publicstaticvoidmain(String[]args){
Aa=newA(20);
A.Bab=newA(10).newB();
}
}
classA{
publicA(intn){}
publicclassB{}
}
publicclassTest5{
publicstaticvoidmain(String[]args){
Aa=newA(20);
//A.B叫做对象引用名
A.Bab=newA(10).newB();
Aaa=newA(100);
A.Bab=aa.newB();//对象.new的语法
}
}
classA{
publicA(intn){
newB();//=this.newB();平时写代码的时候会省略掉的内容
}
publicclassBextendsC{//C,是D的内部类
}
}
classD{
publicclassC{
}
}
小结
如何在内部类中引用外部类?
使用时的3种情况:
什么都不写:
在内部类查找,找不到再去外部类中找。
this:
只在内部类中查找
外部类引用.this:
只在外部类查找
classOuter{
publicvoidfun(){
System.out.println("Outer");
}
classInner{
publicvoidfun(){
System.out.println("Inner");
}
publicvoidtest(){
//内部,外部,都有一个fun方法,此时fun使用的是哪个方法
fun();
}
}
publicvoidtest(){//方法不能是static类型的
Innerinner=this.newInner();//可以省略不写的
inner.test();
}
}
publicclassTest6{
publicstaticvoidmain(String[]args){
Outero=newOuter();
o.test();
}
}
classOuter{
publicvoidfun(){
System.out.println("Outer");
}
classInner{
publicvoidfun(){
System.out.println("Inner");
}
publicvoidtest(){
//fun();
this.fun();
}
}
publicvoidtest(){
Innerinner=newInner();
inner.test();
}
}
publicclassTest6{
publicstaticvoidmain(String[]args){
Outero=newOuter();
o.test();
}
}
classOuter{
publicvoidfun(){
System.out.println("Outer");
}
classInner{
publicvoidfun(){
System.out.println("Inner");
}
publicvoidtest(){
Outer.this.fun();
//fun();
//this.fun();
}
}
publicvoidtest(){
Innerinner=newInner();
inner.test();
}
}
publicclassTest6{
publicstaticvoidmain(String[]args){
Outero=newOuter();
o.test();
}
}
嵌套类
也叫静态成员内部类
1 什么是嵌套类
成员内部类再加上static来修饰就是嵌套类。
2 嵌套类中不能访问外部类的实例内容
因为嵌套类是静态的,它与静态方法一样,都不能访问本类中实例的属性和实例的方法。
publicclassOuter{
privateinti=10;
publicstaticclassInner{
publicvoidfun(){
System.out.println(i);//无法从静态中打印非静态的内容
}
}
}
3 嵌套类基本与外部类没什么关系
嵌套类可以访问外部类的static成员。
其实正常类也可以访问另一个类的static成员,不过访问不了private的静态成员。
(谁访问静态成员都不需要对象来访问,所以嵌套类也没什么特权)。
唯一特权可以是访问外部类中private的静态成员。
4 接口中可以定义嵌套类--没道理的事情
接口中定义的类,默认是publicstatic。
也就是说定义在接口中的类都是嵌套类。
interfaceInterface{--怪异语法
publicstaticclassInner{}
}
5 嵌套类一般是public的
一般来说嵌套类与正常类基本没有太大的区别。
接口中必须死public的
6 外界使用嵌套类
外部类.内部类对象名=new外部类.内部类();
大家可以把这种方法理解为类名中包含了点,也就没有什么奇怪的了。
与使用正常样没有区别。
内部类的好处
1 隐藏代码
成员内部类、局部内部类、匿名类都可以把一个类隐藏起来,让外界不