A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 吴琼 中级黑马   /  2012-6-18 22:15  /  7453 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 吴琼 于 2012-6-24 09:58 编辑

为什么内部类里面不能定义静态的?是内存加载的问题么?能解释下内部类与静态内存是怎么加载的么?

评分

参与人数 1技术分 +1 收起 理由
wangfayin + 1 神马都是浮云

查看全部评分

10 个回复

倒序浏览
类中的数据成员声明为static时,该类的所有实例共享同一成员,与通常C 函数中静态变量很相似。静态数据成员在连接时分配到一块固定的内存区域,象全局变量一样,不过,只有与类名及作用域分辨符连用时,该标识符才处于作用域中。数据成员一般用相同的存储类分配内存。如果一对象声明为auto,其所有数据都是auto类型的;静态对象则有静态数据成员。静态数据成员是一个例外:产生具有静态成员的对象时,静态成员并不分配内存,因为这样将会导致出现static多版本。声明或初始化static变量时,表示法与全局对象十分相似,如下例:

  例  具有静态数据成员的类

class Example
{
  static int value;//声明静态成员,也就是类变量
  int id;        //此为实例变量
}

一数据成员声明为static后,连接器仅为该成员分配一次内存,而且仅在该成员变量被定义之后。还可以在定义static 时同时将其初始化。

看到这,我想你大概应该明白静态是什么概念了,静态变量和静态方法属于类变量和类方法,内部类是指在一个类中申明另一个类,一个类把内部类当做自己的成员,内部类的类体和方法不可以声明类变量和类方法,而 static 无论是数据还是方法均为类所调用,所以内部类里面不能定义静态的。

现在再来说加载的问题,在java程序运行的时候,类的字节码文件会被加载到内存中,如果该类没有创建对象,类的实例变量不会被分配内存,但是,在类被加载到内存中是,类中的类变量就被分配了内存空间,如果该类创建对象,那么不同对象的实例变量互不相同,即分配不同的内存空间,而类变量不再重新分配内存空间,所有的对象共享类变量,类变量的内存空间直到程序退出运行才会释放所占有的内存。
回复 使用道具 举报
非静态内部类不能有静态成员:

对于java类加载顺序我们知道,首先加载类,执行static变量初始化,接下来执行对象的创建,如果我们要执行代码中的变量i初始化,
那么必须先执行加载OuterClass,再加载Innerclass,最后初始化静态变量i,问题就出在加载Innerclass上面,我们可以把InnerClass看成OuterClass的非静态成员,它的初始化必须在外部类对象创建后以后进行,要加载InnerClass必须在实例化OuterClass之后完成 ,java虚拟机要求所有的静态变量必须在对象创建之前完成,这样便产生了矛盾。

静态内部类可以有静态成员:

我们可以把静态内部类作为外部类OuterClass的一个静态成员,在执行类加载过程中,静态内部类在加载OuterClass后会进行初始化,同样的原理,静态内部类的静态成员也将被初始化,进行内存的分配,注意到,这时无论是内部类还是外部类,对象都没有实例化,这也说明了非静态内部类为什么不能有静态成员的原因。

评分

参与人数 1技术分 +1 收起 理由
wangfayin + 1 赞一个!

查看全部评分

回复 使用道具 举报
首先,被static关键字修饰的成员和方法都是先于对象在内存中存在的, 如果你没有对象你怎么去调用它?
然后,内部类必须要实例化外部类才能使用它,这个时候外部类就需要被实例化,它不是默认加载到内存里面的,是你手动实例化以后才加到内存里面的。
   静态的都是默认优先对象加载到内存中的静态方法区的.  这个时候,  你是不是觉得如果内部类是静态的就和下面这句话相违背了?

java人都知道的规矩:静态修饰的属性优先于对象存在,随着类的加载而加载,生命周期长
回复 使用道具 举报
静态的对象,在内存中是默认实例化的,在加载的时候就会存放到内存中。也就是可以直接调用而不需要手动实例化。首先内部的静态类他是不能直接被实例化的。你必须实例化外部类才能实例化它。而外部类不是默认加载的,他只有在手动实例化之后才有内存分配。


