Java静态内部类的作用

在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。由于静态的内部类在定义、使用的时候会有种种的限制。所以在实际工作中用到的并不多。

在开发过程中,内部类中使用的最多的还是非静态地成员内部类。不过在特定的情况下,静态内部类也能够发挥其独特的作用。

一、静态内部类的使用目的。

在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。不过由于种种的原因,如使用上的限制等等因素(具体的使用限制,笔者在下面的内容中会详细阐述),在实际工作中用的并不是很多。但是并不是说其没有价值。在某些特殊的情况下,少了这个静态内部类还真是不行。如在进行代码程序测试的时候,如果在每一个Java源文件中都设置一个主方法(主方法是某个应用程序的入口,必须具有),那么会出现很多额外的代码。而且最主要的时这段主程序的代码对于Java文件来说,只是一个形式,其本身并不需要这种主方法。但是少了这个主方法又是万万不行的。在这种情况下,就可以将主方法写入到静态内部类中,从而不用为每个Java源文件都设置一个类似的主方法。这对于代码测试是非常有用的。在一些中大型的应用程序开发中,则是一个常用的技术手段。为此,这个静态内部类虽然不怎么常用,但是程序开发人员还必须要掌握它。也许在某个关键的时刻,其还可以发挥巨大的作用也说不定。

下面的例子所示:

public class Student {
	//.......代码

}
public class Person{
     //姓名
     private String name;
     //家庭
     private Home home;
     //构造函数设置属性值
     public Person(String _name){
          name = _name;
     }
     /* home、name的getter/setter方法省略 */
 public void setHome(Home home){
	 this.home = home;
 }

 public Home getHome(){
	 return home;
 }

     public static class Home{
          //家庭地址
          private String address;
          //家庭电话
          private String tel;  

          public Home(String _address,String _tel){
            address = _address;
            tel = _tel;
          }
          /* address、tel的getter/setter方法省略 */ 

          public static void main(String[] args) {  
      	    Student student = new Student();
      	}
     }  

} 

二、静态内部类的使用限制。

将某个内部类定义为静态类,跟将其他类定义为静态类的方法基本相同,引用规则也基本一致。不过其细节方面仍然有很大的不同。具体来说,主要有如下几个地方要引起各位程序开发人员的注意。

一是静态成员(包括静态变量与静态成员)的定义。一般情况下,如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态成员变量与静态成员方法的。也就是说,在非静态内部类中不可以声明静态成员。如现在在一个student类中定义了一个内部类age,如果没有将这个类利用static关键字修饰,即没有定义为静态类,那么在这个内部类中如果要利用static关键字来修饰某个成员方法或者成员变量是不允许的。在编译的时候就通不过。故程序开发人员需要注意,只有将某个内部类修饰为静态类,然后才能够在这个类中定义静态的成员变量与成员方法。这是静态内部类都有的一个特性。也正是因为这个原因,有时候少了这个静态的内部类,很多工作就无法完成。或者说要绕一个大圈才能够实现某个用户的需求。这也是静态的内部类之所以要存在的一个重要原因。

二是在成员的引用上,有比较大的限制。一般的非静态内部类,可以随意的访问外部类中的成员变量与成员方法。即使这些成员方法被修饰为private(私有的成员变量或者方法),其非静态内部类都可以随意的访问。则是非静态内部类的特权。因为在其他类中是无法访问被定义为私有的成员变量或则方法。但是如果一个内部类被定义为静态的,那么在银用外部类的成员方法或则成员变量的时候,就会有诸多的限制。如不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法)。这是什么意思呢?如果在外部类中定义了两个变量,一个是非静态的变量,一个是静态的变量。那么在静态内部类中,无论在成员方法内部还是在其他地方,都只能够引用外部类中的静态的变量,而不能够访问非静态的变量。在静态内部类中,可以定义静态的方法(也只有在静态的内部类中可以定义静态的方法),在静态方法中引用外部类的成员。但是无论在内部类的什么地方引用,有一个共同点,即都只能够引用外部类中的静态成员方法或者成员变量。对于那些非静态的成员变量与成员方法,在静态内部类中是无法访问的。这就是静态内部类的最大使用限制。在普通的非静态内部类中是没有这个限制的。也正是这个原因,决定了静态内部类只应用在一些特定的场合。其应用范围远远没有像非静态的内部类那样广泛。

三是在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。

