本文连接地址:http://www.javashuo.com/article/p-zenshsfg-kh.htmlhtml
No enclosing instance of type
SomeClass
is accessible. Must qualify the allocation with an enclosing instance of typeSomeClass
(e.g.x.new A()
wherex
is an instance ofSomeClass
).java
拿Eclipse编写Java的AWT/Swing程序时,编写了一个public class MainFrame extends JFrame
而后在其中放入一个主函数写入了以下内容:面试
public static void main(String args[]) { MainJFrame frmBase = new MainJFrame("Hello Swing"); frmBase.setBackground(Color.white); frmBase.setVisible(true); frmBase.addWindowListener(new MainJWindowListener()); // <--- Error occured here !!! }
也就是我在主函数建立了窗口以后想要继续在主函数里为frmBase
这个JFrame
窗口添加窗口侦听器(class MainJWindowListener implements WindowListener
),其中MainJWindowListener
做为MainFrame
的内类。
而后错误就发生了……eclipse
若是已经了解了静态的内容,请自行跳转至“静态成员说完了,那跟这你遇到的这个问题有什么关系呢??”子节函数
好吧,其实说到底都是main
的static
修饰惹的祸。
咱们知道static
的成员也好,类也好,所谓的“静态”其实说的都是“为整个程序所共享”的意思,说的直白一点,static
的东西都很是的“大公无私”。
固然,其实我写C#写的比较多,对Java的规则还不是很了解,彷佛Java并不像C#那样容许public static class SomeClass
,因此对于Java而言更多的是针对静态成员讨论的。this
做为一个大公无私的内容,static
的成员里面除了本身再构造一些临时对象之外,直接援引的类、函数都不能是为某一对象所特有的。code
不,这里说的“特有”并非这个意思,或许我换个词语会更好一些——对象“个性”的属性。orm
打住,我知道你要问这件事,因此我这里举个糖炒栗子:
好比说类Gold
被定义为:htm
public class Gold { // Properties private static float xau = 1504.35f; // 金单价,也就是每盎司黄金在国际市场的价格,我随便编的数请别在乎…… private float oz; // 该黄金实例(理解成金块金锭金碎末金戒指金项链均可以)的质量(盎司数) // Constructor public Gold(float oz) { this.oz = oz; } // Methods ... }
咱们看到金单价xau
是静态的,由于不管那个金子多沉,长成什么样子,金单价对全部金子都是同样的,并且当xau
变更的时候,全部Gold
的价格也都会随着xau
变更。因此这种属性就不具有“个性”,由于你用我用你们一块儿用,也就是说,这是全体的“共性”。对象
而重量oz
就不同了,一座金山(Kingsoft)可能有1e+xxx的oz
,而一个金粒可能只有1e-xxx的oz
,我可能用一个new Gold(1e+500)
表示我构建了一个黄金星球,我也可能用new Gold(1e-500)
表示我构造了一个金分子之类的。
但总之,他们都是Gold
,他们都有oz
,但是每一个人的oz
都不同,这就是个性
。
你有Freestyle嘛
咱们接下来再看看它的方法想定义些什么(但我如今暂时不定义):
public class Gold { // Properties ... // Constructor ... // Methods // GetPrice() 可以得到该金块的具体价格,按金单价*盎司数计算 // Rise(float price) 提高黄金单价,增长price元 // Reduce(float price) 下降黄金单价,减小price元 // ... }
先看这些函数,很明显咱们能看出一些规律:
像GetPrice
这种函数,它的结果是“个性”的,xau*oz
当中oz
是“个性”的,这个结果固然也就可能彼此不一样。
而Rise
和Reduce
这两个函数,它们要修改的xau
是共性的,并且仅仅牵涉到“共性”,也就是说,它们是可以影响整个黄金国度每个金子的命运的函数。
啊,确实能够,由于非静态的成员可以访问类内全部的其余成员,无所谓静态和非静态。
固然,对于GetPrice来讲,这无所谓,并且其结果自己就是“个性”的:
public class Gold { // Properties ... // Constructor ... // Methods public float GetPrice() // 可以得到该金块的具体价格,按金单价*盎司数计算 { return xau*oz; } public void Rise(float price) //提高黄金单价,增长price元 { xau += price; } public void Reduce(float price) // 下降黄金单价,减小price元 { xau -= price; } // ... }
这么写的话固然没有问题,不犯任何语法错误并且编译是经过的,并且你只要实例化一个金子你也确实可以正确地调用这些函数并获得正确的结果。
像这样:
public void main(String args[]) //主函数,在哪一个类里就别管了 { Gold gNugget = new Gold(0.01f); System.out.println(String.format("%.2f", gNugget.GetPrice())); gNugget.Rise(10.0f); System.out.println(String.format("%.2f", gNugget.GetPrice())); gNugget.Reduce(20.0f); System.out.println(String.format("%.2f", gNugget.GetPrice())); }
输出结果:
15.04 15.14 14.94
结果确实没问题
……固然你也能够弄好多个金子这么玩……
只不过……
当gNugget.Rise()
或者gMountain.Reduce()
被调用的时候,全部金子(固然包含它们自身)都是受到影响的。
想像一下:
gNugget.Reduce(1000.0f);
结果一个小小的金粒致使了黄金市场遭受了惨重的金融危机,你不以为这个小金粒的能耐忒大了点么??
固然,这也就同将Rise()/Reduce()
改为public
也差很少了。
一个普通的,不是static
的函数,意味着它是一种“个性”的行为,这也就是说:
这种行为谁均可以作,想来就来我行我秀u can u up
固然,若是一个函数被声明为static
的,那么也就意味着这不是一种“个性”的行为,而是“共性”的行为,这也就是说:
这种行为并不能由某一个体单独执行,必须赌上全种族的命运,以种族的名义,去吧!!!
因此,若是不但愿金价被某一个金块干扰的话,Rise
和Reduce
也得是static
的:
public static void Rise(float price) //提高黄金单价,增长price元 { xau += price; } public static void Reduce(float price) // 下降黄金单价,减小price元 { xau -= price; }
这样一来,Rise
和Reduce
就必须以Gold.Rise()
和Gold.Reduce()
调用,而不能让Gold的实例来调用,也就是说,这一举措会致使下面的语句出错:
gNugget.Rise(10.0f); gNugget.Reduce(20.0f);
由于这两个函数是“共性”的,想涨价降价你一个小小的gNugget
说了不算的,必须是以Gold
全体的名义来讲:Gold.Rise()
固然,共性行为也会有这样的约束,好比,共性的行为不容许引入个性的内容(书面上来讲就是静态方法中不容许调用非静态的属性和方法和内部类),由于若是一个行为牵扯到个性的因素,那么它就不能以这个类全体的名义去作,好比我把GetPrice
改为static
的就会出错:
public static float GetPrice() // 不行!!!! { return xau*oz; }
由于并不存在属于Gold
全体的oz
,每一个金子都有本身的oz
,因此这个时候调用Gold.GetPrice()
,程序本身也不知道该返回谁的oz
,因此这样是不能够的。
拿Eclipse编写Java的AWT/Swing程序时,编写了一个
public class MainFrame extends JFrame
而后在其中放入一个主函数写入了以下内容:public static void main(String args[]) { MainJFrame frmBase = new MainJFrame("Hello Swing"); frmBase.setBackground(Color.white); frmBase.setVisible(true); frmBase.addWindowListener(new MainJWindowListener()); // <--- Error occured here !!! }也就是我在主函数建立了窗口以后想要继续在主函数里为
frmBase
这个JFrame
窗口添加窗口侦听器(class MainJWindowListener implements WindowListener
),其中MainJWindowListener
做为MainFrame
的内类。
而后错误就发生了……
请注意画线部分!!!
Java里面main
函数强制具有这些修饰:public static void
,也就是说main
理所应当的是个静态成员。
可是,请注意,main
里面试图引入了MainJWindowListener
这个内类并试图调用构造函数进行构造,但是,MainJWindowListener
只是个缺省访问级别的普通动态内类,这就是问题所在了。
这里基于使用了Swing这个事实,解决方案有两种,其中一种是推荐的,而另一种是通用的。
推荐的方法是用于根治在Swing下发生这种问题的一种重构代码的思路,这种方法规避了在静态成员中进行动态内类(这里面动态内类主要指事件侦听器)的引用。
通用的方法是针对咱们遇到的这个问题,经过修改代码使得静态成员可以调用动态内类,这里时刻注意一点,内类由于不是静态的,这意味着内类的构造必须在一个外部类(一个非静态类)实例的范畴下进行。
考虑到我这里的情景,我是要给窗口注册一下窗口关闭的动做,也就是为关闭按钮添加事件侦听器。
可是实际状况是,基本上只要是这个MainJFrame
窗口,我都但愿它注册这个关闭按钮的事件侦听器。因此这个过程彻底能够不在主函数里进行。
而一个非静态类,不管长成什么样子,其构造函数永远也不会是static
的,因此事件侦听的注册彻底能够放到构造函数里去作:
public MainJFrame(String caption) { super(caption); //....Some initial actions...// this.addWindowListener(new MainJWindowListener()); }
而后main
函数只须要负责构造之就能够了:
public static void main(String args[]) { //..Others..// MainJFrame frmBase = new MainJFrame(); //..Others..// }
这是个很是一劳永逸且合乎逻辑的作法,由于就算有多个MainJFrame
,咱们通常都会但愿对用户行为的反馈是一致的,也就是说实际上全部的MainJFrame
都会被配备相同的事件侦听器,既然如此的话放到构造函数统一随着构造的时候执行是再好不过的了。
推荐的方法里面规避了在静态成员中调用这个内部类,转到一个非静态成员中进行,并且事实上证实“效果拔群”。
可是说到底“效果拔群”也只是对这类情形“拔群”,假使咱们非要这么作,好比说我非要在多个MainJFrame
作不一样的事件侦听处理,那就不该该写在构造函数当中,由于这不是统一的构造流程,无法写进一个函数里。
也就是说,咱们非得要在main
函数里作侦听绑定,由于main
函数强制具备static
性质,而MainJWindowListener
不是static
的因此像这样是不能够的:
public static void main(String args[]) { MainJFrame frmBase = new MainJFrame("Hello Swing"); frmBase.setBackground(Color.white); frmBase.setVisible(true); // 不行!!!MainJWindowListener不是静态的!!! frmBase.addWindowListener(new MainJWindowListener()); }
也就是说,MainJWindowListener
必须跟着一个MainJFrame
的实例里面才能够构造,那么咱们非要找一个MainJFrame
实例mjfinstance
不可,而后再new mjfinstance.MainJWindowListener()
……
……巧了,这不是有么??frmBase
不就是一个MainJFrame
么??因此把这一句改为:
frmBase.addWindowListener(new frmBase.MainJWindowListener());
就能够了。