`
talentluke
  • 浏览: 604509 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java 内部类

 
阅读更多

Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类。内部类又分为:常规内部类、局部内部类、匿名内部类和静态嵌套类四种。我们内部类的知识在Android手机开发中经常用到。

一、常规内部类

所谓常规内部类,或者说内部类,指的就是除去后面三种之外的内部类(这算什么解释。。。)

先写一个最简单的内部类的例子,大家感觉一下:

1 public class Outer {
2     public class Inner{
3     }
4 }

编译一下,我们看到目录中出现了两个class文件,其中有一个文件名叫做Outer$Inner.class,带了一个$符号,这个特点让我们很容易的认出来这是内部类编译后的class文件。

K6DP_~XUH}@$_Y$ZEYMFE@T

再写一个稍微复杂一点的内部类:

01 public class Outer {   
02  
03     private int x=1;
04  
05     public Outer(){
06         System.out.println("Outer initial");
07     }
08  
09     public class Inner{
10  
11         public Inner(){
12             System.out.println("Inner initial");
13         }
14  
15         private int x=2;
16  
17         public  void add(){
18             int x=3;
19             System.out.println(x);
20             System.out.println(this.x);
21             System.out.println(Outer.this.x);
22         }
23  
24     }
25  
26     public static void main(String[] args){
27         Inner inner = new Outer().new Inner();
28         inner.add();
29     }
30 }

我们编译以后,运行一下看看:

 image

在上面的例子里我们可以清晰的看到:

  1. 内部类就像一个实例成员一样存在于外部类中。
  2. 内部类可以访问外部类的所有成员就想访问自己的成员一样没有限制。
  3. 内部类中的this指的是内部类的实例对象本身,如果要用外部类的实例对象就可以用类名.this的方式获得。
  4. 内部类对象中不能有静态成员,原因很简单,内部类的实例对象是外部类实例对象的一个成员。

下面我们再小结一下内部类的创建方法:

  1. 在外部类的内部,可以用 Inner inner = new Inner(); 方法直接创建
  2. 在外部类外部,必须先创建外部类实例,然后再创建内部类实例,除了上面 Inner inner = new Outer().new Inner()的写法以外,还有 Outer outer = new Outer(); Inner inner = outer.new Inner();的写法

 

二、局部内部类

我们也可以把类定义在方法内部,这时候我们称这个类叫局部内部类。

我们再看一个例子:

01 public class Outer {
02  
03     int x =1;
04     public void doSomething(){
05         final int y=2;
06         class Inner{
07             int x =3;
08             void print(){
09                 int x=4;
10                 System.out.println(x);
11                 System.out.println(this.x);
12                 System.out.println(Outer.this.x);
13                 System.out.println(y);
14             }
15         }
16         Inner inner = new Inner();
17         inner.print();
18     }
19  
20     public static void main(String[] args){
21         Outer outer = new Outer();
22         outer.doSomething();
23     }
24 }

运行程序,查看结果:

image

我们通过上面这里例子也可以看到下面几点:

  1. 局部内部类的地位和方法内的局部变量的位置类似,因此不能修饰局部变量的修饰符也不能修饰局部内部类,譬如public、private、protected、static、transient等
  2. 局部内部类只能在声明的方法内是可见的,因此定义局部内部类之后,想用的话就要在方法内直接实例化,记住这里顺序不能反了,一定是要先声明后使用,否则编译器会说找不到。
  3. 局部内部类不能访问定义它的方法内的局部变量,除非这个变量被定义为final 。

是不是有点不好理解?关于为什么用final修饰以后就可以用了,我打算专门在番外篇里专门写一篇博客给你讲清楚,先记住吧。

三、匿名内部类

当我们把内部类的定义和声明写到一起时,就不用给这个类起个类名而是直接使用了,这种形式的内部类根本就没有类名,因此我们叫它匿名内部类。

我们再看一个有趣的例子:

01 public class Dog {
02  
03     public interface Pet {
04  
05         public void beFriendly();
06         public void play();
07  
08     }
09  
10     public static void main(String[] args){
11  
12         Pet dog = new Pet(){
13             @Override
14             public void beFriendly() {
15                 System.out.println("蹭蹭你^_^");
16             }
17             @Override
18             public void play() {
19                 System.out.println("把飞盘叼给你,逼你把飞盘丢出去,然后它再捡回来让你继续扔,连续500次^_^");
20             }
21         };
22  
23         dog.beFriendly();
24         dog.play();
25  
26     }
27 }

编译和运行程序,查看结果:

image

竟然编译和运行都很正常,我们知道抽象类和接口肯定无法实例化的,因此刚才的例子肯定有点意思:

  1. 第一匿名内部类可以是个接口,这个没什么好奇怪的哈。
  2. 第12行到第21行是一个语句,就是定义了一个对象,因此21行大括号后面有个分号。
  3. 匿名内部类用 new Pet(){ … } 的方式把声明类的过程和创建类的实例的过程合二为一。
  4. 匿名内部类可以是某个类的继承子类也可以是某个接口的实现类。

好吧我们再看一个例子,方法参数内的匿名内部类

01 public class Dog {
02  
03     static abstract class Ball {
04         abstract String getName();
05     }
06  
07     void play(Ball b){
08         System.out.println(b.getName());
09     }
10  
11     public static void main(String[] args){
12         Dog dog = new Dog();
13  
14         dog.play(new Ball(){
15             @Override
16             String getName() {
17                 return "qiu qiu";
18             }});
19     }
20 }

编译和运行以后的截图我就不给你了,返回值就是“qiu qiu”。

从第14行到第18行是一句话,就是执行一个play方法,而这个方法的参数就由一个匿名内部类的实例来提供。

四、静态嵌套类

为了让你感觉舒服一些,我们也把最简单的内部类放在最后讲。

当一个内部类前面用static修饰时,我们称之为静态嵌套类或者说静态内部类。

上面的例子里其实我们已经看到过静态嵌套类了,下面我们再举一个例子:

01 public class Outer {
02  
03     static int x =1;
04  
05     static class Nest {
06  
07         void print(){
08             System.out.println("Nest "+x);
09         }
10     }
11  
12     public static void main(String[] args){
13         Outer.Nest nest = new Outer.Nest();
14         nest.print();
15     }
16 }

因为静态嵌套类和其他静态方法一样只能访问其它静态的成员,而不能访问实例成员。因此静态嵌套类和外部类(封装类)之间的联系就很少了,他们之间可能也就是命名空间上的一些关联。上面例子中你需要注意的就是静态嵌套类的声明方法 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();                  //调用其静态方法

 

 

java 静态内部类的使用

http://blog.csdn.net/xys_777/article/details/6755836

[java] view plaincopy
 
  1. package Chapter10;  
  2. public class StaticInternal {  
  3.     private static String name = "\"聂庆亮\"";  
  4.     public static void setStatic(String n) {        // 外部类的非静态方法  
  5.         System.out.println("[现在访问的是外部类的静态方法!]");  
  6.         name = n;  
  7.     }  
  8.     static class InnerClass_2 {            // 静态内部类开始  
  9.         String address, mail;        // 声明String类型变量  
  10.         long phoneNum;        // 声明long类型变量  
  11.         int qq;                // 声明int类型变量  
  12.         static void getStatic() {    // 静态内部类的静态方法  
  13.             System.out.println("[访问外部类的静态变量] name = " + name);  
  14.             setStatic("尹继平");     // 访问外部类的静态方法  
  15.         }  
  16.         // 静态内部类的非静态方法  
  17.         public void setString(String address, String mail) {  
  18.             System.out.println("1.静态内部类的带String型参数的非静态主法");  
  19.             this.address = address;  
  20.             this.mail = mail;  
  21.         }  
  22.         public void setInt(long phoneNum, int qq) {  
  23.             System.out.println("2.静态内部类的带int型参数的非静态主法!");  
  24.             this.phoneNum = phoneNum;  
  25.             this.qq = qq;  
  26.         }  
  27.     }                            // 静态内部类结束  
  28.     public void setValue() {             // 外部类访问静态内部类的静态成员:内部类.静态成员  
  29.         InnerClass_2.getStatic();         // 访问静态内部类的静态方法  
  30.         InnerClass_2 inner = new InnerClass_2();                 // 实例化对象  
  31.         inner.setString("北京昌平区沙河镇""yinjiping@sina.com");     // 访问静态内部类的非静态方法  
  32.         inner.setInt(89653310313557706);  
  33.         System.out.println("\n外部类访问静态内部类的结果如下:");  
  34.         System.out.println("姓名:" + this.name);  
  35.         System.out.println("住址:" + inner.address);  
  36.         System.out.println("联系电话" + inner.phoneNum);  
  37.         System.out.println("E-mail:" + inner.mail);  
  38.         System.out.println("QQ号码:" + inner.qq);  
  39.     }  
  40.     public static void main(String[] args) {                        // java程序主入口处  
  41.         StaticInternal sin = new StaticInternal();  
  42.         sin.setValue();                                         // 调用方法  
  43.     }  
  44. }  

Java内部类与静态内部类

http://hi.baidu.com/zhumulangma/item/bcd478c140427b2cef466532

定义在一个类内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明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. 也是最吸引人的原因,每个内部类都能独立地继承一个接口,而无论外部类是否已经继承了某个接口。因此,内部类使多重继承的解决方案变得更加完整。

分享到:
评论

相关推荐

    java内部类详解

    Java 内部类详解 Java 内部类是一种高级特性,允许在一个类的定义内部创建另一个类。这种设计模式提供了更灵活的代码组织方式,同时还可以实现特定的封装和访问控制。内部类主要分为四种类型:静态内部类、成员内部...

    Java内部类总结

    ### Java内部类总结 在Java编程语言中,内部类是一个重要的概念,它允许开发者在一个类的内部定义另一个类。这种特性极大地增强了代码的封装性和复用性,同时也为解决特定问题提供了灵活的方法。本文将围绕Java内部...

    java内部类的讲解

    ### Java内部类详解 #### 一、内部类的分类与概念 Java的内部类机制是其强大特性之一,它允许类作为另一个类的成员存在,从而增强了代码的封装性和复用性。根据定义和作用域的不同,Java内部类主要分为四类: 1. ...

    Java 内部类

    Java 内部类是Java语言特性中的一个重要组成部分,它允许我们在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现复杂逻辑和封装上具有很大的灵活性。下面我们将详细...

    浅谈Java内部类的四个应用场景

    ### Java内部类的应用场景 #### 场景一:当某个类除了它的外部类,不再被其他的类使用时 内部类的使用场景之一是当某个类仅需被其外部类使用时。这种情况下,将此类定义为内部类可以提高代码的封装性和可维护性。 ...

    java内部类使用例子

    Java内部类是Java语言提供的一种独特特性,它允许我们在一个类的定义内部定义另一个类。这种内部类可以是成员内部类、局部内部类、匿名内部类或静态内部类,每种都有其特定的用途和使用场景。在这个"java内部类使用...

    12.java内部类.zip

    12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类...

    java 内部类应用

    Java内部类是Java语言的一个特色特性,它允许我们在一个类的内部定义另一个类。这种设计模式在处理一些特定情况时非常有用,例如实现匿名回调、封装特定逻辑或创建与外部类有紧密关系的类。本篇文章将深入探讨Java...

    JAVA 内部类 PPT

    Java内部类是Java语言的一个独特特性,它允许我们在一个类的内部定义另一个类。这种设计提供了更高级别的封装和组织代码的方式。以下是关于内部类及其相关知识点的详细说明: 1. **内部类基本语法** - **实例内部...

    JAVA内部类总结

    ### JAVA内部类总结 在Java编程语言中,内部类(Inner Classes)是一种非常重要的特性,它允许我们在一个类的内部定义另一个类。这种结构不仅能够提高代码的组织性,还能帮助我们更好地处理类与类之间的关系。根据...

    java 内部类使用(内部匿名类)

    Java内部类是Java语言提供的一种独特机制,它允许在一个类的内部定义另一个类。这种设计模式使得代码结构更紧凑,可以更好地封装和隐藏实现细节,同时也增强了代码的复用性。内部类分为几种类型,包括成员内部类、...

    java内部类总结(含概念和实例)

    Java 内部类总结 Java 内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用 protected 和 private 修饰(而外部类只能使用 public 和缺省的包...

    java 内部类 局部内部类 匿名类 实例代码

    Java内部类是Java语言特性中一个独特而强大的部分,它允许在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现某些特定设计模式时非常有用。本篇文章将深入探讨Java中的...

    Java语法总结 - 内部类

    Java内部类详解 Java内部类是Java语言中的一种特殊类别,它是指定义在另外一个类内部的类。内部类可以访问外部类的所有成员变量和方法,包括私有的变量和方法。内部类可以分为四种:成员内部类、静态嵌套类、方法...

    Java内部类的四个应用场景

    谈Java内部类的四个应用场景

    java内部类使用总结

    Java内部类是Java语言中一个独特且强大的特性,它允许我们在一个类的内部定义另一个类。内部类提供了增强封装的能力,使得内部类可以被隐藏在外部类中,仅对外部类可见,从而增加了代码的隐私性和安全性。同时,内部...

    Java内部类的作用

    ### Java内部类的作用 #### 一、定义及概念 内部类,顾名思义,指的是一个定义在另一个类内部的类。这样的结构让内部类能够访问外部类的成员(包括私有成员),并且允许内部类拥有不同的访问级别,如`private`、`...

    Java内部类_动力节点Java学院整理

    Java内部类是Java语言的一个重要特性,它允许我们在一个类的内部定义另一个类。这种设计模式使得代码结构更加紧凑,同时也提供了更高级的封装和抽象。内部类主要有两种类型:成员内部类和局部内部类。 1. 成员内部...

Global site tag (gtag.js) - Google Analytics