黑马程序员技术交流社区

标题: 关于静态内部类的一个问题 [打印本页]

作者: kid1943    时间: 2014-10-21 10:15
标题: 关于静态内部类的一个问题
今天看到一代码,该代码实例化了一个内部类,但却不用先实例化其外部类。于是感到奇怪,因为以前实例化内部类都是需要类似的格式:
  1. Outclass.Innerclass ic=new Outclass.new Innerclass();
复制代码
但外部类想实例化静态内部类却不能这么写:
  1. package com.kid.innerclass;

  2. import com.kid.innerclass.Outclass.Innerclass;

  3. public class Outclass {

  4.         public static class Innerclass {

  5.                 Innerclass() {

  6.                         System.out.println("Innerclass is comming");
  7.                 }
  8.         }
  9. }

  10. class Test1 {

  11.         public static void main(String args[]) {
  12.                 Innerclass ic = new Innerclass();
  13.                 Outclass.Innerclass ic2 = new Outclass.Innerclass();
  14.                 Innerclass ic3 = new Outclass.Innerclass();

  15.                 /*
  16.                  * Innerclass ic4=new Outclass().new Innerclass();//这种写法错误
  17.                  */      
  18.         }

  19. }
复制代码

问题来了,为什么不可以这么写:
  1. Outclass.Innerclass ic=new Outclass.new Innerclass();
复制代码
它和程序上其他三种写法有何区别呢?





作者: HM2014nuli    时间: 2014-10-21 10:19
话说有24行的那种写法吗
作者: kid1943    时间: 2014-10-21 10:20
HM2014nuli 发表于 2014-10-21 10:19
话说有24行的那种写法吗

有啊 不过前提是你的内部类是非静态 你可以测试一下看看
作者: HM2014nuli    时间: 2014-10-21 10:26
kid1943 发表于 2014-10-21 10:20
有啊 不过前提是你的内部类是非静态 你可以测试一下看看

19和21都是错的吧
作者: liuxiang    时间: 2014-10-21 12:43
这就要搞清静态了,静态方法的调用,是不需要建立对象直接用类名调用的,因为一加载类,静态就存在了,那么静态内部类也是在外部类的成员位置上,也就不需建立外部类对象再调用内部类对象了
作者: mingtianrsm    时间: 2014-10-21 14:42
不知道是不是我的myeclipse有问题,这个代码里第5、19、21行也是错的。第5行Outclass这个类不能用public修饰。而Innerclass这个类根本就不存在,怎么可以直接用它来声明呢?
作者: kid1943    时间: 2014-10-21 16:58
HM2014nuli 发表于 2014-10-21 10:26
19和21都是错的吧

可能是jdk版本问题,我写这段代码是没错误的
作者: kid1943    时间: 2014-10-21 17:00
mingtianrsm 发表于 2014-10-21 14:42
不知道是不是我的myeclipse有问题,这个代码里第5、19、21行也是错的。第5行Outclass这个类不能用public修 ...

那就奇怪了 我在eclipse写是没问题的 我的是jdk7 不知道是不是jdk版本问题
作者: mingtianrsm    时间: 2014-10-21 20:32
kid1943 发表于 2014-10-21 17:00
那就奇怪了 我在eclipse写是没问题的 我的是jdk7 不知道是不是jdk版本问题

不会吧?:o我也是jdk7的啊!明显没有定义Innerclass这个类,咋会没错呢?
作者: cs8630323    时间: 2014-10-22 13:03
本帖最后由 cs8630323 于 2014-10-22 13:11 编辑
mingtianrsm 发表于 2014-10-21 20:32
不会吧?我也是jdk7的啊!明显没有定义Innerclass这个类,咋会没错呢?

已删..........................
作者: cs8630323    时间: 2014-10-22 13:19
感觉是你导入的类和静态内部类混淆了
作者: mingtianrsm    时间: 2014-10-22 18:37
kid1943 发表于 2014-10-21 17:00
那就奇怪了 我在eclipse写是没问题的 我的是jdk7 不知道是不是jdk版本问题

哦,发现了,你用静态导入了。我把导入那里删掉了
作者: cvnmklop    时间: 2014-10-22 18:51
首先先解答下前面有人认为以下两行代码错误
  1. Innerclass ic = new Innerclass();
  2. Innerclass ic3 = new Outclass.Innerclass();
复制代码
这两行代码没有错误因为前面有导入内部类
  1. import com.kid.innerclass.Outclass.Innerclass;
复制代码

我用了下eclipse看了下,说实话我很怀疑这种写法的正确性,请贴出具体来源是从哪里看的,然后你看到的代码有验证过吗?
  1. Outclass.Innerclass ic= new Outclass.new Innerclass();
复制代码
这种写法编译器就通不过,我是这么理解的 new 后面跟的是构造函数 new Outclass.new Innerclass();第一个new 后面是什么?无法理解。那么还有一种写法,两个new正确呢?new Outclass().new Innerclass()是因为内部类非静态只有当外部类实例化后才能创建内部类对象。本质上是对象调用对象中的成员。只不过这个成员比较特殊是内部类的构造函数。
然后让我有疑问的问题就产生了为什么下面这个代码是错误的

  1. Innerclass ic=new Outclass().new Innerclass();
复制代码

照理说成员是静态的直接用类名调用是可以的,那么创建对象再调用那就更加没问题了。我试验了下在Outclass类中添加了静态成员变量
  1. public static int num = 5;