通常情况下,在一个类中创建成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。也就是说,在创建内部类之前要先在外部类中要利用new关键字来创建这个内部类的对象。如此的话如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。也就是说,普通非静态内部类的对象是依附在外部类对象之中的。但是,如果成员开发人员创建的时静态内部类,那么这就又另当别论了。通常情况下,程序员在定义静态内部类的时候,是不需要定义绑定在外部类的实例上的。也就是说,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,不需要其外部类的对象。具体为什么会这样,一般程序开发人员不需要了解这么深入,只需要记住有这个规则即可。在定义静态内部类的时候,千万不要犯画蛇添足的错误。

从以上的分析中可以看出,静态内部类与非静态的内部类还是有很大的不同的。一般程序开发人员可以这么理解,非晶态的内部类对象隐式地在外部类中保存了一个引用,指向创建它的外部类对象。 不管怎么理解,程序开发人员都需要牢记静态内部类与非静态内部类的差异。如是否可以创建静态的成员方法与成员变量(静态内部类可以创建静态的成员而非静态的内部类不可以)、对于访问外部类的成员的限制(静态内部类只可以访问外部类中的静态成员变量与成员方法而非静态的内部类即可以访问静态的也可以访问非静态的外部类成员方法与成员变量)。这两个差异是静态内部类与非静态外部类最大的差异,也是静态内部类之所以存在的原因。了解了这个差异之后,程序开发人员还需要知道,在什么情况下该使用静态内部类。如在程序测试的时候,为了避免在各个Java源文件中书写主方法的代码,可以将主方法写入到静态内部类中,以减少代码的书写量,让代码更加的简洁。

总之,静态内部类在Java语言中是一个很特殊的类,跟普通的静态类以及非静态的内部类都有很大的差异。作为程序开发人员,必须要知道他们之间的差异,并在实际工作中在合适的地方采用合适的类。不过总的来说,静态内部类的使用频率并不是很高。但是在有一些场合,如果没有这个内部静态类的话,可能会起到事倍功半的反面效果.

静态内部类和非静态内部类的区别:

package com.devin;

public class MyMain{
    private static String name = "woobo";
    private String num = "X001";

    // 静态内部类可以用public,protected,private修饰
    static class Person {
        // 静态内部类中可以定义静态或者非静态的成员
        private String address = "China";

        private static String x = "as";
        public String mail = "[email protected]";// 内部类公有成员

        public void display() {
            // System.out.println(num);//不能直接访问外部类的非静态成员

            // 静态内部类不能访问外部类的非静态成员(包括非静态变量和非静态方法)
            System.out.println(name);// 只能直接访问外部类的静态成员

            // 静态内部类只能访问外部类的静态成员(包括静态变量和静态方法)
            System.out.println("Inner " + address);// 访问本内部类成员。
        }
    }

    public void printInfo() {
        Person person = new Person();

        // 外部类访问内部类的非静态成员:实例化内部类即可
        person.display();

        // System.out.println(mail);//不可访问
        // System.out.println(address);//不可访问
        System.out.println(person.address);// 可以访问内部类的私有成员

        System.out.println(Person.x);// 外部类访问内部类的静态成员:内部类.静态成员
        System.out.println(person.mail);// 可以访问内部类的公有成员
    }

    public static void main(String[] args) {
        MyMain staticTest = new MyMain();
        staticTest.printInfo();
    }
}

1. 嵌套类的对象,并不需要其外围类的对象。 即它可以不依赖于外部类实例被实例化。

2. 不能从嵌套类的对象中访问非静态的外围类对象。 这是由Java语法中"静态方法不能直接访问非静态成员"所限定

3. 外部类访问内部类的的成员有些特别, 不能直接访问, 但可以通过内部类实例来访问, 这是因为静态嵌套内的所有成员和方法默认为静态的了.同时注意, 内部静态类Person只在类StaticTest 范围内可见, 若在其它类中引用或初始化, 均是错误的.

4 . 静态内部类可以有静态成员,而非静态内部类则不能有静态成员。

5. 静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类的非静态变量;

6 . 非静态内部类的非静态成员可以访问外部类的非静态变量。

生成一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成:Outer.Inner in = new Outer.Inner();而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类(正常情况下,你不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,因为它是static 的。只是将嵌套类置于接口的命名空间内,这并不违反接口的规则)

Java里面static一般用来修饰成员变量或函数。但有一种特殊用法是用static修饰内部类,普通类是不允许声明为静态的,只有内部类才可以。被static修饰的内部类可以直接作为一个普通类来使用,而不需实例一个外部类(见如下代码):

public class OuterClass {
	public static class InnerClass{
		InnerClass(){
			System.out.println("============= 我是一个内部类'InnerClass' =============");
		}
	}
}
public class TestStaticClass {
	public static void main(String[] args) {
		// 不需要new一个OutClass
		new OuterClass.InnerClass();
	}
}

