http://android.yaohuiji.com/archives/3247html
本讲内容:内部类java
Java语言容许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。咱们内部类的知识在Android手机开发中常常用到。android
1、常规内部类ide
所谓常规内部类,或者说内部类,指的就是除去后面三种以外的内部类(这算什么解释。。。)oop
先写一个最简单的内部类的例子,你们感受一下:ui
编译一下,咱们看到目录中出现了两个class文件,其中有一个文件名叫作Outer$Inner.class,带了一个$符号,这个特色让咱们很容易的认出来这是内部类编译后的class文件。this

再写一个稍微复杂一点的内部类:spa
06 |
System.out.println( "Outer initial" ); |
12 |
System.out.println( "Inner initial" ); |
19 |
System.out.println(x); |
20 |
System.out.println( this .x); |
21 |
System.out.println(Outer. this .x); |
26 |
public static void main(String[] args){ |
27 |
Inner inner = new Outer(). new Inner(); |
咱们编译之后,运行一下看看:.net

在上面的例子里咱们能够清晰的看到:code
- 内部类就像一个实例成员同样存在于外部类中。
- 内部类能够访问外部类的全部成员就想访问本身的成员同样没有限制。
- 内部类中的this指的是内部类的实例对象自己,若是要用外部类的实例对象就能够用类名.this的方式得到。
- 内部类对象中不能有静态成员,缘由很简单,内部类的实例对象是外部类实例对象的一个成员。
下面咱们再小结一下内部类的建立方法:
- 在外部类的内部,能够用 Inner inner = new Inner(); 方法直接建立
- 在外部类外部,必须先建立外 部类实例,而后再建立内部类实例,除了上面 Inner inner = new Outer().new Inner()的写法之外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner();的写法
2、局部内部类
咱们也能够把类定义在方法内部,这时候咱们称这个类叫局部内部类。
咱们再看一个例子:
04 |
public void doSomething(){ |
10 |
System.out.println(x); |
11 |
System.out.println( this .x); |
12 |
System.out.println(Outer. this .x); |
13 |
System.out.println(y); |
16 |
Inner inner = new Inner(); |
20 |
public static void main(String[] args){ |
21 |
Outer outer = new Outer(); |
运行程序,查看结果:

咱们经过上面这里例子也能够看到下面几点:
- 局部内部类的地位和方法内的局部变量的位置相似,所以不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等
- 局部内部类只能在声明的方法内是可见的,所以定义局部内部类以后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,必定是要先声明后使用,不然编译器会说找不到。
- 局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。
是否是有点很差理解?关于为何用final修饰之后就能够用了,我打算专门在番外篇里专门写一篇博客给你讲清楚,先记住吧。
3、匿名内部类
当咱们把内部类的定义和声明写到一块儿时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,所以咱们叫它匿名内部类。
咱们再看一个有趣的例子:
03 |
public interface Pet { |
05 |
public void beFriendly(); |
10 |
public static void main(String[] args){ |
14 |
public void beFriendly() { |
15 |
System.out.println( "蹭蹭你^_^" ); |
19 |
System.out.println( "把飞盘叼给你,逼你把飞盘丢出去,而后它再捡回来让你继续扔,连续500次^_^" ); |
编译和运行程序,查看结果:
居然编译和运行都很正常,咱们知道抽象类和接口确定没法实例化的,所以刚才的例子确定有点意思:
- 第一匿名内部类能够是个接口,这个没什么好奇怪的哈。
- 第12行到第21行是一个语句,就是定义了一个对象,所以21行大括号后面有个分号。
- 匿名内部类用 new Pet(){ … } 的方式把声明类的过程和建立类的实例的过程合二为一。
- 匿名内部类能够是某个类的继承子类也能够是某个接口的实现类。
好吧咱们再看一个例子,方法参数内的匿名内部类:
03 |
static abstract class Ball { |
04 |
abstract String getName(); |
08 |
System.out.println(b.getName()); |
11 |
public static void main(String[] args){ |
编译和运行之后的截图我就不给你了,返回值就是“qiu qiu”。
从第14行到第18行是一句话,就是执行一个play方法,而这个方法的参数就由一个匿名内部类的实例来提供。
4、静态嵌套类
为了让你感受舒服一些,咱们也把最简单的内部类放在最后讲。
当一个内部类前面用static修饰时,咱们称之为静态嵌套类或者说静态内部类。
上面的例子里其实咱们已经看到过静态嵌套类了,下面咱们再举一个例子:
08 |
System.out.println( "Nest " +x); |
12 |
public static void main(String[] args){ |
13 |
Outer.Nest nest = new Outer.Nest(); |
由于静态嵌套类和其余静态方法同样只能访问其它静态的成员,而不能访问实例成员。所以静态嵌套类和外部类(封装类)之间的联系就不多了,他们之间可 能也就是命名空间上的一些关联。上面例子中你须要注意的就是静态嵌套类的声明方法 new Outer.Nest() 连续写了两个类名,以致于咱们都怀疑前面的Outer是个包名了,好在包名通常都小写的,要不还真分不清……
再强调一遍,内部类在Android中应用的很是多,理解和使用好显得蛮重要。好了,本讲就到这里。
如何应用Java的静态内部类
http://java.chinaitlab.com/oop/787330.html
在上一小节咱们讨论了内部类,即在一个类中包含有另一个或者多个类(见本书12.3.3小节)。与内部类类似,静态内部类指在一个类的内部包含有另一个或者多个静态类。例如:
public class OuterClass {
...
static class StaticInnerClass1 { //内部静态类
//只能够访问OuterClass的静态成员
...
} //StaticInnerClass结束
...
static class StaticInnerClassN { //更多静态内部类
//只能够访问OuterClass的静态成员
...
} //StaticInnerClassN结束
} //OuterClass结束
与通常内部类不一样,在静态代码中不可以使用this操做,因此在静态内部类中只能够访问外部类的静态变量和静态方法。使用静态内部类的目的和使用内部类相同。若是一个内部类不依赖于其外部类的实例变量,或与实例变量无关,则选择应用静态内部类。
以下例子演示怎样使用静态内部类:
///完整程序存在本书配套资源目录Ch12名为StaticInnerClassTest.java
public class StaticInnerClassTest {
public static void main( String args[] ) {
OuterClass2 outer = new OuterClass2();
OuterClass2.StaticInnerClass.innerMethod();
//调用静态内部类的静态方法
OuterClass2.outerMethod();
//建立静态内部类对象
OuterClass2.StaticInnerClass staticInner = new OuterClass2.StaticInnerClass();
int num = staticInner.innerMethod2(); //调用静态内部类实例方法
}
}
class OuterClass2 { //外部类
private double x = 0.0; //内部静态类不能够访问外部类实 例变量
static private int n = 10; //外部类静态变量
static void outerMethod() { //外部类静态方法
System.out.println("from OuterClass...");
}
void outerMethod2() {
System.out.println("from OuterClass’ instance method2()...");
}
static class StaticInnerClass { //静态内部类
static private int m = 5; //静态内部类静态变量
static void innerMethod() { //静态内部类静态方法
int sum;
n = 20; //只能够访问外部类静态变量
sum = n + m;
System.out.println("from InnerClass sum = " + sum);
outerMethod(); //只能够调用外部类静态方法
}
int innerMethod2() {
n = 100;
outerMethod();
System.out.println("from InnerMethod2() n = " + n);
return n;
}
} //静态内部类结束
} //外部类结束
如同不用建立对象就可调用静态方法同样,上例静态内部类中的静态方法利用:
OuterClass2.StaticInnerClass.innerMethod(); //静态内部类调用其静态方法
来调用。注意,能够在静态内部类的方法中,直接访问外部类的静态变量n和调用静态方法outerMethod()。但不容许访问外部类的实例变量x以及实例方法outerMethod2()。
静态内部类中也能够提供实例方法,如:
static class StaticInnerClass {
int innerMethod2() {
n = 100; //只可访问外部类静态变量
outerMethod(); //只可调用外部类静态方法
System.out.println("from InnerMethod2() n = " + n);
return n;
}
} //静态内部类结束
静态内部类的实例方法中亦只容许访问外部类的静态成员。
可使用下列语法格式建立一个静态内部类对象而且调用其实例方法,以及静态方法:
OuterClass2.StaticInnerClass staticInner = new OuterClass2.StaticInner Class(); //建立静态内部类对象
int num = staticInner.innerMethod2(); //调用实例方法
staticInner.innerMethod(); //调用其静态方法
- package Chapter10;
- public class StaticInternal {
- private static String name = "\"聂庆亮\"";
- public static void setStatic(String n) {
- System.out.println("[如今访问的是外部类的静态方法!]");
- name = n;
- }
- static class InnerClass_2 {
- String address, mail;
- long phoneNum;
- int qq;
- static void getStatic() {
- System.out.println("[访问外部类的静态变量] name = " + name);
- setStatic("尹继平");
- }
-
- public void setString(String address, String mail) {
- System.out.println("1.静态内部类的带String型参数的非静态主法");
- this.address = address;
- this.mail = mail;
- }
- public void setInt(long phoneNum, int qq) {
- System.out.println("2.静态内部类的带int型参数的非静态主法!");
- this.phoneNum = phoneNum;
- this.qq = qq;
- }
- }
- public void setValue() {
- InnerClass_2.getStatic();
- InnerClass_2 inner = new InnerClass_2();
- inner.setString("北京昌平区沙河镇", "yinjiping@sina.com");
- inner.setInt(89653310, 313557706);
- System.out.println("\n外部类访问静态内部类的结果以下:");
- System.out.println("姓名:" + this.name);
- System.out.println("住址:" + inner.address);
- System.out.println("联系电话" + inner.phoneNum);
- System.out.println("E-mail:" + inner.mail);
- System.out.println("QQ号码:" + inner.qq);
- }
- public static void main(String[] args) {
- StaticInternal sin = new StaticInternal();
- sin.setValue();
- }
- }
Java内部类与静态内部类
定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类能够声明public、protected、private等访问限制,能够声明 为abstract的供其余内部类或外部类继承与扩展,或者声明为static、final的,也能够实现特定的接口。外部类按常规的类访问方式使用内部 类,惟一的差异是外部类能够访问内部类的全部方法与属性,包括私有方法与属性。
(1)建立实例
OutClass.InnerClass obj = outClassInstance.new InnerClass(); //注意是外部类实例.new,内部类
AAA.StaticInner in = new AAA.StaticInner();//注意是外部类自己,静态内部类
(2)内部类中的this
内部类中的this与其余类同样是指的自己。建立内部类对象时,它会与创造它的外围对象有了某种联系,因而能访问外围类的全部成员,不需任何特殊条 件,可理解为内部类连接到外部类。 用外部类建立内部类对象时,此内部类对象会秘密的捕获一个指向外部类的引用,因而,能够经过这个引用来访问外围类的成员。
(3)外部类访问内部类
内部类相似外部类的属性,所以访问内部类对象时老是须要一个建立好的外部类对象。内部类对象经过‘外部类名.this.xxx’的形式访问外部类的属性与方法。如:
System.out.println("Print in inner Outer.index=" + pouter.this.index);
System.out.println("Print in inner Inner.index=" + this.index);
(4)内部类向上转型
内部类也能够和普通类同样拥有向上转型的特性。将内部类向上转型为基类型,尤为是接口时,内部类就有了用武之地。若是内部类是private的,只能够被它的外部类问,从而彻底隐藏实现的细节。
(5)方法内的类
方法内建立的类(注意方法中也能定义类),不能加访问修饰符。另外,方法内部的类也不是在调用方法时才会建立的,它们同样也被事先编译了。
(6)静态内部类
定义静态内部类:在定义内部类的时候,能够在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。
一般称为嵌套类,当内部类是static时,意味着:
[1]要建立嵌套类的对象,并不须要其外围类的对象;
[2]不能从嵌套类的对象中访问非静态的外围类对象(不可以从静态内部类的对象中访问外部类的非静态成员);
嵌套类与普通的内部类还有一个区别:普通内部类的字段的字段与方法,只能放在类的外部层次上,因此普通的内部类不能有static数据和 static字段,也不能包含嵌套类。可是在嵌套类里能够包含全部这些东西。也就是说,在非静态内部类中不能够声明静态成员,只有将某个内部类修饰为静态 类,而后才可以在这个类中定义静态的成员变量与成员方法。
另外,在建立静态内部类时不须要将静态内部类的实例绑定在外部类的实例上。普通非静态内部类的对象是依附在外部类对象之中的,要在一个外部类中定义 一个静态的内部类,不须要利用关键字new来建立内部类的实例。静态类和方法只属于类自己,并不属于该类的对象,更不属于其余外部类的对象。
(7)内部类标识符
每一个类会产生一个.class文件,文件名即为类名。一样,内部类也会产生这么一个.class文件,可是它的名称却不是内部类的类名,而是有着严格的限制:外围类的名字,加上$,再加上内部类名字。
(8)为什么要用内部类?
1. 内部类通常只为其外部类使用;
2. 内部类提供了某种进入外部类的窗户;
3. 也是最吸引人的缘由,每一个内部类都能独立地继承一个接口,而不管外部类是否已经继承了某个接口。所以,内部类使多重继承的解决方案变得更加完整。