复制代码
然后创建外部类对象调用num没有问题为什么 Innerclass ic=new Outclass().new Innerclass();这个形式错了呢?
源码如下,望高手指教  以下代码用的是junit测试的
  1. package com.kid.innerclass;

  2. public class Outclass {
  3.        
  4.                 public static int num = 5;
  5.         public static class Innerclass {

  6.                 Innerclass() {

  7.                         System.out.println("Innerclass is comming");
  8.                 }
  9.         }
  10. }
复制代码
  1. package com.kid.innerclass;

  2. import org.junit.Test;

  3. import com.kid.innerclass.Outclass.Innerclass;


  4. public class Test1 {

  5.            @Test
  6.       public void tt() {
  7.                               int num = new Outclass().num;
  8.                               System.out.println("num----->"+num);
  9.                Innerclass ic1 = new Innerclass();
  10.                Outclass.Innerclass ic2 = new Outclass.Innerclass();
  11.                Innerclass ic3 = new Outclass.Innerclass();
  12.                
  13.              //  Outclass.Innerclass ic4= new Outclass.new Innerclass();

  14.               
  15.                         //Innerclass ic5=new Outclass().new Innerclass();//为什么这种写法错误??
  16.                      
  17.        }

  18. }
复制代码







作者: kid1943    时间: 2014-10-28 08:08
cvnmklop 发表于 2014-10-22 18:51
首先先解答下前面有人认为以下两行代码错误
这两行代码没有错误因为前面有导入内部类
我用了下eclipse看了 ...
  1. Outclass.Innerclass ic= new Outclass.new Innerclass();
复制代码

我 忘加括号了应该是
  1. Outclass.Innerclass ic= new Outclass().new Innerclass();
复制代码

作者: 嘿~~    时间: 2014-10-28 11:05
你定义的是静态内部类。Outclass.Innerclass ic=Outclass.new Innerclass();应该这样
作者: 嘿~~    时间: 2014-10-28 11:06
kid1943 发表于 2014-10-28 08:08
我 忘加括号了应该是

这种写法是非静态内部类
作者: 戏言丶    时间: 2014-10-28 11:36
cvnmklop 发表于 2014-10-22 18:51
首先先解答下前面有人认为以下两行代码错误
这两行代码没有错误因为前面有导入内部类
我用了下eclipse看了 ...

因为内部类是静态的,不能直接new内部类,相当于不能在静态方法中使用this一样的道理
作者: 戏言丶    时间: 2014-10-28 11:38
嘿~~ 发表于 2014-10-28 11:05
你定义的是静态内部类。Outclass.Innerclass ic=Outclass.new Innerclass();应该这样

没有这种写法,如果不导入静态内部类要OuterClass.Innerclass ic2 = new OuterClass.Innerclass();
作者: 刘家斌    时间: 2014-10-28 11:59
你这里相当于导入了一个静态的成员,就如同导入静态方法一样,类名可以省略,只用在有同样方法的时候才要写类名表明调用的是哪个对象中的方法,所以前三种都是这种情况,外部类可以省略,写法四你是创建了外部类名.内部类名这样一个对象,你只用内部类接收,肯定是错的啊
作者: wzg1015    时间: 2014-10-28 12:02
  1. Innerclass ic4=new Outclass().new Innerclass();//这种写法错误
复制代码

前面的正确是可行的,静态内部类不依存于对象。
最后一种错误,我认为是受了对象可以调用静态成员的影响,你认为那是正确的。
我的想法是:本来静态成员变量,静态方法的调用也不应该使用对象进行调用的,但是那样用的人多了,所以sun做了优化,可以通过对象进行调用,但编译器应该会自动将其处理为类的调用。
而静态内部类,本来就用的很少,通过对象去调用静态成员成员本来应该是错误的。静态类也可以看做静态成员,但是sun公司并未做优化。所以是错误的。
对象调用静态成员,方法本来就只是一个迁就习惯的解决方式。
作者: cvnmklop    时间: 2014-10-28 13:59
戏言丶 发表于 2014-10-28 11:36
因为内部类是静态的,不能直接new内部类,相当于不能在静态方法中使用this一样的道理 ...

静态方法是优先于对象先存在的,当静态方法访问非静态成员时,那些非静态成员的对象都不存在,那些成员更不可能调用。
  1. class Person{
  2.         public String name;
  3.        
  4.         public static void show(){
  5.        
  6.                 /*
  7.                 静态方法优先于对象先存在,在执行show()这个方法的时候很有可能这个对象还不存在
  8.                 所以这个this就没有任何的意思,编译的时候直接报错
  9.                 */
  10.                 System.out.println(this.name);
  11.                 this.menthod();
  12.         }

  13.         public void menthod(){
  14.        
  15.         }
  16. }
复制代码
但是这个代码,跟你说的情况不一样,首先已经先创建了外部类对象,对于静态内部类而言这个this已经存在。再者在这个静态内部类中并没有调用非静态成员。
  1. Innerclass ic=new Outclass().new Innerclass();
复制代码
现在唯一能说的通的解释就是20楼所说的情况,这个情况记住就行了。因为这规则就是这样没有为什么。就好像为什么红灯停绿灯行,这就是规则


作者: 践行渐远    时间: 2014-10-28 16:17
本帖最后由 践行渐远 于 2014-10-28 16:19 编辑

内部类可以当做一个类成员来看待的,楼主之所以可以直接用内部类来创建对象,是因为前面import了外部类与内部类。
作者: kid1943    时间: 2014-10-31 16:44
cvnmklop 发表于 2014-10-28 13:59
静态方法是优先于对象先存在的,当静态方法访问非静态成员时,那些非静态成员的对象都不存在,那些成员更 ...

只好先记住啦 谢谢




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