如果没有用static修饰InterClass,则只能按如下方式调用:

package inner_class;

public class OuterClass {
	public class InnerClass{
		InnerClass(){
			System.out.println("============= 我是一个内部类'InnerClass' =============");
		}
	}
}
public class TestStaticClass {
	public static void main(String[] args) {
		// OutClass需要先生成一个实例
		OuterClass oc = new OuterClass();
		oc.new InnerClass();
	}
}

时间: 2024-10-28 13:46:18

Java静态内部类的作用的相关文章

Java静态内部类详解

从事Java开发的人对内部类相信不陌生.什么是内部类呢?定义在一个类内部的类就叫做内部类.比较常见的是非静态内部类,使用相当广泛.而其实静态内部类在某些情况下也有很大的用处,只是它在使用的时候会有一些限制,所以在软件开发中静态内部类不太常见.本文就详解下Java静态内部类使用的相关知识,以帮助大家了解它的意义和使用限制,更好的使用静态内部类. 一.静态内部类的使用目的 在定义内部类的时候,可以在其前面加上一个权限修饰符static.此时这个内部类就变为了静态内部类.不过由于种种的原因,如使用上的

java内部类的作用分析

提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就是在类中又定义了一个类(下文会看到,内部类可以在很多地方定义),而实际上并没有那么简单,乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的深入了解,你会发现Java的设计者在内部类身上的确是用心良苦.学会使用内部类,是掌握Java高级编程的一部分,它可以让你更优雅地

java 接口的作用和好处

1.java 接口的作用 http://blog.csdn.net/hack_bug/article/details/7634737 2.一位Java大牛的回答 很多JAVA初级程序员对于接口存在的意义很疑惑.不知道接口到底是有什么作用,为什么要定义接口. 好像定义接口是提前做了个多余的工作.下面我给大家总结了4点关于JAVA中接口存在的意义: 1.重要性:在Java语言中, abstract class 和interface 是支持抽象类定义的两种机制.正是由于这两种机制的存在,才赋予了Jav

Java序列化的作用

很多人都认为Java序列化的作用有以下两方面: 1) 把对象的字节序列永久地保存到硬盘上(通常存放在一个文件中): 2) 在网络上传送对象的字节序列. 可是我有一个疑问:第一个作用在什么情况会用到呢?第二个作用在什么情况会用到呢? 答: 归纳起来,就是把你的数据换个时间和/或换个地方,继续使用 换个时间,比如存盘 换个地方,比如网络传输 当然,实现"换个时间/地方用"的方式很多很多 正解...真正自己去序列化的还是比较少的,很多框架里面都做好了的..类似序列化功能的实现方式很多,不一定

java中static作用详解

static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. 只要这个类被加载,Java虚拟机就能根据类名在运行时数据区的方法区内定找到他们.因此,static对象可以在它的任何对象创建之前访问,无需引用任何对象. 用public修饰的static成员变量和成员方法本质是全局变量和全局方法,当声明它类

Java静态内部类

两种内部类 Java的内部类有两种,一种是静态内部类,另一种是普通内部类,普通内部类可以获得外部对象的引用, 所以在普通内部类能够访问外部对象的成员变量 ,也就能够使用外部类的资源,可以说普通内部类依赖 于外部类,普通内部类与外部类是共生共死的,创建普通内部类的对象之前,必须先创建外部类的对象. 创建普通内部类的代码如下: Outer o = new Outer(); Outer.Inner inner = o.new Inner(); Outer.Inner inner = new o.Inn

java 引用类型及作用

java 引用类型 0. 引言 Java 中一共有 4 种类型的引用 : StrongReference. SoftReference. WeakReference 以及 PhantomReference , 这 4 种类型的引用与 GC 有着密切的关系. 1. 强引用 (StrongReference) 普通的引用做法,如: String str = "hello"; 只要引用存在就不会被回收,除非手动置为null,或者超出范围,gc才会回收 2. 软引用 (SoftReferenc

Java移位运算符 “<<” 作用及详解

左移运算符(<<) 基本用法 将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0). 例:a = a << 2 将a的二进制位左移2位,右补0, 左移1位后a = a *2; 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2. 举例以及困惑 给出下面的程序,大家可以猜一猜结果是什么? public class MainClass { public static void main(String[] args) { long i = 1L <<

JAVA关键字及作用

Java关键字及其作用 一. 总览: 访问控制 private protected public 类,方法和变量修饰符 abstract class extends final implements interface native new static strictfp synchronized transient volatile 程序控制 break continue return do while if else for instanceof switch case default 异常