黑马程序员技术交流社区

标题: 内部类定义在局部时的疑问 [打印本页]

作者: 孙峰    时间: 2012-6-21 10:57
标题: 内部类定义在局部时的疑问
本帖最后由 孙峰 于 2012-6-21 13:12 编辑

       当内部类在一个成员位置上时,相当于一个成员,能别成员修饰符修饰,能访问外部类的成员。
     为什么当内部类定义在局部时就有些不能了呢? 这里定义成局部是不是意思 说该内部类放在一个方法中?     这时不可以被成员修饰符修饰, 不可以访问其所在局部中的局部变量。  
     但是该内部类在这个局部中和那些局部变量不是平等的关系吗?怎么就不能访问了呢? 也作为局部中的一个成员,怎么就不能被修饰呢?


  要是说 局部变量的数据是因为 随着 方法的存在而放在 栈 内存中,随方法消失而消失。 那调用该内部类不是肯定会加载这个方法的嘛。 那么这些局部变量不是也会存在。
作者: 崔云飞    时间: 2012-6-21 11:14
首先方法中定义内部类,是为了控制这个类的可见性,编译之后,也会出现外部类和内部类各自的字节码,他们有各自的成员变量和方法。
在内存中,类的属性会被分配到栈中的。当调用结束的时候就会退栈,也就是说在内存中这个属性就消失了。内部类也是类,只有在内存中对他的引用消失了内部类才会死亡。也就是说局部类的生命周期要比类的局部变量的生命周期要长。所以内部类不可能调用类中已经结束调用的属性。
解决:可以在方法中的变量前加final,当某一属性加此关键词后就成为常量了,而常量的生命周期为程序的整个执行期间
作者: 李元峰    时间: 2012-6-21 11:23
楼正说的对,当定义局部类的方法(带参数)结束的时候,内部类可能才刚开始运行,这时候他正准备使用 局部变量!
但是,这时候局部变量已经随着这个方法的结束而死去?这回出现什么不可预料的后果呢?所以编译器必须显示局部变量的类型,。
以保证,局部变量与在局部类建立的拷贝一致!
作者: 耿鑫    时间: 2012-6-21 11:25
本帖最后由 耿鑫 于 2012-6-21 11:51 编辑

下面就你说的问题做个总结:

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

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

    public static class Inner
    {
        public void test()
        {
            System.out.println(a);
        }
    }
}

public class StaticInnerClassTest
{
    public static void main(String[] args)
    {
        StaticInner.Inner inner = new StaticInner.Inner();
        
        inner.test();
    }
}

如果你把static去掉会报错,这个内部类会生成一个独立的class文件 名字是StaticInnerClass$Inner.class

3. 成员内部类(member inner class):可以访问外部类的静态与非静态的方法与成员变量。生成成员内部类对象的方式为:
     OuterClass.InnerClass inner = new OuterClass().new InnerClass();
例子:
class MemberInner
{
    private int a = 4;
   
    public class Inner2
    {
        private int a = 5;
        
        public void doSomething()
        {
            System.out.println(MemberInner.this.a);
        }
    }
   
    public void method()
    {
        Inner2 inner = this.new Inner2();
    }
}

public class MemberInnerClassTest
{
    public static void main(String[] args)
    {
        MemberInner.Inner2 inner = new MemberInner().new Inner2();
        
        inner.doSomething();        
    }
}
它可以访问外部类的所有成员

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

5. 局部内部类(Local Inner Class):定义在方法当中,只能访问方法中声明的final类型的变量。

class LocalInner
{
    public void doSomething()
    {
       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 localInner = new LocalInner();
        
        localInner.doSomething();
    }
}

外部类不能生成局部内部类的对象,如果你把final去掉会报错的。
6. 匿名内部类(Anonymous Inner Class):匿名内部类会隐式地继承一个父类或实现一个接口。
例子
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()
        {
            public String toLocaleString()
            {
                return "hello world";
            }
        });
        
        System.out.println(str);

红色的部分表示生成了继承Date类的子类的对象,而不是Date对象,这就是隐式地继承一个父类或实现一个接口
作者: 余清兰    时间: 2012-6-21 11:49
1、当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类对象。格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象
例如以上代码最后两句可写为:Outer.Inner c = new Outer( ).new Inner( );
                                    c.funcation();
2、当内部类在成员位置上,就可以被成员修饰符所修饰。比如,private:将内部类在外部类中进行封装。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的。

作者: 黑马-王言龙    时间: 2012-6-21 12:00
当内部类在一个成员位置上时,相当于一个成员,能被成员修饰符修饰,能访问外部类的成员。
     为什么当内部类定义在局部时就有些不能了呢?
     这里定义成局部是不是意思 说该内部类放在一个方法中?内部类放在方法中是局部内部类
   你可以这样理解局部内部类:即除定义成“成员内部类“以外的其它情况定义的类     
     这时不可以被成员修饰符修饰, 不可以访问其所在局部中的局部变量。  
     但是该内部类在这个局部中和那些局部变量不是平等的关系吗?怎么就不能访问了呢? 也作为局部中的一个成员,怎么就不能被修饰呢?
   
答:从内存中看,当局部变量所在方法结束时,该变量即在栈内存中消失;而内部类其实是一个类,
只有内存中对它的所有引用都消失后,该内部类才"死亡"。即内部类的生命周期可能比局部变量长久,于是
java规定局部内部类不能访问一般的局部变量;但能访问被final修饰的局部变量,被final修饰后的变量,我们
称之为"常量",它的生命周期和类的生命周期相同。

要是说 局部变量的数据是因为 随着 方法的存在而放在 栈 内存中,随方法消失而消失。 那调用该内部类不是肯定会加载这个方法的嘛。 那么这些局部变量不是也会存在。
调用该内部类,可以不加载这个方法

作者: 徐传任    时间: 2012-10-10 12:21
看看...........................




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2