首先是测试代码:
public class Test {
class A{
// 非静态类
}
static class B{
// 静态类
}
int i = 10;//非静态变量
static int j = 10;//静态变量
// 这是一个非静态方法
public void test() {
i = 9;//直接修改i,成功
main(new String[0]);//随便塞个参数给main函数来调用静态方法,成功
}
// 这是一个静态方法
public static void main(String[] args) {
A a1 = new Test().new A();//通过创建类Test然后由Test声明内部类A的方式创建对象a1
// A a2 = new A();试图直接声明对象a2,报错
B b1 = new B();//直接声明对象b1
// B b2 = new Test().new B();试图通过创建类Test然后声明对象b2,报错
new Test().i = 8;//通过先将Test实例化再修改其中变量,成功(该代码无任何意义,因为该类没有被保存)
// System.out.println(i);无法直接调用非静态变量i
// Test.i = 8;试图通过类名访问非静态变量,报错
// i = 9;同上上行,报错
Test.j = 9;//通过类名直接访问静态变量
j = 8;//直接访问静态变量
new Test().j = 7;//通过将Test实例化再修改其中静态变量(多此一举,该代码仅为了测试)
}
}
由以上代码可知,一个静态方法想要访问非静态方法或非静态变量,必须通过类的实例化然后引用的方式进行。
反之,非静态方法可以随意访问同一类下的其他所有方法或全局变量。
原理解释:这是因为静态方法和静态变量优先于类的实例化,在类被实例化之前静态方法和静态变量便被加载到了内存中。(具体原理涉及JVM构造,在此不过多叙述)
而此时类的其他非静态方法和非静态变量还未被加载到内存中。
为了避免出现调用一个还没有被加载,也就是还不存在的方法或变量的情况出现,编译器会禁止该类操作。
通俗解释:在代码中我们可以不将一个类实例化便去访问其静态变量或静态方法,但这种情况下该类的其他非静态变量和非静态方法还没有被实例化。
如果其静态方法涉及到了非静态变量或非静态方法便会导致其访问了一个没有被实例化,也就是不存在的数据。
那么显然会出现错误,为了避免这种情况的出现,编译器会禁止该类操作。