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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 马雨铎 黑马帝   /  2011-7-31 00:01  /  2417 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

[code=java]public class Outer
{
    public static void main(String[] args) throws Exception
    {
        new Outer().greetWorld();
    }

    private void greetWorld()throws Exception
    {
        System.out.println( Inner.class.newInstance() );
    }

    public class Inner
    {
        public String toString()
        {
            return "Hello world";
        }
    }
}[/code]我是这么设计的,Outer中的main方法创建了一个Outer实例,并且调用了它的greetWorld方法,这个方法以字符串形式打印了通过反射创建的一个新的Inner实例。Inner的toString方法总是返回标准的问候语,程序的输出应该输出Hello World。
但是编译的时候出错了  没想明白哪错了  童鞋们  给指点下 !

4 个回复

倒序浏览
黑马网友  发表于 2011-7-31 01:14:37
沙发

回复 楼主 的帖子

因为无法实例化对象,把Inner类改为静态类就OK了,这是简单一点的做法,如果非要实例化非静态类就要复杂一点。
回复 使用道具 举报
黑马网友  发表于 2011-7-31 08:31:37
藤椅
你不要把Inner以内部类的形式声明,把Inner声明在Outer的外部,如果非要声明为内部类就要声明为static类型的如:static class Inner{}
下面是以外部类形式声明的[code]public class Outer
        {   
        public static void main(String[] args) throws Exception  
        {        
                        new Outer().greetWorld();
        }
        private void greetWorld()throws Exception   
        {      
               
                        System.out.println( Inner.class.newInstance() );   
        }  
         
}
class Inner   
{      
        public String toString()        
        {            
                return "Hello world";      
        }   
} [/code]
回复 使用道具 举报
告诉你编译不会出错,运行报错Exception in thread "main" java.lang.InstantiationException: cn.itcast.generic.Outer$Inner。你没明白:当Outer类在内存中加载了,虽然内部类Inner类被加载到内存中去,但JvM会改变内部类的名字,下面代码得到真正的Inner类名:
package cn.itcast.generic;
public class Outer
{
    public static void main(String[] args) throws Exception
    {
            System.out.println(Inner.class);
    }

    private void greetWorld()throws Exception
    {
        System.out.println(Class.forName("cn.itcast.generic.Outer$Inner"));
    }

    public class Inner
    {
        public String toString()
        {
            return "Hello world";
        }
    }
}
//打印结果: class cn.itcast.generic.Outer$Inner
这个类名只有虚拟机能解析,你不能不能直接拿来用,所以只能通过构造方法实例化,从而你写的
Inner.class也不会存在。
而且我们要注意内部类默认构造方法不是void,而是需要传一个Outer对象,看以下代码可以知道package cn.itcast.generic;
public class Outer
{
    public static void main(String[] args) throws Exception
    {
//            System.out.println(Inner.class);
            new Outer().greetWorld();
    }

    private void greetWorld()throws Exception
    {
        System.out.println(Inner.class.getConstructors()[0].getParameterTypes()[0].getName());
    }

    public class Inner
    {
       public Inner(){}
            public String toString()
        {
            return "Hello world";
        }
    }
//打印结果为:cn.itcast.generic.Outer
可知参数类型为Outer对象。
所以应该这样写可以得到你的结果
package cn.itcast.generic;
public class Outer
{
    public static void main(String[] args) throws Exception
    {
//     System.out.println(Inner.class);
     new Outer().greetWorld();
    }
    private void greetWorld()throws Exception
    {
        System.out.println(Inner.class.getConstructors()[0].newInstance(new Outer()));
    }
    public class Inner
    {
       public Inner(){}
     public String toString()
        {
            return "Hello world";
        }
    }
}


当然像上面同学加static的话,运行时会有一份单独的名叫Inner的字节码会加载到内存中去,也就可以实例化了。
推荐可以看看类的加载的方式,就可以深入明白了。
[ 本帖最后由 蔡园园 于 2011-07-31  11:48 编辑 ]
回复 使用道具 举报
静态成员不能访问非静态成员,----外部类的静态方法、静态代码块不能访问非静态内部类百科不能使用非静态内部类定义的变量、创建实例等
总之:不允许在外部类的静态成员中直接使用非静态内部类。[code=java]package cn.itcast.heima
public class TestStatic
{
        //定义一个非静态的内部类,是一个空类
        private class In{}
        //外部类的静态方法
        public static void main(String[] args)
        {
                //下面代码引发编译异常,因为静态成员(main方法)无法访问非静态成员(In类)
                new In();
        }
}[/code]总结对于static而言,类成员(包括方法、初始化快、内部类和枚举类)不能访问实例成员(包括属性、方法、初始化快、内部类和枚举类);
因为这是类成员是属于类的,类成员的作用域比实例成员的作用域更大,完全可能出现类成员已经初始化完成,但是实例成员还不能初始化,如果运行类成员访问实例成员讲话引起大量错误。
[ 本帖最后由 詹季春 于 2011-07-31  10:09 编辑 ]
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马