回复 使用道具 举报
本帖最后由 陆强强 于 2012-6-19 08:13 编辑

静态下的内部类:当内部类在成员位置上时就可以被成员修饰符所修饰,被static修饰的内部类就叫静态内部类。

              |----当内部类成员被static修饰时,该内部类必须是静态;
              |----当内部类是静态时只能访问外部类的静态成员,可以直接访问内部类自己的非静态成员

静态是随类的加载而加载,所以内部类定义静态也是有条件的,必须在成员位置上,不然当在方法内部时,方法不是静态,而内部类是静态这就会残生加载冲突

评分

参与人数 1技术分 +1 收起 理由
wangfayin + 1 赞一个!

查看全部评分

回复 使用道具 举报
其实有种情况内部类里面也可以定义静态的,当内部类定义在成员位置上时,就可以被成员修饰符修饰,比如static,
这时内部类里面就可以定义static的变量,但是内部类有了static的特性,只能直接访问外部类中static成员,出现了访问局限性。
例:class Without
{
        static private int x = 10;
        static class Inside //静态内部类
        {
                void funcation()
                {
                        System.out.println(x);

                }
                static  String a = "hello";

        }
}
class DemoText
{
        public static void main(String[] args)
        {
                System.out.println((Without.Inside.a));
                new Without.Inside().funcation();
        }
}
分析:变量x是静态的,跟着类的加载而直接存在在内存中,可以直接显示,即不用建立外部类对象。而funcation这个方法是非静态的,要调用此方法,就需要新建个内部类对象,再用内部类对象来调用此方法:new Without.Inside().funcation();
在外部其他类中,如何直接访问静态内部类的静态成员呢?
如果funcation这个方法是静态的,访问格式为:Without.Inside().funcation();
注意:当内部类中定义了静态成员,该内部类也必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。

内部类定义在局部时:1、不可以被成员修饰符修饰。2、可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。
例:
class Outside
{
        private int x = 6;
        void show(final int a)
        {
                final int y =12;
                class Inside
                {
                        void funcation()
                        {
                                System.out.println("x="+x);
                                System.out.println("y="+y);
                                System.out.println("a="+a);
                        }
                }
                new Inside().funcation();
        }
       
}
class DemoText
{
        public static void main(String[] args)
        {
                 Outside out = new Outside();
                 out.show(2);
                 out.show(3);

        }
}

点评

赞一个!  发表于 2012-7-26 00:01

评分

参与人数 1技术分 +1 收起 理由
wangfayin + 1 赞一个!

查看全部评分

回复 使用道具 举报
刘笑 中级黑马 2012-6-19 10:26:09
8#
静态的对象,在内存中实默认实例化的,在加载的时候就会存放到内存中。也就是可以直接调用而不需要手动实例化。
内部的静态类他是不能直接被实例化的。你必须实例化外部类才能实例化它。而外部类不是默认加载的,他只有在手动实例化之后才有内存分配。
两者冲突,故内部类里不能定义静态的属性和方法。正是由于内存分配的原因才导致的。楼主明白了?
回复 使用道具 举报
李文龙 发表于 2012-6-18 22:35
类中的数据成员声明为static时,该类的所有实例共享同一成员,与通常C 函数中静态变量很相似。静态数据成员 ...
静态变量和静态方法属于类变量和类方法,内部类是指在一个类中申明另一个类,一个类把内部类当做自己的成员,内部类的类体和方法不可以声明类变量和类方法,而 static 无论是数据还是方法均为类所调用,所以内部类里面不能定义静态的。
内部类可以是静态的吧
回复 使用道具 举报
这个也是看到单例的实现遇到的问题,
public class Singleton {   
    private Singleton() {}   
  
    private static final class  Holder {   
        static final Singleton instance = new Singleton();   
    }   
  
    public static Singleton getInstance() {   
        return Holder.instance;   
    }   
}
回复 使用道具 举报
刘笑 发表于 2012-6-19 10:26
静态的对象,在内存中实默认实例化的,在加载的时候就会存放到内存中。也就是可以直接调用而不需要手动实例 ...

这个解释有点误导
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马