JavaSE第八十五讲:内部类深度剖析及常见使用陷阱

来源:互联网 发布:零基础学算法豆瓣 编辑:程序博客网 时间:2024/05/06 16:32

   内部类在我们实际开发中用的不是特别多,但是在Swing中用的相对多点,看框架的内部类要读懂,特别是Android开发这块相对比较重要点,特别是匿名内部类。

1. 内部类(Inner Class),内部类共分为4种。

1)Group related classes and thus reduce namespace clutterdefined at a scope smaller than a package [将相关类的组织在一起,降低了命名空间的混乱,它是定义在小于包的范围内,我们通常定义类的范围是定义在包里。]
2) An inner class can be defined inside another class, inside a method, and even as part of an expression
3) There are four types of inner classes

(1)static inner classes (also called nested classes)
(2)member inner classes
(3)local inner classes
(4)anonymous inner classes

2.静态内部类(static inner class)

1)The simplest form of inner class
2) Can’t have the same name as the enclosing class
3) Compiled into a completely separate .class file from the outer class
4) Can access only static members and methods of the enclosing class, including private static members
5) Create an instance of a static inner class out of enclosing class:

(1) new outerclass.innerclass()

程序demo如下:

package com.ahuier.innerclass;class StaticInner{private static int a = 4;/* * 定义静态的内部类,必须是要class前面加static * 注意在外部类中是不可能加static的,也就是如果这个类用static修饰,则它一定是一个内部类 */public static class Inner{public void test(){/* * 注意这边静态内部类访问外部成员变量,必须是静态的成员变量 * 依旧以前所讲的:静态的只能访问静态,非静态的可以反问一切 */System.out.println(a);}}}public class StaticInnerClassTest {public static void main(String[] args) {/* * 竟然静态内部类是一个类,则它可以new出一个实例的,它也有自己的方法 * 注意new出一个实例写法:new StaticInner.Inner(); */StaticInner.Inner inner = new StaticInner.Inner();inner.test();}}

编译执行结果:

4

说明】:它会生成一个独立的.class文件,命名中间用$符号链接,如下图所示,从这边可以看出我们在定义类名的时候不要用$符号命名,这样会与内部类产生冲突。

静态内部类(static inner class):只能访问外部类的静态成员变量与静态方法,生成 静态内部类对象的方式为:    OuterClass.InnerClass inner = new OuterClass.InnerClass();

3.成员内部类(member inner class)[与静态内部类可以比喻成静态成员变量和成员变量]

1)Defined in an enclosing class without using the static modifier
2) Like instance variables
3) Can access all members of the enclosing class
4) Create an instance within the enclosing class

  this.newInnerclass();
5)Create an instance out of the enclosing class

   (new Outerclass()).new Innerclass();
6) Access members of the enclosing class within inner classes

   Outerclass.this.member

程序demo如下:

package com.ahuier.innerclass;class MemberInner{private int a = 4;/* * 定义一个成员内部类 */public class Inner2{private int a = 5;public void doSomething(){/* * 非静态变量可以访问一切,但是外部类的a是访问不到,只能访问到内部类的a * System.out.println(a);  *///访问外部类的成员变量System.out.println(MemberInner.this.a);}}public void method(){//在方法里面创建内部类的实例Inner2 inner = this.new Inner2();}}public class MemberInnerClassTest {public static void main(String[] args) {/* * 注意生成成员内部类实例方式 * 如果是静态内部类的话,则这个类是属于外部类本身的,这个类被外部类所有对象所共享,所以可以通过  外部类. 的方式访问 * 如果是非静态的内部类,则这个类是不属于外部类本身,而是外部类的每个对象自己都有维护,则必须通过  new出外部类对象后再去new它的内部类 * 类似于静态成员变量和成员变量访问机制的不同   */MemberInner.Inner2 inner = (new MemberInner()).new Inner2();inner.doSomething();}}

编译执行结果:

4

【说明】1. 成员内部类(member inner class):可以访问外部类的静态与非静态的方法与成员变量。生成成员内部类对象的方式为: 

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

2. 若想在局部内部类中访问外部类的成员变量,语法为:OuterClass.this.a; 


4.局部内部类(Local Inner Class)[用的比较少]

1)Defined within the scope of a method, even smaller blocks within methods
2) The least used form of inner class
3) Like local variables, can’t be declared public, protected, private and static
4) Can only access final local variables

程序demo:

package com.ahuier.innerclass;class LocalInner{public void doSomething(){//局部内部类引用的变量必须是用final修饰的final int a = 4;/* * 定义局部内部类 * 类比局部变量,局部变量只能被方法所用,方法用完则变量消失了 *  */class Inner3{public void test(){System.out.println(a);}}//只能在方法里面实例化这个内部类new Inner3().test();}}public class LocalInnerClassTest {public static void main(String[] args) {LocalInner test = new LocalInner();test.doSomething();}}

编译执行结果:

4

5.匿名内部类(Anonymous Inner Class)[很重要]

 
1)Local inner classes which don’t have class names
2) No key word class
3) No key word extends and implements
4) No constructors
5) Implicitly extend a superclass or implement an interface[匿名内部类会隐式地继承一个父类或实现一个接口](这一点是最重要的)

程序demo如下:

package com.ahuier.innerclass;import java.util.Date;public class AnonymousInnerClassTest {@SuppressWarnings("deprecation")public String get(Date date){return date.toLocaleString();}public static void main(String[] args) {AnonymousInnerClassTest test = new AnonymousInnerClassTest();/*通常的写法  String str = test.get(new Date());System.out.println(str);*//* * 使用内部类方式实现 * 表示定义了匿名内部类,同时继承了Date类 * new Date(){} 这个参数不是Date类的参数,这个参数传递的是继承了Date类的那个匿名内部类的实例。如果是接口就是实现了 */String str = test.get(new Date(){//在匿名内部类中重写了 Date()方法。@Override@Deprecatedpublic String toLocaleString() {return "hello world";}});System.out.println(str); }}
编译执行结果:

hello world

查看编译之后的.class文件如下图所示:

【说明】:从图中可以看出这边生成的.class文件中有一个带有$ 符号的就是匿名内部类产生的,由于匿名内部类没有名字,所以它生成的名字以$符号带数字1结尾,如果有两个则按这个方式顺序命名下去1,2,3...


原创粉丝点击